From: Luke Howard Date: Wed, 14 Sep 2011 06:11:37 +0000 (+1000) Subject: Merge branch 'windows' X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.orig;a=commitdiff_plain;h=5bf61a81066da96847e6317c00db9d4f96447db2;hp=a6c7d98460d495778ea61b180dfa7a38b385c1ba Merge branch 'windows' Conflicts: moonshot/configure.ac moonshot/mech_eap/Makefile.am moonshot/mech_eap/accept_sec_context.c moonshot/mech_eap/acquire_cred.c moonshot/mech_eap/add_cred.c moonshot/mech_eap/add_cred_with_password.c moonshot/mech_eap/canonicalize_name.c moonshot/mech_eap/compare_name.c moonshot/mech_eap/context_time.c moonshot/mech_eap/delete_name_attribute.c moonshot/mech_eap/delete_sec_context.c moonshot/mech_eap/display_name.c moonshot/mech_eap/display_name_ext.c moonshot/mech_eap/display_status.c moonshot/mech_eap/duplicate_name.c moonshot/mech_eap/eap_mech.c moonshot/mech_eap/export_name.c moonshot/mech_eap/export_name_composite.c moonshot/mech_eap/export_sec_context.c moonshot/mech_eap/get_mic.c moonshot/mech_eap/get_name_attribute.c moonshot/mech_eap/gssapiP_eap.h moonshot/mech_eap/import_name.c moonshot/mech_eap/import_sec_context.c moonshot/mech_eap/indicate_mechs.c moonshot/mech_eap/init_sec_context.c moonshot/mech_eap/inquire_attrs_for_mech.c moonshot/mech_eap/inquire_context.c moonshot/mech_eap/inquire_cred.c moonshot/mech_eap/inquire_cred_by_oid.c moonshot/mech_eap/inquire_mech_for_saslname.c moonshot/mech_eap/inquire_mechs_for_name.c moonshot/mech_eap/inquire_name.c moonshot/mech_eap/inquire_names_for_mech.c moonshot/mech_eap/inquire_saslname_for_mech.c moonshot/mech_eap/inquire_sec_context_by_oid.c moonshot/mech_eap/map_name_to_any.c moonshot/mech_eap/process_context_token.c moonshot/mech_eap/pseudo_random.c moonshot/mech_eap/release_any_name_mapping.c moonshot/mech_eap/release_cred.c moonshot/mech_eap/release_name.c moonshot/mech_eap/set_name_attribute.c moonshot/mech_eap/set_sec_context_option.c moonshot/mech_eap/store_cred.c moonshot/mech_eap/unwrap.c moonshot/mech_eap/unwrap_iov.c moonshot/mech_eap/util.h moonshot/mech_eap/util_context.c moonshot/mech_eap/util_cred.c moonshot/mech_eap/util_krb.c moonshot/mech_eap/util_name.c moonshot/mech_eap/util_tld.c moonshot/mech_eap/verify_mic.c moonshot/mech_eap/wrap.c moonshot/mech_eap/wrap_iov.c moonshot/mech_eap/wrap_iov_length.c moonshot/mech_eap/wrap_size_limit.c --- diff --git a/acinclude.m4 b/acinclude.m4 index 336332a..ea542db 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,5 +1,13 @@ 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= @@ -9,23 +17,22 @@ AC_ARG_WITH(krb5, [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([ @@ -136,7 +143,7 @@ AC_MSG_RESULT($found_shibsp) 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). @@ -144,11 +151,12 @@ if test x_$found_shibsp != x_yes; then ]) 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 @@ -161,6 +169,7 @@ AC_ARG_WITH(shibresolver, [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 @@ -170,11 +179,14 @@ for dir in $check_shibresolver_dir $prefix /usr /usr/local ; do 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). @@ -187,17 +199,53 @@ else 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) @@ -274,3 +322,43 @@ else 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 + diff --git a/configure.ac b/configure.ac index 5948d74..3d77b93 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ AC_GNU_SOURCE 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 @@ -71,13 +71,20 @@ AC_SUBST(TARGET_CFLAGS) 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 diff --git a/mech_eap/Makefile.am b/mech_eap/Makefile.am index 4ccdabe..ba6e8dd 100644 --- a/mech_eap/Makefile.am +++ b/mech_eap/Makefile.am @@ -6,8 +6,15 @@ gssinclude_HEADERS = gssapi_eap.h 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 @@ -21,16 +28,22 @@ mech_eap_la_CXXFLAGS = -Werror -Wall -Wunused-parameter 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 \ @@ -39,7 +52,6 @@ mech_eap_la_SOURCES = \ canonicalize_name.c \ compare_name.c \ context_time.c \ - delete_name_attribute.c \ delete_sec_context.c \ display_name.c \ display_name_ext.c \ @@ -47,10 +59,8 @@ mech_eap_la_SOURCES = \ 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 \ @@ -67,21 +77,17 @@ mech_eap_la_SOURCES = \ 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 \ @@ -90,6 +96,7 @@ mech_eap_la_SOURCES = \ util_krb.c \ util_lucid.c \ util_mech.c \ + util_moonshot.c \ util_name.c \ util_oid.c \ util_ordering.c \ @@ -102,12 +109,33 @@ mech_eap_la_SOURCES = \ 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 @@ -124,9 +152,6 @@ radius_ad_la_SOURCES = util_adshim.c endif endif -if TARGET_WINDOWS -mech_eap_la_LDFLAGS += -debug -else gsseap_err.h gsseap_err.c: gsseap_err.et $(COMPILE_ET) $< @@ -137,4 +162,3 @@ radsec_err.c: radsec_err.h clean-generic: rm -f gsseap_err.[ch] radsec_err.[ch] -endif diff --git a/mech_eap/TODO b/mech_eap/TODO index 0e4d9fd..567deed 100644 --- a/mech_eap/TODO +++ b/mech_eap/TODO @@ -1,12 +1,5 @@ - 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 diff --git a/mech_eap/accept_sec_context.c b/mech_eap/accept_sec_context.c index 7d3dfed..d010e34 100644 --- a/mech_eap/accept_sec_context.c +++ b/mech_eap/accept_sec_context.c @@ -36,7 +36,7 @@ */ #include "gssapiP_eap.h" -#ifdef GSSEAP_ENABLE_ACCEPTOR + #ifdef GSSEAP_ENABLE_REAUTH static OM_uint32 eapGssSmAcceptGssReauth(OM_uint32 *minor, @@ -431,10 +431,10 @@ createRadiusHandle(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; @@ -616,6 +616,40 @@ cleanup: } 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, @@ -628,20 +662,26 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, 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)) { @@ -652,11 +692,36 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, *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, @@ -688,42 +753,28 @@ 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; } @@ -769,6 +820,13 @@ static struct gss_eap_sm eapGssAcceptorSm[] = { 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, @@ -776,11 +834,11 @@ static struct gss_eap_sm eapGssAcceptorSm[] = { 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 { @@ -793,85 +851,54 @@ static struct gss_eap_sm eapGssAcceptorSm[] = { #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, @@ -921,18 +948,10 @@ gss_accept_sec_context(OM_uint32 *ACCEPTOR_PARAM(minor), 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, @@ -1014,4 +1033,62 @@ eapGssSmAcceptGssReauth(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; +} diff --git a/mech_eap/acquire_cred.c b/mech_eap/acquire_cred.c index 5ae30f9..ae2648e 100644 --- a/mech_eap/acquire_cred.c +++ b/mech_eap/acquire_cred.c @@ -36,7 +36,7 @@ #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, @@ -46,7 +46,7 @@ gss_acquire_cred(OM_uint32 *minor, 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); } diff --git a/mech_eap/acquire_cred_with_password.c b/mech_eap/acquire_cred_with_password.c index c0f4159..8e08358 100644 --- a/mech_eap/acquire_cred_with_password.c +++ b/mech_eap/acquire_cred_with_password.c @@ -36,7 +36,7 @@ #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, @@ -47,7 +47,21 @@ gssspi_acquire_cred_with_password(OM_uint32 *minor, 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; } diff --git a/mech_eap/add_cred.c b/mech_eap/add_cred.c index 81c74b2..64d97c0 100644 --- a/mech_eap/add_cred.c +++ b/mech_eap/add_cred.c @@ -41,7 +41,7 @@ * 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, @@ -71,7 +71,6 @@ gss_add_cred(OM_uint32 *minor, major = gssEapAcquireCred(minor, desired_name, - GSS_C_NO_BUFFER, time_req, &mechs, cred_usage, diff --git a/mech_eap/add_cred_with_password.c b/mech_eap/add_cred_with_password.c index 7b7ac1c..b982f0d 100644 --- a/mech_eap/add_cred_with_password.c +++ b/mech_eap/add_cred_with_password.c @@ -36,7 +36,7 @@ #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, @@ -50,7 +50,7 @@ gss_add_cred_with_password(OM_uint32 *minor, 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; @@ -67,18 +67,27 @@ gss_add_cred_with_password(OM_uint32 *minor, 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; } diff --git a/mech_eap/authorize_localname.c b/mech_eap/authorize_localname.c index ef5788e..0037e2b 100644 --- a/mech_eap/authorize_localname.c +++ b/mech_eap/authorize_localname.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/canonicalize_name.c b/mech_eap/canonicalize_name.c index a84dafb..5e66798 100644 --- a/mech_eap/canonicalize_name.c +++ b/mech_eap/canonicalize_name.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/compare_name.c b/mech_eap/compare_name.c index 7e0e499..edadf3e 100644 --- a/mech_eap/compare_name.c +++ b/mech_eap/compare_name.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/context_time.c b/mech_eap/context_time.c index c6d75a1..ae47d6c 100644 --- a/mech_eap/context_time.c +++ b/mech_eap/context_time.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/delete_name_attribute.c b/mech_eap/delete_name_attribute.c index 2d91283..fe0ff8f 100644 --- a/mech_eap/delete_name_attribute.c +++ b/mech_eap/delete_name_attribute.c @@ -36,12 +36,11 @@ #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; @@ -58,7 +57,4 @@ gss_delete_name_attribute(OM_uint32 *minor, GSSEAP_MUTEX_UNLOCK(&name->mutex); return major; -#else - return GSS_S_UNAVAILABLE; -#endif } diff --git a/mech_eap/delete_sec_context.c b/mech_eap/delete_sec_context.c index 9619ead..7913e45 100644 --- a/mech_eap/delete_sec_context.c +++ b/mech_eap/delete_sec_context.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/display_name.c b/mech_eap/display_name.c index b0cb4ba..2d87e66 100644 --- a/mech_eap/display_name.c +++ b/mech_eap/display_name.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/display_name_ext.c b/mech_eap/display_name_ext.c index ec9efbe..d6791d4 100644 --- a/mech_eap/display_name_ext.c +++ b/mech_eap/display_name_ext.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/display_status.c b/mech_eap/display_status.c index 89d8628..6eac550 100644 --- a/mech_eap/display_status.c +++ b/mech_eap/display_status.c @@ -43,7 +43,7 @@ struct gss_eap_status_info { }; void -gssEapDestroyStatusInfo(struct gss_eap_status_info* p) +gssEapDestroyStatusInfo(struct gss_eap_status_info *p) { struct gss_eap_status_info *next; @@ -65,10 +65,10 @@ static void 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) @@ -78,9 +78,9 @@ saveStatusInfoNoCopy(OM_uint32 minor, char *message) } next = &p->next; } - p = GSSEAP_CALLOC(1, sizeof(*p)); } + if (p == NULL) { if (message != NULL) GSSEAP_FREE(message); @@ -93,18 +93,17 @@ saveStatusInfoNoCopy(OM_uint32 minor, char *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; } @@ -115,6 +114,22 @@ getStatusInfo(OM_uint32 minor) 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; @@ -122,19 +137,19 @@ gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...) 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; @@ -143,18 +158,6 @@ gss_display_status(OM_uint32 *minor, 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); @@ -175,3 +178,26 @@ gss_display_status(OM_uint32 *minor, 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); +} diff --git a/mech_eap/duplicate_name.c b/mech_eap/duplicate_name.c index 1d65c16..303619e 100644 --- a/mech_eap/duplicate_name.c +++ b/mech_eap/duplicate_name.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/eap_mech.c b/mech_eap/eap_mech.c index 995a8ee..0b64df9 100644 --- a/mech_eap/eap_mech.c +++ b/mech_eap/eap_mech.c @@ -165,10 +165,10 @@ gssEapInitLibRadsec(OM_uint32 *minor) 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; @@ -188,11 +188,13 @@ gssEapInitiatorInit(void) #endif } -static void +void gssEapFinalize(void) { +#ifdef GSSEAP_ENABLE_ACCEPTOR OM_uint32 minor; gssEapAttrProvidersFinalize(&minor); +#endif eap_peer_unregister_methods(); } diff --git a/mech_eap/export_name.c b/mech_eap/export_name.c index 086bfca..d91033f 100644 --- a/mech_eap/export_name.c +++ b/mech_eap/export_name.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/export_name_composite.c b/mech_eap/export_name_composite.c index 7b70e35..b2a90ae 100644 --- a/mech_eap/export_name_composite.c +++ b/mech_eap/export_name_composite.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/export_sec_context.c b/mech_eap/export_sec_context.c index 98003d5..50f90f7 100644 --- a/mech_eap/export_sec_context.c +++ b/mech_eap/export_sec_context.c @@ -36,6 +36,7 @@ */ #include "gssapiP_eap.h" + #ifdef GSSEAP_ENABLE_ACCEPTOR static OM_uint32 gssEapExportPartialContext(OM_uint32 *minor, @@ -135,6 +136,7 @@ gssEapExportSecContext(OM_uint32 *minor, if (GSS_ERROR(major)) goto cleanup; } + #ifdef GSSEAP_ENABLE_ACCEPTOR /* * The partial context is only transmitted for unestablished acceptor @@ -208,7 +210,7 @@ cleanup: 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) diff --git a/mech_eap/get_mic.c b/mech_eap/get_mic.c index 1ac8d93..7161e9c 100644 --- a/mech_eap/get_mic.c +++ b/mech_eap/get_mic.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/get_name_attribute.c b/mech_eap/get_name_attribute.c index a77577b..a885823 100644 --- a/mech_eap/get_name_attribute.c +++ b/mech_eap/get_name_attribute.c @@ -36,7 +36,7 @@ * 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, @@ -46,7 +46,6 @@ gss_get_name_attribute(OM_uint32 *minor, gss_buffer_t display_value, int *more) { -#ifdef GSSEAP_ENABLE_ACCEPTOR OM_uint32 major; *minor = 0; @@ -65,7 +64,4 @@ gss_get_name_attribute(OM_uint32 *minor, GSSEAP_MUTEX_UNLOCK(&name->mutex); return major; -#else - return GSS_S_UNAVAILABLE; -#endif } diff --git a/mech_eap/gssapiP_eap.h b/mech_eap/gssapiP_eap.h index a2ce5d6..cd5315d 100644 --- a/mech_eap/gssapiP_eap.h +++ b/mech_eap/gssapiP_eap.h @@ -42,16 +42,27 @@ #include #include #include -#if defined(HAVE_UNISTD_H) +#ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_STDLIB_H #include +#endif +#ifdef HAVE_STDARG_H #include +#endif #include -#if defined(HAVE_SYS_PARAM_H) +#ifdef HAVE_SYS_PARAM_H #include #endif +#ifdef WIN32 +#ifndef MAXHOSTNAMELEN +# include +# define MAXHOSTNAMELEN NI_MAXHOST +#endif +#endif + /* GSS headers */ #include #include @@ -87,19 +98,16 @@ extern "C" { #include #include -////Because freeradius/autoconf.h is evil! -////#undef uint16_t -////#undef uint32_t -////#undef uint8_t #undef pid_t +/* libradsec headers */ #include #include #ifdef __cplusplus #undef operator } #endif -#endif /*GSSEAP_ENABLE_ACCEPTOR*/ +#endif /* GSSEAP_ENABLE_ACCEPTOR */ #include "gsseap_err.h" #include "radsec_err.h" @@ -127,14 +135,16 @@ struct gss_name_struct 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 @@ -146,11 +156,15 @@ struct gss_cred_id_struct 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; @@ -212,7 +226,7 @@ struct gss_ctx_id_struct 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 @@ -225,6 +239,8 @@ struct gss_ctx_id_struct #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 @@ -236,6 +252,36 @@ struct gss_ctx_id_struct #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, @@ -279,9 +325,18 @@ rfc4121Flags(gss_ctx_id_t ctx, int receiving); 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, @@ -289,6 +344,13 @@ gssEapExportSecContext(OM_uint32 *minor, gss_buffer_t token); +/* eap_mech.c */ +void +gssEapInitiatorInit(void); + +void +gssEapFinalize(void); + #ifdef __cplusplus } #endif diff --git a/mech_eap/gssapi_eap.h b/mech_eap/gssapi_eap.h index 9f713ec..588665b 100644 --- a/mech_eap/gssapi_eap.h +++ b/mech_eap/gssapi_eap.h @@ -71,6 +71,13 @@ extern gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA; 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. */ diff --git a/mech_eap/gsseap_err.et b/mech_eap/gsseap_err.et index 6bcfff0..f8ec5ef 100644 --- a/mech_eap/gsseap_err.et +++ b/mech_eap/gsseap_err.et @@ -82,6 +82,18 @@ error_code GSSEAP_CRED_EXPIRED, "Attributes indicate credentials 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 # diff --git a/mech_eap/import_name.c b/mech_eap/import_name.c index fbde67d..8049e01 100644 --- a/mech_eap/import_name.c +++ b/mech_eap/import_name.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/import_sec_context.c b/mech_eap/import_sec_context.c index 8854bf4..a2a712c 100644 --- a/mech_eap/import_sec_context.c +++ b/mech_eap/import_sec_context.c @@ -305,6 +305,7 @@ gssEapImportContext(OM_uint32 *minor, 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 @@ -316,11 +317,11 @@ gssEapImportContext(OM_uint32 *minor, if (GSS_ERROR(major)) return major; } -#endif #ifdef GSSEAP_DEBUG assert(remain == 0); #endif +#endif /* GSSEAP_ENABLE_ACCEPTOR */ major = GSS_S_COMPLETE; *minor = 0; @@ -328,7 +329,7 @@ gssEapImportContext(OM_uint32 *minor, 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) diff --git a/mech_eap/indicate_mechs.c b/mech_eap/indicate_mechs.c index 24b6f85..d4d275e 100644 --- a/mech_eap/indicate_mechs.c +++ b/mech_eap/indicate_mechs.c @@ -36,7 +36,7 @@ #include "gssapiP_eap.h" -OM_uint32 KRB5_CALLCONV +OM_uint32 GSSAPI_CALLCONV gss_indicate_mechs(OM_uint32 *minor, gss_OID_set *mech_set) { diff --git a/mech_eap/init_sec_context.c b/mech_eap/init_sec_context.c index 023f70e..e5bc107 100644 --- a/mech_eap/init_sec_context.c +++ b/mech_eap/init_sec_context.c @@ -195,15 +195,14 @@ extern int wpa_debug_level; #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; @@ -254,6 +253,11 @@ peerConfigInit(OM_uint32 *minor, 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; } @@ -341,7 +345,6 @@ initReady(OM_uint32 *minor, gss_ctx_id_t ctx, OM_uint32 reqFlags) static OM_uint32 initBegin(OM_uint32 *minor, - gss_cred_id_t cred, gss_ctx_id_t ctx, gss_name_t target, gss_OID mech, @@ -350,6 +353,7 @@ initBegin(OM_uint32 *minor, gss_channel_bindings_t chanBindings GSSEAP_UNUSED) { OM_uint32 major; + gss_cred_id_t cred = ctx->cred; assert(cred != GSS_C_NO_CREDENTIAL); @@ -634,7 +638,7 @@ eapGssSmInitIdentity(OM_uint32 *minor, 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, @@ -647,14 +651,13 @@ eapGssSmInitAuthenticate(OM_uint32 *minor, { 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; @@ -668,7 +671,7 @@ eapGssSmInitAuthenticate(OM_uint32 *minor, 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); @@ -715,6 +718,30 @@ cleanup: } 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, @@ -746,6 +773,33 @@ eapGssSmInitGssChannelBindings(OM_uint32 *minor, 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, @@ -774,39 +828,24 @@ 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; @@ -866,6 +905,13 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { }, { 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, @@ -873,10 +919,10 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { }, { 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 { @@ -889,18 +935,18 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { #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, @@ -913,60 +959,26 @@ gss_init_sec_context(OM_uint32 *minor, 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; @@ -1007,6 +1019,68 @@ gss_init_sec_context(OM_uint32 *minor, 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)) diff --git a/mech_eap/inquire_attrs_for_mech.c b/mech_eap/inquire_attrs_for_mech.c index ec37491..a359f68 100644 --- a/mech_eap/inquire_attrs_for_mech.c +++ b/mech_eap/inquire_attrs_for_mech.c @@ -45,8 +45,7 @@ #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, diff --git a/mech_eap/inquire_context.c b/mech_eap/inquire_context.c index 1c85662..d37818d 100644 --- a/mech_eap/inquire_context.c +++ b/mech_eap/inquire_context.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/inquire_cred.c b/mech_eap/inquire_cred.c index fc59e61..227ab16 100644 --- a/mech_eap/inquire_cred.c +++ b/mech_eap/inquire_cred.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/inquire_cred_by_mech.c b/mech_eap/inquire_cred_by_mech.c index 24da201..191902d 100644 --- a/mech_eap/inquire_cred_by_mech.c +++ b/mech_eap/inquire_cred_by_mech.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/inquire_cred_by_oid.c b/mech_eap/inquire_cred_by_oid.c index b8ff40e..2ad34ed 100644 --- a/mech_eap/inquire_cred_by_oid.c +++ b/mech_eap/inquire_cred_by_oid.c @@ -36,7 +36,7 @@ #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, @@ -45,15 +45,16 @@ static struct { }; #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) { @@ -66,7 +67,7 @@ gss_inquire_cred_by_oid(OM_uint32 *minor, 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, @@ -74,9 +75,6 @@ gss_inquire_cred_by_oid(OM_uint32 *minor, break; } } -#else - (void)i; - (void)desired_object; #endif GSSEAP_MUTEX_UNLOCK(&cred_handle->mutex); diff --git a/mech_eap/inquire_mech_for_saslname.c b/mech_eap/inquire_mech_for_saslname.c index c6411b1..bd518c0 100644 --- a/mech_eap/inquire_mech_for_saslname.c +++ b/mech_eap/inquire_mech_for_saslname.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/inquire_mechs_for_name.c b/mech_eap/inquire_mechs_for_name.c index 863a810..89c869c 100644 --- a/mech_eap/inquire_mechs_for_name.c +++ b/mech_eap/inquire_mechs_for_name.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/inquire_name.c b/mech_eap/inquire_name.c index f3eeadf..78b08a0 100644 --- a/mech_eap/inquire_name.c +++ b/mech_eap/inquire_name.c @@ -36,7 +36,7 @@ #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, @@ -64,11 +64,7 @@ gss_inquire_name(OM_uint32 *minor, 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); diff --git a/mech_eap/inquire_names_for_mech.c b/mech_eap/inquire_names_for_mech.c index 1f99eb7..0e60340 100644 --- a/mech_eap/inquire_names_for_mech.c +++ b/mech_eap/inquire_names_for_mech.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/inquire_saslname_for_mech.c b/mech_eap/inquire_saslname_for_mech.c index 3564c1c..d6d7c14 100644 --- a/mech_eap/inquire_saslname_for_mech.c +++ b/mech_eap/inquire_saslname_for_mech.c @@ -36,7 +36,7 @@ #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) diff --git a/mech_eap/inquire_sec_context_by_oid.c b/mech_eap/inquire_sec_context_by_oid.c index 537ff25..67b2ec8 100644 --- a/mech_eap/inquire_sec_context_by_oid.c +++ b/mech_eap/inquire_sec_context_by_oid.c @@ -104,7 +104,7 @@ static struct { }, }; -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, diff --git a/mech_eap/map_name_to_any.c b/mech_eap/map_name_to_any.c index 7d9c871..2a8a96c 100644 --- a/mech_eap/map_name_to_any.c +++ b/mech_eap/map_name_to_any.c @@ -32,7 +32,7 @@ #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, @@ -50,13 +50,7 @@ gss_map_name_to_any(OM_uint32 *minor, 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); diff --git a/mech_eap/mech_eap-noacceptor.exports b/mech_eap/mech_eap-noacceptor.exports new file mode 100644 index 0000000..4ecbc52 --- /dev/null +++ b/mech_eap/mech_eap-noacceptor.exports @@ -0,0 +1,52 @@ +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 diff --git a/mech_eap/mech_eap.exports b/mech_eap/mech_eap.exports index 12f7f54..10c7f81 100644 --- a/mech_eap/mech_eap.exports +++ b/mech_eap/mech_eap.exports @@ -5,6 +5,7 @@ gss_add_cred_with_password gss_canonicalize_name gss_compare_name gss_context_time +gss_delete_name_attribute gss_delete_sec_context gss_display_name gss_display_name_ext @@ -50,6 +51,10 @@ 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 diff --git a/mech_eap/mech_invoke.c b/mech_eap/mech_invoke.c index 2b7fb7e..bc9bba3 100644 --- a/mech_eap/mech_invoke.c +++ b/mech_eap/mech_invoke.c @@ -32,7 +32,7 @@ #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, diff --git a/mech_eap/process_context_token.c b/mech_eap/process_context_token.c index 7f0310d..02a4b6d 100644 --- a/mech_eap/process_context_token.c +++ b/mech_eap/process_context_token.c @@ -32,7 +32,7 @@ #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) diff --git a/mech_eap/pseudo_random.c b/mech_eap/pseudo_random.c index 684af94..476f1c5 100644 --- a/mech_eap/pseudo_random.c +++ b/mech_eap/pseudo_random.c @@ -59,7 +59,7 @@ #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, @@ -134,7 +134,7 @@ gss_pseudo_random(OM_uint32 *minor, 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) { diff --git a/mech_eap/release_any_name_mapping.c b/mech_eap/release_any_name_mapping.c index 08e4e10..d68fb45 100644 --- a/mech_eap/release_any_name_mapping.c +++ b/mech_eap/release_any_name_mapping.c @@ -32,7 +32,7 @@ #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, @@ -49,12 +49,7 @@ gss_release_any_name_mapping(OM_uint32 *minor, 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; diff --git a/mech_eap/release_cred.c b/mech_eap/release_cred.c index c7d3645..8bb7e54 100644 --- a/mech_eap/release_cred.c +++ b/mech_eap/release_cred.c @@ -36,7 +36,7 @@ #include "gssapiP_eap.h" -OM_uint32 KRB5_CALLCONV +OM_uint32 GSSAPI_CALLCONV gss_release_cred(OM_uint32 *minor, gss_cred_id_t *cred_handle) { diff --git a/mech_eap/release_name.c b/mech_eap/release_name.c index 0bbf537..3d527ce 100644 --- a/mech_eap/release_name.c +++ b/mech_eap/release_name.c @@ -36,7 +36,7 @@ #include "gssapiP_eap.h" -OM_uint32 KRB5_CALLCONV +OM_uint32 GSSAPI_CALLCONV gss_release_name(OM_uint32 *minor, gss_name_t *name) { diff --git a/mech_eap/release_oid.c b/mech_eap/release_oid.c index 4e0d4f0..291da40 100644 --- a/mech_eap/release_oid.c +++ b/mech_eap/release_oid.c @@ -36,7 +36,7 @@ #include "gssapiP_eap.h" -OM_uint32 +OM_uint32 GSSAPI_CALLCONV gss_internal_release_oid(OM_uint32 *minor, gss_OID *oid) { diff --git a/mech_eap/set_cred_option.c b/mech_eap/set_cred_option.c index bfffa1f..7bb9b7b 100644 --- a/mech_eap/set_cred_option.c +++ b/mech_eap/set_cred_option.c @@ -42,7 +42,7 @@ setCredRadiusConfigFile(OM_uint32 *minor, 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) { @@ -51,10 +51,8 @@ setCredRadiusConfigFile(OM_uint32 *minor, 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; @@ -66,7 +64,7 @@ setCredRadiusConfigStanza(OM_uint32 *minor, 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) { @@ -75,10 +73,8 @@ setCredRadiusConfigStanza(OM_uint32 *minor, 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; @@ -116,6 +112,15 @@ setCredFlag(OM_uint32 *minor, 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, @@ -136,13 +141,19 @@ static struct { { 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, diff --git a/mech_eap/set_name_attribute.c b/mech_eap/set_name_attribute.c index 961bdef..2ccf5d7 100644 --- a/mech_eap/set_name_attribute.c +++ b/mech_eap/set_name_attribute.c @@ -36,14 +36,13 @@ #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) { @@ -58,7 +57,4 @@ gss_set_name_attribute(OM_uint32 *minor, GSSEAP_MUTEX_UNLOCK(&name->mutex); return major; -#else - return GSS_S_UNAVAILABLE; -#endif } diff --git a/mech_eap/set_sec_context_option.c b/mech_eap/set_sec_context_option.c index 14278dc..f9fa3a6 100644 --- a/mech_eap/set_sec_context_option.c +++ b/mech_eap/set_sec_context_option.c @@ -36,7 +36,7 @@ #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, @@ -45,15 +45,17 @@ static struct { }; #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; @@ -66,7 +68,7 @@ gss_set_sec_context_option(OM_uint32 *minor, 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, @@ -74,10 +76,6 @@ gss_set_sec_context_option(OM_uint32 *minor, break; } } -#else - (void)i; - (void)desired_object; - (void)value; #endif if (pCtx != NULL && *pCtx == NULL) diff --git a/mech_eap/store_cred.c b/mech_eap/store_cred.c index 5beb730..d17a3ac 100644 --- a/mech_eap/store_cred.c +++ b/mech_eap/store_cred.c @@ -32,7 +32,7 @@ #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, diff --git a/mech_eap/unwrap.c b/mech_eap/unwrap.c index e3d5d6f..a185035 100644 --- a/mech_eap/unwrap.c +++ b/mech_eap/unwrap.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/unwrap_iov.c b/mech_eap/unwrap_iov.c index 30318c7..9e3ef19 100644 --- a/mech_eap/unwrap_iov.c +++ b/mech_eap/unwrap_iov.c @@ -319,7 +319,7 @@ unwrapStream(OM_uint32 *minor, 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; @@ -346,8 +346,7 @@ unwrapStream(OM_uint32 *minor, } 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)); @@ -529,7 +528,7 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor, return major; } -OM_uint32 KRB5_CALLCONV +OM_uint32 GSSAPI_CALLCONV gss_unwrap_iov(OM_uint32 *minor, gss_ctx_id_t ctx, int *conf_state, diff --git a/mech_eap/util.h b/mech_eap/util.h index 6e35fd4..ae83923 100644 --- a/mech_eap/util.h +++ b/mech_eap/util.h @@ -61,10 +61,10 @@ #ifndef _UTIL_H_ #define _UTIL_H_ 1 -#if defined(HAVE_SYS_PARAM_H) +#ifdef HAVE_SYS_PARAM_H #include #endif -#if defined(HAVE_STDINT_H) +#ifdef HAVE_STDINT_H #include #endif #include @@ -72,8 +72,9 @@ #include -#if defined(WIN32) -#define inline __inline +#ifdef WIN32 +#define inline __inline +#define snprintf _snprintf #endif #ifdef __cplusplus @@ -85,43 +86,24 @@ extern "C" { #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, @@ -132,6 +114,13 @@ duplicateBuffer(OM_uint32 *minor, 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) { @@ -212,12 +201,17 @@ enum gss_eap_token_type { #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); @@ -240,14 +234,26 @@ gssEapContextTime(OM_uint32 *minor, 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, @@ -255,6 +261,22 @@ gssEapAcquireCred(OM_uint32 *minor, 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 @@ -492,6 +514,17 @@ gssEapOidToSaslName(const gss_OID oid); 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 @@ -673,16 +706,29 @@ void 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); @@ -708,6 +754,18 @@ verifyTokenHeader(OM_uint32 *minor, #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; \ @@ -715,26 +773,30 @@ verifyTokenHeader(OM_uint32 *minor, } while (0) #ifdef WIN32 + #include -#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 -#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)) @@ -748,7 +810,8 @@ inline int win32_mutex_init(CRITICAL_SECTION* 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 @@ -899,6 +962,23 @@ gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data) 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 @@ -906,8 +986,8 @@ gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data) #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 diff --git a/mech_eap/util_attr.cpp b/mech_eap/util_attr.cpp index 01c3135..9496863 100644 --- a/mech_eap/util_attr.cpp +++ b/mech_eap/util_attr.cpp @@ -57,12 +57,16 @@ gssEapAttrProvidersInitInternal(void) 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 @@ -86,19 +90,19 @@ gssEapAttrProvidersInit(OM_uint32 *minor) 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]; diff --git a/mech_eap/util_attr.h b/mech_eap/util_attr.h index e3f3567..2af0850 100644 --- a/mech_eap/util_attr.h +++ b/mech_eap/util_attr.h @@ -53,8 +53,10 @@ typedef bool 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 diff --git a/mech_eap/util_context.c b/mech_eap/util_context.c index 8ff6c50..78c3636 100644 --- a/mech_eap/util_context.c +++ b/mech_eap/util_context.c @@ -52,12 +52,13 @@ gssEapAllocContext(OM_uint32 *minor, } 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 @@ -70,8 +71,7 @@ gssEapAllocContext(OM_uint32 *minor, 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; @@ -120,21 +120,22 @@ gssEapReleaseContext(OM_uint32 *minor, 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); @@ -155,6 +156,8 @@ gssEapMakeToken(OM_uint32 *minor, { 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) { @@ -232,3 +235,149 @@ gssEapContextTime(OM_uint32 *minor, 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); +} diff --git a/mech_eap/util_cred.c b/mech_eap/util_cred.c index 40a8c11..bd5bf66 100644 --- a/mech_eap/util_cred.c +++ b/mech_eap/util_cred.c @@ -36,20 +36,12 @@ #include "gssapiP_eap.h" -#if defined(WIN32) -/*This didn't work for me(Alexey) when Visual Studio 2005 Express is used: */ -#include -/*This didn't work for me(Kevin) when Visual Studio 2010 Express is used: */ -/*#include */ - -#if !defined(snprintf) -#define snprintf _snprintf -#endif - +#ifdef WIN32 +# include /* may need to use ShFolder.h instead */ +# include #else -#include +# include #endif -#include /* for BUFSIZ */ OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred) @@ -66,7 +58,7 @@ 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; } @@ -77,6 +69,18 @@ gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred) 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) { @@ -91,16 +95,15 @@ 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) { @@ -123,54 +126,55 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred) } 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"); @@ -195,16 +199,20 @@ readDefaultIdentityAndCreds(OM_uint32 *minor, 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) { @@ -222,16 +230,29 @@ cleanup: 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, @@ -241,10 +262,6 @@ gssEapAcquireCred(OM_uint32 *minor, { 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; @@ -278,21 +295,6 @@ gssEapAcquireCred(OM_uint32 *minor, 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); @@ -303,78 +305,6 @@ gssEapAcquireCred(OM_uint32 *minor, } 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) { @@ -394,12 +324,6 @@ gssEapAcquireCred(OM_uint32 *minor, 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; } @@ -424,6 +348,72 @@ gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech) 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, @@ -436,9 +426,16 @@ gssEapInquireCred(OM_uint32 *minor, 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) { @@ -463,7 +460,7 @@ gssEapInquireCred(OM_uint32 *minor, else major = gssEapIndicateMechs(minor, mechanisms); if (GSS_ERROR(major)) - return major; + goto cleanup; } if (cred->expiryTime == 0) { @@ -480,12 +477,263 @@ gssEapInquireCred(OM_uint32 *minor, } 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; } diff --git a/mech_eap/util_crypt.c b/mech_eap/util_crypt.c index f230da2..8d7a9d3 100644 --- a/mech_eap/util_crypt.c +++ b/mech_eap/util_crypt.c @@ -191,7 +191,7 @@ mapIov(krb5_context context, int dce_style, size_t ec, size_t rrc, */ 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; diff --git a/mech_eap/util_json.cpp b/mech_eap/util_json.cpp index 0133772..97eb1ed 100644 --- a/mech_eap/util_json.cpp +++ b/mech_eap/util_json.cpp @@ -322,6 +322,7 @@ JSONObject::number(void) const return json_number_value(m_obj); } +#ifdef HAVE_SHIBRESOLVER JSONObject JSONObject::ddf(DDF &ddf) { @@ -409,6 +410,7 @@ JSONObject::ddf(void) const return ddf; } +#endif /* HAVE_SHIBRESOLVER */ bool JSONObject::isObject(void) const { diff --git a/mech_eap/util_json.h b/mech_eap/util_json.h index e2c5e29..4ffecc8 100644 --- a/mech_eap/util_json.h +++ b/mech_eap/util_json.h @@ -42,9 +42,11 @@ #include #include -#include +#ifdef HAVE_SHIBRESOLVER +#include using namespace shibsp; +#endif namespace gss_eap_util { class JSONObject; @@ -88,7 +90,9 @@ namespace gss_eap_util { 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; @@ -123,7 +127,9 @@ namespace gss_eap_util { 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; diff --git a/mech_eap/util_krb.c b/mech_eap/util_krb.c index 73cf108..d56c7a8 100644 --- a/mech_eap/util_krb.c +++ b/mech_eap/util_krb.c @@ -80,18 +80,17 @@ cleanup: 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; @@ -280,7 +279,7 @@ rfc3961ChecksumTypeForKey(OM_uint32 *minor, #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; } diff --git a/mech_eap/util_moonshot.c b/mech_eap/util_moonshot.c new file mode 100644 index 0000000..75db452 --- /dev/null +++ b/mech_eap/util_moonshot.c @@ -0,0 +1,238 @@ +/* + * 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 + +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 */ diff --git a/mech_eap/util_name.c b/mech_eap/util_name.c index 0e7d004..6f038ef 100644 --- a/mech_eap/util_name.c +++ b/mech_eap/util_name.c @@ -81,7 +81,7 @@ gssEapAllocName(OM_uint32 *minor, gss_name_t *pName) } if (GSSEAP_MUTEX_INIT(&name->mutex) != 0) { - *minor = errno; + *minor = GSSEAP_GET_LAST_ERROR(); gssEapReleaseName(&tmpMinor, &name); return GSS_S_FAILURE; } @@ -427,19 +427,18 @@ gssEapImportNameInternal(OM_uint32 *minor, 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; @@ -569,16 +568,14 @@ gssEapExportNameInternal(OM_uint32 *minor, 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) { @@ -678,15 +675,13 @@ gssEapCanonicalizeName(OM_uint32 *minor, 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; diff --git a/mech_eap/util_radius.h b/mech_eap/util_radius.h index 82d12cb..d209347 100644 --- a/mech_eap/util_radius.h +++ b/mech_eap/util_radius.h @@ -154,7 +154,7 @@ OM_uint32 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 */ @@ -171,9 +171,6 @@ gssEapRadiusMapError(OM_uint32 *minor, #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 diff --git a/mech_eap/util_saml.cpp b/mech_eap/util_saml.cpp index 41bedad..9a3862a 100644 --- a/mech_eap/util_saml.cpp +++ b/mech_eap/util_saml.cpp @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -322,8 +323,17 @@ gss_eap_saml_assertion_provider::prefix(void) const 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 diff --git a/mech_eap/util_shib.cpp b/mech_eap/util_shib.cpp index 311de41..4c268ec 100644 --- a/mech_eap/util_shib.cpp +++ b/mech_eap/util_shib.cpp @@ -49,7 +49,13 @@ * Local attribute provider implementation. */ +#include "gssapiP_eap.h" + #include +#ifndef HAVE_OPENSAML +#include +#include +#endif #include @@ -61,14 +67,16 @@ #include -#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) { @@ -143,12 +151,33 @@ gss_eap_shib_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager, gss_release_buffer(&minor, &mechName); } +#ifdef HAVE_OPENSAML const gss_eap_saml_assertion_provider *saml; saml = static_cast (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 + (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(); @@ -436,8 +465,7 @@ gss_eap_shib_attr_provider::init(void) bool ret = false; try { - if (SPConfig::getConfig().getFeatures() == 0) - ret = ShibbolethResolver::init(); + ret = ShibbolethResolver::init(); } catch (exception &e) { } diff --git a/mech_eap/util_sm.c b/mech_eap/util_sm.c index bf216dd..8d36085 100644 --- a/mech_eap/util_sm.c +++ b/mech_eap/util_sm.c @@ -98,29 +98,22 @@ static OM_uint32 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; } @@ -130,64 +123,26 @@ makeErrorToken(OM_uint32 *minor, 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 @@ -205,11 +160,10 @@ gssEapSmStep(OM_uint32 *minor, 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; @@ -250,17 +204,17 @@ gssEapSmStep(OM_uint32 *minor, 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]; @@ -286,8 +240,8 @@ gssEapSmStep(OM_uint32 *minor, 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; @@ -295,8 +249,8 @@ gssEapSmStep(OM_uint32 *minor, break; } processToken = 1; - innerInputToken = &innerInputTokens->elements[j]; - inputTokenType = &inputTokenTypes[j]; + innerInputToken = &inputTokens.buffers.elements[j]; + inputTokenType = &inputTokens.types[j]; } } if (GSS_ERROR(major)) @@ -324,18 +278,18 @@ gssEapSmStep(OM_uint32 *minor, 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; } @@ -348,13 +302,13 @@ gssEapSmStep(OM_uint32 *minor, } } - 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; @@ -368,25 +322,21 @@ gssEapSmStep(OM_uint32 *minor, 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; @@ -409,13 +359,13 @@ gssEapSmStep(OM_uint32 *minor, 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; } diff --git a/mech_eap/util_tld.c b/mech_eap/util_tld.c index 7679233..f6feeba 100644 --- a/mech_eap/util_tld.c +++ b/mech_eap/util_tld.c @@ -30,130 +30,126 @@ * 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; } diff --git a/mech_eap/util_token.c b/mech_eap/util_token.c index a929198..9b05560 100644 --- a/mech_eap/util_token.c +++ b/mech_eap/util_token.c @@ -59,8 +59,7 @@ 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; @@ -70,10 +69,8 @@ gssEapEncodeInnerTokens(OM_uint32 *minor, 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; } /* @@ -91,22 +88,20 @@ gssEapEncodeInnerTokens(OM_uint32 *minor, 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); @@ -126,21 +121,16 @@ cleanup: 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; @@ -152,7 +142,7 @@ gssEapDecodeInnerTokens(OM_uint32 *minor, do { OM_uint32 *ntypes; - gss_buffer_desc extension; + gss_buffer_desc tokenBuffer, *newTokenBuffers; if (remain < 8) { major = GSS_S_DEFECTIVE_TOKEN; @@ -160,42 +150,61 @@ gssEapDecodeInnerTokens(OM_uint32 *minor, 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; } @@ -415,3 +424,70 @@ verifyTokenHeader(OM_uint32 *minor, *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; +} diff --git a/mech_eap/vasprintf.c b/mech_eap/vasprintf.c deleted file mode 100644 index 85d4fb1..0000000 --- a/mech_eap/vasprintf.c +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- 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 -#include -#include -#include - -#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; -} diff --git a/mech_eap/verify_mic.c b/mech_eap/verify_mic.c index 89bb081..d72c57e 100644 --- a/mech_eap/verify_mic.c +++ b/mech_eap/verify_mic.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/wrap.c b/mech_eap/wrap.c index ef1b5fc..2e27fb3 100644 --- a/mech_eap/wrap.c +++ b/mech_eap/wrap.c @@ -36,7 +36,7 @@ #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, diff --git a/mech_eap/wrap_iov.c b/mech_eap/wrap_iov.c index 0162916..a40b980 100644 --- a/mech_eap/wrap_iov.c +++ b/mech_eap/wrap_iov.c @@ -336,7 +336,7 @@ cleanup: 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, diff --git a/mech_eap/wrap_iov_length.c b/mech_eap/wrap_iov_length.c index 9ee1364..65bb6ec 100644 --- a/mech_eap/wrap_iov_length.c +++ b/mech_eap/wrap_iov_length.c @@ -196,7 +196,7 @@ gssEapWrapIovLength(OM_uint32 *minor, 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, diff --git a/mech_eap/wrap_size_limit.c b/mech_eap/wrap_size_limit.c index b5f9cdf..d11fd63 100644 --- a/mech_eap/wrap_size_limit.c +++ b/mech_eap/wrap_size_limit.c @@ -36,7 +36,7 @@ #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,