dnl Based on the one from the Boinc project by Reinhard
+AC_DEFUN([AX_CHECK_WINDOWS],
+[AC_MSG_CHECKING(for windows)
+target_windows="no"
+AC_CHECK_HEADER(windows.h,[target_windows="yes"],[target_windows="no"])
+AC_MSG_RESULT($target_windows)
+AM_CONDITIONAL(TARGET_WINDOWS,test "x$target_windows" = "xyes")
+])dnl
+
AC_DEFUN([AX_CHECK_KRB5],
[AC_MSG_CHECKING(for GSS-API and Kerberos implementation)
KRB5_DIR=
[Use krb5 (in specified installation directory)]),
[check_krb5_dir="$withval"],
[check_krb5_dir=])
-AM_COND_IF(TARGET_WINDOWS,[
- found_krb5="yes"
- krb5dir=$check_krb5_dir
- KRB5_CFLAGS=-I"$check_krb5_dir/include"
- KRB5_LIBS="-L$check_krb5_dir/lib/ -lkrb5_32 -lgssapi32"
- COMPILE_ET=
-],
-[for dir in $check_krb5_dir $prefix /usr /usr/local ; do
+for dir in $check_krb5_dir $prefix /usr /usr/local ; do
krb5dir="$dir"
if test -x "$dir/bin/krb5-config"; then
found_krb5="yes";
- KRB5_CFLAGS=`$dir/bin/krb5-config gssapi --cflags`;
- KRB5_LIBS=`$dir/bin/krb5-config gssapi --libs`;
- COMPILE_ET="$dir/bin/compile_et";
+ if test "x$target_windows" = "xyes"; then
+ KRB5_CFLAGS=-I"$check_krb5_dir/include";
+ KRB5_LIBS="-L$check_krb5_dir/lib/ -lkrb5_32 -lgssapi32";
+ COMPILE_ET="$check_krb5_dir/bin/compile_et";
+ else
+ KRB5_CFLAGS=`$dir/bin/krb5-config gssapi --cflags`;
+ KRB5_LIBS=`$dir/bin/krb5-config gssapi --libs`;
+ COMPILE_ET="$dir/bin/compile_et";
+ fi
break;
fi
-done])
+done
AC_MSG_RESULT($found_krb5)
if test x_$found_krb5 != x_yes; then
AC_MSG_ERROR([
if test x_$found_shibsp != x_yes; then
AC_MSG_ERROR([
----------------------------------------------------------------------
- Cannot find Shibboleth/OpenSAML libraries.
+ Cannot find Shibboleth libraries.
Please install Shibboleth or specify installation directory with
--with-shibsp=(dir).
])
else
printf "Shibboleth found in $shibspdir\n";
- SHIBSP_LIBS="-lshibsp -lsaml -lxml-security-c -lxmltooling -lxerces-c";
+ SHIBSP_LIBS="-lshibsp -lsaml -lxml-security-c -lxmltooling -lxerces-c";
SHIBSP_LDFLAGS="-L$shibspdir/lib";
AC_SUBST(SHIBSP_CXXFLAGS)
AC_SUBST(SHIBSP_LDFLAGS)
AC_SUBST(SHIBSP_LIBS)
+ AC_DEFINE_UNQUOTED([HAVE_SHIBSP], 1, [Define is Shibboleth SP is available])
fi
])dnl
[Use Shibboleth resolver (in specified installation directory)]),
[check_shibresolver_dir="$withval"],
[check_shibresolver_dir=])
+if test x_$check_shibresolver_dir != x_no; then
for dir in $check_shibresolver_dir $prefix /usr /usr/local ; do
shibresolverdir="$dir"
if test -f "$dir/include/shibresolver/resolver.h"; then
break;
fi
done
+fi
AC_MSG_RESULT($found_shibresolver)
+if test x_$check_shibresolver_dir != x_no; then
if test x_$found_shibresolver != x_yes; then
- AC_MSG_ERROR([
+ AC_MSG_WARN([
----------------------------------------------------------------------
- Cannot find Shibboleth resolver libraries.
+ Cannot find Shibboleth resolver libraries, building without
+ Shibboleth support.
Please install Shibboleth or specify installation directory with
--with-shibresolver=(dir).
AC_SUBST(SHIBRESOLVER_CXXFLAGS)
AC_SUBST(SHIBRESOLVER_LDFLAGS)
AC_SUBST(SHIBRESOLVER_LIBS)
+ AC_DEFINE_UNQUOTED([HAVE_SHIBRESOLVER], 1, [Define is Shibboleth resolver is available])
+fi
fi
])dnl
-AC_DEFUN([AX_CHECK_WINDOWS],
-[AC_MSG_CHECKING(for windows)
-target_windows="no"
-AC_CHECK_HEADER(windows.h,[target_windows="yes"],[target_windows="no"])
-AC_MSG_RESULT($target_windows)
-AM_CONDITIONAL(TARGET_WINDOWS,test "x$target_windows" = "xyes")
-])dnl
+AC_DEFUN([AX_CHECK_OPENSAML],
+[AC_MSG_CHECKING(for OpenSAML implementation)
+OPENSAML_DIR=
+found_opensaml="no"
+AC_ARG_WITH(opensaml,
+ AC_HELP_STRING([--with-opensaml],
+ [Use OpenSAML (in specified installation directory)]),
+ [check_opensaml_dir="$withval"],
+ [check_opensaml_dir=])
+if test x_$check_opensaml_dir != x_no; then
+for dir in $check_opensaml_dir $prefix /usr /usr/local ; do
+ opensamldir="$dir"
+ if test -f "$dir/include/saml/Assertion.h"; then
+ found_opensaml="yes";
+ OPENSAML_DIR="${opensamldir}"
+ OPENSAML_CXXFLAGS="-I$opensamldir/include";
+ break;
+ fi
+done
+fi
+AC_MSG_RESULT($found_opensaml)
+if test x_$check_opensaml_dir != x_no; then
+if test x_$found_opensaml != x_yes; then
+ AC_MSG_WARN([
+----------------------------------------------------------------------
+ Cannot find OpenSAML libraries, building without OpenSAML support.
+ Please install OpenSAML or specify installation directory with
+ --with-opensaml=(dir).
+----------------------------------------------------------------------
+])
+else
+ printf "OpenSAML found in $opensamldir\n";
+ OPENSAML_LIBS="-lsaml -lxml-security-c -lxmltooling -lxerces-c";
+ OPENSAML_LDFLAGS="-L$opensamldir/lib";
+ AC_SUBST(OPENSAML_CXXFLAGS)
+ AC_SUBST(OPENSAML_LDFLAGS)
+ AC_SUBST(OPENSAML_LIBS)
+ AC_DEFINE_UNQUOTED([HAVE_OPENSAML], 1, [Define is OpenSAML is available])
+fi
+fi
+])dnl
AC_DEFUN([AX_CHECK_RADSEC],
[AC_MSG_CHECKING(for radsec)
AC_SUBST(JANSSON_LIBS)
fi
])dnl
+
+AC_DEFUN([AX_CHECK_LIBMOONSHOT],
+[AC_MSG_CHECKING(for Moonshot identity selector implementation)
+LIBMOONSHOT_DIR=
+found_libmoonshot="no"
+AC_ARG_WITH(libmoonshot,
+ AC_HELP_STRING([--with-libmoonshot],
+ [Use libmoonshot (in specified installation directory)]),
+ [check_libmoonshot_dir="$withval"],
+ [check_libmoonshot_dir=])
+for dir in $check_libmoonshot_dir $prefix /usr /usr/local ../../moonshot-ui/libmoonshot ; do
+ libmoonshotdir="$dir"
+ if test -f "$dir/include/libmoonshot.h"; then
+ found_libmoonshot="yes";
+ LIBMOONSHOT_DIR="${libmoonshotdir}"
+ LIBMOONSHOT_CFLAGS="-I$libmoonshotdir/include";
+ break;
+ fi
+done
+AC_MSG_RESULT($found_libmoonshot)
+if test x_$found_libmoonshot != x_yes; then
+ AC_MSG_ERROR([
+----------------------------------------------------------------------
+ Cannot find Moonshot identity selector libraries.
+
+ Please install wpa_supplicant or specify installation directory with
+ --with-libmoonshot=(dir).
+----------------------------------------------------------------------
+])
+else
+ printf "libmoonshot found in $libmoonshotdir\n";
+ LIBMOONSHOT_LIBS="-lmoonshot";
+ LIBMOONSHOT_LDFLAGS="-L$libmoonshot/lib";
+ AC_SUBST(LIBMOONSHOT_CFLAGS)
+ AC_SUBST(LIBMOONSHOT_LDFLAGS)
+ AC_SUBST(LIBMOONSHOT_LIBS)
+ AC_CHECK_LIB(moonshot, moonshot_get_identity, [AC_DEFINE_UNQUOTED([HAVE_MOONSHOT_GET_IDENTITY], 1, [Define if Moonshot identity selector is available])], [], "$LIBMOONSHOT_LIBS")
+fi
+])dnl
+
AM_INIT_AUTOMAKE
AM_PROG_CC_C_O
AM_MAINTAINER_MODE()
-LT_PREREQ([2.4])
+LT_PREREQ([2.2])
LT_INIT([dlopen disable-static win32-dll])
dnl AC_PROG_CC
AC_SUBST(TARGET_LDFLAGS)
AX_CHECK_WINDOWS
AX_CHECK_KRB5
-AM_CONDITIONAL(HEIMDAL, test "x$heimdal" != "xno")
-dnl AX_CHECK_EAP
-if test "x$acceptor" = "xyes" ; then
+AX_CHECK_OPENSAML
+AM_CONDITIONAL(OPENSAML, test "x_$check_opensaml_dir" != "x_no")
+
+AX_CHECK_SHIBRESOLVER
+AM_CONDITIONAL(SHIBRESOLVER, test "x_$check_shibresolver_dir" != "x_no")
+if test x_$found_shibresolver = x_yes; then
AX_CHECK_SHIBSP
- AX_CHECK_SHIBRESOLVER
+fi
+
+if test "x$acceptor" = "xyes" ; then
AX_CHECK_RADSEC
AX_CHECK_JANSSON
fi
+
+AX_CHECK_LIBMOONSHOT
AC_CONFIG_FILES([Makefile libeap/Makefile mech_eap/Makefile])
AC_OUTPUT
EAP_CFLAGS = -I$(srcdir)/../libeap/src -I$(srcdir)/../libeap/src/common -I$(srcdir)/../libeap/src/eap_common \
-I$(srcdir)/../libeap/src/utils
+if GSSEAP_ENABLE_ACCEPTOR
+GSSEAP_EXPORTS = mech_eap.exports
+else
+GSSEAP_EXPORTS = mech_eap-noacceptor.exports
+endif
+
gssdir = $(libdir)/gss
gss_LTLIBRARIES = mech_eap.la
+
if TARGET_WINDOWS
EAP_CFLAGS += -DCONFIG_WIN32_DEFAULTS -DUSE_INTERNAL_CRYPTO
OS_LIBS = -lshell32 -ladvapi32 -lws2_32 -lcomerr32
endif
mech_eap_la_CPPFLAGS = -DBUILD_GSSEAP_LIB -DSYSCONFDIR=\"${sysconfdir}\" -DDATAROOTDIR=\"${datarootdir}\"
-mech_eap_la_CFLAGS += @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
-mech_eap_la_CXXFLAGS += @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @SHIBRESOLVER_CXXFLAGS@ @SHIBSP_CXXFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
+mech_eap_la_CFLAGS = -Werror -Wall -Wunused-parameter \
+ @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
+mech_eap_la_CXXFLAGS = -Werror -Wall -Wunused-parameter \
+ @KRB5_CFLAGS@ @RADSEC_CFLAGS@ \
+ @OPENSAML_CXXFLAGS@ @SHIBRESOLVER_CXXFLAGS@ @SHIBSP_CXXFLAGS@ \
+ @TARGET_CFLAGS@ $(EAP_CFLAGS)
mech_eap_la_LDFLAGS = -avoid-version -module \
- -export-symbols $(srcdir)/mech_eap.exports -no-undefined \
+ -export-symbols $(GSSEAP_EXPORTS) -no-undefined \
@RADSEC_LDFLAGS@ @TARGET_LDFLAGS@
-mech_eap_la_LIBADD = @KRB5_LIBS@ ../libeap/libeap.la @RADSEC_LIBS@ \
- @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@ $(OS_LIBS) $(LTLIBOBJS)
+if TARGET_WINDOWS
+mech_eap_la_LDFLAGS += -debug
+endif
+mech_eap_la_LIBADD = @KRB5_LIBS@ ../libeap/libeap.la @RADSEC_LIBS@ \
+ @OPENSAML_LIBS@ @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@
mech_eap_la_SOURCES = \
- accept_sec_context.c \
acquire_cred.c \
acquire_cred_with_password.c \
add_cred.c \
canonicalize_name.c \
compare_name.c \
context_time.c \
- delete_name_attribute.c \
delete_sec_context.c \
display_name.c \
display_name_ext.c \
duplicate_name.c \
eap_mech.c \
export_name.c \
- export_name_composite.c \
export_sec_context.c \
get_mic.c \
- get_name_attribute.c \
gsseap_err.c \
import_name.c \
import_sec_context.c \
inquire_names_for_mech.c \
inquire_saslname_for_mech.c \
inquire_sec_context_by_oid.c \
- map_name_to_any.c \
process_context_token.c \
pseudo_random.c \
radsec_err.c \
- release_any_name_mapping.c \
release_cred.c \
release_name.c \
release_oid.c \
- set_name_attribute.c \
set_cred_option.c \
set_sec_context_option.c \
store_cred.c \
unwrap.c \
unwrap_iov.c \
- util_base64.c \
util_buffer.c \
util_context.c \
util_cksum.c \
util_krb.c \
util_lucid.c \
util_mech.c \
+ util_moonshot.c \
util_name.c \
util_oid.c \
util_ordering.c \
wrap_iov_length.c \
wrap_size_limit.c
-BUILT_SOURCES = gsseap_err.c radsec_err.c
-
if GSSEAP_ENABLE_ACCEPTOR
-mech_eap_la_SOURCES += util_attr.cpp util_json.cpp util_radius.cpp util_shib.cpp util_saml.cpp
+
+mech_eap_la_SOURCES += \
+ accept_sec_context.c \
+ delete_name_attribute.c \
+ export_name_composite.c \
+ get_name_attribute.c \
+ map_name_to_any.c \
+ release_any_name_mapping.c \
+ set_name_attribute.c \
+ util_attr.cpp \
+ util_base64.c \
+ util_json.cpp \
+ util_radius.cpp
+
+if OPENSAML
+mech_eap_la_SOURCES += util_saml.cpp
endif
+if SHIBRESOLVER
+mech_eap_la_SOURCES += util_shib.cpp
+endif
+
+endif
+
+BUILT_SOURCES = gsseap_err.c radsec_err.c
+
if GSSEAP_ENABLE_REAUTH
mech_eap_la_SOURCES += util_reauth.c
endif
endif
-if TARGET_WINDOWS
-mech_eap_la_LDFLAGS += -debug
-else
gsseap_err.h gsseap_err.c: gsseap_err.et
$(COMPILE_ET) $<
clean-generic:
rm -f gsseap_err.[ch] radsec_err.[ch]
-endif
- integration with initiator-side EAP channel bindings
-- integration with final supplicant architecture
-- test Heimdal port
-
-- fix ABNF: no slash in the case where there is no host
- always intern OIDs so they never need to be freed
-
-- handle many-to-many Shibboleth attribute mappings; need to encode
- both attribute and value index into more
+- handle many-to-many Shibboleth attribute mappings; need to encode both attribute and value index into more
- add --with-xerces option
-- proper acquire_cred_ext implementation
-- MIC on flags token (merge ext-mic branch)
+- proper acquire_cred_ext implementation pending specification
*/
#include "gssapiP_eap.h"
-#ifdef GSSEAP_ENABLE_ACCEPTOR
+
#ifdef GSSEAP_ENABLE_REAUTH
static OM_uint32
eapGssSmAcceptGssReauth(OM_uint32 *minor,
return GSS_S_FAILURE;
}
- if (cred->radiusConfigFile != NULL)
- configFile = cred->radiusConfigFile;
- if (cred->radiusConfigStanza != NULL)
- configStanza = cred->radiusConfigStanza;
+ if (cred->radiusConfigFile.value != NULL)
+ configFile = (const char *)cred->radiusConfigFile.value;
+ if (cred->radiusConfigStanza.value != NULL)
+ configStanza = (const char *)cred->radiusConfigStanza.value;
ralloc.calloc = GSSEAP_CALLOC;
ralloc.malloc = GSSEAP_MALLOC;
}
static OM_uint32
+eapGssSmAcceptGssFlags(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken GSSEAP_UNUSED,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ unsigned char *p;
+ OM_uint32 initiatorGssFlags;
+
+ assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
+
+ if (inputToken->length < 4) {
+ *minor = GSSEAP_TOK_TRUNC;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ /* allow flags to grow for future expansion */
+ p = (unsigned char *)inputToken->value + inputToken->length - 4;
+
+ initiatorGssFlags = load_uint32_be(p);
+ initiatorGssFlags &= GSSEAP_WIRE_FLAGS_MASK;
+
+ ctx->gssFlags |= initiatorGssFlags;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
gss_buffer_t outputToken GSSEAP_UNUSED,
OM_uint32 *smFlags GSSEAP_UNUSED)
{
- OM_uint32 major, tmpMinor;
+ OM_uint32 major;
gss_iov_buffer_desc iov[2];
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_STREAM;
- iov[1].buffer = *inputToken;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM | GSS_IOV_BUFFER_FLAG_ALLOCATED;
+
+ /* XXX necessary because decrypted in place and we verify it later */
+ major = duplicateBuffer(minor, inputToken, &iov[1].buffer);
+ if (GSS_ERROR(major))
+ return major;
major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
iov, 2, TOK_TYPE_WRAP);
- if (GSS_ERROR(major))
+ if (GSS_ERROR(major)) {
+ gssEapReleaseIov(iov, 2);
return major;
+ }
if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS &&
!bufferEqual(&iov[0].buffer, &chanBindings->application_data)) {
*minor = 0;
}
- gss_release_buffer(&tmpMinor, &iov[0].buffer);
+ gssEapReleaseIov(iov, 2);
return major;
}
+static OM_uint32
+eapGssSmAcceptInitiatorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken GSSEAP_UNUSED,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ OM_uint32 major;
+
+ major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ GSSEAP_SM_TRANSITION_NEXT(ctx);
+
+ *minor = 0;
+ return GSS_S_CONTINUE_NEEDED;
+}
+
#ifdef GSSEAP_ENABLE_REAUTH
static OM_uint32
eapGssSmAcceptReauthCreds(OM_uint32 *minor,
#endif
static OM_uint32
-eapGssSmAcceptCompleteInitiatorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags GSSEAP_UNUSED)
+eapGssSmAcceptAcceptorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken GSSEAP_UNUSED,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags)
{
- GSSEAP_SM_TRANSITION_NEXT(ctx);
-
- *minor = 0;
+ OM_uint32 major;
- return GSS_S_CONTINUE_NEEDED;
-}
+ major = gssEapMakeTokenMIC(minor, ctx, outputToken);
+ if (GSS_ERROR(major))
+ return major;
-static OM_uint32
-eapGssSmAcceptCompleteAcceptorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags)
-{
GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
*minor = 0;
- *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
+ *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
return GSS_S_COMPLETE;
}
eapGssSmAcceptAuthenticate
},
{
+ ITOK_TYPE_GSS_FLAGS,
+ ITOK_TYPE_NONE,
+ GSSEAP_STATE_INITIATOR_EXTS,
+ 0,
+ eapGssSmAcceptGssFlags
+ },
+ {
ITOK_TYPE_GSS_CHANNEL_BINDINGS,
ITOK_TYPE_NONE,
GSSEAP_STATE_INITIATOR_EXTS,
eapGssSmAcceptGssChannelBindings,
},
{
- ITOK_TYPE_NONE,
+ ITOK_TYPE_INITIATOR_MIC,
ITOK_TYPE_NONE,
GSSEAP_STATE_INITIATOR_EXTS,
- 0,
- eapGssSmAcceptCompleteInitiatorExts,
+ SM_ITOK_FLAG_REQUIRED,
+ eapGssSmAcceptInitiatorMIC,
},
#ifdef GSSEAP_ENABLE_REAUTH
{
#endif
{
ITOK_TYPE_NONE,
- ITOK_TYPE_NONE,
+ ITOK_TYPE_ACCEPTOR_MIC,
GSSEAP_STATE_ACCEPTOR_EXTS,
0,
- eapGssSmAcceptCompleteAcceptorExts
+ eapGssSmAcceptAcceptorMIC
},
};
-#endif /* GSSEAP_ENABLE_ACCEPTOR */
-#ifdef GSSEAP_ENABLE_ACCEPTOR
-#define ACCEPTOR_PARAM(p) p
-#else
-#define ACCEPTOR_PARAM(p) UNUSED_PARAM(p)
-#endif
-
-OM_uint32 KRB5_CALLCONV
-gss_accept_sec_context(OM_uint32 *ACCEPTOR_PARAM(minor),
- gss_ctx_id_t *ACCEPTOR_PARAM(context_handle),
- gss_cred_id_t ACCEPTOR_PARAM(cred),
- gss_buffer_t ACCEPTOR_PARAM(input_token),
- gss_channel_bindings_t ACCEPTOR_PARAM(input_chan_bindings),
- gss_name_t *ACCEPTOR_PARAM(src_name),
- gss_OID *ACCEPTOR_PARAM(mech_type),
- gss_buffer_t ACCEPTOR_PARAM(output_token),
- OM_uint32 *ACCEPTOR_PARAM(ret_flags),
- OM_uint32 *ACCEPTOR_PARAM(time_rec),
- gss_cred_id_t *ACCEPTOR_PARAM(delegated_cred_handle))
+OM_uint32
+gssEapAcceptSecContext(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t input_token,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle)
{
-#ifdef GSSEAP_ENABLE_ACCEPTOR
OM_uint32 major, tmpMinor;
- gss_ctx_id_t ctx = *context_handle;
-
- *minor = 0;
-
- output_token->length = 0;
- output_token->value = NULL;
-
- if (src_name != NULL)
- *src_name = GSS_C_NO_NAME;
-
- if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
- *minor = GSSEAP_TOK_TRUNC;
- return GSS_S_DEFECTIVE_TOKEN;
- }
- if (ctx == GSS_C_NO_CONTEXT) {
- major = gssEapAllocContext(minor, &ctx);
- if (GSS_ERROR(major))
- return major;
-
- *context_handle = ctx;
- }
-
- GSSEAP_MUTEX_LOCK(&ctx->mutex);
-
if (cred == GSS_C_NO_CREDENTIAL) {
- if (ctx->defaultCred == GSS_C_NO_CREDENTIAL) {
+ if (ctx->cred == GSS_C_NO_CREDENTIAL) {
major = gssEapAcquireCred(minor,
GSS_C_NO_NAME,
- GSS_C_NO_BUFFER,
GSS_C_INDEFINITE,
GSS_C_NO_OID_SET,
GSS_C_ACCEPT,
- &ctx->defaultCred,
+ &ctx->cred,
NULL,
NULL);
if (GSS_ERROR(major))
goto cleanup;
}
- cred = ctx->defaultCred;
+ cred = ctx->cred;
}
GSSEAP_MUTEX_LOCK(&cred->mutex);
- if (cred->name != GSS_C_NO_NAME) {
- major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName);
- if (GSS_ERROR(major))
- goto cleanup;
- }
+ /*
+ * Calling gssEapInquireCred() forces the default acceptor credential name
+ * to be resolved.
+ */
+ major = gssEapInquireCred(minor, cred, &ctx->acceptorName, NULL, NULL, NULL);
+ if (GSS_ERROR(major))
+ goto cleanup;
major = gssEapSmStep(minor,
cred,
cleanup:
if (cred != GSS_C_NO_CREDENTIAL)
GSSEAP_MUTEX_UNLOCK(&cred->mutex);
- GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
-
- if (GSS_ERROR(major))
- gssEapReleaseContext(&tmpMinor, context_handle);
return major;
-#else
- return GSS_S_UNAVAILABLE;
-#endif /* GSSEAP_ENABLE_ACCEPTOR */
}
-#ifdef GSSEAP_ENABLE_ACCEPTOR
#ifdef GSSEAP_ENABLE_REAUTH
static OM_uint32
acceptReadyKrb(OM_uint32 *minor,
return major;
}
#endif /* GSSEAP_ENABLE_REAUTH */
-#endif /* GSSEAP_ENABLE_ACCEPTOR */
\ No newline at end of file
+
+OM_uint32 GSSAPI_CALLCONV
+gss_accept_sec_context(OM_uint32 *minor,
+ gss_ctx_id_t *context_handle,
+ gss_cred_id_t cred,
+ gss_buffer_t input_token,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle)
+{
+ OM_uint32 major, tmpMinor;
+ gss_ctx_id_t ctx = *context_handle;
+
+ *minor = 0;
+
+ output_token->length = 0;
+ output_token->value = NULL;
+
+ if (src_name != NULL)
+ *src_name = GSS_C_NO_NAME;
+
+ if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
+ *minor = GSSEAP_TOK_TRUNC;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ if (ctx == GSS_C_NO_CONTEXT) {
+ major = gssEapAllocContext(minor, &ctx);
+ if (GSS_ERROR(major))
+ return major;
+
+ *context_handle = ctx;
+ }
+
+ GSSEAP_MUTEX_LOCK(&ctx->mutex);
+
+ major = gssEapAcceptSecContext(minor,
+ ctx,
+ cred,
+ input_token,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ output_token,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle);
+
+ GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
+
+ if (GSS_ERROR(major))
+ gssEapReleaseContext(&tmpMinor, context_handle);
+
+ return major;
+}
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_acquire_cred(OM_uint32 *minor,
gss_name_t desired_name,
OM_uint32 time_req,
gss_OID_set *actual_mechs,
OM_uint32 *time_rec)
{
- return gssEapAcquireCred(minor, desired_name, GSS_C_NO_BUFFER,
+ return gssEapAcquireCred(minor, desired_name,
time_req, desired_mechs, cred_usage,
output_cred_handle, actual_mechs, time_rec);
}
#include "gssapiP_eap.h"
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
gssspi_acquire_cred_with_password(OM_uint32 *minor,
const gss_name_t desired_name,
const gss_buffer_t password,
gss_OID_set *actual_mechs,
OM_uint32 *time_rec)
{
- return gssEapAcquireCred(minor, desired_name, password,
- time_req, desired_mechs, cred_usage,
- output_cred_handle, actual_mechs, time_rec);
+ OM_uint32 major, tmpMinor;
+
+ major = gssEapAcquireCred(minor, desired_name,
+ time_req, desired_mechs, cred_usage,
+ output_cred_handle, actual_mechs, time_rec);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapSetCredPassword(minor, *output_cred_handle, password);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+cleanup:
+ if (GSS_ERROR(major))
+ gssEapReleaseCred(&tmpMinor, output_cred_handle);
+
+ return major;
}
* apart from the mechanism glue layer. However, Heimdal does call into the
* mechanism here.
*/
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_add_cred(OM_uint32 *minor,
gss_cred_id_t input_cred_handle GSSEAP_UNUSED,
gss_name_t desired_name,
major = gssEapAcquireCred(minor,
desired_name,
- GSS_C_NO_BUFFER,
time_req,
&mechs,
cred_usage,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_add_cred_with_password(OM_uint32 *minor,
const gss_cred_id_t input_cred_handle GSSEAP_UNUSED,
const gss_name_t desired_name,
OM_uint32 *initiator_time_rec,
OM_uint32 *acceptor_time_rec)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
OM_uint32 time_req, time_rec = 0;
gss_OID_set_desc mechs;
major = gssEapAcquireCred(minor,
desired_name,
- password,
time_req,
&mechs,
cred_usage,
output_cred_handle,
actual_mechs,
&time_rec);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapSetCredPassword(minor, *output_cred_handle, password);
+ if (GSS_ERROR(major))
+ goto cleanup;
if (initiator_time_rec != NULL)
*initiator_time_rec = time_rec;
if (acceptor_time_rec != NULL)
*acceptor_time_rec = time_rec;
+cleanup:
+ if (GSS_ERROR(major))
+ gssEapReleaseCred(&tmpMinor, output_cred_handle);
+
return major;
}
#include "gssapiP_eap.h"
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
gssspi_authorize_localname(OM_uint32 *minor,
const gss_name_t name GSSEAP_UNUSED,
gss_const_buffer_t local_user GSSEAP_UNUSED,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_canonicalize_name(OM_uint32 *minor,
const gss_name_t input_name,
const gss_OID mech_type,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_compare_name(OM_uint32 *minor,
gss_name_t name1,
gss_name_t name2,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_context_time(OM_uint32 *minor,
gss_ctx_id_t ctx,
OM_uint32 *time_rec)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_delete_name_attribute(OM_uint32 *minor,
gss_name_t name,
gss_buffer_t attr)
{
-#ifdef GSSEAP_ENABLE_ACCEPTOR
OM_uint32 major;
*minor = 0;
GSSEAP_MUTEX_UNLOCK(&name->mutex);
return major;
-#else
- return GSS_S_UNAVAILABLE;
-#endif
}
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_delete_sec_context(OM_uint32 *minor,
gss_ctx_id_t *context_handle,
gss_buffer_t output_token)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_display_name(OM_uint32 *minor,
gss_name_t name,
gss_buffer_t output_name_buffer,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_display_name_ext(OM_uint32 *minor,
gss_name_t name GSSEAP_UNUSED,
gss_OID display_as_name_type GSSEAP_UNUSED,
};
void
-gssEapDestroyStatusInfo(struct gss_eap_status_info* p)
+gssEapDestroyStatusInfo(struct gss_eap_status_info *p)
{
struct gss_eap_status_info *next;
saveStatusInfoNoCopy(OM_uint32 minor, char *message)
{
struct gss_eap_status_info **next = NULL, *p=NULL;
+ struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
- struct gss_eap_thread_local_data* tld = gssEapGetThreadLocalData();
if (tld != NULL) {
- for (p = tld->status_info; p != NULL; p = p->next) {
+ for (p = tld->statusInfo; p != NULL; p = p->next) {
if (p->code == minor) {
/* Set message in-place */
if (p->message != NULL)
}
next = &p->next;
}
-
p = GSSEAP_CALLOC(1, sizeof(*p));
}
+
if (p == NULL) {
if (message != NULL)
GSSEAP_FREE(message);
if (next != NULL)
*next = p;
else
- tld->status_info = p;
+ tld->statusInfo = p;
}
static const char *
getStatusInfo(OM_uint32 minor)
{
struct gss_eap_status_info *p;
- struct gss_eap_thread_local_data *tld=gssEapGetThreadLocalData();
+ struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
+
if (tld != NULL) {
- for (p = tld->status_info;
- p != NULL;
- p = p->next) {
+ for (p = tld->statusInfo; p != NULL; p = p->next) {
if (p->code == minor)
return p->message;
}
void
gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...)
{
+#ifdef WIN32
+ OM_uint32 tmpMajor, tmpMinor;
+ char buf[BUFSIZ];
+ gss_buffer_desc s = GSS_C_EMPTY_BUFFER;
+ va_list ap;
+
+ if (format != NULL) {
+ va_start(ap, format);
+ snprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+ }
+
+ tmpMajor = makeStringBuffer(&tmpMinor, buf, &s);
+ if (!GSS_ERROR(tmpMajor))
+ saveStatusInfoNoCopy(minor, (char *)s.value);
+#else
char *s = NULL;
int n;
va_list ap;
if (format != NULL) {
va_start(ap, format);
n = vasprintf(&s, format, ap);
+ if (n == -1)
+ s = NULL;
va_end(ap);
}
saveStatusInfoNoCopy(minor, s);
+#endif /* WIN32 */
}
-OM_uint32 KRB5_CALLCONV
-gss_display_status(OM_uint32 *minor,
- OM_uint32 status_value,
- int status_type,
- gss_OID mech_type,
- OM_uint32 *message_context,
- gss_buffer_t status_string)
+OM_uint32
+gssEapDisplayStatus(OM_uint32 *minor,
+ OM_uint32 status_value,
+ gss_buffer_t status_string)
{
OM_uint32 major;
krb5_context krbContext = NULL;
status_string->length = 0;
status_string->value = NULL;
- if (!gssEapIsMechanismOid(mech_type)) {
- *minor = GSSEAP_WRONG_MECH;
- return GSS_S_BAD_MECH;
- }
-
- if (status_type != GSS_C_MECH_CODE ||
- *message_context != 0) {
- /* we rely on the mechglue for GSS_C_GSS_CODE */
- *minor = 0;
- return GSS_S_BAD_STATUS;
- }
-
errMsg = getStatusInfo(status_value);
if (errMsg == NULL) {
GSSEAP_KRB_INIT(&krbContext);
return major;
}
+
+OM_uint32 GSSAPI_CALLCONV
+gss_display_status(OM_uint32 *minor,
+ OM_uint32 status_value,
+ int status_type,
+ gss_OID mech_type,
+ OM_uint32 *message_context,
+ gss_buffer_t status_string)
+{
+ if (!gssEapIsMechanismOid(mech_type)) {
+ *minor = GSSEAP_WRONG_MECH;
+ return GSS_S_BAD_MECH;
+ }
+
+ if (status_type != GSS_C_MECH_CODE ||
+ *message_context != 0) {
+ /* we rely on the mechglue for GSS_C_GSS_CODE */
+ *minor = 0;
+ return GSS_S_BAD_STATUS;
+ }
+
+ return gssEapDisplayStatus(minor, status_value, status_string);
+}
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_duplicate_name(OM_uint32 *minor,
const gss_name_t input_name,
gss_name_t *dest_name)
return GSS_S_COMPLETE;
}
-static void gssEapInitiatorInit(void) GSSEAP_CONSTRUCTOR;
-static void gssEapFinalize(void) GSSEAP_DESTRUCTOR;
+void gssEapInitiatorInit(void) GSSEAP_CONSTRUCTOR;
+void gssEapFinalize(void) GSSEAP_DESTRUCTOR;
-static void
+void
gssEapInitiatorInit(void)
{
OM_uint32 major, minor;
#endif
}
-static void
+void
gssEapFinalize(void)
{
+#ifdef GSSEAP_ENABLE_ACCEPTOR
OM_uint32 minor;
gssEapAttrProvidersFinalize(&minor);
+#endif
eap_peer_unregister_methods();
}
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_export_name(OM_uint32 *minor,
const gss_name_t input_name,
gss_buffer_t exported_name)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_export_name_composite(OM_uint32 *minor,
gss_name_t input_name,
gss_buffer_t exported_name)
*/
#include "gssapiP_eap.h"
+
#ifdef GSSEAP_ENABLE_ACCEPTOR
static OM_uint32
gssEapExportPartialContext(OM_uint32 *minor,
if (GSS_ERROR(major))
goto cleanup;
}
+
#ifdef GSSEAP_ENABLE_ACCEPTOR
/*
* The partial context is only transmitted for unestablished acceptor
return major;
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_export_sec_context(OM_uint32 *minor,
gss_ctx_id_t *context_handle,
gss_buffer_t interprocess_token)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_get_mic(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_qop_t qop_req,
* Wrapper for retrieving a naming attribute.
*/
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_get_name_attribute(OM_uint32 *minor,
gss_name_t name,
gss_buffer_t attr,
gss_buffer_t display_value,
int *more)
{
-#ifdef GSSEAP_ENABLE_ACCEPTOR
OM_uint32 major;
*minor = 0;
GSSEAP_MUTEX_UNLOCK(&name->mutex);
return major;
-#else
- return GSS_S_UNAVAILABLE;
-#endif
}
#include <assert.h>
#include <string.h>
#include <errno.h>
-#if defined(HAVE_UNISTD_H)
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STDARG_H
#include <stdarg.h>
+#endif
#include <time.h>
-#if defined(HAVE_SYS_PARAM_H)
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
+#ifdef WIN32
+#ifndef MAXHOSTNAMELEN
+# include <WinSock2.h>
+# define MAXHOSTNAMELEN NI_MAXHOST
+#endif
+#endif
+
/* GSS headers */
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_krb5.h>
#include <freeradius/libradius.h>
#include <freeradius/radius.h>
-////Because freeradius/autoconf.h is evil!
-////#undef uint16_t
-////#undef uint32_t
-////#undef uint8_t
#undef pid_t
+/* libradsec headers */
#include <radsec/radsec.h>
#include <radsec/request.h>
#ifdef __cplusplus
#undef operator
}
#endif
-#endif /*GSSEAP_ENABLE_ACCEPTOR*/
+#endif /* GSSEAP_ENABLE_ACCEPTOR */
#include "gsseap_err.h"
#include "radsec_err.h"
OM_uint32 flags;
gss_OID mechanismUsed; /* this is immutable */
krb5_principal krbPrincipal; /* this is immutable */
+#ifdef GSSEAP_ENABLE_ACCEPTOR
struct gss_eap_attr_ctx *attrCtx;
+#endif
};
#define CRED_FLAG_INITIATE 0x00010000
#define CRED_FLAG_ACCEPT 0x00020000
-#define CRED_FLAG_DEFAULT_IDENTITY 0x00040000
-#define CRED_FLAG_PASSWORD 0x00080000
-#define CRED_FLAG_DEFAULT_CCACHE 0x00100000
+#define CRED_FLAG_PASSWORD 0x00040000
+#define CRED_FLAG_DEFAULT_CCACHE 0x00080000
+#define CRED_FLAG_RESOLVED 0x00100000
#define CRED_FLAG_PUBLIC_MASK 0x0000FFFF
#ifdef HAVE_HEIMDAL_VERSION
GSSEAP_MUTEX mutex;
OM_uint32 flags;
gss_name_t name;
+ gss_name_t target; /* for initiator */
gss_buffer_desc password;
gss_OID_set mechanisms;
time_t expiryTime;
- char *radiusConfigFile;
- char *radiusConfigStanza;
+ gss_buffer_desc radiusConfigFile;
+ gss_buffer_desc radiusConfigStanza;
+ gss_buffer_desc caCertificate;
+ gss_buffer_desc subjectNameConstraint;
+ gss_buffer_desc subjectAltNameConstraint;
#ifdef GSSEAP_ENABLE_REAUTH
krb5_ccache krbCredCache;
gss_cred_id_t reauthCred;
time_t expiryTime;
uint64_t sendSeq, recvSeq;
void *seqState;
- gss_cred_id_t defaultCred;
+ gss_cred_id_t cred;
union {
struct gss_eap_initiator_ctx initiator;
#define initiatorCtx ctxU.initiator
#define reauthCtx ctxU.reauth
#endif
} ctxU;
+ const struct gss_eap_token_buffer_set *inputTokens;
+ const struct gss_eap_token_buffer_set *outputTokens;
};
#define TOK_FLAG_SENDER_IS_ACCEPTOR 0x01
#define KEY_USAGE_INITIATOR_SEAL 24
#define KEY_USAGE_INITIATOR_SIGN 25
+/* accept_sec_context.c */
+OM_uint32
+gssEapAcceptSecContext(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t input_token,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle);
+
+/* init_sec_context.c */
+OM_uint32
+gssEapInitSecContext(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t ctx,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec);
+
/* wrap_iov.c */
OM_uint32
gssEapWrapOrGetMIC(OM_uint32 *minor,
void
gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...);
+OM_uint32
+gssEapDisplayStatus(OM_uint32 *minor,
+ OM_uint32 status_value,
+ gss_buffer_t status_string);
+
#define IS_WIRE_ERROR(err) ((err) > GSSEAP_RESERVED && \
(err) <= GSSEAP_RADIUS_PROT_FAILURE)
+/* upper bound of RADIUS error range must be kept in sync with radsec.h */
+#define IS_RADIUS_ERROR(err) ((err) >= ERROR_TABLE_BASE_rse && \
+ (err) <= ERROR_TABLE_BASE_rse + 20)
+
/* export_sec_context.c */
OM_uint32
gssEapExportSecContext(OM_uint32 *minor,
gss_buffer_t token);
+/* eap_mech.c */
+void
+gssEapInitiatorInit(void);
+
+void
+gssEapFinalize(void);
+
#ifdef __cplusplus
}
#endif
extern gss_OID GSS_EAP_CRED_SET_CRED_FLAG;
/*
+ * Password; for mechanism glues that do not support
+ * gss_acquire_cred_with_password(), this can be set
+ * on an existing credentials handle.
+ */
+extern gss_OID GSS_EAP_CRED_SET_CRED_PASSWORD;
+
+/*
* Credentials flag indicating the local attributes
* processing should be skipped.
*/
error_code GSSEAP_BAD_CRED_OPTION, "Bad credential option"
error_code GSSEAP_NO_DEFAULT_IDENTITY, "Default credentials identity unavailable"
error_code GSSEAP_NO_DEFAULT_CRED, "Missing default password or other credentials"
+error_code GSSEAP_CRED_RESOLVED, "Credential is already fully resolved"
+
+#
+# Local identity service errors
+#
+error_code GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE, "Unable to start identity service"
+error_code GSSEAP_NO_IDENTITY_SELECTED, "No identity selected"
+error_code GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR, "Identity service installation error"
+error_code GSSEAP_IDENTITY_SERVICE_OS_ERROR, "Identity service OS error"
+error_code GSSEAP_IDENTITY_SERVICE_IPC_ERROR, "Identity service IPC error"
+error_code GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR, "Unknown identity service error"
+
#
# Wrap/unwrap/PRF errors
#
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_import_name(OM_uint32 *minor,
gss_buffer_t import_name_buffer,
gss_OID input_name_type,
major = sequenceInternalize(minor, &ctx->seqState, &p, &remain);
if (GSS_ERROR(major))
return major;
+
#ifdef GSSEAP_ENABLE_ACCEPTOR
/*
* The partial context should only be expected for unestablished
if (GSS_ERROR(major))
return major;
}
-#endif
#ifdef GSSEAP_DEBUG
assert(remain == 0);
#endif
+#endif /* GSSEAP_ENABLE_ACCEPTOR */
major = GSS_S_COMPLETE;
*minor = 0;
return major;
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_import_sec_context(OM_uint32 *minor,
gss_buffer_t interprocess_token,
gss_ctx_id_t *context_handle)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_indicate_mechs(OM_uint32 *minor,
gss_OID_set *mech_set)
{
#endif
static OM_uint32
-peerConfigInit(OM_uint32 *minor,
- gss_cred_id_t cred,
- gss_ctx_id_t ctx)
+peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
{
OM_uint32 major;
krb5_context krbContext;
struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
+ gss_cred_id_t cred = ctx->cred;
eapPeerConfig->identity = NULL;
eapPeerConfig->identity_len = 0;
eapPeerConfig->password = (unsigned char *)cred->password.value;
eapPeerConfig->password_len = cred->password.length;
+ /* certs */
+ eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
+ eapPeerConfig->subject_match = (unsigned char *)cred->subjectNameConstraint.value;
+ eapPeerConfig->altsubject_match = (unsigned char *)cred->subjectAltNameConstraint.value;
+
*minor = 0;
return GSS_S_COMPLETE;
}
static OM_uint32
initBegin(OM_uint32 *minor,
- gss_cred_id_t cred,
gss_ctx_id_t ctx,
gss_name_t target,
gss_OID mech,
gss_channel_bindings_t chanBindings GSSEAP_UNUSED)
{
OM_uint32 major;
+ gss_cred_id_t cred = ctx->cred;
assert(cred != GSS_C_NO_CREDENTIAL);
static OM_uint32
eapGssSmInitAuthenticate(OM_uint32 *minor,
- gss_cred_id_t cred,
+ gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
gss_name_t target GSSEAP_UNUSED,
gss_OID mech GSSEAP_UNUSED,
{
OM_uint32 major;
OM_uint32 tmpMinor;
- int code;
struct wpabuf *resp = NULL;
*minor = 0;
assert(inputToken != GSS_C_NO_BUFFER);
- major = peerConfigInit(minor, cred, ctx);
+ major = peerConfigInit(minor, ctx);
if (GSS_ERROR(major))
goto cleanup;
major = GSS_S_CONTINUE_NEEDED;
- code = eap_peer_sm_step(ctx->initiatorCtx.eap);
+ eap_peer_sm_step(ctx->initiatorCtx.eap);
if (ctx->flags & CTX_FLAG_EAP_RESP) {
ctx->flags &= ~(CTX_FLAG_EAP_RESP);
}
static OM_uint32
+eapGssSmInitGssFlags(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken GSSEAP_UNUSED,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+ unsigned char wireFlags[4];
+ gss_buffer_desc flagsBuf;
+
+ store_uint32_be(ctx->gssFlags & GSSEAP_WIRE_FLAGS_MASK, wireFlags);
+
+ flagsBuf.length = sizeof(wireFlags);
+ flagsBuf.value = wireFlags;
+
+ return duplicateBuffer(minor, &flagsBuf, outputToken);
+}
+
+static OM_uint32
eapGssSmInitGssChannelBindings(OM_uint32 *minor,
gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
return GSS_S_CONTINUE_NEEDED;
}
+static OM_uint32
+eapGssSmInitInitiatorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken GSSEAP_UNUSED,
+ gss_buffer_t outputToken,
+ OM_uint32 *smFlags)
+{
+ OM_uint32 major;
+
+ major = gssEapMakeTokenMIC(minor, ctx, outputToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ GSSEAP_SM_TRANSITION_NEXT(ctx);
+
+ *minor = 0;
+ *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
#ifdef GSSEAP_ENABLE_REAUTH
static OM_uint32
eapGssSmInitReauthCreds(OM_uint32 *minor,
#endif /* GSSEAP_ENABLE_REAUTH */
static OM_uint32
-eapGssSmInitCompleteInitiatorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags)
+eapGssSmInitAcceptorMIC(OM_uint32 *minor,
+ gss_cred_id_t cred GSSEAP_UNUSED,
+ gss_ctx_id_t ctx,
+ gss_name_t target GSSEAP_UNUSED,
+ gss_OID mech GSSEAP_UNUSED,
+ OM_uint32 reqFlags GSSEAP_UNUSED,
+ OM_uint32 timeReq GSSEAP_UNUSED,
+ gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken GSSEAP_UNUSED,
+ OM_uint32 *smFlags GSSEAP_UNUSED)
{
- GSSEAP_SM_TRANSITION_NEXT(ctx);
-
- *minor = 0;
- *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
+ OM_uint32 major;
- return GSS_S_CONTINUE_NEEDED;
-}
+ major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
+ if (GSS_ERROR(major))
+ return major;
-static OM_uint32
-eapGssSmInitCompleteAcceptorExts(OM_uint32 *minor,
- gss_cred_id_t cred GSSEAP_UNUSED,
- gss_ctx_id_t ctx,
- gss_name_t target GSSEAP_UNUSED,
- gss_OID mech GSSEAP_UNUSED,
- OM_uint32 reqFlags GSSEAP_UNUSED,
- OM_uint32 timeReq GSSEAP_UNUSED,
- gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
- gss_buffer_t inputToken GSSEAP_UNUSED,
- gss_buffer_t outputToken GSSEAP_UNUSED,
- OM_uint32 *smFlags GSSEAP_UNUSED)
-{
GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
*minor = 0;
},
{
ITOK_TYPE_NONE,
+ ITOK_TYPE_GSS_FLAGS,
+ GSSEAP_STATE_INITIATOR_EXTS,
+ 0,
+ eapGssSmInitGssFlags
+ },
+ {
+ ITOK_TYPE_NONE,
ITOK_TYPE_GSS_CHANNEL_BINDINGS,
GSSEAP_STATE_INITIATOR_EXTS,
SM_ITOK_FLAG_REQUIRED,
},
{
ITOK_TYPE_NONE,
- ITOK_TYPE_NONE,
+ ITOK_TYPE_INITIATOR_MIC,
GSSEAP_STATE_INITIATOR_EXTS,
- 0,
- eapGssSmInitCompleteInitiatorExts
+ SM_ITOK_FLAG_REQUIRED,
+ eapGssSmInitInitiatorMIC
},
#ifdef GSSEAP_ENABLE_REAUTH
{
#endif
/* other extensions go here */
{
- ITOK_TYPE_NONE,
+ ITOK_TYPE_ACCEPTOR_MIC,
ITOK_TYPE_NONE,
GSSEAP_STATE_ACCEPTOR_EXTS,
- 0,
- eapGssSmInitCompleteAcceptorExts
+ SM_ITOK_FLAG_REQUIRED,
+ eapGssSmInitAcceptorMIC
}
};
-OM_uint32 KRB5_CALLCONV
-gss_init_sec_context(OM_uint32 *minor,
+OM_uint32
+gssEapInitSecContext(OM_uint32 *minor,
gss_cred_id_t cred,
- gss_ctx_id_t *context_handle,
+ gss_ctx_id_t ctx,
gss_name_t target_name,
gss_OID mech_type,
OM_uint32 req_flags,
OM_uint32 *time_rec)
{
OM_uint32 major, tmpMinor;
- gss_ctx_id_t ctx = *context_handle;
- int initialContextToken = 0;
-
- *minor = 0;
+ int initialContextToken = (ctx->mechanismUsed == GSS_C_NO_OID);
- output_token->length = 0;
- output_token->value = NULL;
-
- if (ctx == GSS_C_NO_CONTEXT) {
- if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
- *minor = GSSEAP_WRONG_SIZE;
- return GSS_S_DEFECTIVE_TOKEN;
- }
+ if (cred != GSS_C_NO_CREDENTIAL)
+ GSSEAP_MUTEX_LOCK(&cred->mutex);
- major = gssEapAllocContext(minor, &ctx);
+ if (ctx->cred == GSS_C_NO_CREDENTIAL) {
+ major = gssEapResolveInitiatorCred(minor, cred, target_name, &ctx->cred);
if (GSS_ERROR(major))
- return major;
-
- ctx->flags |= CTX_FLAG_INITIATOR;
- initialContextToken = 1;
-
- *context_handle = ctx;
- }
-
- GSSEAP_MUTEX_LOCK(&ctx->mutex);
-
- if (cred == GSS_C_NO_CREDENTIAL) {
- if (ctx->defaultCred == GSS_C_NO_CREDENTIAL) {
- major = gssEapAcquireCred(minor,
- GSS_C_NO_NAME,
- GSS_C_NO_BUFFER,
- time_req,
- GSS_C_NO_OID_SET,
- GSS_C_INITIATE,
- &ctx->defaultCred,
- NULL,
- NULL);
- if (GSS_ERROR(major))
- goto cleanup;
- }
+ goto cleanup;
- cred = ctx->defaultCred;
+ assert(ctx->cred != GSS_C_NO_CREDENTIAL);
}
- GSSEAP_MUTEX_LOCK(&cred->mutex);
+ GSSEAP_MUTEX_LOCK(&ctx->cred->mutex);
- if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
- major = GSS_S_NO_CRED;
- *minor = GSSEAP_CRED_USAGE_MISMATCH;
- goto cleanup;
- }
+ assert(ctx->cred->flags & CRED_FLAG_RESOLVED);
+ assert(ctx->cred->flags & CRED_FLAG_INITIATE);
if (initialContextToken) {
- major = initBegin(minor, cred, ctx, target_name, mech_type,
+ major = initBegin(minor, ctx, target_name, mech_type,
req_flags, time_req, input_chan_bindings);
if (GSS_ERROR(major))
goto cleanup;
cleanup:
if (cred != GSS_C_NO_CREDENTIAL)
GSSEAP_MUTEX_UNLOCK(&cred->mutex);
+ if (ctx->cred != GSS_C_NO_CREDENTIAL)
+ GSSEAP_MUTEX_UNLOCK(&ctx->cred->mutex);
+
+ return major;
+}
+
+OM_uint32 GSSAPI_CALLCONV
+gss_init_sec_context(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t *context_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ OM_uint32 major, tmpMinor;
+ gss_ctx_id_t ctx = *context_handle;
+
+ *minor = 0;
+
+ output_token->length = 0;
+ output_token->value = NULL;
+
+ assert(ctx == GSS_C_NO_CONTEXT || ctx->mechanismUsed != GSS_C_NO_OID);
+
+ if (ctx == GSS_C_NO_CONTEXT) {
+ if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
+ *minor = GSSEAP_WRONG_SIZE;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ major = gssEapAllocContext(minor, &ctx);
+ if (GSS_ERROR(major))
+ return major;
+
+ ctx->flags |= CTX_FLAG_INITIATOR;
+
+ *context_handle = ctx;
+ }
+
+ GSSEAP_MUTEX_LOCK(&ctx->mutex);
+
+ major = gssEapInitSecContext(minor,
+ cred,
+ ctx,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec);
+
GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
if (GSS_ERROR(major))
#define MA_SUPPORTED(ma) MA_ADD((ma), mech_attrs)
#define MA_KNOWN(ma) MA_ADD((ma), known_mech_attrs)
-OM_uint32 KRB5_CALLCONV
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_attrs_for_mech(OM_uint32 *minor,
gss_const_OID mech_oid,
gss_OID_set *mech_attrs,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_context(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_name_t *src_name,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_cred(OM_uint32 *minor,
gss_cred_id_t cred,
gss_name_t *name,
#include "gssapiP_eap.h"
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_cred_by_mech(OM_uint32 *minor,
gss_cred_id_t cred,
gss_OID mech_type,
#include "gssapiP_eap.h"
-#ifdef HAVE_INQUIRECREDOPS /* Windows doesn't like zero-sized arrays; define this when we actually have any of these */
+#if 0
static struct {
gss_OID_desc oid;
OM_uint32 (*inquire)(OM_uint32 *, const gss_cred_id_t,
};
#endif
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_cred_by_oid(OM_uint32 *minor,
const gss_cred_id_t cred_handle,
- const gss_OID desired_object,
+ const gss_OID desired_object GSSEAP_UNUSED,
gss_buffer_set_t *data_set)
{
OM_uint32 major;
+#if 0
int i;
-
+#endif
*data_set = GSS_C_NO_BUFFER_SET;
if (cred_handle == GSS_C_NO_CREDENTIAL) {
major = GSS_S_UNAVAILABLE;
*minor = GSSEAP_BAD_CRED_OPTION;
-#ifdef HAVE_INQUIRECREDOPS
+#if 0
for (i = 0; i < sizeof(inquireCredOps) / sizeof(inquireCredOps[0]); i++) {
if (oidEqual(&inquireCredOps[i].oid, desired_object)) {
major = (*inquireCredOps[i].inquire)(minor, cred_handle,
break;
}
}
-#else
- (void)i;
- (void)desired_object;
#endif
GSSEAP_MUTEX_UNLOCK(&cred_handle->mutex);
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_saslname_for_mech(OM_uint32 *minor,
const gss_OID mech,
gss_buffer_t sasl_mech_name,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_mechs_for_name(OM_uint32 *minor,
const gss_name_t input_name,
gss_OID_set *mech_types)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_name(OM_uint32 *minor,
gss_name_t name,
int *name_is_MN,
GSSEAP_MUTEX_LOCK(&name->mutex);
-#ifdef GSSEAP_ENABLE_ACCEPTOR
major = gssEapInquireName(minor, name, name_is_MN, MN_mech, attrs);
-#else
- major = GSS_S_UNAVAILABLE;
-#endif
GSSEAP_MUTEX_UNLOCK(&name->mutex);
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_names_for_mech(OM_uint32 *minor,
gss_OID mechanism,
gss_OID_set *ret_name_types)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_mech_for_saslname(OM_uint32 *minor,
const gss_buffer_t sasl_mech_name,
gss_OID *mech_type)
},
};
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_inquire_sec_context_by_oid(OM_uint32 *minor,
const gss_ctx_id_t ctx,
const gss_OID desired_object,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_map_name_to_any(OM_uint32 *minor,
gss_name_t name,
int authenticated,
GSSEAP_MUTEX_LOCK(&name->mutex);
-#ifdef GSSEAP_ENABLE_ACCEPTOR
major = gssEapMapNameToAny(minor, name, authenticated, type_id, output);
-#else
- (void)authenticated;
- (void)type_id;
- major = GSS_S_COMPLETE;
-#endif
GSSEAP_MUTEX_UNLOCK(&name->mutex);
--- /dev/null
+gss_acquire_cred
+gss_add_cred
+gss_add_cred_with_password
+gss_canonicalize_name
+gss_compare_name
+gss_context_time
+gss_delete_sec_context
+gss_display_name
+gss_display_name_ext
+gss_display_status
+gss_duplicate_name
+gss_export_name
+gss_export_sec_context
+gss_get_mic
+gss_import_name
+gss_import_sec_context
+gss_indicate_mechs
+gss_init_sec_context
+gss_inquire_attrs_for_mech
+gss_inquire_context
+gss_inquire_cred
+gss_inquire_cred_by_mech
+gss_inquire_cred_by_oid
+gss_inquire_mechs_for_name
+gss_inquire_mech_for_saslname
+gss_inquire_names_for_mech
+gss_inquire_saslname_for_mech
+gss_inquire_sec_context_by_oid
+gss_process_context_token
+gss_pseudo_random
+gss_release_cred
+gss_release_name
+gss_internal_release_oid
+gss_set_sec_context_option
+gss_store_cred
+gss_unwrap
+gss_unwrap_iov
+gss_verify_mic
+gss_wrap
+gss_wrap_iov
+gss_wrap_iov_length
+gss_wrap_size_limit
+GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM
+GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM
+GSS_EAP_NT_EAP_NAME
+GSS_EAP_CRED_SET_CRED_FLAG
+GSS_EAP_CRED_SET_CRED_PASSWORD
+GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE
+GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA
+gssspi_acquire_cred_with_password
+gssspi_authorize_localname
+gssspi_set_cred_option
gss_canonicalize_name
gss_compare_name
gss_context_time
+gss_delete_name_attribute
gss_delete_sec_context
gss_display_name
gss_display_name_ext
GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM
GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM
GSS_EAP_NT_EAP_NAME
+GSS_EAP_CRED_SET_CRED_FLAG
+GSS_EAP_CRED_SET_CRED_PASSWORD
+GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE
+GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA
gssspi_acquire_cred_with_password
gssspi_authorize_localname
gssspi_set_cred_option
#include "gssapiP_eap.h"
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
gssspi_mech_invoke(OM_uint32 *minor,
const gss_OID desired_mech,
const gss_OID desired_object,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_process_context_token(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_buffer_t token_buffer)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_pseudo_random(OM_uint32 *minor,
gss_ctx_id_t ctx,
int prf_key,
goto cleanup;
}
- memcpy(ns.data + 4, prf_in->value, prf_in->length);
+ memcpy((unsigned char *)ns.data + 4, prf_in->value, prf_in->length);
i = 0;
p = (unsigned char *)prf_out->value;
while (desired_output_len > 0) {
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_release_any_name_mapping(OM_uint32 *minor,
gss_name_t name,
gss_buffer_t type_id,
GSSEAP_MUTEX_LOCK(&name->mutex);
-#ifdef GSSEAP_ENABLE_ACCEPTOR
major = gssEapReleaseAnyNameMapping(minor, name, type_id, input);
-#else
- (void)type_id;
- major = GSS_S_COMPLETE;
-#endif
*input = NULL;
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_release_cred(OM_uint32 *minor,
gss_cred_id_t *cred_handle)
{
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_release_name(OM_uint32 *minor,
gss_name_t *name)
{
#include "gssapiP_eap.h"
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
gss_internal_release_oid(OM_uint32 *minor,
gss_OID *oid)
{
const gss_OID oid GSSEAP_UNUSED,
const gss_buffer_t buffer)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
gss_buffer_desc configFileBuffer = GSS_C_EMPTY_BUFFER;
if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
return major;
}
- if (cred->radiusConfigFile != NULL)
- GSSEAP_FREE(cred->radiusConfigFile);
-
- cred->radiusConfigFile = (char *)configFileBuffer.value;
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
+ cred->radiusConfigFile = configFileBuffer;
*minor = 0;
return GSS_S_COMPLETE;
const gss_OID oid GSSEAP_UNUSED,
const gss_buffer_t buffer)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
gss_buffer_desc configStanzaBuffer = GSS_C_EMPTY_BUFFER;
if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
return major;
}
- if (cred->radiusConfigStanza != NULL)
- GSSEAP_FREE(cred->radiusConfigStanza);
-
- cred->radiusConfigStanza = (char *)configStanzaBuffer.value;
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
+ cred->radiusConfigStanza = configStanzaBuffer;
*minor = 0;
return GSS_S_COMPLETE;
return GSS_S_COMPLETE;
}
+static OM_uint32
+setCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_OID oid GSSEAP_UNUSED,
+ const gss_buffer_t buffer)
+{
+ return gssEapSetCredPassword(minor, cred, buffer);
+}
+
static struct {
gss_OID_desc oid;
OM_uint32 (*setOption)(OM_uint32 *, gss_cred_id_t cred,
{ 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x03" },
setCredFlag,
},
+ /* 1.3.6.1.4.1.5322.22.3.3.4 */
+ {
+ { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x04" },
+ setCredPassword,
+ },
};
gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE = &setCredOps[0].oid;
gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA = &setCredOps[1].oid;
gss_OID GSS_EAP_CRED_SET_CRED_FLAG = &setCredOps[2].oid;
+gss_OID GSS_EAP_CRED_SET_CRED_PASSWORD = &setCredOps[3].oid;
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
gssspi_set_cred_option(OM_uint32 *minor,
gss_cred_id_t *pCred,
const gss_OID desired_object,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_set_name_attribute(OM_uint32 *minor,
gss_name_t name,
int complete,
gss_buffer_t attr,
gss_buffer_t value)
{
-#ifdef GSSEAP_ENABLE_ACCEPTOR
OM_uint32 major;
if (name == GSS_C_NO_NAME) {
GSSEAP_MUTEX_UNLOCK(&name->mutex);
return major;
-#else
- return GSS_S_UNAVAILABLE;
-#endif
}
#include "gssapiP_eap.h"
-#ifdef HAVE_SETCTXOPS /* Windows doesn't like zero-sized arrays; define this when we actually have any of these */
+#if 0
static struct {
gss_OID_desc oid;
OM_uint32 (*setOption)(OM_uint32 *, gss_ctx_id_t *pCtx,
};
#endif
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_set_sec_context_option(OM_uint32 *minor,
gss_ctx_id_t *pCtx,
- const gss_OID desired_object,
- const gss_buffer_t value)
+ const gss_OID desired_object GSSEAP_UNUSED,
+ const gss_buffer_t value GSSEAP_UNUSED)
{
OM_uint32 major;
gss_ctx_id_t ctx;
+#if 0
int i;
+#endif
major = GSS_S_UNAVAILABLE;
*minor = GSSEAP_BAD_CONTEXT_OPTION;
if (ctx != GSS_C_NO_CONTEXT)
GSSEAP_MUTEX_LOCK(&ctx->mutex);
-#ifdef HAVE_SETCTXOPS
+#if 0
for (i = 0; i < sizeof(setCtxOps) / sizeof(setCtxOps[0]); i++) {
if (oidEqual(&setCtxOps[i].oid, desired_object)) {
major = (*setCtxOps[i].setOption)(minor, &ctx,
break;
}
}
-#else
- (void)i;
- (void)desired_object;
- (void)value;
#endif
if (pCtx != NULL && *pCtx == NULL)
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_store_cred(OM_uint32 *minor,
const gss_cred_id_t cred,
gss_cred_usage_t input_usage,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_unwrap(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_buffer_t input_message_buffer,
unsigned char *ptr;
OM_uint32 code = 0, major = GSS_S_FAILURE;
krb5_context krbContext;
- int conf_req_flag, toktype2;
+ int conf_req_flag;
int i = 0, j;
gss_iov_buffer_desc *tiov = NULL;
gss_iov_buffer_t stream, data = NULL;
}
ptr = (unsigned char *)stream->buffer.value;
- toktype2 = load_uint16_be(ptr);
- ptr += 2;
+ ptr += 2; /* skip token type */
tiov = (gss_iov_buffer_desc *)GSSEAP_CALLOC((size_t)iov_count + 2,
sizeof(gss_iov_buffer_desc));
return major;
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_unwrap_iov(OM_uint32 *minor,
gss_ctx_id_t ctx,
int *conf_state,
#ifndef _UTIL_H_
#define _UTIL_H_ 1
-#if defined(HAVE_SYS_PARAM_H)
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
-#if defined(HAVE_STDINT_H)
+#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <string.h>
#include <krb5.h>
-#if defined(WIN32)
-#define inline __inline
+#ifdef WIN32
+#define inline __inline
+#define snprintf _snprintf
#endif
#ifdef __cplusplus
#endif
#if !defined(WIN32) && !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#define GSSEAP_UNUSED __attribute__ ((__unused__))
+#define GSSEAP_UNUSED __attribute__ ((__unused__))
#else
#define GSSEAP_UNUSED
#endif
-#if !defined(WIN32)
-#define GSSEAP_CONSTRUCTOR __attribute__((constructor))
-#define GSSEAP_DESTRUCTOR __attribute__((destructor))
-#else
-#define GSSEAP_CONSTRUCTOR
-#define GSSEAP_DESTRUCTOR
-#endif
-
-/* thread local storage */
-struct gss_eap_status_info;
-
-struct gss_eap_thread_local_data
-{
- krb5_context context;
- struct gss_eap_status_info* status_info;
-};
-
-struct gss_eap_thread_local_data*
-gssEapGetThreadLocalData();
-
-void
-gssEapDestroyStatusInfo(struct gss_eap_status_info* status);
-
-void
-gssEapDestroyKrbContext(krb5_context context);
-
/* util_buffer.c */
OM_uint32
makeStringBuffer(OM_uint32 *minor,
const char *string,
gss_buffer_t buffer);
+#define makeStringBufferOrCleanup(src, dst) \
+ do { \
+ major = makeStringBuffer((minor), (src), (dst));\
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
OM_uint32
bufferToString(OM_uint32 *minor,
const gss_buffer_t buffer,
const gss_buffer_t src,
gss_buffer_t dst);
+#define duplicateBufferOrCleanup(src, dst) \
+ do { \
+ major = duplicateBuffer((minor), (src), (dst)); \
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
static inline int
bufferEqual(const gss_buffer_t b1, const gss_buffer_t b2)
{
#define ITOK_TYPE_REAUTH_RESP 0x00000009 /* optional */
#define ITOK_TYPE_VERSION_INFO 0x0000000A /* optional */
#define ITOK_TYPE_VENDOR_INFO 0x0000000B /* optional */
+#define ITOK_TYPE_GSS_FLAGS 0x0000000C /* optional */
+#define ITOK_TYPE_INITIATOR_MIC 0x0000000D /* critical, required, if not reauth */
+#define ITOK_TYPE_ACCEPTOR_MIC 0x0000000E /* TBD */
#define ITOK_FLAG_CRITICAL 0x80000000 /* critical, wire flag */
#define ITOK_FLAG_VERIFIED 0x40000000 /* verified, API flag */
#define ITOK_TYPE_MASK (~(ITOK_FLAG_CRITICAL | ITOK_FLAG_VERIFIED))
+#define GSSEAP_WIRE_FLAGS_MASK GSS_C_MUTUAL_FLAG
+
OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
gss_ctx_id_t context_handle,
OM_uint32 *time_rec);
+OM_uint32
+gssEapMakeTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC);
+
+OM_uint32
+gssEapVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t tokenMIC);
+
/* util_cred.c */
OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
+gss_OID
+gssEapPrimaryMechForCred(gss_cred_id_t cred);
+
OM_uint32
gssEapAcquireCred(OM_uint32 *minor,
const gss_name_t desiredName,
- const gss_buffer_t password,
OM_uint32 timeReq,
const gss_OID_set desiredMechs,
int cred_usage,
gss_OID_set *pActualMechs,
OM_uint32 *timeRec);
+OM_uint32
+gssEapSetCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t password);
+
+OM_uint32
+gssEapSetCredService(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t target);
+
+OM_uint32
+gssEapResolveInitiatorCred(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ const gss_name_t target,
+ gss_cred_id_t *resolvedCred);
+
int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech);
OM_uint32
gss_OID
gssEapSaslNameToOid(const gss_buffer_t name);
+/* util_moonshot.c */
+OM_uint32
+libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName);
+
+OM_uint32
+libMoonshotResolveInitiatorCred(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t targetName);
+
/* util_name.c */
#define EXPORT_NAME_FLAG_OID 0x1
#define EXPORT_NAME_FLAG_COMPOSITE 0x2
gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
/* util_token.c */
+struct gss_eap_token_buffer_set {
+ gss_buffer_set_desc buffers; /* pointers only */
+ OM_uint32 *types;
+};
+
OM_uint32
gssEapEncodeInnerTokens(OM_uint32 *minor,
- gss_buffer_set_t extensions,
- OM_uint32 *types,
+ struct gss_eap_token_buffer_set *tokens,
gss_buffer_t buffer);
OM_uint32
gssEapDecodeInnerTokens(OM_uint32 *minor,
const gss_buffer_t buffer,
- gss_buffer_set_t *pExtensions,
- OM_uint32 **pTypes);
+ struct gss_eap_token_buffer_set *tokens);
+
+OM_uint32
+gssEapReleaseInnerTokens(OM_uint32 *minor,
+ struct gss_eap_token_buffer_set *tokens,
+ int freeBuffers);
+
+OM_uint32
+gssEapAllocInnerTokens(OM_uint32 *minor,
+ size_t count,
+ struct gss_eap_token_buffer_set *tokens);
size_t
tokenSize(const gss_OID_desc *mech, size_t body_size);
#define GSSEAP_FREE free
#define GSSEAP_REALLOC realloc
+#ifndef GSSAPI_CALLCONV
+#define GSSAPI_CALLCONV KRB5_CALLCONV
+#endif
+
+#ifdef WIN32
+#define GSSEAP_CONSTRUCTOR
+#define GSSEAP_DESTRUCTOR
+#else
+#define GSSEAP_CONSTRUCTOR __attribute__((constructor))
+#define GSSEAP_DESTRUCTOR __attribute__((destructor))
+#endif
+
#define GSSEAP_NOT_IMPLEMENTED do { \
assert(0 && "not implemented"); \
*minor = ENOSYS; \
} while (0)
#ifdef WIN32
+
#include <winbase.h>
-#define GSSEAP_MUTEX CRITICAL_SECTION
-// wrapper for EnterCriticalSection() to provide return value
-inline int win32_mutex_init(CRITICAL_SECTION* m)
-{
- EnterCriticalSection(m);
- return 0;
-}
-#define GSSEAP_MUTEX_INIT(m) win32_mutex_init((m))
+#define GSSEAP_GET_LAST_ERROR() (GetLastError())
+
+#define GSSEAP_MUTEX CRITICAL_SECTION
+#define GSSEAP_MUTEX_INIT(m) (InitializeCriticalSection((m)), 0)
#define GSSEAP_MUTEX_DESTROY(m) DeleteCriticalSection((m))
#define GSSEAP_MUTEX_LOCK(m) EnterCriticalSection((m))
#define GSSEAP_MUTEX_UNLOCK(m) LeaveCriticalSection((m))
+/* Thread-local is handled separately */
+
+#define GSSEAP_THREAD_ONCE INIT_ONCE
+#define GSSEAP_ONCE(o, i) InitOnceExecuteOnce((o), (i))
+#define GSSEAP_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
+
#else
+
#include <pthread.h>
-#define GSSEAP_MUTEX pthread_mutex_t
-#define GSSEAP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define GSSEAP_GET_LAST_ERROR() (errno)
+#define GSSEAP_MUTEX pthread_mutex_t
#define GSSEAP_MUTEX_INIT(m) pthread_mutex_init((m), NULL)
#define GSSEAP_MUTEX_DESTROY(m) pthread_mutex_destroy((m))
#define GSSEAP_MUTEX_LOCK(m) pthread_mutex_lock((m))
#define GSSEAP_THREAD_ONCE pthread_once_t
#define GSSEAP_ONCE(o, i) pthread_once((o), (i))
#define GSSEAP_ONCE_INITIALIZER PTHREAD_ONCE_INIT
-#endif
+
+#endif /* WIN32 */
/* Helper functions */
static inline void
data->length = buffer->length;
}
+/* util_tld.c */
+struct gss_eap_status_info;
+
+struct gss_eap_thread_local_data {
+ krb5_context krbContext;
+ struct gss_eap_status_info *statusInfo;
+};
+
+struct gss_eap_thread_local_data *
+gssEapGetThreadLocalData(void);
+
+void
+gssEapDestroyStatusInfo(struct gss_eap_status_info *status);
+
+void
+gssEapDestroyKrbContext(krb5_context context);
+
#ifdef __cplusplus
}
#endif
#ifdef GSSEAP_ENABLE_ACCEPTOR
#include "util_json.h"
#include "util_attr.h"
-#endif
#include "util_base64.h"
+#endif /* GSSEAP_ENABLE_ACCEPTOR */
#ifdef GSSEAP_ENABLE_REAUTH
#include "util_reauth.h"
#endif
if (GSS_ERROR(major))
goto cleanup;
+#ifdef HAVE_OPENSAML
major = gssEapSamlAttrProvidersInit(&minor);
if (GSS_ERROR(major))
goto cleanup;
+#endif
+#ifdef HAVE_SHIBRESOLVER
/* Allow Shibboleth initialization failure to be non-fatal */
gssEapLocalAttrProviderInit(&minor);
+#endif
cleanup:
#ifdef GSSEAP_DEBUG
OM_uint32
gssEapAttrProvidersFinalize(OM_uint32 *minor)
{
- OM_uint32 major = GSS_S_COMPLETE;
-
if (gssEapAttrProvidersInitStatus == GSS_S_COMPLETE) {
- major = gssEapLocalAttrProviderFinalize(minor);
- if (major == GSS_S_COMPLETE)
- major = gssEapSamlAttrProvidersFinalize(minor);
- if (major == GSS_S_COMPLETE)
- major = gssEapRadiusAttrProviderFinalize(minor);
+#ifdef HAVE_SHIBRESOLVER
+ gssEapLocalAttrProviderFinalize(minor);
+#endif
+#ifdef HAVE_OPENSAML
+ gssEapSamlAttrProvidersFinalize(minor);
+#endif
+ gssEapRadiusAttrProviderFinalize(minor);
gssEapAttrProvidersInitStatus = GSS_S_UNAVAILABLE;
}
- return major;
+ return GSS_S_COMPLETE;
}
static gss_eap_attr_create_provider gssEapAttrFactories[ATTR_TYPE_MAX + 1];
void *data);
#define ATTR_TYPE_RADIUS 0U /* RADIUS AVPs */
+#ifdef HAVE_OPENSAML
#define ATTR_TYPE_SAML_ASSERTION 1U /* SAML assertion */
#define ATTR_TYPE_SAML 2U /* SAML attributes */
+#endif
#define ATTR_TYPE_LOCAL 3U /* Local attributes */
#define ATTR_TYPE_MIN ATTR_TYPE_RADIUS
#define ATTR_TYPE_MAX ATTR_TYPE_LOCAL
}
if (GSSEAP_MUTEX_INIT(&ctx->mutex) != 0) {
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
gssEapReleaseContext(&tmpMinor, &ctx);
return GSS_S_FAILURE;
}
ctx->state = GSSEAP_STATE_INITIAL;
+ ctx->mechanismUsed = GSS_C_NO_OID;
/*
* Integrity, confidentiality, sequencing and replay detection are
GSS_C_INTEG_FLAG | /* integrity */
GSS_C_CONF_FLAG | /* confidentiality */
GSS_C_SEQUENCE_FLAG | /* sequencing */
- GSS_C_REPLAY_FLAG| /* replay detection */
- GSS_C_MUTUAL_FLAG; /*xxx big hack */
+ GSS_C_REPLAY_FLAG; /* replay detection */
*pCtx = ctx;
if (ctx->flags & CTX_FLAG_KRB_REAUTH) {
gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
} else
-#endif
+#endif /* GSSEAP_ENABLE_REAUTH */
if (CTX_IS_INITIATOR(ctx)) {
releaseInitiatorContext(&ctx->initiatorCtx);
- } else {
+ }
#ifdef GSSEAP_ENABLE_ACCEPTOR
+ else {
releaseAcceptorContext(&ctx->acceptorCtx);
-#endif
}
+#endif /* GSSEAP_ENABLE_ACCEPTOR */
krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key);
gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
sequenceFree(&tmpMinor, &ctx->seqState);
- gssEapReleaseCred(&tmpMinor, &ctx->defaultCred);
+ gssEapReleaseCred(&tmpMinor, &ctx->cred);
GSSEAP_MUTEX_DESTROY(&ctx->mutex);
{
unsigned char *p;
+ assert(ctx->mechanismUsed != GSS_C_NO_OID);
+
outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length);
outputToken->value = GSSEAP_MALLOC(outputToken->length);
if (outputToken->value == NULL) {
return GSS_S_COMPLETE;
}
+
+static OM_uint32
+gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC,
+ int verifyMIC)
+{
+ OM_uint32 major;
+ gss_iov_buffer_desc *iov = NULL;
+ size_t i = 0, j;
+ enum gss_eap_token_type tokType;
+ OM_uint32 micTokType;
+ unsigned char wireTokType[2];
+ unsigned char *innerTokTypes = NULL, *innerTokLengths = NULL;
+ const struct gss_eap_token_buffer_set *tokens;
+
+ tokens = verifyMIC ? ctx->inputTokens : ctx->outputTokens;
+
+ assert(tokens != NULL);
+
+ iov = GSSEAP_CALLOC(2 + (3 * tokens->buffers.count) + 1, sizeof(*iov));
+ if (iov == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ innerTokTypes = GSSEAP_MALLOC(4 * tokens->buffers.count);
+ if (innerTokTypes == NULL) {
+ *minor = ENOMEM;
+ major = GSS_S_FAILURE;
+ goto cleanup;
+ }
+
+ innerTokLengths = GSSEAP_MALLOC(4 * tokens->buffers.count);
+ if (innerTokLengths == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Mechanism OID */
+ assert(ctx->mechanismUsed != GSS_C_NO_OID);
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = ctx->mechanismUsed->length;
+ iov[i].buffer.value = ctx->mechanismUsed->elements;
+ i++;
+
+ /* Token type */
+ if (CTX_IS_INITIATOR(ctx) ^ verifyMIC) {
+ tokType = TOK_TYPE_INITIATOR_CONTEXT;
+ micTokType = ITOK_TYPE_INITIATOR_MIC;
+ } else {
+ tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
+ micTokType = ITOK_TYPE_ACCEPTOR_MIC;
+ }
+ store_uint16_be(tokType, wireTokType);
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = sizeof(wireTokType);
+ iov[i].buffer.value = wireTokType;
+ i++;
+
+ for (j = 0; j < tokens->buffers.count; j++) {
+ if (verifyMIC &&
+ (tokens->types[j] & ITOK_TYPE_MASK) == micTokType)
+ continue; /* will use this slot for trailer */
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = 4;
+ iov[i].buffer.value = &innerTokTypes[j * 4];
+ store_uint32_be(tokens->types[j] & ~(ITOK_FLAG_VERIFIED),
+ iov[i].buffer.value);
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = 4;
+ iov[i].buffer.value = &innerTokLengths[j * 4];
+ store_uint32_be(tokens->buffers.elements[j].length,
+ iov[i].buffer.value);
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer = tokens->buffers.elements[j];
+ i++;
+ }
+
+ if (verifyMIC) {
+ assert(tokenMIC->length >= 16);
+
+ assert(i < 2 + (3 * tokens->buffers.count));
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER;
+ iov[i].buffer.length = 16;
+ iov[i].buffer.value = tokenMIC->value;
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+ iov[i].buffer.length = tokenMIC->length - 16;
+ iov[i].buffer.value = (unsigned char *)tokenMIC->value + 16;
+ i++;
+
+ major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
+ iov, i, TOK_TYPE_MIC);
+ } else {
+ iov[i++].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+ major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
+ iov, i, TOK_TYPE_MIC);
+ if (!GSS_ERROR(major))
+ *tokenMIC = iov[i - 1].buffer;
+ }
+
+cleanup:
+ if (iov != NULL)
+ gssEapReleaseIov(iov, tokens->buffers.count);
+ if (innerTokTypes != NULL)
+ GSSEAP_FREE(innerTokTypes);
+ if (innerTokLengths != NULL)
+ GSSEAP_FREE(innerTokLengths);
+
+ return major;
+}
+
+OM_uint32
+gssEapMakeTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC)
+{
+ tokenMIC->length = 0;
+ tokenMIC->value = NULL;
+
+ return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, FALSE);
+}
+
+OM_uint32
+gssEapVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t tokenMIC)
+{
+ if (tokenMIC->length < 16) {
+ *minor = GSSEAP_TOK_TRUNC;
+ return GSS_S_BAD_SIG;
+ }
+
+ return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, TRUE);
+}
#include "gssapiP_eap.h"
-#if defined(WIN32)
-/*This didn't work for me(Alexey) when Visual Studio 2005 Express is used: */
-#include <Shlobj.h>
-/*This didn't work for me(Kevin) when Visual Studio 2010 Express is used: */
-/*#include <ShFolder.h>*/
-
-#if !defined(snprintf)
-#define snprintf _snprintf
-#endif
-
+#ifdef WIN32
+# include <shlobj.h> /* may need to use ShFolder.h instead */
+# include <stdio.h>
#else
-#include <pwd.h>
+# include <pwd.h>
#endif
-#include <stdio.h> /* for BUFSIZ */
OM_uint32
gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
}
if (GSSEAP_MUTEX_INIT(&cred->mutex) != 0) {
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
gssEapReleaseCred(&tmpMinor, &cred);
return GSS_S_FAILURE;
}
return GSS_S_COMPLETE;
}
+static void
+zeroAndReleasePassword(gss_buffer_t password)
+{
+ if (password->value != NULL) {
+ memset(password->value, 0, password->length);
+ GSSEAP_FREE(password->value);
+ }
+
+ password->value = NULL;
+ password->length = 0;
+}
+
OM_uint32
gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
{
GSSEAP_KRB_INIT(&krbContext);
gssEapReleaseName(&tmpMinor, &cred->name);
+ gssEapReleaseName(&tmpMinor, &cred->target);
- if (cred->password.value != NULL) {
- memset(cred->password.value, 0, cred->password.length);
- GSSEAP_FREE(cred->password.value);
- }
+ zeroAndReleasePassword(&cred->password);
- if (cred->radiusConfigFile != NULL)
- GSSEAP_FREE(cred->radiusConfigFile);
- if (cred->radiusConfigStanza != NULL)
- GSSEAP_FREE(cred->radiusConfigStanza);
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
+ gss_release_buffer(&tmpMinor, &cred->caCertificate);
+ gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
+ gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
#ifdef GSSEAP_ENABLE_REAUTH
if (cred->krbCredCache != NULL) {
}
static OM_uint32
-readDefaultIdentityAndCreds(OM_uint32 *minor,
- gss_buffer_t defaultIdentity,
- gss_buffer_t defaultCreds)
+readStaticIdentityFile(OM_uint32 *minor,
+ gss_buffer_t defaultIdentity,
+ gss_buffer_t defaultPassword)
{
OM_uint32 major, tmpMinor;
FILE *fp = NULL;
char buf[BUFSIZ];
char *ccacheName;
-#if !defined(WIN32)
- char pwbuf[BUFSIZ];
+ int i = 0;
+#ifndef WIN32
struct passwd *pw = NULL, pwd;
+ char pwbuf[BUFSIZ];
#endif
defaultIdentity->length = 0;
defaultIdentity->value = NULL;
- defaultCreds->length = 0;
- defaultCreds->value = NULL;
+ if (defaultPassword != GSS_C_NO_BUFFER) {
+ defaultPassword->length = 0;
+ defaultPassword->value = NULL;
+ }
ccacheName = getenv("GSSEAP_IDENTITY");
if (ccacheName == NULL) {
-#if !defined(WIN32)
- if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
- pw == NULL || pw->pw_dir == NULL) {
+#ifdef WIN32
+ TCHAR szPath[MAX_PATH];
+
+ if (!SUCCEEDED(SHGetFolderPath(NULL,
+ CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
+ NULL, /* User access token */
+ 0, /* SHGFP_TYPE_CURRENT */
+ szPath))) {
major = GSS_S_CRED_UNAVAIL;
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */
goto cleanup;
}
- snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
- ccacheName = buf;
+ snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
#else
- TCHAR szPath[MAX_PATH];
-
- if(!SUCCEEDED(SHGetFolderPath(NULL,
- CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
- NULL, /* User access token */
- 0, /* == SHGFP_TYPE_CURRENT from ShlObj.h */
- szPath))) {
+ if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
+ pw == NULL || pw->pw_dir == NULL) {
major = GSS_S_CRED_UNAVAIL;
-////Needs to be correctly converted from the GetLastError();
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
goto cleanup;
- }
+ }
- snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
+ snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
+#endif /* WIN32 */
ccacheName = buf;
-#endif
}
fp = fopen(ccacheName, "r");
break;
}
- if (defaultIdentity->value == NULL)
+ if (i == 0)
dst = defaultIdentity;
- else if (defaultCreds->value == NULL)
- dst = defaultCreds;
+ else if (i == 1)
+ dst = defaultPassword;
else
break;
- major = duplicateBuffer(minor, &src, dst);
- if (GSS_ERROR(major))
- goto cleanup;
+ if (dst != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, &src, dst);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ i++;
}
if (defaultIdentity->length == 0) {
if (GSS_ERROR(major)) {
gss_release_buffer(&tmpMinor, defaultIdentity);
- gss_release_buffer(&tmpMinor, defaultCreds);
+ zeroAndReleasePassword(defaultPassword);
}
+ memset(buf, 0, sizeof(buf));
+
return major;
}
+gss_OID
+gssEapPrimaryMechForCred(gss_cred_id_t cred)
+{
+ gss_OID nameMech = GSS_C_NO_OID;
+
+ if (cred->mechanisms != GSS_C_NO_OID_SET &&
+ cred->mechanisms->count == 1)
+ nameMech = &cred->mechanisms->elements[0];
+
+ return nameMech;
+}
+
OM_uint32
gssEapAcquireCred(OM_uint32 *minor,
const gss_name_t desiredName,
- const gss_buffer_t password,
OM_uint32 timeReq GSSEAP_UNUSED,
const gss_OID_set desiredMechs,
int credUsage,
{
OM_uint32 major, tmpMinor;
gss_cred_id_t cred;
- gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
- gss_name_t defaultIdentityName = GSS_C_NO_NAME;
- gss_buffer_desc defaultCreds = GSS_C_EMPTY_BUFFER;
- gss_OID nameMech = GSS_C_NO_OID;
/* XXX TODO validate with changed set_cred_option API */
*pCred = GSS_C_NO_CREDENTIAL;
if (GSS_ERROR(major))
goto cleanup;
- if (cred->mechanisms != GSS_C_NO_OID_SET &&
- cred->mechanisms->count == 1)
- nameMech = &cred->mechanisms->elements[0];
-
- if (cred->flags & CRED_FLAG_INITIATE) {
- major = readDefaultIdentityAndCreds(minor, &defaultIdentity, &defaultCreds);
- if (major == GSS_S_COMPLETE) {
- major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
- nameMech, &defaultIdentityName);
- if (GSS_ERROR(major))
- goto cleanup;
- } else if (major != GSS_S_CRED_UNAVAIL)
- goto cleanup;
- }
-
if (desiredName != GSS_C_NO_NAME) {
GSSEAP_MUTEX_LOCK(&desiredName->mutex);
}
GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
-
- if (defaultIdentityName != GSS_C_NO_NAME) {
- int nameEqual;
-
- major = gssEapCompareName(minor, desiredName,
- defaultIdentityName, &nameEqual);
- if (GSS_ERROR(major))
- goto cleanup;
- else if (nameEqual)
- cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
- }
- } else {
- if (cred->flags & CRED_FLAG_ACCEPT) {
- gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
- char serviceName[5 + MAXHOSTNAMELEN];
-
- /* default host-based service is host@localhost */
- memcpy(serviceName, "host@", 5);
- if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
- major = GSS_S_FAILURE;
- *minor = GSSEAP_NO_HOSTNAME;
- goto cleanup;
- }
-
- nameBuf.value = serviceName;
- nameBuf.length = strlen((char *)nameBuf.value);
-
- major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
- nameMech, &cred->name);
- if (GSS_ERROR(major))
- goto cleanup;
- } else if (cred->flags & CRED_FLAG_INITIATE) {
- if (defaultIdentityName == GSS_C_NO_NAME) {
- major = GSS_S_CRED_UNAVAIL;
- *minor = GSSEAP_NO_DEFAULT_IDENTITY;
- goto cleanup;
- }
-
- cred->name = defaultIdentityName;
- defaultIdentityName = GSS_C_NO_NAME;
- }
- cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
- }
-
- assert(cred->name != GSS_C_NO_NAME);
-
- if (password != GSS_C_NO_BUFFER) {
- major = duplicateBuffer(minor, password, &cred->password);
- if (GSS_ERROR(major))
- goto cleanup;
-
- cred->flags |= CRED_FLAG_PASSWORD;
- } else if (defaultCreds.value != NULL &&
- (cred->flags & CRED_FLAG_DEFAULT_IDENTITY)) {
- cred->password = defaultCreds;
-
- defaultCreds.length = 0;
- defaultCreds.value = NULL;
-
- cred->flags |= CRED_FLAG_PASSWORD;
- } else if (cred->flags & CRED_FLAG_INITIATE) {
- /*
- * OK, here we need to ask the supplicant if we have creds or it
- * will acquire them, so GS2 can know whether to prompt for a
- * password or not.
- */
-#if 0
- && !gssEapCanReauthP(cred, GSS_C_NO_NAME, timeReq)
-#endif
- major = GSS_S_CRED_UNAVAIL;
- *minor = GSSEAP_NO_DEFAULT_CRED;
- goto cleanup;
}
if (pActualMechs != NULL) {
cleanup:
if (GSS_ERROR(major))
gssEapReleaseCred(&tmpMinor, &cred);
- gssEapReleaseName(&tmpMinor, &defaultIdentityName);
- gss_release_buffer(&tmpMinor, &defaultIdentity);
- if (defaultCreds.value != NULL) {
- memset(defaultCreds.value, 0, defaultCreds.length);
- gss_release_buffer(&tmpMinor, &defaultCreds);
- }
return major;
}
return present;
}
+static OM_uint32
+staticIdentityFileResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+ gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
+
+ *pName = GSS_C_NO_NAME;
+
+ major = readStaticIdentityFile(minor, &defaultIdentity, GSS_C_NO_BUFFER);
+ if (major == GSS_S_COMPLETE) {
+ major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
+ nameMech, pName);
+ }
+
+ gss_release_buffer(&tmpMinor, &defaultIdentity);
+
+ return major;
+}
+
+static OM_uint32
+gssEapResolveCredIdentity(OM_uint32 *minor,
+ gss_cred_id_t cred)
+{
+ OM_uint32 major;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+
+ if (cred->name != GSS_C_NO_NAME) {
+ *minor = 0;
+ return GSS_S_COMPLETE;
+ }
+
+ if (cred->flags & CRED_FLAG_ACCEPT) {
+ gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
+ char serviceName[5 + MAXHOSTNAMELEN];
+
+ /* default host-based service is host@localhost */
+ memcpy(serviceName, "host@", 5);
+ if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
+ *minor = GSSEAP_NO_HOSTNAME;
+ return GSS_S_FAILURE;
+ }
+
+ nameBuf.value = serviceName;
+ nameBuf.length = strlen((char *)nameBuf.value);
+
+ major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
+ nameMech, &cred->name);
+ if (GSS_ERROR(major))
+ return major;
+ } else if (cred->flags & CRED_FLAG_INITIATE) {
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+ major = libMoonshotResolveDefaultIdentity(minor, cred, &cred->name);
+ if (major == GSS_S_CRED_UNAVAIL)
+#endif
+ major = staticIdentityFileResolveDefaultIdentity(minor, cred, &cred->name);
+ if (major != GSS_S_CRED_UNAVAIL)
+ return major;
+ }
+
+ *minor = 0;
+ return GSS_S_COMPLETE;
+}
+
OM_uint32
gssEapInquireCred(OM_uint32 *minor,
gss_cred_id_t cred,
time_t now, lifetime;
if (name != NULL) {
- major = gssEapDuplicateName(minor, cred->name, name);
+ major = gssEapResolveCredIdentity(minor, cred);
if (GSS_ERROR(major))
- return major;
+ goto cleanup;
+
+ if (cred->name != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, cred->name, name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ } else
+ *name = GSS_C_NO_NAME;
}
if (cred_usage != NULL) {
else
major = gssEapIndicateMechs(minor, mechanisms);
if (GSS_ERROR(major))
- return major;
+ goto cleanup;
}
if (cred->expiryTime == 0) {
}
if (lifetime == 0) {
+ major = GSS_S_CREDENTIALS_EXPIRED;
*minor = GSSEAP_CRED_EXPIRED;
- return GSS_S_CREDENTIALS_EXPIRED;
+ goto cleanup;
}
major = GSS_S_COMPLETE;
*minor = 0;
+cleanup:
+ return major;
+}
+
+OM_uint32
+gssEapSetCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t password)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc newPassword = GSS_C_EMPTY_BUFFER;
+
+ if (cred->flags & CRED_FLAG_RESOLVED) {
+ major = GSS_S_FAILURE;
+ *minor = GSSEAP_CRED_RESOLVED;
+ goto cleanup;
+ }
+
+ if (password != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, password, &newPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ cred->flags |= CRED_FLAG_PASSWORD;
+ } else {
+ cred->flags &= ~(CRED_FLAG_PASSWORD);
+ }
+
+ gss_release_buffer(&tmpMinor, &cred->password);
+ cred->password = newPassword;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ return major;
+}
+
+OM_uint32
+gssEapSetCredService(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t target)
+{
+ OM_uint32 major, tmpMinor;
+ gss_name_t newTarget = GSS_C_NO_NAME;
+
+ if (cred->flags & CRED_FLAG_RESOLVED) {
+ major = GSS_S_FAILURE;
+ *minor = GSSEAP_CRED_RESOLVED;
+ goto cleanup;
+ }
+
+ if (target != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, target, &newTarget);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ gssEapReleaseName(&tmpMinor, &cred->target);
+ cred->target = newTarget;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ return major;
+}
+
+static OM_uint32
+gssEapDuplicateCred(OM_uint32 *minor,
+ const gss_cred_id_t src,
+ gss_cred_id_t *pDst)
+{
+ OM_uint32 major, tmpMinor;
+ gss_cred_id_t dst = GSS_C_NO_CREDENTIAL;
+
+ *pDst = GSS_C_NO_CREDENTIAL;
+
+ major = gssEapAllocCred(minor, &dst);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ dst->flags = src->flags;
+
+ if (src->name != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, src->name, &dst->name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (src->target != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, src->target, &dst->target);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (src->password.value != NULL) {
+ major = duplicateBuffer(minor, &src->password, &dst->password);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ major = duplicateOidSet(minor, src->mechanisms, &dst->mechanisms);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ dst->expiryTime = src->expiryTime;
+
+ if (src->radiusConfigFile.value != NULL)
+ duplicateBufferOrCleanup(&src->radiusConfigFile, &dst->radiusConfigFile);
+ if (src->radiusConfigStanza.value != NULL)
+ duplicateBufferOrCleanup(&src->radiusConfigStanza, &dst->radiusConfigStanza);
+ if (src->caCertificate.value != NULL)
+ duplicateBufferOrCleanup(&src->caCertificate, &dst->caCertificate);
+ if (src->subjectNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint);
+ if (src->subjectAltNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint);
+
+#ifdef GSSEAP_ENABLE_REAUTH
+ /* XXX krbCredCache, reauthCred */
+#endif
+
+ *pDst = dst;
+ dst = GSS_C_NO_CREDENTIAL;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ gssEapReleaseCred(&tmpMinor, &dst);
+
+ return major;
+}
+
+static OM_uint32
+staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
+ gss_name_t defaultIdentityName = GSS_C_NO_NAME;
+ gss_buffer_desc defaultPassword = GSS_C_EMPTY_BUFFER;
+ int isDefaultIdentity = FALSE;
+
+ major = readStaticIdentityFile(minor, &defaultIdentity, &defaultPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
+ gssEapPrimaryMechForCred(cred), &defaultIdentityName);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ if (defaultIdentityName == GSS_C_NO_NAME) {
+ if (cred->name == GSS_C_NO_NAME) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_IDENTITY;
+ goto cleanup;
+ }
+ } else {
+ if (cred->name == GSS_C_NO_NAME) {
+ cred->name = defaultIdentityName;
+ defaultIdentityName = GSS_C_NO_NAME;
+ isDefaultIdentity = TRUE;
+ } else {
+ major = gssEapCompareName(minor, cred->name,
+ defaultIdentityName, &isDefaultIdentity);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+ }
+
+ if (isDefaultIdentity &&
+ (cred->flags & CRED_FLAG_PASSWORD) == 0) {
+ major = gssEapSetCredPassword(minor, cred, &defaultPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+cleanup:
+ gssEapReleaseName(&tmpMinor, &defaultIdentityName);
+ zeroAndReleasePassword(&defaultPassword);
+ gss_release_buffer(&tmpMinor, &defaultIdentity);
+
+ return major;
+}
+
+OM_uint32
+gssEapResolveInitiatorCred(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ const gss_name_t targetName
+#ifndef HAVE_MOONSHOT_GET_IDENTITY
+ GSSEAP_UNUSED
+#endif
+ ,
+ gss_cred_id_t *pResolvedCred)
+{
+ OM_uint32 major, tmpMinor;
+ gss_cred_id_t resolvedCred = GSS_C_NO_CREDENTIAL;
+
+ if (cred == GSS_C_NO_CREDENTIAL) {
+ major = gssEapAcquireCred(minor,
+ GSS_C_NO_NAME,
+ GSS_C_INDEFINITE,
+ GSS_C_NO_OID_SET,
+ GSS_C_INITIATE,
+ &resolvedCred,
+ NULL,
+ NULL);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ } else {
+ if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
+ major = GSS_S_NO_CRED;
+ *minor = GSSEAP_CRED_USAGE_MISMATCH;
+ goto cleanup;
+ }
+
+ major = gssEapDuplicateCred(minor, cred, &resolvedCred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if ((resolvedCred->flags & CRED_FLAG_RESOLVED) == 0) {
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+ major = libMoonshotResolveInitiatorCred(minor, resolvedCred, targetName);
+ if (major == GSS_S_CRED_UNAVAIL)
+#endif
+ major = staticIdentityFileResolveInitiatorCred(minor, resolvedCred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ if ((resolvedCred->flags & CRED_FLAG_PASSWORD) == 0) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_CRED;
+ goto cleanup;
+ }
+
+ resolvedCred->flags |= CRED_FLAG_RESOLVED;
+ }
+
+ *pResolvedCred = resolvedCred;
+ resolvedCred = GSS_C_NO_CREDENTIAL;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ gssEapReleaseCred(&tmpMinor, &resolvedCred);
+
return major;
}
*/
kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
kiov[i].data.length = k5_trailerlen;
- kiov[i].data.data = kiov[i - 1].data.data + ec + 16; /* E(Header) */
+ kiov[i].data.data = (char *)kiov[i - 1].data.data + ec + 16; /* E(Header) */
i++;
*pkiov = kiov;
return json_number_value(m_obj);
}
+#ifdef HAVE_SHIBRESOLVER
JSONObject
JSONObject::ddf(DDF &ddf)
{
return ddf;
}
+#endif /* HAVE_SHIBRESOLVER */
bool JSONObject::isObject(void) const
{
#include <new>
#include <jansson.h>
-#include <shibsp/remoting/ddf.h>
+#ifdef HAVE_SHIBRESOLVER
+#include <shibsp/remoting/ddf.h>
using namespace shibsp;
+#endif
namespace gss_eap_util {
class JSONObject;
static JSONObject object(void);
static JSONObject array(void);
static JSONObject null(void);
+#ifdef HAVE_SHIBRESOLVER
static JSONObject ddf(DDF &value);
+#endif
char *dump(size_t flags = 0) const;
void dump(FILE *fp, size_t flags = JSON_INDENT(4)) const;
json_int_t integer(void) const;
double real(void) const;
double number(void) const;
+#ifdef HAVE_SHIBRESOLVER
DDF ddf(void) const;
+#endif
bool isObject(void) const;
bool isArray(void) const;
OM_uint32
gssEapKerberosInit(OM_uint32 *minor, krb5_context *context)
{
- struct gss_eap_thread_local_data* tld;
+ struct gss_eap_thread_local_data *tld;
+
*minor = 0;
tld = gssEapGetThreadLocalData();
- if (tld)
- {
- *context = tld->context;
+ if (tld != NULL) {
+ *context = tld->krbContext;
if (*context == NULL) {
*minor = initKrbContext(context);
- if (*minor == 0) {
- tld->context = *context;
- }
+ if (*minor == 0)
+ tld->krbContext = *context;
}
}
return *minor == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
#endif /* HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE */
if (!krb5_c_is_keyed_cksum(*cksumtype)) {
- *minor = KRB5KRB_AP_ERR_INAPP_CKSUM;
+ *minor = (OM_uint32)KRB5KRB_AP_ERR_INAPP_CKSUM;
return GSS_S_FAILURE;
}
--- /dev/null
+/*
+ * Copyright (c) 2011, 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"
+
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+#include <libmoonshot.h>
+
+static OM_uint32
+libMoonshotMapError(OM_uint32 *minor,
+ MoonshotError **pError)
+{
+ MoonshotError *error = *pError;
+
+ assert(error != NULL);
+
+ switch (error->code) {
+ case MOONSHOT_ERROR_UNABLE_TO_START_SERVICE:
+ *minor = GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE;
+ break;
+ case MOONSHOT_ERROR_NO_IDENTITY_SELECTED:
+ *minor = GSSEAP_NO_IDENTITY_SELECTED;
+ break;
+ case MOONSHOT_ERROR_INSTALLATION_ERROR:
+ *minor = GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR;
+ break;
+ case MOONSHOT_ERROR_OS_ERROR:
+ *minor = GSSEAP_IDENTITY_SERVICE_OS_ERROR;
+ break;
+ case MOONSHOT_ERROR_IPC_ERROR:
+ *minor = GSSEAP_IDENTITY_SERVICE_IPC_ERROR;
+ break;
+ default:
+ *minor = GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR;
+ break;
+ }
+
+ gssEapSaveStatusInfo(*minor, error->message);
+ moonshot_error_free(error);
+ *pError = NULL;
+
+ return GSS_S_CRED_UNAVAIL;
+}
+
+OM_uint32
+libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+ gss_name_t name = GSS_C_NO_NAME;
+ gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
+ char *nai = NULL;
+ char *password = NULL;
+ char *serverCertificateHash = NULL;
+ char *caCertificate = NULL;
+ char *subjectNameConstraint = NULL;
+ char *subjectAltNameConstraint = NULL;
+ MoonshotError *error = NULL;
+
+ *pName = GSS_C_NO_NAME;
+
+ if (!moonshot_get_default_identity(&nai,
+ &password,
+ &serverCertificateHash,
+ &caCertificate,
+ &subjectNameConstraint,
+ &subjectAltNameConstraint,
+ &error)) {
+ if (error->code == MOONSHOT_ERROR_NO_IDENTITY_SELECTED) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_IDENTITY;
+ moonshot_error_free(error);
+ } else
+ major = libMoonshotMapError(minor, &error);
+ goto cleanup;
+ }
+
+ tmpBuffer.value = nai;
+ tmpBuffer.length = strlen(nai);
+
+ major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME, nameMech, &name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ *pName = name;
+ name = GSS_C_NO_NAME;
+
+cleanup:
+ moonshot_free(nai);
+ moonshot_free(password);
+ moonshot_free(serverCertificateHash);
+ moonshot_free(caCertificate);
+ moonshot_free(subjectNameConstraint);
+ moonshot_free(subjectAltNameConstraint);
+
+ gssEapReleaseName(&tmpMinor, &name);
+
+ return major;
+}
+
+OM_uint32
+libMoonshotResolveInitiatorCred(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t targetName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+ gss_buffer_desc initiator = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc target = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
+ char *nai = NULL;
+ char *password = NULL;
+ char *serverCertificateHash = NULL;
+ char *caCertificate = NULL;
+ char *subjectNameConstraint = NULL;
+ char *subjectAltNameConstraint = NULL;
+ MoonshotError *error = NULL;
+
+ if (cred->name != GSS_C_NO_NAME) {
+ major = gssEapExportName(minor, cred->name, &initiator);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (targetName != GSS_C_NO_NAME) {
+ major = gssEapExportName(minor, targetName, &target);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (!moonshot_get_identity((const char *)initiator.value,
+ (const char *)cred->password.value,
+ (const char *)target.value,
+ &nai,
+ &password,
+ &serverCertificateHash,
+ &caCertificate,
+ &subjectNameConstraint,
+ &subjectAltNameConstraint,
+ &error)) {
+ major = libMoonshotMapError(minor, &error);
+ goto cleanup;
+ }
+
+ gssEapReleaseName(&tmpMinor, &cred->name);
+
+ tmpBuffer.value = nai;
+ tmpBuffer.length = strlen(nai);
+
+ major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME,
+ nameMech, &cred->name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ tmpBuffer.value = password;
+ tmpBuffer.length = strlen(password);
+
+ major = gssEapSetCredPassword(minor, cred, &tmpBuffer);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ gss_release_buffer(&tmpMinor, &cred->caCertificate);
+ gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
+ gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
+
+ if (serverCertificateHash != NULL) {
+ size_t len = strlen(serverCertificateHash);
+
+ #define HASH_PREFIX "hash://server/sha256/"
+ #define HASH_PREFIX_LEN (sizeof(HASH_PREFIX) - 1)
+
+ cred->caCertificate.value = GSSEAP_MALLOC(HASH_PREFIX_LEN + len + 1);
+ if (cred->caCertificate.value == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ memcpy(cred->caCertificate.value, HASH_PREFIX, HASH_PREFIX_LEN);
+ memcpy((char *)cred->caCertificate.value + HASH_PREFIX_LEN, serverCertificateHash, len);
+
+ ((char *)cred->caCertificate.value)[HASH_PREFIX_LEN + len] = '\0';
+
+ cred->caCertificate.length = HASH_PREFIX_LEN + len;
+ } else if (caCertificate != NULL) {
+ makeStringBufferOrCleanup(caCertificate, &cred->caCertificate);
+ }
+
+ if (subjectNameConstraint != NULL)
+ makeStringBufferOrCleanup(subjectNameConstraint, &cred->subjectNameConstraint);
+ if (subjectAltNameConstraint != NULL)
+ makeStringBufferOrCleanup(subjectAltNameConstraint, &cred->subjectAltNameConstraint);
+
+cleanup:
+ moonshot_free(nai);
+ moonshot_free(password);
+ moonshot_free(serverCertificateHash);
+ moonshot_free(caCertificate);
+ moonshot_free(subjectNameConstraint);
+ moonshot_free(subjectAltNameConstraint);
+
+ gss_release_buffer(&tmpMinor, &initiator);
+ gss_release_buffer(&tmpMinor, &target);
+
+ return major;
+}
+#endif /* HAVE_MOONSHOT_GET_IDENTITY */
}
if (GSSEAP_MUTEX_INIT(&name->mutex) != 0) {
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
gssEapReleaseName(&tmpMinor, &name);
return GSS_S_FAILURE;
}
name->mechanismUsed = mechanismUsed;
mechanismUsed = GSS_C_NO_OID;
+#ifdef GSSEAP_ENABLE_ACCEPTOR
if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
gss_buffer_desc buf;
buf.length = remain;
buf.value = p;
-#ifdef GSSEAP_ENABLE_ACCEPTOR
+
major = gssEapImportAttrContext(minor, &buf, name);
-#else
- major = GSS_S_UNAVAILABLE;
-#endif
if (GSS_ERROR(major))
goto cleanup;
}
+#endif
major = GSS_S_COMPLETE;
*minor = 0;
exportedNameLen += 6 + mech->length;
}
exportedNameLen += 4 + nameBuf.length;
- if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
#ifdef GSSEAP_ENABLE_ACCEPTOR
+ if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
major = gssEapExportAttrContext(minor, name, &attrs);
-#else
- major = GSS_S_UNAVAILABLE;
-#endif
if (GSS_ERROR(major))
goto cleanup;
exportedNameLen += attrs.length;
}
+#endif
exportedName->value = GSSEAP_MALLOC(exportedNameLen);
if (exportedName->value == NULL) {
goto cleanup;
}
- if (input_name->attrCtx != NULL) {
#ifdef GSSEAP_ENABLE_ACCEPTOR
+ if (input_name->attrCtx != NULL) {
major = gssEapDuplicateAttrContext(minor, input_name, name);
-#else
- major = GSS_S_UNAVAILABLE;
-#endif
if (GSS_ERROR(major))
goto cleanup;
}
+#endif
*dest_name = name;
gssEapRadiusMapError(OM_uint32 *minor,
struct rs_error *err);
-////This really need to be a function call on Windows
+/* This really needs to be a function call on Windows */
#define RS_CONFIG_FILE SYSCONFDIR "/radsec.conf"
#define VENDORPEC_MS 311 /* RFC 2548 */
#define PW_SAML_AAA_ASSERTION 132
#define PW_MS_WINDOWS_AUTH_DATA 133
-#define IS_RADIUS_ERROR(code) ((code) >= ERROR_TABLE_BASE_rse && \
- (code) <= ERROR_TABLE_BASE_rse + RSE_TIMEOUT_IO)
-
#ifdef __cplusplus
}
#endif
#include <xmltooling/util/DateTime.h>
#include <saml/exceptions.h>
+#include <saml/SAMLConfig.h>
#include <saml/saml1/core/Assertions.h>
#include <saml/saml2/core/Assertions.h>
#include <saml/saml2/metadata/Metadata.h>
bool
gss_eap_saml_assertion_provider::init(void)
{
- gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML_ASSERTION, createAttrContext);
- return true;
+ bool ret = false;
+
+ try {
+ ret = SAMLConfig::getConfig().init();
+ } catch (exception &e) {
+ }
+
+ if (ret)
+ gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML_ASSERTION, createAttrContext);
+
+ return ret;
}
void
* Local attribute provider implementation.
*/
+#include "gssapiP_eap.h"
+
#include <xmltooling/XMLObject.h>
+#ifndef HAVE_OPENSAML
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/ParserPool.h>
+#endif
#include <saml/saml2/core/Assertions.h>
#include <sstream>
-#include "gssapiP_eap.h"
-
using namespace shibsp;
using namespace shibresolver;
-using namespace opensaml::saml2md;
-using namespace opensaml;
using namespace xmltooling;
using namespace std;
+#ifdef HAVE_OPENSAML
+using namespace opensaml::saml2md;
+using namespace opensaml;
+#else
+using namespace xercesc;
+#endif
gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(void)
{
gss_release_buffer(&minor, &mechName);
}
+#ifdef HAVE_OPENSAML
const gss_eap_saml_assertion_provider *saml;
saml = static_cast<const gss_eap_saml_assertion_provider *>
(m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
if (saml != NULL && saml->getAssertion() != NULL) {
resolver->addToken(saml->getAssertion());
}
+#else
+ /* If no OpenSAML, parse the XML assertion explicitly */
+ const gss_eap_radius_attr_provider *radius;
+ int authenticated, complete;
+ gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
+
+ radius = static_cast<const gss_eap_radius_attr_provider *>
+ (m_manager->getProvider(ATTR_TYPE_RADIUS));
+ if (radius != NULL &&
+ radius->getFragmentedAttribute(PW_SAML_AAA_ASSERTION,
+ VENDORPEC_UKERNA,
+ &authenticated, &complete, &value)) {
+ string str((char *)value.value, value.length);
+ istringstream istream(str);
+ DOMDocument *doc = XMLToolingConfig::getConfig().getParser().parse(istream);
+ const XMLObjectBuilder *b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
+ resolver->addToken(b->buildFromDocument(doc));
+ gss_release_buffer(&minor, &value);
+ }
+#endif /* HAVE_OPENSAML */
try {
resolver->resolve();
bool ret = false;
try {
- if (SPConfig::getConfig().getFeatures() == 0)
- ret = ShibbolethResolver::init();
+ ret = ShibbolethResolver::init();
} catch (exception &e) {
}
makeErrorToken(OM_uint32 *minor,
OM_uint32 majorStatus,
OM_uint32 minorStatus,
- gss_buffer_set_t *outputToken)
+ struct gss_eap_token_buffer_set *token)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
unsigned char errorData[8];
gss_buffer_desc errorBuffer;
assert(GSS_ERROR(majorStatus));
- major = gss_create_empty_buffer_set(minor, outputToken);
- if (GSS_ERROR(major))
- return major;
-
/*
* Only return error codes that the initiator could have caused,
* to avoid information leakage.
*/
-#ifdef GSSEAP_ENABLE_ACCEPTOR
if (IS_RADIUS_ERROR(minorStatus)) {
/* Squash RADIUS error codes */
minorStatus = GSSEAP_RADIUS_PROT_FAILURE;
- } else
-#endif
- if (!IS_WIRE_ERROR(minorStatus)) {
+ } else if (!IS_WIRE_ERROR(minorStatus)) {
/* Don't return non-wire error codes */
return GSS_S_COMPLETE;
}
store_uint32_be(majorStatus, &errorData[0]);
store_uint32_be(minorStatus, &errorData[4]);
- errorBuffer.length = sizeof(errorData);
- errorBuffer.value = errorData;
-
- major = gss_add_buffer_set_member(minor, &errorBuffer, outputToken);
- if (GSS_ERROR(major))
+ major = gssEapAllocInnerTokens(&tmpMinor, 1, token);
+ if (GSS_ERROR(major)) {
+ *minor = tmpMinor;
return major;
-
- return GSS_S_COMPLETE;
-}
-
-static OM_uint32
-allocInnerTokens(OM_uint32 *minor,
- size_t count,
- gss_buffer_set_t *pTokens,
- OM_uint32 **pTokenTypes)
-{
- OM_uint32 major, tmpMinor;
- gss_buffer_set_t tokens = GSS_C_NO_BUFFER_SET;
- OM_uint32 *tokenTypes = NULL;
-
- major = gss_create_empty_buffer_set(minor, &tokens);
- if (GSS_ERROR(major))
- goto cleanup;
-
- assert(tokens->count == 0);
- assert(tokens->elements == NULL);
-
- tokens->elements = (gss_buffer_desc *)GSSEAP_CALLOC(count, sizeof(gss_buffer_desc));
- if (tokens->elements == NULL) {
- major = GSS_S_FAILURE;
- *minor = ENOMEM;
- goto cleanup;
- }
-
- tokenTypes = (OM_uint32 *)GSSEAP_CALLOC(count, sizeof(OM_uint32));
- if (tokenTypes == NULL) {
- major = GSS_S_FAILURE;
- *minor = ENOMEM;
- goto cleanup;
}
- major = GSS_S_COMPLETE;
- *minor = 0;
+ errorBuffer.length = sizeof(errorData);
+ errorBuffer.value = errorData;
-cleanup:
+ major = duplicateBuffer(&tmpMinor, &errorBuffer, &token->buffers.elements[0]);
if (GSS_ERROR(major)) {
- gss_release_buffer_set(&tmpMinor, &tokens);
- tokens = GSS_C_NO_BUFFER_SET;
- if (tokenTypes != NULL) {
- GSSEAP_FREE(tokenTypes);
- tokenTypes = NULL;
- }
+ gssEapReleaseInnerTokens(&tmpMinor, token, 1);
+ *minor = tmpMinor;
+ return major;
}
- *pTokens = tokens;
- *pTokenTypes = tokenTypes;
+ token->types[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL;
- return major;
+ *minor = 0;
+ return GSS_S_COMPLETE;
}
OM_uint32
size_t smCount)
{
OM_uint32 major, tmpMajor, tmpMinor;
+ struct gss_eap_token_buffer_set inputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
+ struct gss_eap_token_buffer_set outputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
gss_buffer_desc unwrappedInputToken = GSS_C_EMPTY_BUFFER;
gss_buffer_desc unwrappedOutputToken = GSS_C_EMPTY_BUFFER;
- gss_buffer_set_t innerInputTokens = GSS_C_NO_BUFFER_SET;
- gss_buffer_set_t innerOutputTokens = GSS_C_NO_BUFFER_SET;
- OM_uint32 *inputTokenTypes = NULL, *outputTokenTypes = NULL;
unsigned int smFlags = 0;
size_t i, j;
int initialContextToken = 0;
assert(ctx->state < GSSEAP_STATE_ESTABLISHED);
- major = gssEapDecodeInnerTokens(minor, &unwrappedInputToken,
- &innerInputTokens, &inputTokenTypes);
+ major = gssEapDecodeInnerTokens(minor, &unwrappedInputToken, &inputTokens);
if (GSS_ERROR(major))
goto cleanup;
- assert(innerInputTokens != GSS_C_NO_BUFFER_SET);
-
- major = allocInnerTokens(minor, smCount, &innerOutputTokens, &outputTokenTypes);
+ major = gssEapAllocInnerTokens(minor, smCount, &outputTokens);
if (GSS_ERROR(major))
goto cleanup;
+ ctx->inputTokens = &inputTokens;
+ ctx->outputTokens = &outputTokens;
+
/* Process all the tokens that are valid for the current state. */
for (i = 0; i < smCount; i++) {
struct gss_eap_sm *smp = &sm[i];
processToken = 1;
} else if ((smFlags & SM_FLAG_TRANSITED) == 0) {
/* Don't regurgitate a token which belonds to a previous state. */
- for (j = 0; j < innerInputTokens->count; j++) {
- if ((inputTokenTypes[j] & ITOK_TYPE_MASK) == smp->inputTokenType) {
+ for (j = 0; j < inputTokens.buffers.count; j++) {
+ if ((inputTokens.types[j] & ITOK_TYPE_MASK) == smp->inputTokenType) {
if (processToken) {
/* Check for duplicate inner tokens */
major = GSS_S_DEFECTIVE_TOKEN;
break;
}
processToken = 1;
- innerInputToken = &innerInputTokens->elements[j];
- inputTokenType = &inputTokenTypes[j];
+ innerInputToken = &inputTokens.buffers.elements[j];
+ inputTokenType = &inputTokens.types[j];
}
}
if (GSS_ERROR(major))
smFlags |= SM_FLAG_TRANSITED;
if (innerOutputToken.value != NULL) {
- innerOutputTokens->elements[innerOutputTokens->count] = innerOutputToken;
+ outputTokens.buffers.elements[outputTokens.buffers.count] = innerOutputToken;
assert(smp->outputTokenType != ITOK_TYPE_NONE);
- outputTokenTypes[innerOutputTokens->count] = smp->outputTokenType;
+ outputTokens.types[outputTokens.buffers.count] = smp->outputTokenType;
if (smFlags & SM_FLAG_OUTPUT_TOKEN_CRITICAL)
- outputTokenTypes[innerOutputTokens->count] |= ITOK_FLAG_CRITICAL;
- innerOutputTokens->count++;
+ outputTokens.types[outputTokens.buffers.count] |= ITOK_FLAG_CRITICAL;
+ outputTokens.buffers.count++;
}
/*
* Break out if we made a state transition and have some tokens to send.
*/
if ((smFlags & SM_FLAG_TRANSITED) &&
- ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || innerOutputTokens->count != 0)) {
+ ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || outputTokens.buffers.count != 0)) {
SM_ASSERT_VALID(ctx, major);
break;
}
}
}
- assert(innerOutputTokens->count <= smCount);
+ assert(outputTokens.buffers.count <= smCount);
/* Check we understood all critical tokens sent by peer */
if (!GSS_ERROR(major)) {
- for (j = 0; j < innerInputTokens->count; j++) {
- if ((inputTokenTypes[j] & ITOK_FLAG_CRITICAL) &&
- (inputTokenTypes[j] & ITOK_FLAG_VERIFIED) == 0) {
+ for (j = 0; j < inputTokens.buffers.count; j++) {
+ if ((inputTokens.types[j] & ITOK_FLAG_CRITICAL) &&
+ (inputTokens.types[j] & ITOK_FLAG_VERIFIED) == 0) {
major = GSS_S_UNAVAILABLE;
*minor = GSSEAP_CRIT_ITOK_UNAVAILABLE;
goto cleanup;
goto cleanup; /* return error directly to caller */
/* replace any emitted tokens with error token */
- gss_release_buffer_set(&tmpMinor, &innerOutputTokens);
+ gssEapReleaseInnerTokens(&tmpMinor, &outputTokens, 1);
- tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &innerOutputTokens);
+ tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &outputTokens);
if (GSS_ERROR(tmpMajor)) {
major = tmpMajor;
*minor = tmpMinor;
goto cleanup;
}
-
- if (innerOutputTokens->count != 0)
- outputTokenTypes[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL;
}
/* Format output token from inner tokens */
- if (innerOutputTokens->count != 0 || /* inner tokens to send */
+ if (outputTokens.buffers.count != 0 || /* inner tokens to send */
!CTX_IS_INITIATOR(ctx) || /* any leg acceptor */
!CTX_IS_ESTABLISHED(ctx)) { /* non-last leg initiator */
- tmpMajor = gssEapEncodeInnerTokens(&tmpMinor, innerOutputTokens,
- outputTokenTypes, &unwrappedOutputToken);
+ tmpMajor = gssEapEncodeInnerTokens(&tmpMinor, &outputTokens, &unwrappedOutputToken);
if (tmpMajor == GSS_S_COMPLETE) {
if (CTX_IS_INITIATOR(ctx))
tokType = TOK_TYPE_INITIATOR_CONTEXT;
SM_ASSERT_VALID(ctx, major);
cleanup:
- gss_release_buffer_set(&tmpMinor, &innerInputTokens);
- gss_release_buffer_set(&tmpMinor, &innerOutputTokens);
- if (inputTokenTypes != NULL)
- GSSEAP_FREE(inputTokenTypes);
- if (outputTokenTypes != NULL)
+ gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 0);
+ gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 1);
+
gss_release_buffer(&tmpMinor, &unwrappedOutputToken);
- GSSEAP_FREE(outputTokenTypes);
+
+ ctx->inputTokens = NULL;
+ ctx->outputTokens = NULL;
return major;
}
* SUCH DAMAGE.
*/
-/* Access all thread-local data through these methods which
- * use pthreads to manage thread-local memory on Unix and TlsFoo() on Windows.
- * This would be more flexible, scalable, and extensible
- * if implemented through a callback interface, but given that
- * there are currently only two 'clients', hard-coding seems more
- * straightforward
+/*
+ * Thread local data abstraction, using pthreads on Unix and the TlsXXX
+ * APIs on Windows.
*/
+
#include "gssapiP_eap.h"
/* Clean up thread-local data; called on thread detach */
static void
-destroyThreadLocalData(struct gss_eap_thread_local_data* tld)
+destroyThreadLocalData(struct gss_eap_thread_local_data *tld)
{
- if (tld->status_info)
- gssEapDestroyStatusInfo(tld->status_info);
- if (tld->context)
- gssEapDestroyKrbContext(tld->context);
+ if (tld->statusInfo != NULL)
+ gssEapDestroyStatusInfo(tld->statusInfo);
+ if (tld->krbContext != NULL)
+ gssEapDestroyKrbContext(tld->krbContext);
GSSEAP_FREE(tld);
}
#ifdef WIN32
-/* This is the tls index returned by TlsAlloc() on process init.
- * Each thread, on thread attach in DllMain(), allocates its thread-local data and uses this index with TlsSetValue() to store it.
- * It can then subsequently be retrieved with TlsGetValue()
+/*
+ * This is the tls index returned by TlsAlloc() on process init.
+ * Each thread, on thread attach in DllMain(), allocates its thread-local
+ * data and uses this index with TlsSetValue() to store it.
+ * It can then subsequently be retrieved with TlsGetValue().
*/
static DWORD tlsIndex;
/* Access thread-local data */
struct gss_eap_thread_local_data *
-gssEapGetThreadLocalData()
+gssEapGetThreadLocalData(void)
{
return TlsGetValue(tlsIndex);
}
-
-/* DllMain() is the entry-point function for this DLL. */
-BOOL WINAPI DllMain(HINSTANCE hDLL, /* DLL module handle */
- DWORD reason, /* reason called */
- LPVOID reserved) /* reserved */
-{
+
+BOOL WINAPI
+DllMain(HINSTANCE hDLL, /* DLL module handle */
+ DWORD reason, /* reason called */
+ LPVOID reserved) /* reserved */
+{
struct gss_eap_thread_local_data *tlsData;
- switch (reason)
- {
- // The DLL is loading due to process
- // initialization or a call to LoadLibrary.
- case DLL_PROCESS_ATTACH:
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
/* Allocate a TLS index. */
- if ((tlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
- return FALSE;
+ gssEapInitiatorInit();
+ tlsIndex = TlsAlloc();
+ if (tlsIndex == TLS_OUT_OF_INDEXES)
+ return FALSE;
/* No break: Initialize the index for first thread.*/
-
- /* The attached process creates a new thread. */
- case DLL_THREAD_ATTACH:
+ case DLL_THREAD_ATTACH:
/* Initialize the TLS index for this thread. */
tlsData = GSSEAP_CALLOC(1, sizeof(*tlsData));
- if (tlsData != NULL)
- TlsSetValue(tlsIndex, tlsData);
-
- break;
-
- /* The thread of the attached process terminates. */
- case DLL_THREAD_DETACH:
+ if (tlsData != NULL)
+ TlsSetValue(tlsIndex, tlsData);
+ break;
+ case DLL_THREAD_DETACH:
/* Release the allocated memory for this thread. */
- tlsData = TlsGetValue(tlsIndex);
- if (tlsData != NULL)
- {
- destroyThreadLocalData(tlsData);
+ tlsData = TlsGetValue(tlsIndex);
+ if (tlsData != NULL) {
+ destroyThreadLocalData(tlsData);
TlsSetValue(tlsIndex, NULL);
}
-
- break;
-
- /* DLL unload due to process termination or FreeLibrary. */
- case DLL_PROCESS_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
/* Release the allocated memory for this thread. */
- tlsData = TlsGetValue(tlsIndex);
- if (tlsData != NULL)
- destroyThreadLocalData(tlsData);
+ tlsData = TlsGetValue(tlsIndex);
+ if (tlsData != NULL)
+ destroyThreadLocalData(tlsData);
/* Release the TLS index. */
- TlsFree(tlsIndex);
- break;
-
- default:
- break;
- }
-
- return TRUE;
- UNREFERENCED_PARAMETER(hDLL);
- UNREFERENCED_PARAMETER(reserved);
+ TlsFree(tlsIndex);
+ gssEapFinalize();
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+ UNREFERENCED_PARAMETER(hDLL);
+ UNREFERENCED_PARAMETER(reserved);
}
#else /* WIN32 */
-/* PTHREAD implementation */
+/* pthreads implementation */
+
static GSSEAP_THREAD_ONCE tldKeyOnce = GSSEAP_ONCE_INITIALIZER;
static GSSEAP_THREAD_KEY tldKey;
-static void
-pthreadDestroyThreadLocalData(void* arg)
+
+static void
+pthreadDestroyThreadLocalData(void *arg)
{
struct gss_eap_thread_local_data* tld = arg;
- if (tld)
- {
+
+ if (tld != NULL)
destroyThreadLocalData(tld);
- }
}
-static void
+static void
createThreadLocalDataKey(void)
{
GSSEAP_KEY_CREATE(&tldKey, pthreadDestroyThreadLocalData);
}
-struct gss_eap_thread_local_data *
+struct gss_eap_thread_local_data *
gssEapGetThreadLocalData()
{
struct gss_eap_thread_local_data *tld;
+
GSSEAP_ONCE(&tldKeyOnce, createThreadLocalDataKey);
+
tld = GSSEAP_GETSPECIFIC(tldKey);
- if (!tld)
- {
+ if (tld == NULL) {
tld = GSSEAP_CALLOC(1, sizeof(*tld));
+ if (tld == NULL)
+ return NULL;
+
GSSEAP_SETSPECIFIC(tldKey, tld);
}
+
return tld;
}
OM_uint32
gssEapEncodeInnerTokens(OM_uint32 *minor,
- gss_buffer_set_t extensions,
- OM_uint32 *types,
+ struct gss_eap_token_buffer_set *tokens,
gss_buffer_t buffer)
{
OM_uint32 major, tmpMinor;
buffer->value = NULL;
buffer->length = 0;
- if (extensions != GSS_C_NO_BUFFER_SET) {
- for (i = 0; i < extensions->count; i++) {
- required += 8 + extensions->elements[i].length;
- }
+ for (i = 0; i < tokens->buffers.count; i++) {
+ required += 8 + tokens->buffers.elements[i].length;
}
/*
buffer->length = required;
p = (unsigned char *)buffer->value;
- if (extensions != GSS_C_NO_BUFFER_SET) {
- for (i = 0; i < extensions->count; i++) {
- gss_buffer_t extension = &extensions->elements[i];
+ for (i = 0; i < tokens->buffers.count; i++) {
+ gss_buffer_t tokenBuffer = &tokens->buffers.elements[i];
- assert((types[i] & ITOK_FLAG_VERIFIED) == 0); /* private flag */
+ assert((tokens->types[i] & ITOK_FLAG_VERIFIED) == 0); /* private flag */
- /*
- * Extensions are encoded as type-length-value, where the upper
- * bit of the type indicates criticality.
- */
- store_uint32_be(types[i], &p[0]);
- store_uint32_be(extension->length, &p[4]);
- memcpy(&p[8], extension->value, extension->length);
+ /*
+ * Extensions are encoded as type-length-value, where the upper
+ * bit of the type indicates criticality.
+ */
+ store_uint32_be(tokens->types[i], &p[0]);
+ store_uint32_be(tokenBuffer->length, &p[4]);
+ memcpy(&p[8], tokenBuffer->value, tokenBuffer->length);
- p += 8 + extension->length;
- }
+ p += 8 + tokenBuffer->length;
}
assert(p == (unsigned char *)buffer->value + required);
OM_uint32
gssEapDecodeInnerTokens(OM_uint32 *minor,
const gss_buffer_t buffer,
- gss_buffer_set_t *pExtensions,
- OM_uint32 **pTypes)
+ struct gss_eap_token_buffer_set *tokens)
{
OM_uint32 major, tmpMinor;
- gss_buffer_set_t extensions = GSS_C_NO_BUFFER_SET;
- OM_uint32 *types = NULL;
unsigned char *p;
+ size_t count = 0;
size_t remain;
- *pExtensions = GSS_C_NO_BUFFER_SET;
- *pTypes = NULL;
-
- major = gss_create_empty_buffer_set(minor, &extensions);
- if (GSS_ERROR(major))
- goto cleanup;
+ tokens->buffers.count = 0;
+ tokens->buffers.elements = NULL;
+ tokens->types = NULL;
if (buffer->length == 0) {
major = GSS_S_COMPLETE;
do {
OM_uint32 *ntypes;
- gss_buffer_desc extension;
+ gss_buffer_desc tokenBuffer, *newTokenBuffers;
if (remain < 8) {
major = GSS_S_DEFECTIVE_TOKEN;
goto cleanup;
}
- ntypes = GSSEAP_REALLOC(types,
- (extensions->count + 1) * sizeof(OM_uint32));
- if (ntypes == NULL) {
- major = GSS_S_FAILURE;
- *minor = ENOMEM;
- goto cleanup;
+ if (tokens->buffers.count <= count) {
+ if (count == 0)
+ count = 1;
+ else
+ count *= 2;
+
+ ntypes = GSSEAP_MALLOC(count * sizeof(OM_uint32));
+ if (ntypes == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+ if (tokens->types != NULL) {
+ memcpy(ntypes, tokens->types, tokens->buffers.count * sizeof(OM_uint32));
+ GSSEAP_FREE(tokens->types);
+ }
+ tokens->types = ntypes;
+
+ newTokenBuffers = GSSEAP_MALLOC(count * sizeof(gss_buffer_desc));
+ if (newTokenBuffers == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+ if (tokens->buffers.elements != NULL) {
+ memcpy(newTokenBuffers, tokens->buffers.elements,
+ tokens->buffers.count * sizeof(gss_buffer_desc));
+ GSSEAP_FREE(tokens->buffers.elements);
+ }
+ tokens->buffers.elements = newTokenBuffers;
}
- types = ntypes;
- types[extensions->count] = load_uint32_be(&p[0]);
- extension.length = load_uint32_be(&p[4]);
+ tokens->types[tokens->buffers.count] = load_uint32_be(&p[0]);
+ tokenBuffer.length = load_uint32_be(&p[4]);
- if (remain < 8 + extension.length) {
+ if (remain < 8 + tokenBuffer.length) {
major = GSS_S_DEFECTIVE_TOKEN;
*minor = GSSEAP_TOK_TRUNC;
goto cleanup;
}
- extension.value = &p[8];
+ tokenBuffer.value = &p[8];
- major = gss_add_buffer_set_member(minor, &extension, &extensions);
- if (GSS_ERROR(major))
- goto cleanup;
+ tokens->buffers.elements[tokens->buffers.count] = tokenBuffer;
+ tokens->buffers.count++;
- p += 8 + extension.length;
- remain -= 8 + extension.length;
+ p += 8 + tokenBuffer.length;
+ remain -= 8 + tokenBuffer.length;
} while (remain != 0);
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
cleanup:
- if (GSS_ERROR(major)) {
- gss_release_buffer_set(&tmpMinor, &extensions);
- if (types != NULL)
- GSSEAP_FREE(types);
- } else {
- *pExtensions = extensions;
- *pTypes = types;
- }
+ if (GSS_ERROR(major))
+ gssEapReleaseInnerTokens(&tmpMinor, tokens, 0);
return major;
}
*minor = 0;
return GSS_S_COMPLETE;
}
+
+OM_uint32
+gssEapAllocInnerTokens(OM_uint32 *minor,
+ size_t count,
+ struct gss_eap_token_buffer_set *tokens)
+{
+ OM_uint32 major;
+
+ tokens->buffers.count = 0;
+ tokens->buffers.elements = (gss_buffer_desc *)GSSEAP_CALLOC(count, sizeof(gss_buffer_desc));
+ if (tokens->buffers.elements == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ tokens->types = (OM_uint32 *)GSSEAP_CALLOC(count, sizeof(OM_uint32));
+ if (tokens->types == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ if (GSS_ERROR(major)) {
+ if (tokens->buffers.elements != NULL) {
+ GSSEAP_FREE(tokens->buffers.elements);
+ tokens->buffers.elements = NULL;
+ }
+ if (tokens->types != NULL) {
+ GSSEAP_FREE(tokens->types);
+ tokens->types = NULL;
+ }
+ }
+
+ return major;
+}
+
+OM_uint32
+gssEapReleaseInnerTokens(OM_uint32 *minor,
+ struct gss_eap_token_buffer_set *tokens,
+ int freeBuffers)
+{
+ OM_uint32 tmpMinor;
+ size_t i;
+
+ if (tokens->buffers.elements != NULL) {
+ if (freeBuffers) {
+ for (i = 0; i < tokens->buffers.count; i++)
+ gss_release_buffer(&tmpMinor, &tokens->buffers.elements[i]);
+ }
+ GSSEAP_FREE(tokens->buffers.elements);
+ tokens->buffers.elements = NULL;
+ }
+ tokens->buffers.count = 0;
+
+ if (tokens->types != NULL) {
+ GSSEAP_FREE(tokens->types);
+ tokens->types = NULL;
+ }
+
+ *minor = 0;
+ return GSS_S_COMPLETE;
+}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * printf.c
- *
- * Copyright 2003, 2004, 2005, 2007, 2008 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.
- *
- *
- * Provide {,v}asprintf for platforms that don't have them.
- */
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t)((size_t)0 - 1))
-#endif
-#if defined(HAS_VA_COPY) || defined(va_copy)
-/* Do nothing. */
-#else
-#define va_copy(dest, src) ((dest) = (src))
-#endif
-#if 0 /* Given that this used to specify 'memcmp' instead of 'memcpy', it is safe to say it has not really been tested and we should not use it */
-/* Assume array type, but still simply copyable.
-
- There is, theoretically, the possibility that va_start will
- allocate some storage pointed to by the va_list, and in that case
- we'll just lose. If anyone cares, we could try to devise a test
- for that case. */
-#define va_copy(dest, src) memcpy(dest, src, sizeof(va_list)) /* was 'memcmp' which is almost certainly not right...*/
-#endif
-
-/* On error: BSD: Set *ret to NULL. GNU: *ret is undefined.
-
- Since we want to be able to use the GNU version directly, we need
- provide only the weaker guarantee in this version. */
-int
-vasprintf(char **ret, const char *format, va_list ap)
-{
- va_list ap2;
- char *str = NULL, *nstr;
- size_t len = 80;
- int len2;
-
- while (1) {
- if (len >= SIZE_MAX || len == 0)
- goto fail;
- nstr = realloc(str, len);
- if (nstr == NULL)
- goto fail;
- str = nstr;
-
- /* In theory, by c99 rules, vsnprintf() may destructively modify the passed in va_list. Therefore, we va_copy it first.
- * In practice, the va_list _isn't_ modified on windows and windows does not provide a native va_copy(), but the va_list
- * is just a pointer, which is why the va_copy() we defined above works. If there were a platform where vsnprintf, etc,
- * destructively modified the va_list _and_ it didn't define a va_copy() macro _and_ it didn't have a vasprintf(),
- * we could be in trouble. But I don't think I'll be losing any sleep. */
- va_copy(ap2, ap);
- len2 = vsnprintf(str, len, format, ap2);
- va_end(ap2);
- /* ISO C vsnprintf returns the needed length. Some old
- vsnprintf implementations return -1 on truncation. */
- if (len2 < 0) {
- /* Don't know how much space we need, just that we didn't
- supply enough; get a bigger buffer and try again. */
- if (len <= SIZE_MAX/2)
- len *= 2;
- else if (len < SIZE_MAX)
- len = SIZE_MAX;
- else
- goto fail;
- } else if ((unsigned int) len2 >= SIZE_MAX) {
- /* Need more space than we can request. */
- goto fail;
- } else if ((size_t) len2 >= len) {
- /* Need more space, but we know how much. */
- len = (size_t) len2 + 1;
- } else {
- /* Success! */
- break;
- }
- }
- /* We might've allocated more than we need, if we're still using
- the initial guess, or we got here by doubling. */
- if ((size_t) len2 < len - 1) {
- nstr = realloc(str, (size_t) len2 + 1);
- if (nstr)
- str = nstr;
- }
- *ret = str;
- return len2;
-
-fail:
- free(str);
- return -1;
-}
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_verify_mic(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_buffer_t message_buffer,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_wrap(OM_uint32 *minor,
gss_ctx_id_t ctx,
int conf_req_flag,
return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_wrap_iov(OM_uint32 *minor,
gss_ctx_id_t ctx,
int conf_req_flag,
return GSS_S_COMPLETE;
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_wrap_iov_length(OM_uint32 *minor,
gss_ctx_id_t ctx,
int conf_req_flag,
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_wrap_size_limit(OM_uint32 *minor,
gss_ctx_id_t ctx,
int conf_req_flag,