Revert "Support EAP-TLS in Moonshot (requires OpenSSL)"
authorLuke Howard <lukeh@padl.com>
Mon, 28 Nov 2011 15:01:39 +0000 (02:01 +1100)
committerLuke Howard <lukeh@padl.com>
Mon, 28 Nov 2011 15:01:39 +0000 (02:01 +1100)
This reverts commit 2ef42df0ecea8745a678fe26ff9b16072b93586b.

1  2 
acinclude.m4
configure.ac
libeap/Makefile.am
mech_eap/Makefile.am
mech_eap/gssapiP_eap.h
mech_eap/gssapi_eap.h
mech_eap/init_sec_context.c
mech_eap/set_cred_option.c
mech_eap/util.h
mech_eap/util_cred.c

diff --cc acinclude.m4
index 401ad2a,0000000..ff06090
mode 100644,000000..100644
--- /dev/null
@@@ -1,399 -1,0 +1,361 @@@
-       EAP_LIBS="-leap -lutils -lcrypto -ltls -lssl";
 +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=
 +found_krb5="no"
 +AC_ARG_WITH(krb5,
 +    AC_HELP_STRING([--with-krb5],
 +       [Use krb5 (in specified installation directory)]),
 +    [check_krb5_dir="$withval"],
 +    [check_krb5_dir=])
 +for dir in $check_krb5_dir $prefix /usr /usr/local ; do
 +   krb5dir="$dir"
 +   if test -x "$dir/bin/krb5-config"; then
 +     found_krb5="yes";
 +     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";
 +      AC_MSG_RESULT([yes])
 +     else
 +        KRB5_CFLAGS=`$dir/bin/krb5-config gssapi --cflags`;
 +        KRB5_LIBS=`$dir/bin/krb5-config gssapi --libs`
 +AC_MSG_RESULT([yes])
 +        AC_PATH_PROG(COMPILE_ET, [compile_et], [compile_et], [$dir/bin$PATH_SEPARATOr])
 +     fi
 +     break;
 +   fi
 +done
 +if test x_$found_krb5 != x_yes; then
 +   AC_MSG_RESULT($found_krb5)
 +   AC_MSG_ERROR([
 +----------------------------------------------------------------------
 +  Cannot find GSS-API/Kerberos libraries.
 +
 +  Please install MIT or Heimdal or specify installation directory with
 +  --with-krb5=(dir).
 +----------------------------------------------------------------------
 +])
 +else
 +      printf "Kerberos found in $krb5dir\n";
 +      AC_SUBST(KRB5_CFLAGS)
 +      AC_SUBST(KRB5_LIBS)
 +      AC_SUBST(COMPILE_ET)
 +      AC_CHECK_LIB(krb5, GSS_C_NT_COMPOSITE_EXPORT, [AC_DEFINE_UNQUOTED([HAVE_GSS_C_NT_COMPOSITE_EXPORT], 1, [Define if GSS-API library supports recent naming extensions draft])], [], "$KRB5_LIBS")
 +      AC_CHECK_LIB(krb5, gss_inquire_attrs_for_mech, [AC_DEFINE_UNQUOTED([HAVE_GSS_INQUIRE_ATTRS_FOR_MECH], 1, [Define if GSS-API library supports RFC 5587])], [], "$KRB5_LIBS")
 +      AC_CHECK_LIB(krb5, gss_krb5_import_cred, [AC_DEFINE_UNQUOTED([HAVE_GSS_KRB5_IMPORT_CRED], 1, [Define if GSS-API library supports gss_krb5_import_cred])], [], "$KRB5_LIBS")
 +      AC_CHECK_LIB(krb5, heimdal_version, [AC_DEFINE_UNQUOTED([HAVE_HEIMDAL_VERSION], 1, [Define if building against Heimdal Kerberos implementation]), heimdal=yes], [heimdal=no], "$KRB5_LIBS")
 +      AM_CONDITIONAL(HEIMDAL, test "x$heimdal" != "xno")
 +fi
 +])dnl
 +
 +AC_DEFUN([AX_CHECK_EAP],
 +[AC_MSG_CHECKING(for EAP implementation)
 +EAP_DIR=
 +found_eap="no"
 +AC_ARG_WITH(eap,
 +    AC_HELP_STRING([--with-eap],
 +       [Use eap (in specified installation directory)]),
 +    [check_eap_dir="$withval"],
 +    [check_eap_dir=])
 +for dir in $check_eap_dir $prefix /usr /usr/local ../libeap ; do
 +   eapdir="$dir"
 +   if test -f "$dir/src/eap_peer/eap.h"; then
 +     found_eap="yes";
 +     EAP_DIR="${eapdir}"
 +     EAP_CFLAGS="-I$eapdir/src/common -I$eapdir/src -I$eapdir/src/utils";
 +     break;
 +   fi
 +done
 +AC_MSG_RESULT($found_eap)
 +if test x_$found_eap != x_yes; then
 +   AC_MSG_ERROR([
 +----------------------------------------------------------------------
 +  Cannot find EAP libraries.
 +
 +  Please install wpa_supplicant or specify installation directory with
 +  --with-eap=(dir).
 +----------------------------------------------------------------------
 +])
 +else
 +      printf "EAP found in $eapdir\n";
 +      EAP_CFLAGS="$EAP_CFLAGS \
 +-DEAP_TLS \
 +-DEAP_PEAP \
 +-DEAP_TTLS \
 +-DEAP_MD5 \
 +-DEAP_MSCHAPv2 \
 +-DEAP_GTC \
 +-DEAP_OTP \
 +-DEAP_LEAP \
 +-DEAP_PSK \
 +-DEAP_PAX \
 +-DEAP_SAKE \
 +-DEAP_GPSK \
 +-DEAP_GPSK_SHA256 \
 +-DEAP_SERVER_IDENTITY \
 +-DEAP_SERVER_TLS \
 +-DEAP_SERVER_PEAP \
 +-DEAP_SERVER_TTLS \
 +-DEAP_SERVER_MD5 \
 +-DEAP_SERVER_MSCHAPV2 \
 +-DEAP_SERVER_GTC \
 +-DEAP_SERVER_PSK \
 +-DEAP_SERVER_PAX \
 +-DEAP_SERVER_SAKE \
 +-DEAP_SERVER_GPSK \
 +-DEAP_SERVER_GPSK_SHA256 \
 +-DIEEE8021X_EAPOL";
- AC_DEFUN([AX_CHECK_OPENSSL],
- [AC_MSG_CHECKING(for OpenSSL)
- OPENSSL_DIR=
- found_openssl="no"
- AC_ARG_WITH(openssl,
-     AC_HELP_STRING([--with-openssl],
-        [Use OpenSSL (in specified installation directory)]),
-     [check_openssl_dir="$withval"],
-     [check_openssl_dir=])
- for dir in $check_openssl_dir $prefix /usr /usr/local ; do
-    openssldir="$dir"
-    if test -f "$dir/include/openssl/opensslv.h"; then
-      found_openssl="yes";
-      OPENSSL_DIR="${openssldir}"
-      OPENSSL_CFLAGS="-I$openssldir/include";
-      break;
-    fi
- done
- AC_MSG_RESULT($found_openssl)
- if test x_$found_openssl != x_yes; then
-    AC_MSG_ERROR([
- ----------------------------------------------------------------------
-   Cannot find OpenSSL libraries.
-   Please install libssl or specify installation directory with
-   --with-openssl=(dir).
- ----------------------------------------------------------------------
- ])
- else
-       printf "OpenSSL found in $openssldir\n";
-       OPENSSL_LIBS="-lssl -lcrypto";
-       OPENSSL_LDFLAGS="-L$openssldir/lib";
-       AC_SUBST(OPENSSL_CFLAGS)
-       AC_SUBST(OPENSSL_LDFLAGS)
-       AC_SUBST(OPENSSL_LIBS)
- fi
- ])dnl
++      EAP_LIBS="-leap -lutils -lcrypto -ltls";
 +      EAP_LDFLAGS="-L$eapdir/eap_example -L$eapdir/src/utils -L$eapdir/src/crypto -L$eapdir/src/tls";
 +      AC_SUBST(EAP_CFLAGS)
 +      AC_SUBST(EAP_LDFLAGS)
 +      AC_SUBST(EAP_LIBS)
 +fi
 +])dnl
 +
 +AC_DEFUN([AX_CHECK_SHIBSP],
 +[AC_MSG_CHECKING(for Shibboleth implementation)
 +SHIBSP_DIR=
 +found_shibsp="no"
 +AC_ARG_WITH(shibsp,
 +    AC_HELP_STRING([--with-shibsp],
 +       [Use shibspboleth (in specified installation directory)]),
 +    [check_shibsp_dir="$withval"],
 +    [check_shibsp_dir=])
 +for dir in $check_shibsp_dir $prefix /usr /usr/local ; do
 +   shibspdir="$dir"
 +   if test -f "$dir/include/shibsp/SPConfig.h"; then
 +     found_shibsp="yes";
 +     SHIBSP_DIR="${shibspdir}"
 +     SHIBSP_CXXFLAGS="-I$shibspdir/include";
 +     break;
 +   fi
 +done
 +AC_MSG_RESULT($found_shibsp)
 +if test x_$found_shibsp != x_yes; then
 +   AC_MSG_ERROR([
 +----------------------------------------------------------------------
 +  Cannot find Shibboleth libraries.
 +
 +  Please install Shibboleth or specify installation directory with
 +  --with-shibsp=(dir).
 +----------------------------------------------------------------------
 +])
 +else
 +      printf "Shibboleth found in $shibspdir\n";
 +      SHIBSP_LIBS="-lshibsp -lsaml -lxml-security-c -lxmltooling -lxerces-c";
 +      SHIBSP_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
 +
 +AC_DEFUN([AX_CHECK_SHIBRESOLVER],
 +[AC_MSG_CHECKING(for Shibboleth resolver implementation)
 +SHIBRESOLVER_DIR=
 +found_shibresolver="no"
 +AC_ARG_WITH(shibresolver,
 +    AC_HELP_STRING([--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
 +     found_shibresolver="yes";
 +     SHIBRESOLVER_DIR="${shibresolverdir}"
 +     SHIBRESOLVER_CXXFLAGS="-I$shibresolverdir/include";
 +     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_WARN([
 +----------------------------------------------------------------------
 +  Cannot find Shibboleth resolver libraries, building without
 +  Shibboleth support.
 +
 +  Please install Shibboleth or specify installation directory with
 +  --with-shibresolver=(dir).
 +----------------------------------------------------------------------
 +])
 +else
 +      printf "Shibboleth resolver found in $shibresolverdir\n";
 +      SHIBRESOLVER_LIBS="-lshibresolver";
 +      SHIBRESOLVER_LDFLAGS="-L$shibresolverdir/lib";
 +      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_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)
 +RADSEC_DIR=
 +found_radsec="no"
 +AC_ARG_WITH(radsec,
 +    AC_HELP_STRING([--with-radsec],
 +       [Use radsec (in specified installation directory)]),
 +    [check_radsec_dir="$withval"],
 +    [check_radsec_dir=])
 +for dir in $check_radsec_dir $prefix /usr /usr/local ; do
 +   radsecdir="$dir"
 +   if test -f "$dir/include/radsec/radsec.h"; then
 +     found_radsec="yes";
 +     RADSEC_DIR="${radsecdir}"
 +     RADSEC_CFLAGS="-I$radsecdir/include";
 +     break;
 +   fi
 +done
 +AC_MSG_RESULT($found_radsec)
 +if test x_$found_radsec != x_yes; then
 +   AC_MSG_ERROR([
 +----------------------------------------------------------------------
 +  Cannot find radsec libraries.
 +
 +  Please install libradsec or specify installation directory with
 +  --with-radsec=(dir).
 +----------------------------------------------------------------------
 +])
 +else
 +      printf "radsec found in $radsecdir\n";
 +      RADSEC_LIBS="-lradsec";
 +      RADSEC_LDFLAGS="-L$radsecdir/lib";
 +      AC_SUBST(RADSEC_CFLAGS)
 +      AC_SUBST(RADSEC_LDFLAGS)
 +      AC_SUBST(RADSEC_LIBS)
 +fi
 +])dnl
 +
 +AC_DEFUN([AX_CHECK_JANSSON],
 +[AC_MSG_CHECKING(for jansson)
 +JANSSON_DIR=
 +found_jansson="no"
 +AC_ARG_WITH(jansson,
 +    AC_HELP_STRING([--with-jansson],
 +       [Use jansson (in specified installation directory)]),
 +    [check_jansson_dir="$withval"],
 +    [check_jansson_dir=])
 +for dir in $check_jansson_dir $prefix /usr /usr/local ; do
 +   janssondir="$dir"
 +   if test -f "$dir/include/jansson.h"; then
 +     found_jansson="yes";
 +     JANSSON_DIR="${janssondir}"
 +     JANSSON_CFLAGS="-I$janssondir/include";
 +     break;
 +   fi
 +done
 +AC_MSG_RESULT($found_jansson)
 +if test x_$found_jansson != x_yes; then
 +   AC_MSG_ERROR([
 +----------------------------------------------------------------------
 +  Cannot find jansson libraries.
 +
 +  Please install libjansson or specify installation directory with
 +  --with-jansson=(dir).
 +----------------------------------------------------------------------
 +])
 +else
 +      printf "jansson found in $janssondir\n";
 +      JANSSON_LIBS="-ljansson";
 +      JANSSON_LDFLAGS="-L$janssondir/lib";
 +      AC_SUBST(JANSSON_CFLAGS)
 +      AC_SUBST(JANSSON_LDFLAGS)
 +      AC_SUBST(JANSSON_LIBS)
 +fi
 +])dnl
 +
 +AC_DEFUN([AX_CHECK_LIBMOONSHOT],
 +[AC_MSG_CHECKING(for Moonshot identity selector implementation)
 +LIBMOONSHOT_DIR=
 +LIBMOONSHOT_CFLAGS=
 +LIBMOONSHOT_LDFLAGS=
 +LIBMOONSHOT_LIBS=
 +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 ; 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
 +    printf "libmoonshot found in $libmoonshotdir\n";
 +    LIBMOONSHOT_LIBS="-lmoonshot";
 +    LIBMOONSHOT_LDFLAGS="-L$libmoonshot/lib";
 +    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
 +    AC_SUBST(LIBMOONSHOT_CFLAGS)
 +    AC_SUBST(LIBMOONSHOT_LDFLAGS)
 +    AC_SUBST(LIBMOONSHOT_LIBS)
 +    AM_CONDITIONAL(LIBMOONSHOT, test "x$found_libmoonshot" != "xno")
 +])dnl
 +
diff --cc configure.ac
index 1049dd7,0000000..4297345
mode 100644,000000..100644
--- /dev/null
@@@ -1,94 -1,0 +1,92 @@@
- AX_CHECK_OPENSSL
 +AC_PREREQ([2.61])
 +AC_INIT([mech_eap], [0.1], [bugs@project-moonshot.org])
 +AC_CONFIG_MACRO_DIR([m4])
 +AC_CONFIG_AUX_DIR([build-aux])
 +
 +dnl AM_INIT_AUTOMAKE([silent-rules])
 +AC_USE_SYSTEM_EXTENSIONS
 +AM_INIT_AUTOMAKE
 +AM_PROG_CC_C_O
 +AM_MAINTAINER_MODE()
 +LT_PREREQ([2.2])
 +LT_INIT([dlopen disable-static win32-dll])
 +
 +dnl AC_PROG_CC
 +AC_PROG_CXX
 +AC_CONFIG_HEADERS([config.h])
 +AC_CHECK_HEADERS(stdarg.h stdio.h stdint.h sys/param.h)
 +AC_REPLACE_FUNCS(vasprintf)
 +
 +dnl Check if we're on Solaris and set CFLAGS accordingly
 +dnl AC_CANONICAL_TARGET
 +dnl case "${target_os}" in
 +dnl   solaris*)
 +dnl     TARGET_CFLAGS="-DSYS_SOLARIS9 -D_POSIX_PTHREAD_SEMANTICS"
 +dnl     if test "$GCC" != yes ; then
 +dnl       TARGET_CFLAGS="$TARGET_CFLAGS -mt"
 +dnl     else
 +dnl       TARGET_CFLAGS="$TARGET_CFLAGS -pthreads"
 +dnl     fi
 +dnl     TARGET_LDFLAGS="-lpthread -lsocket -lnsl"
 +dnl     ;;
 +dnl   *)
 +dnl     TARGET_CFLAGS="-Wall -pedantic -pthread"
 +dnl     TARGET_LDFLAGS=""
 +dnl   esac
 +
 +reauth=no
 +AC_ARG_ENABLE(reauth,
 +  [  --enable-reauth whether to enable fast reauthentication protocol: yes/no; default no ],
 +  [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then
 +      reauth=$enableval
 +    else
 +      echo "--enable-reauth argument must be yes or no"
 +      exit -1
 +    fi
 +  ])
 +
 +if test "x$reauth" = "xyes" ; then
 +  echo "Fast reauthentication protocol enabled"
 +  TARGET_CFLAGS="$TARGET_CFLAGS -DGSSEAP_ENABLE_REAUTH"
 +fi
 +AM_CONDITIONAL(GSSEAP_ENABLE_REAUTH, test "x$reauth" != "xno")
 +
 +acceptor=yes
 +AC_ARG_ENABLE(acceptor,
 +  [  --enable-acceptor whether to enable acceptor codepaths: yes/no; default yes ],
 +  [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then
 +      acceptor=$enableval
 +    else
 +      echo "--enable-acceptor argument must be yes or no"
 +      exit -1
 +    fi
 +  ])
 +
 +if test "x$acceptor" = "xyes" ; then
 +  echo "acceptor enabled"
 +  TARGET_CFLAGS="$TARGET_CFLAGS -DGSSEAP_ENABLE_ACCEPTOR"
 +fi
 +AM_CONDITIONAL(GSSEAP_ENABLE_ACCEPTOR, test "x$acceptor" != "xno")
 +
 +AC_SUBST(TARGET_CFLAGS)
 +AC_SUBST(TARGET_LDFLAGS)
 +AX_CHECK_WINDOWS
 +AX_CHECK_KRB5
 +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
 +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
 +                        mech_eap.spec])
 +AC_OUTPUT
index 8cc9fb5,0000000..163e4ff
mode 100644,000000..100644
--- /dev/null
@@@ -1,191 -1,0 +1,211 @@@
- AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/eap_example -I$(srcdir)/src/utils @OPENSSL_CFLAGS@
 +AUTOMAKE_OPTIONS = foreign
 +
-       src/eap_common/chap.h \
++AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/eap_example -I$(srcdir)/src/utils 
 +noinst_HEADERS = \
 +      src/common/defs.h \
 +      src/common/eapol_common.h \
 +      src/common/ieee802_11_common.h \
 +      src/common/ieee802_11_defs.h \
 +      src/common/privsep_commands.h \
 +      src/common/version.h \
 +      src/common/wpa_common.h \
 +      src/common/wpa_ctrl.h
 +
 +EXTRA_DIST = src/tls/libtommath.c
 +
 +SOURCES_BOTH = src/eap_common/eap_peap_common.c
 +SOURCES_BOTH += src/eap_common/eap_psk_common.c
 +SOURCES_BOTH += src/eap_common/eap_pax_common.c
 +SOURCES_BOTH += src/eap_common/eap_sake_common.c
 +SOURCES_BOTH += src/eap_common/eap_gpsk_common.c
 +SOURCES_BOTH += src/eap_common/chap.c \
- CFLAGS += -DCONFIG_INTERNAL_SHA1
- CFLAGS += -DEAP_TLS_OPENSSL
- CFLAGS += -DPKCS12_FUNCS
++src/eap_common/chap.h \
 +      src/eap_common/eap_common.h \
 +      src/eap_common/eap_defs.h \
 +      src/eap_common/eap_fast_common.h \
 +      src/eap_common/eap_gpsk_common.h \
 +      src/eap_common/eap_ikev2_common.h \
 +      src/eap_common/eap_pax_common.h \
 +      src/eap_common/eap_peap_common.h \
 +      src/eap_common/eap_psk_common.h \
 +      src/eap_common/eap_pwd_common.h \
 +      src/eap_common/eap_sake_common.h \
 +      src/eap_common/eap_sim_common.h \
 +      src/eap_common/eap_tlv_common.h \
 +      src/eap_common/eap_ttls.h \
 +      src/eap_common/eap_wsc_common.h \
 +      src/eap_common/ikev2_common.h
 +
 +
 +SOURCES_peer = src/eap_peer/eap_tls.c
 +SOURCES_peer += src/eap_peer/eap_peap.c
 +SOURCES_peer += src/eap_peer/eap_ttls.c
 +SOURCES_peer += src/eap_peer/eap_md5.c
 +SOURCES_peer += src/eap_peer/eap_mschapv2.c
 +SOURCES_peer += src/eap_peer/mschapv2.c
 +SOURCES_peer += src/eap_peer/eap_otp.c
 +SOURCES_peer += src/eap_peer/eap_gtc.c
 +SOURCES_peer += src/eap_peer/eap_leap.c
 +SOURCES_peer += src/eap_peer/eap_psk.c
 +SOURCES_peer += src/eap_peer/eap_pax.c
 +SOURCES_peer += src/eap_peer/eap_sake.c
 +SOURCES_peer += src/eap_peer/eap_gpsk.c
 +SOURCES_peer += src/eap_peer/eap.c
 +SOURCES_peer += src/eap_common/eap_common.c
 +SOURCES_peer += src/eap_peer/eap_methods.c
 +SOURCES_peer += src/eap_peer/eap_tls_common.c \
 +      src/eap_peer/eap_config.h \
 +      src/eap_peer/eap_fast_pac.h \
 +      src/eap_peer/eap.h \
 +      src/eap_peer/eap_i.h \
 +      src/eap_peer/eap_methods.h \
 +      src/eap_peer/eap_tls_common.h \
 +      src/eap_peer/ikev2.h \
 +      src/eap_peer/mschapv2.h \
 +      src/eap_peer/tncc.h
 +
 +CFLAGS += -DEAP_TLS
 +CFLAGS += -DEAP_PEAP
 +CFLAGS += -DEAP_TTLS
 +CFLAGS += -DEAP_MD5
 +CFLAGS += -DEAP_MSCHAPv2
 +CFLAGS += -DEAP_GTC
 +CFLAGS += -DEAP_OTP
 +CFLAGS += -DEAP_LEAP
 +CFLAGS += -DEAP_PSK
 +CFLAGS += -DEAP_PAX
 +CFLAGS += -DEAP_SAKE
 +CFLAGS += -DEAP_GPSK -DEAP_GPSK_SHA256
 +
 +CFLAGS += -DEAP_SERVER_IDENTITY
 +CFLAGS += -DEAP_SERVER_TLS
 +CFLAGS += -DEAP_SERVER_PEAP
 +CFLAGS += -DEAP_SERVER_TTLS
 +CFLAGS += -DEAP_SERVER_MD5
 +CFLAGS += -DEAP_SERVER_MSCHAPV2
 +CFLAGS += -DEAP_SERVER_GTC
 +CFLAGS += -DEAP_SERVER_PSK
 +CFLAGS += -DEAP_SERVER_PAX
 +CFLAGS += -DEAP_SERVER_SAKE
 +CFLAGS += -DEAP_SERVER_GPSK -DEAP_SERVER_GPSK_SHA256
 +
 +CFLAGS += -DIEEE8021X_EAPOL
 +CFLAGS += -DCONFIG_IPV6
 +
 +CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
-     src/crypto/crypto_openssl.c \
-     src/crypto/tls_openssl.c \
-     src/crypto/aes.h \
-     src/crypto/aes_i.h \
-     src/crypto/aes_wrap.h \
-     src/crypto/crypto.h \
-     src/crypto/md5.h \
-     src/crypto/milenage.h \
-     src/crypto/ms_funcs.h \
-     src/crypto/sha1.h \
-     src/crypto/sha256.h \
-     src/crypto/tls.h
++CFLAGS += -DCONFIG_CRYPTO_INTERNAL
++CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
 +
 +UTILS_SRCS = src/utils/base64.c \
 +      src/utils/common.c \
 +      src/utils/ip_addr.c \
 +      src/utils/radiotap.c \
 +      src/utils/trace.c \
 +      src/utils/uuid.c \
 +      src/utils/wpa_debug.c \
 +      src/utils/wpabuf.c \
 +      src/utils/os_unix.c \
 +      src/utils/base64.h \
 +      src/utils/build_config.h \
 +      src/utils/common.h \
 +      src/utils/eloop.h \
 +      src/utils/includes.h \
 +      src/utils/ip_addr.h \
 +      src/utils/list.h \
 +      src/utils/os.h \
 +      src/utils/pcsc_funcs.h \
 +      src/utils/radiotap.h \
 +      src/utils/radiotap_iter.h \
 +      src/utils/state_machine.h \
 +      src/utils/trace.h \
 +      src/utils/uuid.h \
 +      src/utils/wpabuf.h \
 +      src/utils/wpa_debug.h
 +
 +
 +CRYPTO_SRCS = \
 +    src/crypto/aes-cbc.c \
 +    src/crypto/aes-ctr.c \
 +    src/crypto/aes-eax.c \
 +    src/crypto/aes-encblock.c \
++    src/crypto/aes-internal.c \
++    src/crypto/aes-internal-dec.c \
++    src/crypto/aes-internal-enc.c \
 +    src/crypto/aes-omac1.c \
 +    src/crypto/aes-unwrap.c \
 +    src/crypto/aes-wrap.c \
++    src/crypto/des-internal.c \
++    src/crypto/dh_group5.c \
++    src/crypto/dh_groups.c \
++    src/crypto/md4-internal.c \
 +    src/crypto/md5.c \
++    src/crypto/md5-internal.c \
 +    src/crypto/md5-non-fips.c \
 +    src/crypto/milenage.c \
 +    src/crypto/ms_funcs.c \
++    src/crypto/rc4.c \
 +    src/crypto/sha1.c \
++    src/crypto/sha1-internal.c \
 +    src/crypto/sha1-pbkdf2.c \
 +    src/crypto/sha1-tlsprf.c \
 +    src/crypto/sha1-tprf.c \
 +    src/crypto/sha256.c \
-     src/tls/asn1.h \
-     src/tls/bignum.h \
-     src/tls/pkcs1.h \
-     src/tls/pkcs5.h \
-     src/tls/pkcs8.h \
-     src/tls/rsa.h \
-     src/tls/tlsv1_client.h \
-     src/tls/tlsv1_client_i.h \
-     src/tls/tlsv1_common.h \
-     src/tls/tlsv1_cred.h \
-     src/tls/tlsv1_record.h \
-     src/tls/tlsv1_server.h \
-     src/tls/tlsv1_server_i.h \
-     src/tls/x509v3.h 
- libeap_la_SOURCES = $(SOURCES_BOTH) $(SOURCES_peer) $(UTILS_SRCS) $(CRYPTO_SRCS)
++    src/crypto/sha256-internal.c \
++    src/crypto/crypto_internal.c \
++    src/crypto/crypto_internal-cipher.c \
++    src/crypto/crypto_internal-modexp.c \
++    src/crypto/crypto_internal-rsa.c \
++    src/crypto/tls_internal.c \
++    src/crypto/fips_prf_internal.c \
++      src/crypto/aes.h \
++      src/crypto/aes_i.h \
++      src/crypto/aes_wrap.h \
++      src/crypto/crypto.h \
++      src/crypto/des_i.h \
++      src/crypto/dh_group5.h \
++      src/crypto/dh_groups.h \
++      src/crypto/md5.h \
++      src/crypto/md5_i.h \
++      src/crypto/milenage.h \
++      src/crypto/ms_funcs.h \
++      src/crypto/sha1.h \
++      src/crypto/sha1_i.h \
++      src/crypto/sha256.h \
++      src/crypto/tls.h
++
 +
 +TLS_SRCS = \
 +    src/tls/asn1.c \
 +    src/tls/bignum.c \
 +    src/tls/pkcs1.c \
 +    src/tls/pkcs5.c \
 +    src/tls/pkcs8.c \
 +    src/tls/rsa.c \
 +    src/tls/tlsv1_client.c \
 +    src/tls/tlsv1_client_read.c \
 +    src/tls/tlsv1_client_write.c \
 +    src/tls/tlsv1_common.c \
 +    src/tls/tlsv1_cred.c \
 +    src/tls/tlsv1_record.c \
 +    src/tls/tlsv1_server.c \
 +    src/tls/tlsv1_server_read.c \
 +    src/tls/tlsv1_server_write.c \
 +    src/tls/x509v3.c \
++      src/tls/asn1.h \
++      src/tls/bignum.h \
++      src/tls/pkcs1.h \
++      src/tls/pkcs5.h \
++      src/tls/pkcs8.h \
++      src/tls/rsa.h \
++      src/tls/tlsv1_client.h \
++      src/tls/tlsv1_client_i.h \
++      src/tls/tlsv1_common.h \
++      src/tls/tlsv1_cred.h \
++      src/tls/tlsv1_record.h \
++      src/tls/tlsv1_server.h \
++      src/tls/tlsv1_server_i.h \
++      src/tls/x509v3.h 
++
++libeap_la_SOURCES = $(SOURCES_BOTH) $(SOURCES_peer) $(UTILS_SRCS) $(CRYPTO_SRCS) $(TLS_SRCS)
 +
 +noinst_LTLIBRARIES = libeap.la
index a652182,0000000..8c6f64c
mode 100644,000000..100644
--- /dev/null
@@@ -1,190 -1,0 +1,189 @@@
-                       @RADSEC_LDFLAGS@ @OPENSSL_LDFLAGS@ @TARGET_LDFLAGS@
 +AUTOMAKE_OPTIONS = foreign
 +
 +EXTRA_DIST = gsseap_err.et radsec_err.et \
 +      mech_eap.exports mech_eap-noacceptor.exports  radius_ad.exports \
 +      LICENSE AUTHORS
 +
 +
 +gssincludedir = $(includedir)/gssapi
 +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
 +mech_eap_la_CFLAGS   = -Zi
 +mech_eap_la_CXXFLAGS = -Zi
 +else
 +EAP_CFLAGS += -DEAP_TLS -DEAP_PEAP -DEAP_TTLS -DEAP_MD5 -DEAP_MSCHAPv2 -DEAP_GTC -DEAP_OTP -DEAP_LEAP -DEAP_PSK -DEAP_PAX -DEAP_SAKE -DEAP_GPSK -DEAP_GPSK_SHA256 -DEAP_SERVER_IDENTITY -DEAP_SERVER_TLS -DEAP_SERVER_PEAP -DEAP_SERVER_TTLS -DEAP_SERVER_MD5 -DEAP_SERVER_MSCHAPV2 -DEAP_SERVER_GTC -DEAP_SERVER_PSK -DEAP_SERVER_PAX -DEAP_SERVER_SAKE -DEAP_SERVER_GPSK -DEAP_SERVER_GPSK_SHA256 -DIEEE8021X_EAPOL
 +OS_LIBS =
 +mech_eap_la_CFLAGS   = -Werror -Wall -Wunused-parameter
 +mech_eap_la_CXXFLAGS = -Werror -Wall -Wunused-parameter
 +endif
 +mech_eap_la_DEPENDENCIES = $(GSSEAP_EXPORTS)
 +
 +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@ \
 +                      @OPENSAML_CXXFLAGS@ @SHIBRESOLVER_CXXFLAGS@ @SHIBSP_CXXFLAGS@ \
 +                      @TARGET_CFLAGS@ $(EAP_CFLAGS)
 +mech_eap_la_LDFLAGS  = -avoid-version -module \
 +                      -export-symbols $(GSSEAP_EXPORTS) -no-undefined \
-                      @OPENSAML_LIBS@ @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@ \
-                      @OPENSSL_LIBS@
++                      @RADSEC_LDFLAGS@ @TARGET_LDFLAGS@
 +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 =                         \
 +      acquire_cred.c                          \
 +      acquire_cred_with_password.c            \
 +      add_cred.c                              \
 +      add_cred_with_password.c                \
 +      authorize_localname.c                   \
 +      canonicalize_name.c                     \
 +      compare_name.c                          \
 +      context_time.c                          \
 +      delete_sec_context.c                    \
 +      display_name.c                          \
 +      display_name_ext.c                      \
 +      display_status.c                        \
 +      duplicate_name.c                        \
 +      eap_mech.c                              \
 +      exchange_meta_data.c                    \
 +      export_name.c                           \
 +      export_sec_context.c                    \
 +      get_mic.c                               \
 +      gsseap_err.c                            \
 +      import_name.c                           \
 +      import_sec_context.c                    \
 +      indicate_mechs.c                        \
 +      init_sec_context.c                      \
 +      inquire_attrs_for_mech.c                \
 +      inquire_context.c                       \
 +      inquire_cred.c                          \
 +      inquire_cred_by_mech.c                  \
 +      inquire_cred_by_oid.c                   \
 +      inquire_mech_for_saslname.c             \
 +      inquire_mechs_for_name.c                \
 +      inquire_names_for_mech.c                \
 +      inquire_saslname_for_mech.c             \
 +      inquire_sec_context_by_oid.c            \
 +      process_context_token.c                 \
 +      pseudo_random.c                         \
 +      query_mechanism_info.c                  \
 +      query_meta_data.c                       \
 +      radsec_err.c                            \
 +      release_cred.c                          \
 +      release_name.c                          \
 +      release_oid.c                           \
 +      set_cred_option.c                       \
 +      set_sec_context_option.c                \
 +      store_cred.c                            \
 +      unwrap.c                                \
 +      unwrap_iov.c                            \
 +      util_buffer.c                           \
 +      util_context.c                          \
 +      util_cksum.c                            \
 +      util_cred.c                             \
 +      util_crypt.c                            \
 +      util_krb.c                              \
 +      util_lucid.c                            \
 +      util_mech.c                             \
 +      util_name.c                             \
 +      util_oid.c                              \
 +      util_ordering.c                         \
 +      util_sm.c                               \
 +      util_tld.c                              \
 +      util_token.c                            \
 +      verify_mic.c                            \
 +      wrap.c                                  \
 +      wrap_iov.c                              \
 +      wrap_iov_length.c                       \
 +      wrap_size_limit.c \
 +      gssapiP_eap.h \
 +      util_attr.h \
 +      util_base64.h \
 +      util.h \
 +      util_json.h \
 +      util_radius.h \
 +      util_reauth.h \
 +      util_saml.h \
 +      util_shib.h
 +
 +if LIBMOONSHOT
 +mech_eap_la_SOURCES += util_moonshot.c
 +mech_eap_la_CFLAGS  += @LIBMOONSHOT_CFLAGS@
 +mech_eap_la_LDFLAGS += @LIBMOONSHOT_LDFLAGS@
 +mech_eap_la_LIBADD  += @LIBMOONSHOT_LIBS@
 +endif
 +
 +
 +if GSSEAP_ENABLE_ACCEPTOR
 +
 +mech_eap_la_SOURCES +=                                \
 +      accept_sec_context.c                    \
 +      delete_name_attribute.c                 \
 +      export_name_composite.c                 \
 +      get_name_attribute.c                    \
 +      inquire_name.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 gsseap_err.h radsec_err.h
 +
 +if GSSEAP_ENABLE_REAUTH
 +mech_eap_la_SOURCES += util_reauth.c
 +
 +if !HEIMDAL
 +krb5pluginsdir = $(libdir)/krb5/plugins/authdata
 +krb5plugins_LTLIBRARIES = radius_ad.la
 +
 +radius_ad_la_CFLAGS  = -Werror -Wall -Wunused-parameter \
 +                      @KRB5_CFLAGS@ $(EAP_CFLAGS) @RADSEC_CFLAGS@ @TARGET_CFLAGS@
 +radius_ad_la_LDFLAGS = -avoid-version -module \
 +                     -export-symbols radius_ad.exports -no-undefined
 +radius_ad_la_LIBADD  = @KRB5_LIBS@
 +radius_ad_la_SOURCES = util_adshim.c authdata_plugin.h
 +endif
 +endif
 +
 +gsseap_err.h gsseap_err.c: gsseap_err.et
 +      $(COMPILE_ET) $<
 +
 +radsec_err.h radsec_err.c: radsec_err.et
 +      $(COMPILE_ET) $<
 +
 +radsec_err.c: radsec_err.h
 +
 +clean-generic:
 +      rm -f gsseap_err.[ch] radsec_err.[ch]
index c763fbd,0000000..d1790a0
mode 100644,000000..100644
--- /dev/null
@@@ -1,413 -1,0 +1,410 @@@
- #define CRED_FLAG_CERTIFICATE               0x00400000
 +/*
 + * 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.
 + */
 +
 +#ifndef _GSSAPIP_EAP_H_
 +#define _GSSAPIP_EAP_H_ 1
 +
 +#include "config.h"
 +
 +#ifdef HAVE_HEIMDAL_VERSION
 +#define KRB5_DEPRECATED         /* so we can use krb5_free_unparsed_name() */
 +#endif
 +
 +#include <assert.h>
 +#include <string.h>
 +#include <errno.h>
 +#ifdef HAVE_UNISTD_H
 +#include <unistd.h>
 +#endif
 +#ifdef HAVE_STDLIB_H
 +#include <stdlib.h>
 +#endif
 +#ifdef HAVE_STDARG_H
 +#include <stdarg.h>
 +#endif
 +#include <time.h>
 +#ifdef HAVE_SYS_PARAM_H
 +#include <sys/param.h>
 +#endif
 +
 +#ifdef WIN32
 +#ifndef MAXHOSTNAMELEN
 +# include <WinSock2.h>
 +# define MAXHOSTNAMELEN NI_MAXHOST
 +#endif
 +#endif
 +
 +/* GSS headers */
 +#include <gssapi/gssapi.h>
 +#include <gssapi/gssapi_krb5.h>
 +#ifdef HAVE_HEIMDAL_VERSION
 +typedef struct gss_any *gss_any_t;
 +#else
 +#include <gssapi/gssapi_ext.h>
 +#endif
 +#include "gssapi_eap.h"
 +
 +#ifndef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
 +typedef const gss_OID_desc *gss_const_OID;
 +#endif
 +
 +/* Kerberos headers */
 +#include <krb5.h>
 +
 +/* EAP headers */
 +#include <includes.h>
 +#include <common.h>
 +#include <eap_peer/eap.h>
 +#include <eap_peer/eap_config.h>
 +#include <eap_peer/eap_methods.h>
 +#include <eap_common/eap_common.h>
 +#include <wpabuf.h>
 +
 +#ifdef GSSEAP_ENABLE_ACCEPTOR
 +/* FreeRADIUS headers */
 +#ifdef __cplusplus
 +extern "C" {
 +#ifndef WIN32
 +#define operator fr_operator
 +#endif
 +#endif
 +#include <freeradius/libradius.h>
 +#include <freeradius/radius.h>
 +
 +#undef pid_t
 +
 +/* libradsec headers */
 +#include <radsec/radsec.h>
 +#include <radsec/request.h>
 +#ifdef __cplusplus
 +#ifndef WIN32
 +#undef operator
 +#endif
 +}
 +#endif
 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
 +
 +#include "gsseap_err.h"
 +#include "radsec_err.h"
 +#include "util.h"
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +/* These name flags are informative and not actually used by anything yet */
 +#define NAME_FLAG_NAI                       0x00000001
 +#define NAME_FLAG_SERVICE                   0x00000002
 +#define NAME_FLAG_COMPOSITE                 0x00000004
 +
 +struct gss_eap_saml_attr_ctx;
 +struct gss_eap_attr_ctx;
 +
 +#ifdef HAVE_HEIMDAL_VERSION
 +struct gss_name_t_desc_struct
 +#else
 +struct gss_name_struct
 +#endif
 +{
 +    GSSEAP_MUTEX mutex; /* mutex protects attrCtx */
 +    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_PASSWORD                  0x00040000
 +#define CRED_FLAG_DEFAULT_CCACHE            0x00080000
 +#define CRED_FLAG_RESOLVED                  0x00100000
 +#define CRED_FLAG_TARGET                    0x00200000
-     gss_buffer_desc clientCertificate;
-     gss_buffer_desc privateKey;
 +#define CRED_FLAG_PUBLIC_MASK               0x0000FFFF
 +
 +#ifdef HAVE_HEIMDAL_VERSION
 +struct gss_cred_id_t_desc_struct
 +#else
 +struct gss_cred_id_struct
 +#endif
 +{
 +    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;
 +    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;
 +#endif
 +};
 +
 +#define CTX_FLAG_INITIATOR                  0x00000001
 +#define CTX_FLAG_KRB_REAUTH                 0x00000002
 +
 +#define CTX_IS_INITIATOR(ctx)               (((ctx)->flags & CTX_FLAG_INITIATOR) != 0)
 +
 +#define CTX_IS_ESTABLISHED(ctx)             ((ctx)->state == GSSEAP_STATE_ESTABLISHED)
 +
 +/* Initiator context flags */
 +#define CTX_FLAG_EAP_SUCCESS                0x00010000
 +#define CTX_FLAG_EAP_RESTART                0x00020000
 +#define CTX_FLAG_EAP_FAIL                   0x00040000
 +#define CTX_FLAG_EAP_RESP                   0x00080000
 +#define CTX_FLAG_EAP_NO_RESP                0x00100000
 +#define CTX_FLAG_EAP_REQ                    0x00200000
 +#define CTX_FLAG_EAP_PORT_ENABLED           0x00400000
 +#define CTX_FLAG_EAP_ALT_ACCEPT             0x00800000
 +#define CTX_FLAG_EAP_ALT_REJECT             0x01000000
 +#define CTX_FLAG_EAP_MASK                   0xFFFF0000
 +
 +struct gss_eap_initiator_ctx {
 +    unsigned int idleWhile;
 +    struct eap_peer_config eapPeerConfig;
 +    struct eap_sm *eap;
 +    struct wpabuf reqData;
 +};
 +
 +#ifdef GSSEAP_ENABLE_ACCEPTOR
 +struct gss_eap_acceptor_ctx {
 +    struct rs_context *radContext;
 +    struct rs_connection *radConn;
 +    char *radServer;
 +    gss_buffer_desc state;
 +    VALUE_PAIR *vps;
 +};
 +#endif
 +
 +#ifdef HAVE_HEIMDAL_VERSION
 +struct gss_ctx_id_t_desc_struct
 +#else
 +struct gss_ctx_id_struct
 +#endif
 +{
 +    GSSEAP_MUTEX mutex;
 +    enum gss_eap_state state;
 +    OM_uint32 flags;
 +    OM_uint32 gssFlags;
 +    gss_OID mechanismUsed;
 +    krb5_cksumtype checksumType;
 +    krb5_enctype encryptionType;
 +    krb5_keyblock rfc3961Key;
 +    gss_name_t initiatorName;
 +    gss_name_t acceptorName;
 +    time_t expiryTime;
 +    uint64_t sendSeq, recvSeq;
 +    void *seqState;
 +    gss_cred_id_t cred;
 +    union {
 +        struct gss_eap_initiator_ctx initiator;
 +        #define initiatorCtx         ctxU.initiator
 +#ifdef GSSEAP_ENABLE_ACCEPTOR
 +        struct gss_eap_acceptor_ctx  acceptor;
 +        #define acceptorCtx          ctxU.acceptor
 +#endif
 +#ifdef GSSEAP_ENABLE_REAUTH
 +        gss_ctx_id_t                 reauth;
 +        #define reauthCtx            ctxU.reauth
 +#endif
 +    } ctxU;
 +    const struct gss_eap_token_buffer_set *inputTokens;
 +    const struct gss_eap_token_buffer_set *outputTokens;
 +};
 +
 +#define TOK_FLAG_SENDER_IS_ACCEPTOR         0x01
 +#define TOK_FLAG_WRAP_CONFIDENTIAL          0x02
 +#define TOK_FLAG_ACCEPTOR_SUBKEY            0x04
 +
 +#define KEY_USAGE_ACCEPTOR_SEAL             22
 +#define KEY_USAGE_ACCEPTOR_SIGN             23
 +#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,
 +                   gss_ctx_id_t ctx,
 +                   int conf_req_flag,
 +                   int *conf_state,
 +                   gss_iov_buffer_desc *iov,
 +                   int iov_count,
 +                   enum gss_eap_token_type toktype);
 +
 +OM_uint32
 +gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
 +                        gss_ctx_id_t ctx,
 +                        int *conf_state,
 +                        gss_qop_t *qop_state,
 +                        gss_iov_buffer_desc *iov,
 +                        int iov_count,
 +                        enum gss_eap_token_type toktype);
 +
 +OM_uint32
 +gssEapWrapIovLength(OM_uint32 *minor,
 +                    gss_ctx_id_t ctx,
 +                    int conf_req_flag,
 +                    gss_qop_t qop_req,
 +                    int *conf_state,
 +                    gss_iov_buffer_desc *iov,
 +                    int iov_count);
 +OM_uint32
 +gssEapWrap(OM_uint32 *minor,
 +           gss_ctx_id_t ctx,
 +           int conf_req_flag,
 +           gss_qop_t qop_req,
 +           gss_buffer_t input_message_buffer,
 +           int *conf_state,
 +           gss_buffer_t output_message_buffer);
 +
 +unsigned char
 +rfc4121Flags(gss_ctx_id_t ctx, int receiving);
 +
 +/* display_status.c */
 +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)
 +
 +/* exchange_meta_data.c */
 +OM_uint32 GSSAPI_CALLCONV
 +gssEapExchangeMetaData(OM_uint32 *minor,
 +                       gss_const_OID mech,
 +                       gss_cred_id_t cred,
 +                       gss_ctx_id_t *ctx,
 +                       const gss_name_t name,
 +                       OM_uint32 req_flags,
 +                       gss_const_buffer_t meta_data);
 +
 +/* export_sec_context.c */
 +OM_uint32
 +gssEapExportSecContext(OM_uint32 *minor,
 +                       gss_ctx_id_t ctx,
 +                       gss_buffer_t token);
 +
 +/* import_sec_context.c */
 +OM_uint32
 +gssEapImportContext(OM_uint32 *minor,
 +                    gss_buffer_t token,
 +                    gss_ctx_id_t ctx);
 +
 +/* inquire_sec_context_by_oid.c */
 +#define NEGOEX_INITIATOR_SALT      "gss-eap-negoex-initiator"
 +#define NEGOEX_INITIATOR_SALT_LEN  (sizeof(NEGOEX_INITIATOR_SALT) - 1)
 +
 +#define NEGOEX_ACCEPTOR_SALT       "gss-eap-negoex-acceptor"
 +#define NEGOEX_ACCEPTOR_SALT_LEN   (sizeof(NEGOEX_ACCEPTOR_SALT) - 1)
 +
 +/* pseudo_random.c */
 +OM_uint32
 +gssEapPseudoRandom(OM_uint32 *minor,
 +                   gss_ctx_id_t ctx,
 +                   int prf_key,
 +                   const gss_buffer_t prf_in,
 +                   ssize_t desired_output_len,
 +                   gss_buffer_t prf_out);
 +
 +/* query_mechanism_info.c */
 +OM_uint32
 +gssQueryMechanismInfo(OM_uint32 *minor,
 +                      gss_const_OID mech_oid,
 +                      unsigned char auth_scheme[16]);
 +
 +/* query_meta_data.c */
 +OM_uint32
 +gssEapQueryMetaData(OM_uint32 *minor,
 +                    gss_const_OID mech GSSEAP_UNUSED,
 +                    gss_cred_id_t cred,
 +                    gss_ctx_id_t *context_handle,
 +                    const gss_name_t name,
 +                    OM_uint32 req_flags GSSEAP_UNUSED,
 +                    gss_buffer_t meta_data);
 +
 +/* eap_mech.c */
 +OM_uint32
 +gssEapInitiatorInit(OM_uint32 *minor);
 +
 +void
 +gssEapFinalize(void);
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif /* _GSSAPIP_EAP_H_ */
index 02f132f,0000000..588665b
mode 100644,000000..100644
--- /dev/null
@@@ -1,97 -1,0 +1,90 @@@
-  * Path to PKCS#12 private key file for use with EAP-TLS
-  * authentication.
-  */
- extern gss_OID GSS_EAP_CRED_SET_CRED_PRIVATE_KEY;
- /*
 +/*
 + * 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.
 + */
 +
 +#ifndef _GSSAPI_EAP_H_
 +#define _GSSAPI_EAP_H_ 1
 +
 +#include <gssapi/gssapi.h>
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif /* __cplusplus */
 +
 +/*
 + * GSS EAP mechanism OIDs.
 + */
 +extern gss_OID GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM;
 +extern gss_OID GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM;
 +
 +/*
 + * Mechanism name OID.
 + */
 +extern gss_OID GSS_EAP_NT_EAP_NAME;
 +
 +/*
 + * The libradsec configuration file; defaults to radsec.conf
 + * in the system configuration directory if unspecified.
 + */
 +extern gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE;
 +
 +/*
 + * The stanza in the libradsec configuration file; defaults
 + * to "gss-eap" if unspecified.
 + */
 +extern gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA;
 +
 +/*
 + * Flags as a 32-bit integer in network byte order,
 + * followed by a boolean octet indicating whether to
 + * clear the specified flags (if absent, defaults to
 + * FALSE, ie. set flags).
 + */
 +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.
 + */
 +#define GSS_EAP_DISABLE_LOCAL_ATTRS_FLAG    0x00000001
 +
 +#ifdef __cplusplus
 +}
 +#endif /* __cplusplus */
 +
 +#endif /* _GSSAPI_EAP_H_ */
index 8a877fd,0000000..e99b479
mode 100644,000000..100644
--- /dev/null
@@@ -1,1105 -1,0 +1,1097 @@@
-     if ((cred->flags & CRED_FLAG_CERTIFICATE) == 0) {
-         eapPeerConfig->password = (unsigned char *)cred->password.value;
-         eapPeerConfig->password_len = cred->password.length;
-     }
 +/*
 + * 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.
 + */
 +
 +/*
 + * Establish a security context on the initiator (client). These functions
 + * wrap around libeap.
 + */
 +
 +#include "gssapiP_eap.h"
 +
 +static OM_uint32
 +policyVariableToFlag(enum eapol_bool_var variable)
 +{
 +    OM_uint32 flag = 0;
 +
 +    switch (variable) {
 +    case EAPOL_eapSuccess:
 +        flag = CTX_FLAG_EAP_SUCCESS;
 +        break;
 +    case EAPOL_eapRestart:
 +        flag = CTX_FLAG_EAP_RESTART;
 +        break;
 +    case EAPOL_eapFail:
 +        flag = CTX_FLAG_EAP_FAIL;
 +        break;
 +    case EAPOL_eapResp:
 +        flag = CTX_FLAG_EAP_RESP;
 +        break;
 +    case EAPOL_eapNoResp:
 +        flag = CTX_FLAG_EAP_NO_RESP;
 +        break;
 +    case EAPOL_eapReq:
 +        flag = CTX_FLAG_EAP_REQ;
 +        break;
 +    case EAPOL_portEnabled:
 +        flag = CTX_FLAG_EAP_PORT_ENABLED;
 +        break;
 +    case EAPOL_altAccept:
 +        flag = CTX_FLAG_EAP_ALT_ACCEPT;
 +        break;
 +    case EAPOL_altReject:
 +        flag = CTX_FLAG_EAP_ALT_REJECT;
 +        break;
 +    }
 +
 +    return flag;
 +}
 +
 +static struct eap_peer_config *
 +peerGetConfig(void *ctx)
 +{
 +    gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
 +
 +    return &gssCtx->initiatorCtx.eapPeerConfig;
 +}
 +
 +static Boolean
 +peerGetBool(void *data, enum eapol_bool_var variable)
 +{
 +    gss_ctx_id_t ctx = data;
 +    OM_uint32 flag;
 +
 +    if (ctx == GSS_C_NO_CONTEXT)
 +        return FALSE;
 +
 +    flag = policyVariableToFlag(variable);
 +
 +    return ((ctx->flags & flag) != 0);
 +}
 +
 +static void
 +peerSetBool(void *data, enum eapol_bool_var variable,
 +            Boolean value)
 +{
 +    gss_ctx_id_t ctx = data;
 +    OM_uint32 flag;
 +
 +    if (ctx == GSS_C_NO_CONTEXT)
 +        return;
 +
 +    flag = policyVariableToFlag(variable);
 +
 +    if (value)
 +        ctx->flags |= flag;
 +    else
 +        ctx->flags &= ~(flag);
 +}
 +
 +static unsigned int
 +peerGetInt(void *data, enum eapol_int_var variable)
 +{
 +    gss_ctx_id_t ctx = data;
 +
 +    if (ctx == GSS_C_NO_CONTEXT)
 +        return FALSE;
 +
 +    GSSEAP_ASSERT(CTX_IS_INITIATOR(ctx));
 +
 +    switch (variable) {
 +    case EAPOL_idleWhile:
 +        return ctx->initiatorCtx.idleWhile;
 +        break;
 +    }
 +
 +    return 0;
 +}
 +
 +static void
 +peerSetInt(void *data, enum eapol_int_var variable,
 +           unsigned int value)
 +{
 +    gss_ctx_id_t ctx = data;
 +
 +    if (ctx == GSS_C_NO_CONTEXT)
 +        return;
 +
 +    GSSEAP_ASSERT(CTX_IS_INITIATOR(ctx));
 +
 +    switch (variable) {
 +    case EAPOL_idleWhile:
 +        ctx->initiatorCtx.idleWhile = value;
 +        break;
 +    }
 +}
 +
 +static struct wpabuf *
 +peerGetEapReqData(void *ctx)
 +{
 +    gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
 +
 +    return &gssCtx->initiatorCtx.reqData;
 +}
 +
 +static void
 +peerSetConfigBlob(void *ctx GSSEAP_UNUSED,
 +                  struct wpa_config_blob *blob GSSEAP_UNUSED)
 +{
 +}
 +
 +static const struct wpa_config_blob *
 +peerGetConfigBlob(void *ctx GSSEAP_UNUSED,
 +                  const char *name GSSEAP_UNUSED)
 +{
 +    return NULL;
 +}
 +
 +static void
 +peerNotifyPending(void *ctx GSSEAP_UNUSED)
 +{
 +}
 +
 +static struct eapol_callbacks gssEapPolicyCallbacks = {
 +    peerGetConfig,
 +    peerGetBool,
 +    peerSetBool,
 +    peerGetInt,
 +    peerSetInt,
 +    peerGetEapReqData,
 +    peerSetConfigBlob,
 +    peerGetConfigBlob,
 +    peerNotifyPending,
 +};
 +
 +#ifdef GSSEAP_DEBUG
 +extern int wpa_debug_level;
 +#endif
 +
 +static OM_uint32
 +peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
 +{
 +    OM_uint32 major;
 +    krb5_context krbContext;
 +    struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
 +    gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
 +    gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
 +    gss_cred_id_t cred = ctx->cred;
 +
 +    eapPeerConfig->identity = NULL;
 +    eapPeerConfig->identity_len = 0;
 +    eapPeerConfig->anonymous_identity = NULL;
 +    eapPeerConfig->anonymous_identity_len = 0;
 +    eapPeerConfig->password = NULL;
 +    eapPeerConfig->password_len = 0;
 +
 +    GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
 +
 +    GSSEAP_KRB_INIT(&krbContext);
 +
 +    eapPeerConfig->fragment_size = 1024;
 +#ifdef GSSEAP_DEBUG
 +    wpa_debug_level = 0;
 +#endif
 +
 +    GSSEAP_ASSERT(cred->name != GSS_C_NO_NAME);
 +
 +    if ((cred->name->flags & (NAME_FLAG_NAI | NAME_FLAG_SERVICE)) == 0) {
 +        *minor = GSSEAP_BAD_INITIATOR_NAME;
 +        return GSS_S_BAD_NAME;
 +    }
 +
 +    /* identity */
 +    major = gssEapDisplayName(minor, cred->name, &identity, NULL);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    eapPeerConfig->identity = (unsigned char *)identity.value;
 +    eapPeerConfig->identity_len = identity.length;
 +
 +    krbPrincRealmToGssBuffer(cred->name->krbPrincipal, &realm);
 +
 +    /* anonymous_identity */
 +    eapPeerConfig->anonymous_identity = GSSEAP_MALLOC(realm.length + 2);
 +    if (eapPeerConfig->anonymous_identity == NULL) {
 +        *minor = ENOMEM;
 +        return GSS_S_FAILURE;
 +    }
 +
 +    eapPeerConfig->anonymous_identity[0] = '@';
 +    memcpy(eapPeerConfig->anonymous_identity + 1, realm.value, realm.length);
 +    eapPeerConfig->anonymous_identity[1 + realm.length] = '\0';
 +    eapPeerConfig->anonymous_identity_len = 1 + realm.length;
 +
 +    /* password */
-     if (cred->flags & CRED_FLAG_CERTIFICATE) {
-         eapPeerConfig->client_cert = (unsigned char *)cred->clientCertificate.value;
-         eapPeerConfig->private_key = (unsigned char *)cred->privateKey.value;
-         eapPeerConfig->private_key_passwd = (unsigned char *)cred->password.value;
-     }
++    eapPeerConfig->password = (unsigned char *)cred->password.value;
++    eapPeerConfig->password_len = cred->password.length;
 +
 +    /* certs */
 +    eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
 +    eapPeerConfig->subject_match = (unsigned char *)cred->subjectNameConstraint.value;
 +    eapPeerConfig->altsubject_match = (unsigned char *)cred->subjectAltNameConstraint.value;
 +
 +    *minor = 0;
 +    return GSS_S_COMPLETE;
 +}
 +
 +static OM_uint32
 +peerConfigFree(OM_uint32 *minor,
 +               gss_ctx_id_t ctx)
 +{
 +    struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
 +
 +    if (eapPeerConfig->identity != NULL) {
 +        GSSEAP_FREE(eapPeerConfig->identity);
 +        eapPeerConfig->identity = NULL;
 +        eapPeerConfig->identity_len = 0;
 +    }
 +
 +    if (eapPeerConfig->anonymous_identity != NULL) {
 +        GSSEAP_FREE(eapPeerConfig->anonymous_identity);
 +        eapPeerConfig->anonymous_identity = NULL;
 +        eapPeerConfig->anonymous_identity_len = 0;
 +    }
 +
 +    *minor = 0;
 +    return GSS_S_COMPLETE;
 +}
 +
 +/*
 + * Mark an initiator context as ready for cryptographic operations
 + */
 +static OM_uint32
 +initReady(OM_uint32 *minor, gss_ctx_id_t ctx, OM_uint32 reqFlags)
 +{
 +    OM_uint32 major;
 +    const unsigned char *key;
 +    size_t keyLength;
 +
 +#if 1
 +    /* XXX actually check for mutual auth */
 +    if (reqFlags & GSS_C_MUTUAL_FLAG)
 +        ctx->gssFlags |= GSS_C_MUTUAL_FLAG;
 +#endif
 +
 +    /* Cache encryption type derived from selected mechanism OID */
 +    major = gssEapOidToEnctype(minor, ctx->mechanismUsed, &ctx->encryptionType);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    if (!eap_key_available(ctx->initiatorCtx.eap)) {
 +        *minor = GSSEAP_KEY_UNAVAILABLE;
 +        return GSS_S_UNAVAILABLE;
 +    }
 +
 +    key = eap_get_eapKeyData(ctx->initiatorCtx.eap, &keyLength);
 +
 +    if (keyLength < EAP_EMSK_LEN) {
 +        *minor = GSSEAP_KEY_TOO_SHORT;
 +        return GSS_S_UNAVAILABLE;
 +    }
 +
 +    major = gssEapDeriveRfc3961Key(minor,
 +                                   &key[EAP_EMSK_LEN / 2],
 +                                   EAP_EMSK_LEN / 2,
 +                                   ctx->encryptionType,
 +                                   &ctx->rfc3961Key);
 +       if (GSS_ERROR(major))
 +           return major;
 +
 +    major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
 +                                      &ctx->checksumType);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    major = sequenceInit(minor,
 +                         &ctx->seqState,
 +                         ctx->recvSeq,
 +                         ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
 +                         ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
 +                         TRUE);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    *minor = 0;
 +    return GSS_S_COMPLETE;
 +}
 +
 +static OM_uint32
 +initBegin(OM_uint32 *minor,
 +          gss_ctx_id_t ctx,
 +          gss_name_t target,
 +          gss_OID mech,
 +          OM_uint32 reqFlags GSSEAP_UNUSED,
 +          OM_uint32 timeReq,
 +          gss_channel_bindings_t chanBindings GSSEAP_UNUSED)
 +{
 +    OM_uint32 major;
 +    gss_cred_id_t cred = ctx->cred;
 +
 +    GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
 +
 +    if (cred->expiryTime)
 +        ctx->expiryTime = cred->expiryTime;
 +    else if (timeReq == 0 || timeReq == GSS_C_INDEFINITE)
 +        ctx->expiryTime = 0;
 +    else
 +        ctx->expiryTime = time(NULL) + timeReq;
 +
 +    /*
 +     * The credential mutex protects its name, however we need to
 +     * explicitly lock the acceptor name (unlikely as it may be
 +     * that it has attributes set on it).
 +     */
 +    major = gssEapDuplicateName(minor, cred->name, &ctx->initiatorName);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    if (target != GSS_C_NO_NAME) {
 +        GSSEAP_MUTEX_LOCK(&target->mutex);
 +
 +        major = gssEapDuplicateName(minor, target, &ctx->acceptorName);
 +        if (GSS_ERROR(major)) {
 +            GSSEAP_MUTEX_UNLOCK(&target->mutex);
 +            return major;
 +        }
 +
 +        GSSEAP_MUTEX_UNLOCK(&target->mutex);
 +    }
 +
 +    major = gssEapCanonicalizeOid(minor,
 +                                  mech,
 +                                  OID_FLAG_NULL_VALID | OID_FLAG_MAP_NULL_TO_DEFAULT_MECH,
 +                                  &ctx->mechanismUsed);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    /* If credentials were provided, check they're usable with this mech */
 +    if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
 +        *minor = GSSEAP_CRED_MECH_MISMATCH;
 +        return GSS_S_BAD_MECH;
 +    }
 +
 +    *minor = 0;
 +    return GSS_S_COMPLETE;
 +}
 +
 +static OM_uint32
 +eapGssSmInitError(OM_uint32 *minor,
 +                  gss_cred_id_t cred GSSEAP_UNUSED,
 +                  gss_ctx_id_t ctx GSSEAP_UNUSED,
 +                  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;
 +    unsigned char *p;
 +
 +    if (inputToken->length < 8) {
 +        *minor = GSSEAP_TOK_TRUNC;
 +        return GSS_S_DEFECTIVE_TOKEN;
 +    }
 +
 +    p = (unsigned char *)inputToken->value;
 +
 +    major = load_uint32_be(&p[0]);
 +    *minor = ERROR_TABLE_BASE_eapg + load_uint32_be(&p[4]);
 +
 +    if (!GSS_ERROR(major) || !IS_WIRE_ERROR(*minor)) {
 +        major = GSS_S_FAILURE;
 +        *minor = GSSEAP_BAD_ERROR_TOKEN;
 +    }
 +
 +    GSSEAP_ASSERT(GSS_ERROR(major));
 +
 +    return major;
 +}
 +
 +#ifdef GSSEAP_ENABLE_REAUTH
 +static OM_uint32
 +eapGssSmInitGssReauth(OM_uint32 *minor,
 +                      gss_cred_id_t cred,
 +                      gss_ctx_id_t ctx,
 +                      gss_name_t target,
 +                      gss_OID mech GSSEAP_UNUSED,
 +                      OM_uint32 reqFlags,
 +                      OM_uint32 timeReq,
 +                      gss_channel_bindings_t chanBindings,
 +                      gss_buffer_t inputToken,
 +                      gss_buffer_t outputToken,
 +                      OM_uint32 *smFlags GSSEAP_UNUSED)
 +{
 +    OM_uint32 major, tmpMinor;
 +    gss_name_t mechTarget = GSS_C_NO_NAME;
 +    gss_OID actualMech = GSS_C_NO_OID;
 +    OM_uint32 gssFlags, timeRec;
 +
 +    /*
 +     * Here we use the passed in credential handle because the resolved
 +     * context credential does not currently have the reauth creds.
 +     */
 +    if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL) {
 +        if (!gssEapCanReauthP(cred, target, timeReq))
 +            return GSS_S_CONTINUE_NEEDED;
 +
 +        ctx->flags |= CTX_FLAG_KRB_REAUTH;
 +    } else if ((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
 +        major = GSS_S_DEFECTIVE_TOKEN;
 +        *minor = GSSEAP_WRONG_ITOK;
 +        goto cleanup;
 +    }
 +
 +    GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
 +
 +    major = gssEapMechToGlueName(minor, target, &mechTarget);
 +    if (GSS_ERROR(major))
 +        goto cleanup;
 +
 +    major = gssInitSecContext(minor,
 +                              cred->reauthCred,
 +                              &ctx->reauthCtx,
 +                              mechTarget,
 +                              (gss_OID)gss_mech_krb5,
 +                              reqFlags | GSS_C_MUTUAL_FLAG,
 +                              timeReq,
 +                              chanBindings,
 +                              inputToken,
 +                              &actualMech,
 +                              outputToken,
 +                              &gssFlags,
 +                              &timeRec);
 +    if (GSS_ERROR(major))
 +        goto cleanup;
 +
 +    ctx->gssFlags = gssFlags;
 +
 +    if (major == GSS_S_COMPLETE) {
 +        GSSEAP_ASSERT(GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE);
 +
 +        major = gssEapReauthComplete(minor, ctx, cred, actualMech, timeRec);
 +        if (GSS_ERROR(major))
 +            goto cleanup;
 +        GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
 +    } else {
 +        GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_REAUTHENTICATE);
 +    }
 +
 +cleanup:
 +    gssReleaseName(&tmpMinor, &mechTarget);
 +
 +    return major;
 +}
 +#endif /* GSSEAP_ENABLE_REAUTH */
 +
 +#ifdef GSSEAP_DEBUG
 +static OM_uint32
 +eapGssSmInitVendorInfo(OM_uint32 *minor,
 +                       gss_cred_id_t cred GSSEAP_UNUSED,
 +                       gss_ctx_id_t ctx GSSEAP_UNUSED,
 +                       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)
 +{
 +    OM_uint32 major;
 +
 +    major = makeStringBuffer(minor, "JANET(UK)", outputToken);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    return GSS_S_CONTINUE_NEEDED;
 +}
 +#endif
 +
 +static OM_uint32
 +eapGssSmInitAcceptorName(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)
 +{
 +    OM_uint32 major;
 +
 +    if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL &&
 +        ctx->acceptorName != GSS_C_NO_NAME) {
 +
 +        /* Send desired target name to acceptor */
 +        major = gssEapDisplayName(minor, ctx->acceptorName,
 +                                  outputToken, NULL);
 +        if (GSS_ERROR(major))
 +            return major;
 +    } else if (inputToken != GSS_C_NO_BUFFER &&
 +               ctx->acceptorName == GSS_C_NO_NAME) {
 +        /* Accept target name hint from acceptor */
 +        major = gssEapImportName(minor, inputToken,
 +                                 GSS_C_NT_USER_NAME,
 +                                 ctx->mechanismUsed,
 +                                 &ctx->acceptorName);
 +        if (GSS_ERROR(major))
 +            return major;
 +    }
 +
 +    /*
 +     * Currently, other parts of the code assume that the acceptor name
 +     * is available, hence this check.
 +     */
 +    if (ctx->acceptorName == GSS_C_NO_NAME) {
 +        *minor = GSSEAP_NO_ACCEPTOR_NAME;
 +        return GSS_S_FAILURE;
 +    }
 +
 +    return GSS_S_CONTINUE_NEEDED;
 +}
 +
 +static OM_uint32
 +eapGssSmInitIdentity(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)
 +{
 +    struct eap_config eapConfig;
 +
 +#ifdef GSSEAP_ENABLE_REAUTH
 +    if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE) {
 +        OM_uint32 tmpMinor;
 +
 +        /* server didn't support reauthentication, sent EAP request */
 +        gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
 +        ctx->flags &= ~(CTX_FLAG_KRB_REAUTH);
 +        GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL);
 +    } else
 +#endif
 +        *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
 +
 +    GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
 +    GSSEAP_ASSERT(inputToken == GSS_C_NO_BUFFER);
 +
 +    memset(&eapConfig, 0, sizeof(eapConfig));
 +
 +    ctx->initiatorCtx.eap = eap_peer_sm_init(ctx,
 +                                             &gssEapPolicyCallbacks,
 +                                             ctx,
 +                                             &eapConfig);
 +    if (ctx->initiatorCtx.eap == NULL) {
 +        *minor = GSSEAP_PEER_SM_INIT_FAILURE;
 +        return GSS_S_FAILURE;
 +    }
 +
 +    ctx->flags |= CTX_FLAG_EAP_RESTART | CTX_FLAG_EAP_PORT_ENABLED;
 +
 +    /* poke EAP state machine */
 +    if (eap_peer_sm_step(ctx->initiatorCtx.eap) != 0) {
 +        *minor = GSSEAP_PEER_SM_STEP_FAILURE;
 +        return GSS_S_FAILURE;
 +    }
 +
 +    GSSEAP_SM_TRANSITION_NEXT(ctx);
 +
 +    *minor = 0;
 +
 +    return GSS_S_CONTINUE_NEEDED;
 +}
 +
 +static OM_uint32
 +eapGssSmInitAuthenticate(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;
 +    OM_uint32 tmpMinor;
 +    struct wpabuf *resp = NULL;
 +
 +    *minor = 0;
 +
 +    GSSEAP_ASSERT(inputToken != GSS_C_NO_BUFFER);
 +
 +    major = peerConfigInit(minor, ctx);
 +    if (GSS_ERROR(major))
 +        goto cleanup;
 +
 +    GSSEAP_ASSERT(ctx->initiatorCtx.eap != NULL);
 +    GSSEAP_ASSERT(ctx->flags & CTX_FLAG_EAP_PORT_ENABLED);
 +
 +    ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
 +
 +    wpabuf_set(&ctx->initiatorCtx.reqData,
 +               inputToken->value, inputToken->length);
 +
 +    major = GSS_S_CONTINUE_NEEDED;
 +
 +    eap_peer_sm_step(ctx->initiatorCtx.eap);
 +    if (ctx->flags & CTX_FLAG_EAP_RESP) {
 +        ctx->flags &= ~(CTX_FLAG_EAP_RESP);
 +
 +        resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
 +    } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
 +        major = initReady(minor, ctx, reqFlags);
 +        if (GSS_ERROR(major))
 +            goto cleanup;
 +
 +        ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS);
 +        major = GSS_S_CONTINUE_NEEDED;
 +        GSSEAP_SM_TRANSITION_NEXT(ctx);
 +    } else if (ctx->flags & CTX_FLAG_EAP_FAIL) {
 +        major = GSS_S_DEFECTIVE_CREDENTIAL;
 +        *minor = GSSEAP_PEER_AUTH_FAILURE;
 +    } else {
 +        major = GSS_S_DEFECTIVE_TOKEN;
 +        *minor = GSSEAP_PEER_BAD_MESSAGE;
 +    }
 +
 +cleanup:
 +    if (resp != NULL) {
 +        OM_uint32 tmpMajor;
 +        gss_buffer_desc respBuf;
 +
 +        GSSEAP_ASSERT(major == GSS_S_CONTINUE_NEEDED);
 +
 +        respBuf.length = wpabuf_len(resp);
 +        respBuf.value = (void *)wpabuf_head(resp);
 +
 +        tmpMajor = duplicateBuffer(&tmpMinor, &respBuf, outputToken);
 +        if (GSS_ERROR(tmpMajor)) {
 +            major = tmpMajor;
 +            *minor = tmpMinor;
 +        }
 +
 +        *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
 +    }
 +
 +    wpabuf_set(&ctx->initiatorCtx.reqData, NULL, 0);
 +    peerConfigFree(&tmpMinor, ctx);
 +
 +    return major;
 +}
 +
 +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,
 +                               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,
 +                               gss_buffer_t inputToken GSSEAP_UNUSED,
 +                               gss_buffer_t outputToken,
 +                               OM_uint32 *smFlags)
 +{
 +    OM_uint32 major;
 +    gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
 +
 +    if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
 +        buffer = chanBindings->application_data;
 +
 +    major = gssEapWrap(minor, ctx, TRUE, GSS_C_QOP_DEFAULT,
 +                       &buffer, NULL, outputToken);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    GSSEAP_ASSERT(outputToken->value != NULL);
 +
 +    *minor = 0;
 +    *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
 +
 +    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,
 +                        gss_cred_id_t cred,
 +                        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;
 +
 +    if (ctx->gssFlags & GSS_C_MUTUAL_FLAG) {
 +        major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken);
 +        if (GSS_ERROR(major))
 +            return major;
 +    }
 +
 +    *minor = 0;
 +    return GSS_S_CONTINUE_NEEDED;
 +}
 +#endif /* GSSEAP_ENABLE_REAUTH */
 +
 +static OM_uint32
 +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)
 +{
 +    OM_uint32 major;
 +
 +    major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
 +    if (GSS_ERROR(major))
 +        return major;
 +
 +    GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
 +
 +    *minor = 0;
 +
 +    return GSS_S_COMPLETE;
 +}
 +
 +static struct gss_eap_sm eapGssInitiatorSm[] = {
 +    {
 +        ITOK_TYPE_CONTEXT_ERR,
 +        ITOK_TYPE_NONE,
 +        GSSEAP_STATE_ALL & ~(GSSEAP_STATE_INITIAL),
 +        0,
 +        eapGssSmInitError
 +    },
 +    {
 +        ITOK_TYPE_ACCEPTOR_NAME_RESP,
 +        ITOK_TYPE_ACCEPTOR_NAME_REQ,
 +        GSSEAP_STATE_INITIAL | GSSEAP_STATE_AUTHENTICATE,
 +        0,
 +        eapGssSmInitAcceptorName
 +    },
 +#ifdef GSSEAP_DEBUG
 +    {
 +        ITOK_TYPE_NONE,
 +        ITOK_TYPE_VENDOR_INFO,
 +        GSSEAP_STATE_INITIAL,
 +        0,
 +        eapGssSmInitVendorInfo
 +    },
 +#endif
 +#ifdef GSSEAP_ENABLE_REAUTH
 +    {
 +        ITOK_TYPE_REAUTH_RESP,
 +        ITOK_TYPE_REAUTH_REQ,
 +        GSSEAP_STATE_INITIAL | GSSEAP_STATE_REAUTHENTICATE,
 +        0,
 +        eapGssSmInitGssReauth
 +    },
 +#endif
 +    {
 +        ITOK_TYPE_NONE,
 +        ITOK_TYPE_NONE,
 +#ifdef GSSEAP_ENABLE_REAUTH
 +        GSSEAP_STATE_REAUTHENTICATE |
 +#endif
 +        GSSEAP_STATE_INITIAL,
 +        SM_ITOK_FLAG_REQUIRED,
 +        eapGssSmInitIdentity
 +    },
 +    {
 +        ITOK_TYPE_EAP_REQ,
 +        ITOK_TYPE_EAP_RESP,
 +        GSSEAP_STATE_AUTHENTICATE,
 +        SM_ITOK_FLAG_REQUIRED,
 +        eapGssSmInitAuthenticate
 +    },
 +    {
 +        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,
 +        eapGssSmInitGssChannelBindings
 +    },
 +    {
 +        ITOK_TYPE_NONE,
 +        ITOK_TYPE_INITIATOR_MIC,
 +        GSSEAP_STATE_INITIATOR_EXTS,
 +        SM_ITOK_FLAG_REQUIRED,
 +        eapGssSmInitInitiatorMIC
 +    },
 +#ifdef GSSEAP_ENABLE_REAUTH
 +    {
 +        ITOK_TYPE_REAUTH_CREDS,
 +        ITOK_TYPE_NONE,
 +        GSSEAP_STATE_ACCEPTOR_EXTS,
 +        0,
 +        eapGssSmInitReauthCreds
 +    },
 +#endif
 +    /* other extensions go here */
 +    {
 +        ITOK_TYPE_ACCEPTOR_MIC,
 +        ITOK_TYPE_NONE,
 +        GSSEAP_STATE_ACCEPTOR_EXTS,
 +        SM_ITOK_FLAG_REQUIRED,
 +        eapGssSmInitAcceptorMIC
 +    }
 +};
 +
 +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)
 +{
 +    OM_uint32 major, tmpMinor;
 +    int initialContextToken = (ctx->mechanismUsed == GSS_C_NO_OID);
 +
 +    /*
 +     * XXX is acquiring the credential lock here necessary? The password is
 +     * mutable but the contract could specify that this is not updated whilst
 +     * a context is being initialized.
 +     */
 +    if (cred != GSS_C_NO_CREDENTIAL)
 +        GSSEAP_MUTEX_LOCK(&cred->mutex);
 +
 +    if (ctx->cred == GSS_C_NO_CREDENTIAL) {
 +        major = gssEapResolveInitiatorCred(minor, cred, target_name, &ctx->cred);
 +        if (GSS_ERROR(major))
 +            goto cleanup;
 +
 +        GSSEAP_ASSERT(ctx->cred != GSS_C_NO_CREDENTIAL);
 +    }
 +
 +    GSSEAP_MUTEX_LOCK(&ctx->cred->mutex);
 +
 +    GSSEAP_ASSERT(ctx->cred->flags & CRED_FLAG_RESOLVED);
 +    GSSEAP_ASSERT(ctx->cred->flags & CRED_FLAG_INITIATE);
 +
 +    if (initialContextToken) {
 +        major = initBegin(minor, ctx, target_name, mech_type,
 +                          req_flags, time_req, input_chan_bindings);
 +        if (GSS_ERROR(major))
 +            goto cleanup;
 +    }
 +
 +    major = gssEapSmStep(minor,
 +                         cred,
 +                         ctx,
 +                         target_name,
 +                         mech_type,
 +                         req_flags,
 +                         time_req,
 +                         input_chan_bindings,
 +                         input_token,
 +                         output_token,
 +                         eapGssInitiatorSm,
 +                         sizeof(eapGssInitiatorSm) / sizeof(eapGssInitiatorSm[0]));
 +    if (GSS_ERROR(major))
 +        goto cleanup;
 +
 +    if (actual_mech_type != NULL) {
 +        OM_uint32 tmpMajor;
 +
 +        tmpMajor = gssEapCanonicalizeOid(&tmpMinor, ctx->mechanismUsed, 0, actual_mech_type);
 +        if (GSS_ERROR(tmpMajor)) {
 +            major = tmpMajor;
 +            *minor = tmpMinor;
 +            goto cleanup;
 +        }
 +    }
 +    if (ret_flags != NULL)
 +        *ret_flags = ctx->gssFlags;
 +    if (time_rec != NULL)
 +        gssEapContextTime(&tmpMinor, ctx, time_rec);
 +
 +    GSSEAP_ASSERT(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED);
 +
 +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;
 +
 +    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))
 +        gssEapReleaseContext(&tmpMinor, context_handle);
 +
 +    return major;
 +}
index 98bb482,0000000..7bb9b7b
mode 100644,000000..100644
--- /dev/null
@@@ -1,223 -1,0 +1,208 @@@
- static OM_uint32
- setCredPrivateKey(OM_uint32 *minor,
-                   gss_cred_id_t cred,
-                   const gss_OID oid GSSEAP_UNUSED,
-                   const gss_buffer_t buffer)
- {
-     return gssEapSetCredClientCertificate(minor, cred, GSS_C_NO_BUFFER, buffer);
- }
 +/*
 + * 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.
 + */
 +
 +/*
 + * Set an extended property on a credential handle.
 + */
 +
 +#include "gssapiP_eap.h"
 +
 +static OM_uint32
 +setCredRadiusConfigFile(OM_uint32 *minor,
 +                        gss_cred_id_t cred,
 +                        const gss_OID oid GSSEAP_UNUSED,
 +                        const gss_buffer_t buffer)
 +{
 +    OM_uint32 major, tmpMinor;
 +    gss_buffer_desc configFileBuffer = GSS_C_EMPTY_BUFFER;
 +
 +    if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
 +        major = duplicateBuffer(minor, buffer, &configFileBuffer);
 +        if (GSS_ERROR(major))
 +            return major;
 +    }
 +
 +    gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
 +    cred->radiusConfigFile = configFileBuffer;
 +
 +    *minor = 0;
 +    return GSS_S_COMPLETE;
 +}
 +
 +static OM_uint32
 +setCredRadiusConfigStanza(OM_uint32 *minor,
 +                          gss_cred_id_t cred,
 +                          const gss_OID oid GSSEAP_UNUSED,
 +                          const gss_buffer_t buffer)
 +{
 +    OM_uint32 major, tmpMinor;
 +    gss_buffer_desc configStanzaBuffer = GSS_C_EMPTY_BUFFER;
 +
 +    if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
 +        major = duplicateBuffer(minor, buffer, &configStanzaBuffer);
 +        if (GSS_ERROR(major))
 +            return major;
 +    }
 +
 +    gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
 +    cred->radiusConfigStanza = configStanzaBuffer;
 +
 +    *minor = 0;
 +    return GSS_S_COMPLETE;
 +}
 +
 +static OM_uint32
 +setCredFlag(OM_uint32 *minor,
 +            gss_cred_id_t cred,
 +            const gss_OID oid GSSEAP_UNUSED,
 +            const gss_buffer_t buffer)
 +{
 +    OM_uint32 flags;
 +    unsigned char *p;
 +
 +    if (buffer == GSS_C_NO_BUFFER) {
 +        *minor = EINVAL;
 +        return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_FAILURE;
 +    }
 +
 +    if (buffer->length < 4) {
 +        *minor = GSSEAP_WRONG_SIZE;
 +        return GSS_S_FAILURE;
 +    }
 +
 +    p = (unsigned char *)buffer->value;
 +
 +    flags = load_uint32_be(buffer->value) & CRED_FLAG_PUBLIC_MASK;
 +
 +    if (buffer->length > 4 && p[4])
 +        cred->flags &= ~(flags);
 +    else
 +        cred->flags |= flags;
 +
 +    *minor = 0;
 +    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);
 +}
 +
-     /* 1.3.6.1.4.1.5322.22.3.3.5 */
-     {
-         { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x05" },
-         setCredPrivateKey,
-     },
 +static struct {
 +    gss_OID_desc oid;
 +    OM_uint32 (*setOption)(OM_uint32 *, gss_cred_id_t cred,
 +                           const gss_OID, const gss_buffer_t);
 +} setCredOps[] = {
 +    /* 1.3.6.1.4.1.5322.22.3.3.1 */
 +    {
 +        { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x01" },
 +        setCredRadiusConfigFile,
 +    },
 +    /* 1.3.6.1.4.1.5322.22.3.3.2 */
 +    {
 +        { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x02" },
 +        setCredRadiusConfigStanza,
 +    },
 +    /* 1.3.6.1.4.1.5322.22.3.3.3 */
 +    {
 +        { 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_CRED_PRIVATE_KEY       = &setCredOps[4].oid;
 +};
 +
 +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 GSSAPI_CALLCONV
 +gssspi_set_cred_option(OM_uint32 *minor,
 +                       gss_cred_id_t *pCred,
 +                       const gss_OID desired_object,
 +                       const gss_buffer_t value)
 +{
 +    OM_uint32 major;
 +    gss_cred_id_t cred = *pCred;
 +    int i;
 +
 +    if (cred == GSS_C_NO_CREDENTIAL) {
 +        *minor = EINVAL;
 +        return GSS_S_UNAVAILABLE;
 +    }
 +
 +    GSSEAP_MUTEX_LOCK(&cred->mutex);
 +
 +    major = GSS_S_UNAVAILABLE;
 +    *minor = GSSEAP_BAD_CRED_OPTION;
 +
 +    for (i = 0; i < sizeof(setCredOps) / sizeof(setCredOps[0]); i++) {
 +        if (oidEqual(&setCredOps[i].oid, desired_object)) {
 +            major = (*setCredOps[i].setOption)(minor, cred,
 +                                               desired_object, value);
 +            break;
 +        }
 +    }
 +
 +    GSSEAP_MUTEX_UNLOCK(&cred->mutex);
 +
 +    return major;
 +}
 +
 +#if 0
 +OM_uint32
 +gsseap_set_cred_flag(OM_uint32 *minor,
 +                     gss_cred_id_t cred,
 +                     OM_uint32 flag,
 +                     int clear)
 +{
 +    unsigned char buf[5];
 +    gss_buffer_desc value;
 +
 +    value.length = sizeof(buf);
 +    value.value = buf;
 +
 +    store_uint32_be(flag, buf);
 +    buf[4] = (clear != 0);
 +
 +    return gssspi_set_cred_option(minor, &cred,
 +                                  GSS_EAP_CRED_SET_CRED_FLAG, &value);
 +}
 +#endif
diff --cc mech_eap/util.h
index 7a6c094,0000000..4f54d41
mode 100644,000000..100644
--- /dev/null
@@@ -1,1038 -1,0 +1,1032 @@@
- gssEapSetCredClientCertificate(OM_uint32 *minor,
-                                gss_cred_id_t cred,
-                                const gss_buffer_t clientCert,
-                                const gss_buffer_t privateKey);
- OM_uint32
 +/*
 + * 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.
 + */
 +/*
 + * Portions Copyright 2003-2010 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.
 + *
 + */
 +
 +/*
 + * Utility functions.
 + */
 +
 +#ifndef _UTIL_H_
 +#define _UTIL_H_ 1
 +
 +#ifdef HAVE_SYS_PARAM_H
 +#include <sys/param.h>
 +#endif
 +#ifdef HAVE_STDINT_H
 +#include <stdint.h>
 +#endif
 +#include <string.h>
 +#include <errno.h>
 +
 +#include <krb5.h>
 +
 +#ifdef WIN32
 +#define inline __inline
 +#define snprintf _snprintf
 +#endif
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +#ifndef MIN
 +#define MIN(_a,_b)  ((_a)<(_b)?(_a):(_b))
 +#endif
 +
 +#if !defined(WIN32) && !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
 +#define GSSEAP_UNUSED __attribute__ ((__unused__))
 +#else
 +#define GSSEAP_UNUSED
 +#endif
 +
 +/* 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,
 +               char **pString);
 +
 +OM_uint32
 +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)
 +{
 +    return (b1->length == b2->length &&
 +            memcmp(b1->value, b2->value, b2->length) == 0);
 +}
 +
 +static inline int
 +bufferEqualString(const gss_buffer_t b1, const char *s)
 +{
 +    gss_buffer_desc b2;
 +
 +    b2.length = strlen(s);
 +    b2.value = (char *)s;
 +
 +    return bufferEqual(b1, &b2);
 +}
 +
 +/* util_cksum.c */
 +int
 +gssEapSign(krb5_context context,
 +           krb5_cksumtype type,
 +           size_t rrc,
 +#ifdef HAVE_HEIMDAL_VERSION
 +           krb5_crypto crypto,
 +#else
 +           krb5_keyblock *key,
 +#endif
 +           krb5_keyusage sign_usage,
 +           gss_iov_buffer_desc *iov,
 +           int iov_count);
 +
 +int
 +gssEapVerify(krb5_context context,
 +             krb5_cksumtype type,
 +             size_t rrc,
 +#ifdef HAVE_HEIMDAL_VERSION
 +             krb5_crypto crypto,
 +#else
 +             krb5_keyblock *key,
 +#endif
 +             krb5_keyusage sign_usage,
 +             gss_iov_buffer_desc *iov,
 +             int iov_count,
 +             int *valid);
 +
 +#if 0
 +OM_uint32
 +gssEapEncodeGssChannelBindings(OM_uint32 *minor,
 +                               gss_channel_bindings_t chanBindings,
 +                               gss_buffer_t encodedBindings);
 +#endif
 +
 +/* util_context.c */
 +#define EAP_EXPORT_CONTEXT_V1           1
 +
 +enum gss_eap_token_type {
 +    TOK_TYPE_NONE                    = 0x0000,  /* no token */
 +    TOK_TYPE_MIC                     = 0x0404,  /* RFC 4121 MIC token */
 +    TOK_TYPE_WRAP                    = 0x0504,  /* RFC 4121 wrap token */
 +    TOK_TYPE_EXPORT_NAME             = 0x0401,  /* RFC 2743 exported name */
 +    TOK_TYPE_EXPORT_NAME_COMPOSITE   = 0x0402,  /* exported composite name */
 +    TOK_TYPE_DELETE_CONTEXT          = 0x0405,  /* RFC 2743 delete context */
 +    TOK_TYPE_INITIATOR_CONTEXT       = 0x0601,  /* initiator-sent context token */
 +    TOK_TYPE_ACCEPTOR_CONTEXT        = 0x0602,  /* acceptor-sent context token */
 +};
 +
 +/* inner token types and flags */
 +#define ITOK_TYPE_NONE                  0x00000000
 +#define ITOK_TYPE_CONTEXT_ERR           0x00000001 /* critical */
 +#define ITOK_TYPE_ACCEPTOR_NAME_REQ     0x00000002 /* TBD */
 +#define ITOK_TYPE_ACCEPTOR_NAME_RESP    0x00000003 /* TBD */
 +#define ITOK_TYPE_EAP_RESP              0x00000004 /* critical, required, if not reauth */
 +#define ITOK_TYPE_EAP_REQ               0x00000005 /* critical, required, if not reauth */
 +#define ITOK_TYPE_GSS_CHANNEL_BINDINGS  0x00000006 /* critical, required, if not reauth */
 +#define ITOK_TYPE_REAUTH_CREDS          0x00000007 /* optional */
 +#define ITOK_TYPE_REAUTH_REQ            0x00000008 /* optional */
 +#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             | \
 +                                          GSS_C_DCE_STYLE               | \
 +                                          GSS_C_IDENTIFY_FLAG           | \
 +                                          GSS_C_EXTENDED_ERROR_FLAG       )
 +
 +OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
 +OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
 +
 +OM_uint32
 +gssEapMakeToken(OM_uint32 *minor,
 +                gss_ctx_id_t ctx,
 +                const gss_buffer_t innerToken,
 +                enum gss_eap_token_type tokenType,
 +                gss_buffer_t outputToken);
 +
 +OM_uint32
 +gssEapVerifyToken(OM_uint32 *minor,
 +                  gss_ctx_id_t ctx,
 +                  const gss_buffer_t inputToken,
 +                  enum gss_eap_token_type *tokenType,
 +                  gss_buffer_t innerInputToken);
 +
 +OM_uint32
 +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,
 +                  OM_uint32 timeReq,
 +                  const gss_OID_set desiredMechs,
 +                  int cred_usage,
 +                  gss_cred_id_t *pCred,
 +                  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
 +gssEapInquireCred(OM_uint32 *minor,
 +                  gss_cred_id_t cred,
 +                  gss_name_t *name,
 +                  OM_uint32 *pLifetime,
 +                  gss_cred_usage_t *cred_usage,
 +                  gss_OID_set *mechanisms);
 +
 +/* util_crypt.c */
 +int
 +gssEapEncrypt(krb5_context context, int dce_style, size_t ec,
 +              size_t rrc,
 +#ifdef HAVE_HEIMDAL_VERSION
 +              krb5_crypto crypto,
 +#else
 +              krb5_keyblock *key,
 +#endif
 +              int usage,
 +              gss_iov_buffer_desc *iov, int iov_count);
 +
 +int
 +gssEapDecrypt(krb5_context context, int dce_style, size_t ec,
 +              size_t rrc,
 +#ifdef HAVE_HEIMDAL_VERSION
 +              krb5_crypto crypto,
 +#else
 +              krb5_keyblock *key,
 +#endif
 +              int usage,
 +              gss_iov_buffer_desc *iov, int iov_count);
 +
 +int
 +gssEapMapCryptoFlag(OM_uint32 type);
 +
 +gss_iov_buffer_t
 +gssEapLocateIov(gss_iov_buffer_desc *iov,
 +                int iov_count,
 +                OM_uint32 type);
 +
 +void
 +gssEapIovMessageLength(gss_iov_buffer_desc *iov,
 +                       int iov_count,
 +                       size_t *data_length,
 +                       size_t *assoc_data_length);
 +
 +void
 +gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count);
 +
 +int
 +gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count);
 +
 +int
 +gssEapAllocIov(gss_iov_buffer_t iov, size_t size);
 +
 +OM_uint32
 +gssEapDeriveRfc3961Key(OM_uint32 *minor,
 +                       const unsigned char *key,
 +                       size_t keyLength,
 +                       krb5_enctype enctype,
 +                       krb5_keyblock *pKey);
 +
 +/* util_krb.c */
 +
 +#ifndef KRB_MALLOC
 +/*
 + * If your Kerberos library uses a different allocator to your
 + * GSS mechanism glue, then you might wish to define these in
 + * config.h or elsewhere. This should eventually go away when
 + * we no longer need to allocate memory that is freed by the
 + * Kerberos library.
 + */
 +#define KRB_CALLOC                      calloc
 +#define KRB_MALLOC                      malloc
 +#define KRB_FREE                        free
 +#define KRB_REALLOC                     realloc
 +#endif /* KRB_MALLOC */
 +
 +#ifdef HAVE_HEIMDAL_VERSION
 +
 +#define KRB_TIME_FOREVER        ((time_t)~0L)
 +
 +#define KRB_KEY_TYPE(key)       ((key)->keytype)
 +#define KRB_KEY_DATA(key)       ((key)->keyvalue.data)
 +#define KRB_KEY_LENGTH(key)     ((key)->keyvalue.length)
 +
 +#define KRB_PRINC_LENGTH(princ) ((princ)->name.name_string.len)
 +#define KRB_PRINC_TYPE(princ)   ((princ)->name.name_type)
 +#define KRB_PRINC_NAME(princ)   ((princ)->name.name_string.val)
 +#define KRB_PRINC_REALM(princ)  ((princ)->realm)
 +
 +#define KRB_KT_ENT_KEYBLOCK(e)  (&(e)->keyblock)
 +#define KRB_KT_ENT_FREE(c, e)   krb5_kt_free_entry((c), (e))
 +
 +#define KRB_CRYPTO_CONTEXT(ctx) (krbCrypto)
 +
 +#define KRB_DATA_INIT(d)        krb5_data_zero((d))
 +
 +#else
 +
 +#define KRB_TIME_FOREVER        KRB5_INT32_MAX
 +
 +#define KRB_KEY_TYPE(key)       ((key)->enctype)
 +#define KRB_KEY_DATA(key)       ((key)->contents)
 +#define KRB_KEY_LENGTH(key)     ((key)->length)
 +
 +#define KRB_PRINC_LENGTH(princ) (krb5_princ_size(NULL, (princ)))
 +#define KRB_PRINC_TYPE(princ)   (krb5_princ_type(NULL, (princ)))
 +#define KRB_PRINC_NAME(princ)   (krb5_princ_name(NULL, (princ)))
 +#define KRB_PRINC_REALM(princ)  (krb5_princ_realm(NULL, (princ)))
 +
 +#define KRB_KT_ENT_KEYBLOCK(e)  (&(e)->key)
 +#define KRB_KT_ENT_FREE(c, e)   krb5_free_keytab_entry_contents((c), (e))
 +
 +#define KRB_CRYPTO_CONTEXT(ctx) (&(ctx)->rfc3961Key)
 +
 +#define KRB_DATA_INIT(d)        do {        \
 +        (d)->magic = KV5M_DATA;             \
 +        (d)->length = 0;                    \
 +        (d)->data = NULL;                   \
 +    } while (0)
 +
 +#endif /* HAVE_HEIMDAL_VERSION */
 +
 +#define KRB_KEY_INIT(key)       do {        \
 +        KRB_KEY_TYPE(key) = ENCTYPE_NULL;   \
 +        KRB_KEY_DATA(key) = NULL;           \
 +        KRB_KEY_LENGTH(key) = 0;            \
 +    } while (0)
 +
 +#define GSSEAP_KRB_INIT(ctx) do {                   \
 +        OM_uint32 tmpMajor;                         \
 +                                                    \
 +        tmpMajor  = gssEapKerberosInit(minor, ctx); \
 +        if (GSS_ERROR(tmpMajor)) {                  \
 +            return tmpMajor;                        \
 +        }                                           \
 +    } while (0)
 +
 +OM_uint32
 +gssEapKerberosInit(OM_uint32 *minor, krb5_context *context);
 +
 +OM_uint32
 +rfc3961ChecksumTypeForKey(OM_uint32 *minor,
 +                          krb5_keyblock *key,
 +                          krb5_cksumtype *cksumtype);
 +
 +krb5_error_code
 +krbCryptoLength(krb5_context krbContext,
 +#ifdef HAVE_HEIMDAL_VERSION
 +                krb5_crypto krbCrypto,
 +#else
 +                krb5_keyblock *key,
 +#endif
 +                int type,
 +                size_t *length);
 +
 +krb5_error_code
 +krbPaddingLength(krb5_context krbContext,
 +#ifdef HAVE_HEIMDAL_VERSION
 +                 krb5_crypto krbCrypto,
 +#else
 +                 krb5_keyblock *key,
 +#endif
 +                 size_t dataLength,
 +                 size_t *padLength);
 +
 +krb5_error_code
 +krbBlockSize(krb5_context krbContext,
 +#ifdef HAVE_HEIMDAL_VERSION
 +                 krb5_crypto krbCrypto,
 +#else
 +                 krb5_keyblock *key,
 +#endif
 +                 size_t *blockSize);
 +
 +krb5_error_code
 +krbEnctypeToString(krb5_context krbContext,
 +                   krb5_enctype enctype,
 +                   const char *prefix,
 +                   gss_buffer_t string);
 +
 +krb5_error_code
 +krbMakeAuthDataKdcIssued(krb5_context context,
 +                         const krb5_keyblock *key,
 +                         krb5_const_principal issuer,
 +#ifdef HAVE_HEIMDAL_VERSION
 +                         const AuthorizationData *authdata,
 +                         AuthorizationData *adKdcIssued
 +#else
 +                         krb5_authdata *const *authdata,
 +                         krb5_authdata ***adKdcIssued
 +#endif
 +                         );
 +
 +krb5_error_code
 +krbMakeCred(krb5_context context,
 +            krb5_auth_context authcontext,
 +            krb5_creds *creds,
 +            krb5_data *data);
 +
 +/* util_lucid.c */
 +OM_uint32
 +gssEapExportLucidSecContext(OM_uint32 *minor,
 +                            gss_ctx_id_t ctx,
 +                            const gss_OID desiredObject,
 +                            gss_buffer_set_t *data_set);
 +
 +/* util_mech.c */
 +extern gss_OID GSS_EAP_MECHANISM;
 +
 +#define OID_FLAG_NULL_VALID                 0x00000001
 +#define OID_FLAG_FAMILY_MECH_VALID          0x00000002
 +#define OID_FLAG_MAP_NULL_TO_DEFAULT_MECH   0x00000004
 +#define OID_FLAG_MAP_FAMILY_MECH_TO_NULL    0x00000008
 +
 +OM_uint32
 +gssEapCanonicalizeOid(OM_uint32 *minor,
 +                      const gss_OID oid,
 +                      OM_uint32 flags,
 +                      gss_OID *pOid);
 +
 +OM_uint32
 +gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid);
 +
 +OM_uint32
 +gssEapDefaultMech(OM_uint32 *minor,
 +                  gss_OID *oid);
 +
 +OM_uint32
 +gssEapIndicateMechs(OM_uint32 *minor,
 +                    gss_OID_set *mechs);
 +
 +OM_uint32
 +gssEapEnctypeToOid(OM_uint32 *minor,
 +                   krb5_enctype enctype,
 +                   gss_OID *pOid);
 +
 +OM_uint32
 +gssEapOidToEnctype(OM_uint32 *minor,
 +                   const gss_OID oid,
 +                   krb5_enctype *enctype);
 +
 +int
 +gssEapIsMechanismOid(const gss_OID oid);
 +
 +int
 +gssEapIsConcreteMechanismOid(const gss_OID oid);
 +
 +OM_uint32
 +gssEapValidateMechs(OM_uint32 *minor,
 +                   const gss_OID_set mechs);
 +
 +gss_buffer_t
 +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
 +#define EXPORT_NAME_FLAG_ALLOW_COMPOSITE        0x4
 +
 +OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
 +OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
 +OM_uint32 gssEapExportName(OM_uint32 *minor,
 +                           const gss_name_t name,
 +                           gss_buffer_t exportedName);
 +OM_uint32 gssEapExportNameInternal(OM_uint32 *minor,
 +                                   const gss_name_t name,
 +                                   gss_buffer_t exportedName,
 +                                   OM_uint32 flags);
 +OM_uint32 gssEapImportName(OM_uint32 *minor,
 +                           const gss_buffer_t input_name_buffer,
 +                           const gss_OID input_name_type,
 +                           const gss_OID input_mech_type,
 +                           gss_name_t *output_name);
 +OM_uint32 gssEapImportNameInternal(OM_uint32 *minor,
 +                                   const gss_buffer_t input_name_buffer,
 +                                   gss_name_t *output_name,
 +                                   OM_uint32 flags);
 +OM_uint32
 +gssEapDuplicateName(OM_uint32 *minor,
 +                    const gss_name_t input_name,
 +                    gss_name_t *dest_name);
 +
 +OM_uint32
 +gssEapCanonicalizeName(OM_uint32 *minor,
 +                       const gss_name_t input_name,
 +                       const gss_OID mech_type,
 +                       gss_name_t *dest_name);
 +
 +OM_uint32
 +gssEapDisplayName(OM_uint32 *minor,
 +                  gss_name_t name,
 +                  gss_buffer_t output_name_buffer,
 +                  gss_OID *output_name_type);
 +
 +OM_uint32
 +gssEapCompareName(OM_uint32 *minor,
 +                  gss_name_t name1,
 +                  gss_name_t name2,
 +                  int *name_equal);
 +
 +/* util_oid.c */
 +OM_uint32
 +composeOid(OM_uint32 *minor_status,
 +           const char *prefix,
 +           size_t prefix_len,
 +           int suffix,
 +           gss_OID_desc *oid);
 +
 +OM_uint32
 +decomposeOid(OM_uint32 *minor_status,
 +             const char *prefix,
 +             size_t prefix_len,
 +             gss_OID_desc *oid,
 +             int *suffix) ;
 +
 +OM_uint32
 +duplicateOid(OM_uint32 *minor_status,
 +             const gss_OID_desc * const oid,
 +             gss_OID *new_oid);
 +
 +OM_uint32
 +duplicateOidSet(OM_uint32 *minor,
 +                const gss_OID_set src,
 +                gss_OID_set *dst);
 +
 +static inline int
 +oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2)
 +{
 +    if (o1 == GSS_C_NO_OID)
 +        return (o2 == GSS_C_NO_OID);
 +    else if (o2 == GSS_C_NO_OID)
 +        return (o1 == GSS_C_NO_OID);
 +    else
 +        return (o1->length == o2->length &&
 +                memcmp(o1->elements, o2->elements, o1->length) == 0);
 +}
 +
 +/* util_ordering.c */
 +OM_uint32
 +sequenceInternalize(OM_uint32 *minor,
 +                    void **vqueue,
 +                    unsigned char **buf,
 +                    size_t *lenremain);
 +
 +OM_uint32
 +sequenceExternalize(OM_uint32 *minor,
 +                    void *vqueue,
 +                    unsigned char **buf,
 +                    size_t *lenremain);
 +
 +size_t
 +sequenceSize(void *vqueue);
 +
 +OM_uint32
 +sequenceFree(OM_uint32 *minor, void **vqueue);
 +
 +OM_uint32
 +sequenceCheck(OM_uint32 *minor, void **vqueue, uint64_t seqnum);
 +
 +OM_uint32
 +sequenceInit(OM_uint32 *minor, void **vqueue, uint64_t seqnum,
 +             int do_replay, int do_sequence, int wide_nums);
 +
 +/* util_sm.c */
 +enum gss_eap_state {
 +    GSSEAP_STATE_INITIAL        = 0x01,     /* initial state */
 +    GSSEAP_STATE_AUTHENTICATE   = 0x02,     /* exchange EAP messages */
 +    GSSEAP_STATE_INITIATOR_EXTS = 0x04,     /* initiator extensions */
 +    GSSEAP_STATE_ACCEPTOR_EXTS  = 0x08,     /* acceptor extensions */
 +#ifdef GSSEAP_ENABLE_REAUTH
 +    GSSEAP_STATE_REAUTHENTICATE = 0x10,     /* GSS reauthentication messages */
 +#endif
 +    GSSEAP_STATE_ESTABLISHED    = 0x20,     /* context established */
 +    GSSEAP_STATE_ALL            = 0x3F
 +};
 +
 +#define GSSEAP_STATE_NEXT(s)    ((s) << 1)
 +
 +#define GSSEAP_SM_STATE(ctx)                ((ctx)->state)
 +
 +#ifdef GSSEAP_DEBUG
 +void gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
 +#define GSSEAP_SM_TRANSITION(ctx, state)    gssEapSmTransition((ctx), (state))
 +#else
 +#define GSSEAP_SM_TRANSITION(ctx, newstate)    do { (ctx)->state = (newstate); } while (0)
 +#endif
 +
 +#define GSSEAP_SM_TRANSITION_NEXT(ctx)      GSSEAP_SM_TRANSITION((ctx), GSSEAP_STATE_NEXT(GSSEAP_SM_STATE((ctx))))
 +
 +/* state machine entry */
 +struct gss_eap_sm {
 +    OM_uint32 inputTokenType;
 +    OM_uint32 outputTokenType;
 +    enum gss_eap_state validStates;
 +    OM_uint32 itokFlags;
 +    OM_uint32 (*processToken)(OM_uint32 *,
 +                              gss_cred_id_t,
 +                              gss_ctx_id_t,
 +                              gss_name_t,
 +                              gss_OID,
 +                              OM_uint32,
 +                              OM_uint32,
 +                              gss_channel_bindings_t,
 +                              gss_buffer_t,
 +                              gss_buffer_t,
 +                              OM_uint32 *);
 +};
 +
 +/* state machine flags, set by handler */
 +#define SM_FLAG_FORCE_SEND_TOKEN            0x00000001  /* send token even if no inner tokens */
 +#define SM_FLAG_OUTPUT_TOKEN_CRITICAL       0x00000002  /* output token is critical */
 +
 +/* state machine flags, set by state machine */
 +#define SM_FLAG_INPUT_TOKEN_CRITICAL        0x10000000  /* input token was critical */
 +
 +#define SM_ITOK_FLAG_REQUIRED               0x00000001  /* received tokens must be present */
 +
 +OM_uint32
 +gssEapSmStep(OM_uint32 *minor,
 +             gss_cred_id_t cred,
 +             gss_ctx_id_t ctx,
 +             gss_name_t target,
 +             gss_OID mech,
 +             OM_uint32 reqFlags,
 +             OM_uint32 timeReq,
 +             gss_channel_bindings_t chanBindings,
 +             gss_buffer_t inputToken,
 +             gss_buffer_t outputToken,
 +             struct gss_eap_sm *sm,
 +             size_t smCount);
 +
 +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,
 +                        struct gss_eap_token_buffer_set *tokens,
 +                        gss_buffer_t buffer);
 +OM_uint32
 +gssEapDecodeInnerTokens(OM_uint32 *minor,
 +                        const gss_buffer_t buffer,
 +                        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);
 +
 +void
 +makeTokenHeader(const gss_OID_desc *mech,
 +                size_t body_size,
 +                unsigned char **buf,
 +                enum gss_eap_token_type tok_type);
 +
 +OM_uint32
 +verifyTokenHeader(OM_uint32 *minor,
 +                  gss_OID mech,
 +                  size_t *body_size,
 +                  unsigned char **buf_in,
 +                  size_t toksize_in,
 +                  enum gss_eap_token_type *ret_tok_type);
 +
 +/* Helper macros */
 +
 +#ifndef GSSEAP_MALLOC
 +#define GSSEAP_CALLOC                   calloc
 +#define GSSEAP_MALLOC                   malloc
 +#define GSSEAP_FREE                     free
 +#define GSSEAP_REALLOC                  realloc
 +#endif
 +
 +#ifndef GSSAPI_CALLCONV
 +#define GSSAPI_CALLCONV                 KRB5_CALLCONV
 +#endif
 +
 +#ifndef GSSEAP_ASSERT
 +#include <assert.h>
 +#define GSSEAP_ASSERT(x)                assert((x))
 +#endif /* !GSSEAP_ASSERT */
 +
 +#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 {            \
 +        GSSEAP_ASSERT(0 && "not implemented");          \
 +        *minor = ENOSYS;                                \
 +        return GSS_S_FAILURE;                           \
 +    } while (0)
 +
 +#ifdef WIN32
 +
 +#include <winbase.h>
 +
 +#define GSSEAP_GET_LAST_ERROR()         (GetLastError()) /* XXX FIXME */
 +
 +#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))
 +#define GSSEAP_ONCE_LEAVE             do { return TRUE; } while (0)
 +
 +/* Thread-local is handled separately */
 +
 +#define GSSEAP_THREAD_ONCE              INIT_ONCE
 +#define GSSEAP_ONCE_CALLBACK(cb)        BOOL CALLBACK cb(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
 +#define GSSEAP_ONCE(o, i)               InitOnceExecuteOnce((o), (i), NULL, NULL)
 +#define GSSEAP_ONCE_INITIALIZER         INIT_ONCE_STATIC_INIT
 +
 +#else
 +
 +#include <pthread.h>
 +
 +#define GSSEAP_GET_LAST_ERROR()         (errno)
 +
 +#define GSSEAP_MUTEX                    pthread_mutex_t
 +#define GSSEAP_MUTEX_INIT(m)            pthread_mutex_init((m), NULL)
 +#define GSSEAP_MUTEX_DESTROY(m)         pthread_mutex_destroy((m))
 +#define GSSEAP_MUTEX_LOCK(m)            pthread_mutex_lock((m))
 +#define GSSEAP_MUTEX_UNLOCK(m)          pthread_mutex_unlock((m))
 +
 +#define GSSEAP_THREAD_KEY               pthread_key_t
 +#define GSSEAP_KEY_CREATE(k, d)         pthread_key_create((k), (d))
 +#define GSSEAP_GETSPECIFIC(k)           pthread_getspecific((k))
 +#define GSSEAP_SETSPECIFIC(k, d)        pthread_setspecific((k), (d))
 +
 +#define GSSEAP_THREAD_ONCE              pthread_once_t
 +#define GSSEAP_ONCE_CALLBACK(cb)        void cb(void)
 +#define GSSEAP_ONCE(o, i)               pthread_once((o), (i))
 +#define GSSEAP_ONCE_INITIALIZER         PTHREAD_ONCE_INIT
 +#define GSSEAP_ONCE_LEAVE             do { } while (0)
 +
 +#endif /* WIN32 */
 +
 +/* Helper functions */
 +static inline void
 +store_uint16_be(uint16_t val, void *vp)
 +{
 +    unsigned char *p = (unsigned char *)vp;
 +
 +    p[0] = (val >>  8) & 0xff;
 +    p[1] = (val      ) & 0xff;
 +}
 +
 +static inline uint16_t
 +load_uint16_be(const void *cvp)
 +{
 +    const unsigned char *p = (const unsigned char *)cvp;
 +
 +    return (p[1] | (p[0] << 8));
 +}
 +
 +static inline void
 +store_uint32_be(uint32_t val, void *vp)
 +{
 +    unsigned char *p = (unsigned char *)vp;
 +
 +    p[0] = (val >> 24) & 0xff;
 +    p[1] = (val >> 16) & 0xff;
 +    p[2] = (val >>  8) & 0xff;
 +    p[3] = (val      ) & 0xff;
 +}
 +
 +static inline uint32_t
 +load_uint32_be(const void *cvp)
 +{
 +    const unsigned char *p = (const unsigned char *)cvp;
 +
 +    return (p[3] | (p[2] << 8)
 +            | ((uint32_t) p[1] << 16)
 +            | ((uint32_t) p[0] << 24));
 +}
 +
 +static inline void
 +store_uint64_be(uint64_t val, void *vp)
 +{
 +    unsigned char *p = (unsigned char *)vp;
 +
 +    p[0] = (unsigned char)((val >> 56) & 0xff);
 +    p[1] = (unsigned char)((val >> 48) & 0xff);
 +    p[2] = (unsigned char)((val >> 40) & 0xff);
 +    p[3] = (unsigned char)((val >> 32) & 0xff);
 +    p[4] = (unsigned char)((val >> 24) & 0xff);
 +    p[5] = (unsigned char)((val >> 16) & 0xff);
 +    p[6] = (unsigned char)((val >>  8) & 0xff);
 +    p[7] = (unsigned char)((val      ) & 0xff);
 +}
 +
 +static inline uint64_t
 +load_uint64_be(const void *cvp)
 +{
 +    const unsigned char *p = (const unsigned char *)cvp;
 +
 +    return ((uint64_t)load_uint32_be(p) << 32) | load_uint32_be(p + 4);
 +}
 +
 +static inline unsigned char *
 +store_buffer(gss_buffer_t buffer, void *vp, int wide_nums)
 +{
 +    unsigned char *p = (unsigned char *)vp;
 +
 +    if (wide_nums) {
 +        store_uint64_be(buffer->length, p);
 +        p += 8;
 +    } else {
 +        store_uint32_be(buffer->length, p);
 +        p += 4;
 +    }
 +
 +    if (buffer->value != NULL) {
 +        memcpy(p, buffer->value, buffer->length);
 +        p += buffer->length;
 +    }
 +
 +    return p;
 +}
 +
 +static inline unsigned char *
 +load_buffer(const void *cvp, size_t length, gss_buffer_t buffer)
 +{
 +    buffer->length = 0;
 +    buffer->value = GSSEAP_MALLOC(length);
 +    if (buffer->value == NULL)
 +        return NULL;
 +    buffer->length = length;
 +    memcpy(buffer->value, cvp, length);
 +    return (unsigned char *)cvp + length;
 +}
 +
 +static inline unsigned char *
 +store_oid(gss_OID oid, void *vp)
 +{
 +    gss_buffer_desc buf;
 +
 +    if (oid != GSS_C_NO_OID) {
 +        buf.length = oid->length;
 +        buf.value = oid->elements;
 +    } else {
 +        buf.length = 0;
 +        buf.value = NULL;
 +    }
 +
 +    return store_buffer(&buf, vp, FALSE);
 +}
 +
 +static inline void
 +krbDataToGssBuffer(krb5_data *data, gss_buffer_t buffer)
 +{
 +    buffer->value = (void *)data->data;
 +    buffer->length = data->length;
 +}
 +
 +static inline void
 +krbPrincComponentToGssBuffer(krb5_principal krbPrinc,
 +                             int index, gss_buffer_t buffer)
 +{
 +#ifdef HAVE_HEIMDAL_VERSION
 +    buffer->value = (void *)KRB_PRINC_NAME(krbPrinc)[index];
 +    buffer->length = strlen((char *)buffer->value);
 +#else
 +    buffer->value = (void *)krb5_princ_component(NULL, krbPrinc, index)->data;
 +    buffer->length = krb5_princ_component(NULL, krbPrinc, index)->length;
 +#endif /* HAVE_HEIMDAL_VERSION */
 +}
 +
 +static inline void
 +krbPrincRealmToGssBuffer(krb5_principal krbPrinc, gss_buffer_t buffer)
 +{
 +#ifdef HAVE_HEIMDAL_VERSION
 +    buffer->value = (void *)KRB_PRINC_REALM(krbPrinc);
 +    buffer->length = strlen((char *)buffer->value);
 +#else
 +    krbDataToGssBuffer(KRB_PRINC_REALM(krbPrinc), buffer);
 +#endif
 +}
 +
 +static inline void
 +gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data)
 +{
 +    data->data = (char *)buffer->value;
 +    data->length = buffer->length;
 +}
 +
 +/* util_tld.c */
 +struct gss_eap_status_info;
 +
 +struct gss_eap_thread_local_data {
 +    krb5_context krbContext;
 +    struct gss_eap_status_info *statusInfo;
 +};
 +
 +struct gss_eap_thread_local_data *
 +gssEapGetThreadLocalData(void);
 +
 +void
 +gssEapDestroyStatusInfo(struct gss_eap_status_info *status);
 +
 +void
 +gssEapDestroyKrbContext(krb5_context context);
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#ifdef GSSEAP_ENABLE_ACCEPTOR
 +#include "util_json.h"
 +#include "util_attr.h"
 +#include "util_base64.h"
 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
 +#ifdef GSSEAP_ENABLE_REAUTH
 +#include "util_reauth.h"
 +#endif
 +
 +#endif /* _UTIL_H_ */
index 53a19a7,0000000..746bd61
mode 100644,000000..100644
--- /dev/null
@@@ -1,844 -1,0 +1,756 @@@
-     gss_release_buffer(&tmpMinor, &cred->privateKey);
-     gss_release_buffer(&tmpMinor, &cred->clientCertificate);
 +/*
 + * 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.
 + */
 +
 +/*
 + * Utility routines for credential handles.
 + */
 +
 +#include "gssapiP_eap.h"
 +
 +#ifdef WIN32
 +# include <shlobj.h>     /* may need to use ShFolder.h instead */
 +# include <stdio.h>
 +#else
 +# include <pwd.h>
 +#endif
 +
 +OM_uint32
 +gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
 +{
 +    OM_uint32 tmpMinor;
 +    gss_cred_id_t cred;
 +
 +    *pCred = GSS_C_NO_CREDENTIAL;
 +
 +    cred = (gss_cred_id_t)GSSEAP_CALLOC(1, sizeof(*cred));
 +    if (cred == NULL) {
 +        *minor = ENOMEM;
 +        return GSS_S_FAILURE;
 +    }
 +
 +    if (GSSEAP_MUTEX_INIT(&cred->mutex) != 0) {
 +        *minor = GSSEAP_GET_LAST_ERROR();
 +        gssEapReleaseCred(&tmpMinor, &cred);
 +        return GSS_S_FAILURE;
 +    }
 +
 +    *pCred = cred;
 +
 +    *minor = 0;
 +    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)
 +{
 +    OM_uint32 tmpMinor;
 +    gss_cred_id_t cred = *pCred;
 +    krb5_context krbContext = NULL;
 +
 +    if (cred == GSS_C_NO_CREDENTIAL) {
 +        return GSS_S_COMPLETE;
 +    }
 +
 +    GSSEAP_KRB_INIT(&krbContext);
 +
 +    gssEapReleaseName(&tmpMinor, &cred->name);
 +    gssEapReleaseName(&tmpMinor, &cred->target);
 +
 +    zeroAndReleasePassword(&cred->password);
 +
 +    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);
-                        gss_buffer_t defaultPassword,
-                        gss_buffer_t defaultPrivateKey)
 +
 +#ifdef GSSEAP_ENABLE_REAUTH
 +    if (cred->krbCredCache != NULL) {
 +        if (cred->flags & CRED_FLAG_DEFAULT_CCACHE)
 +            krb5_cc_close(krbContext, cred->krbCredCache);
 +        else
 +            krb5_cc_destroy(krbContext, cred->krbCredCache);
 +    }
 +    if (cred->reauthCred != GSS_C_NO_CREDENTIAL)
 +        gssReleaseCred(&tmpMinor, &cred->reauthCred);
 +#endif
 +
 +    GSSEAP_MUTEX_DESTROY(&cred->mutex);
 +    memset(cred, 0, sizeof(*cred));
 +    GSSEAP_FREE(cred);
 +    *pCred = NULL;
 +
 +    *minor = 0;
 +    return GSS_S_COMPLETE;
 +}
 +
 +static OM_uint32
 +readStaticIdentityFile(OM_uint32 *minor,
 +                       gss_buffer_t defaultIdentity,
-     if (defaultPrivateKey != GSS_C_NO_BUFFER) {
-         defaultPrivateKey->length = 0;
-         defaultPrivateKey->value = NULL;
-     }
++                       gss_buffer_t defaultPassword)
 +{
 +    OM_uint32 major, tmpMinor;
 +    FILE *fp = NULL;
 +    char buf[BUFSIZ];
 +    char *ccacheName;
 +    int i = 0;
 +#ifndef WIN32
 +    struct passwd *pw = NULL, pwd;
 +    char pwbuf[BUFSIZ];
 +#endif
 +
 +    defaultIdentity->length = 0;
 +    defaultIdentity->value = NULL;
 +
 +    if (defaultPassword != GSS_C_NO_BUFFER) {
 +        defaultPassword->length = 0;
 +        defaultPassword->value = NULL;
 +    }
 +
-         else if (i == 2)
-             dst = defaultPrivateKey;
 +    ccacheName = getenv("GSSEAP_IDENTITY");
 +    if (ccacheName == 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 = GSSEAP_GET_LAST_ERROR(); /* XXX */
 +            goto cleanup;
 +        }
 +
 +        snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
 +#else
 +        if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
 +            pw == NULL || pw->pw_dir == NULL) {
 +            major = GSS_S_CRED_UNAVAIL;
 +            *minor = GSSEAP_GET_LAST_ERROR();
 +            goto cleanup;
 +        }
 +
 +        snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
 +#endif /* WIN32 */
 +        ccacheName = buf;
 +    }
 +
 +    fp = fopen(ccacheName, "r");
 +    if (fp == NULL) {
 +        major = GSS_S_CRED_UNAVAIL;
 +        *minor = GSSEAP_NO_DEFAULT_CRED;
 +        goto cleanup;
 +    }
 +
 +    while (fgets(buf, sizeof(buf), fp) != NULL) {
 +        gss_buffer_desc src, *dst;
 +
 +        src.length = strlen(buf);
 +        src.value = buf;
 +
 +        if (src.length == 0)
 +            break;
 +
 +        if (buf[src.length - 1] == '\n') {
 +            buf[src.length - 1] = '\0';
 +            if (--src.length == 0)
 +                break;
 +        }
 +
 +        if (i == 0)
 +            dst = defaultIdentity;
 +        else if (i == 1)
 +            dst = defaultPassword;
-         gss_release_buffer(&tmpMinor, defaultPrivateKey);
 +        else
 +            break;
 +
 +        if (dst != GSS_C_NO_BUFFER) {
 +            major = duplicateBuffer(minor, &src, dst);
 +            if (GSS_ERROR(major))
 +                goto cleanup;
 +        }
 +
 +        i++;
 +    }
 +
 +    if (defaultIdentity->length == 0) {
 +        major = GSS_S_CRED_UNAVAIL;
 +        *minor = GSSEAP_NO_DEFAULT_CRED;
 +        goto cleanup;
 +    }
 +
 +    major = GSS_S_COMPLETE;
 +    *minor = 0;
 +
 +cleanup:
 +    if (fp != NULL)
 +        fclose(fp);
 +
 +    if (GSS_ERROR(major)) {
 +        gss_release_buffer(&tmpMinor, defaultIdentity);
 +        zeroAndReleasePassword(defaultPassword);
-     major = readStaticIdentityFile(minor, &defaultIdentity,
-                                    GSS_C_NO_BUFFER, GSS_C_NO_BUFFER);
 +    }
 +
 +    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,
 +                  OM_uint32 timeReq GSSEAP_UNUSED,
 +                  const gss_OID_set desiredMechs,
 +                  int credUsage,
 +                  gss_cred_id_t *pCred,
 +                  gss_OID_set *pActualMechs,
 +                  OM_uint32 *timeRec)
 +{
 +    OM_uint32 major, tmpMinor;
 +    gss_cred_id_t cred;
 +
 +    /* XXX TODO validate with changed set_cred_option API */
 +    *pCred = GSS_C_NO_CREDENTIAL;
 +
 +    major = gssEapAllocCred(minor, &cred);
 +    if (GSS_ERROR(major))
 +        goto cleanup;
 +
 +    switch (credUsage) {
 +    case GSS_C_BOTH:
 +        cred->flags |= CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT;
 +        break;
 +    case GSS_C_INITIATE:
 +        cred->flags |= CRED_FLAG_INITIATE;
 +        break;
 +    case GSS_C_ACCEPT:
 +        cred->flags |= CRED_FLAG_ACCEPT;
 +        break;
 +    default:
 +        major = GSS_S_FAILURE;
 +        *minor = GSSEAP_BAD_USAGE;
 +        goto cleanup;
 +        break;
 +    }
 +
 +    major = gssEapValidateMechs(minor, desiredMechs);
 +    if (GSS_ERROR(major))
 +        goto cleanup;
 +
 +    major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms);
 +    if (GSS_ERROR(major))
 +        goto cleanup;
 +
 +    if (desiredName != GSS_C_NO_NAME) {
 +        GSSEAP_MUTEX_LOCK(&desiredName->mutex);
 +
 +        major = gssEapDuplicateName(minor, desiredName, &cred->name);
 +        if (GSS_ERROR(major)) {
 +            GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
 +            goto cleanup;
 +        }
 +
 +        GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
 +    }
 +
 +#ifdef GSSEAP_ENABLE_ACCEPTOR
 +    if (cred->flags & CRED_FLAG_ACCEPT) {
 +        struct rs_context *radContext;
 +
 +        major = gssEapCreateRadiusContext(minor, cred, &radContext);
 +        if (GSS_ERROR(major))
 +            goto cleanup;
 +
 +        rs_context_destroy(radContext);
 +    }
 +#endif
 +
 +    if (pActualMechs != NULL) {
 +        major = duplicateOidSet(minor, cred->mechanisms, pActualMechs);
 +        if (GSS_ERROR(major))
 +            goto cleanup;
 +    }
 +
 +    if (timeRec != NULL)
 +        *timeRec = GSS_C_INDEFINITE;
 +
 +    *pCred = cred;
 +
 +    major = GSS_S_COMPLETE;
 +    *minor = 0;
 +
 +cleanup:
 +    if (GSS_ERROR(major))
 +        gssEapReleaseCred(&tmpMinor, &cred);
 +
 +    return major;
 +}
 +
 +/*
 + * Return TRUE if cred available for mechanism. Caller need no acquire
 + * lock because mechanisms list is immutable.
 + */
 +int
 +gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech)
 +{
 +    OM_uint32 minor;
 +    int present = 0;
 +
 +    GSSEAP_ASSERT(mech != GSS_C_NO_OID);
 +
 +    if (cred == GSS_C_NO_CREDENTIAL || cred->mechanisms == GSS_C_NO_OID_SET)
 +        return TRUE;
 +
 +    gss_test_oid_set_member(&minor, mech, cred->mechanisms, &present);
 +
 +    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;
 +
- /*
-  * Currently only the privateKey path is exposed to the application
-  * (via gss_set_cred_option() or the third line in ~/.gss_eap_id).
-  * At some point in the future we may add support for setting the
-  * client certificate separately.
-  */
- OM_uint32
- gssEapSetCredClientCertificate(OM_uint32 *minor,
-                               gss_cred_id_t cred,
-                               const gss_buffer_t clientCert,
-                               const gss_buffer_t privateKey)
- {
-     OM_uint32 major, tmpMinor;
-     gss_buffer_desc newClientCert = GSS_C_EMPTY_BUFFER;
-     gss_buffer_desc newPrivateKey = GSS_C_EMPTY_BUFFER;
-     if (cred->flags & CRED_FLAG_RESOLVED) {
-         major = GSS_S_FAILURE;
-         *minor = GSSEAP_CRED_RESOLVED;
-         goto cleanup;
-     }
-     if (clientCert == GSS_C_NO_BUFFER &&
-         privateKey == GSS_C_NO_BUFFER) {
-         cred->flags &= ~(CRED_FLAG_CERTIFICATE);
-         major = GSS_S_COMPLETE;
-         *minor = 0;
-         goto cleanup;
-     }
-     if (clientCert != GSS_C_NO_BUFFER) {
-         major = duplicateBuffer(minor, clientCert, &newClientCert);
-         if (GSS_ERROR(major))
-             goto cleanup;
-     }
-     if (privateKey != GSS_C_NO_BUFFER) {
-         major = duplicateBuffer(minor, privateKey, &newPrivateKey);
-         if (GSS_ERROR(major))
-             goto cleanup;
-     }
-     cred->flags |= CRED_FLAG_CERTIFICATE;
-     gss_release_buffer(&tmpMinor, &cred->clientCertificate);
-     cred->clientCertificate = newClientCert;
-     gss_release_buffer(&tmpMinor, &cred->privateKey);
-     cred->privateKey = newPrivateKey;
-     major = GSS_S_COMPLETE;
-     *minor = 0;
- cleanup:
-     if (GSS_ERROR(major)) {
-         gss_release_buffer(&tmpMinor, &newClientCert);
-         gss_release_buffer(&tmpMinor, &newPrivateKey);
-     }
-     return major;
- }
++    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,
 +                  gss_name_t *name,
 +                  OM_uint32 *pLifetime,
 +                  gss_cred_usage_t *cred_usage,
 +                  gss_OID_set *mechanisms)
 +{
 +    OM_uint32 major;
 +    time_t now, lifetime;
 +
 +    if (name != NULL) {
 +        major = gssEapResolveCredIdentity(minor, cred);
 +        if (GSS_ERROR(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) {
 +        OM_uint32 flags = (cred->flags & (CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT));
 +
 +        switch (flags) {
 +        case CRED_FLAG_INITIATE:
 +            *cred_usage = GSS_C_INITIATE;
 +            break;
 +        case CRED_FLAG_ACCEPT:
 +            *cred_usage = GSS_C_ACCEPT;
 +            break;
 +        default:
 +            *cred_usage = GSS_C_BOTH;
 +            break;
 +        }
 +    }
 +
 +    if (mechanisms != NULL) {
 +        if (cred->mechanisms != GSS_C_NO_OID_SET)
 +            major = duplicateOidSet(minor, cred->mechanisms, mechanisms);
 +        else
 +            major = gssEapIndicateMechs(minor, mechanisms);
 +        if (GSS_ERROR(major))
 +            goto cleanup;
 +    }
 +
 +    if (cred->expiryTime == 0) {
 +        lifetime = GSS_C_INDEFINITE;
 +    } else  {
 +        now = time(NULL);
 +        lifetime = now - cred->expiryTime;
 +        if (lifetime < 0)
 +            lifetime = 0;
 +    }
 +
 +    if (pLifetime != NULL) {
 +        *pLifetime = lifetime;
 +    }
 +
 +    if (lifetime == 0) {
 +        major = GSS_S_CREDENTIALS_EXPIRED;
 +        *minor = GSSEAP_CRED_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;
 +}
 +
-     if (src->privateKey.value != NULL)
-         duplicateBufferOrCleanup(&src->privateKey, &dst->privateKey);
 +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;
 +
 +        cred->flags |= CRED_FLAG_TARGET;
 +    } else {
 +        cred->flags &= ~(CRED_FLAG_TARGET);
 +    }
 +
 +    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);
-     gss_buffer_desc defaultPrivateKey = GSS_C_EMPTY_BUFFER;
 +
 +#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;
-     major = readStaticIdentityFile(minor, &defaultIdentity,
-                                    &defaultPassword, &defaultPrivateKey);
 +    int isDefaultIdentity = FALSE;
 +
-     if (isDefaultIdentity) {
-         if (defaultPrivateKey.length != 0) {
-             major = gssEapSetCredClientCertificate(minor, cred, GSS_C_NO_BUFFER,
-                                                   &defaultPrivateKey);
-             if (GSS_ERROR(major))
-                 goto cleanup;
-         }
-         if ((cred->flags & CRED_FLAG_PASSWORD) == 0) {
-             major = gssEapSetCredPassword(minor, cred, &defaultPassword);
-             if (GSS_ERROR(major))
-                 goto cleanup;
-         }
++    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;
 +        }
 +    }
 +
-     gss_release_buffer(&tmpMinor, &defaultPrivateKey);
++    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);
-         if ((resolvedCred->flags &
-              (CRED_FLAG_PASSWORD | CRED_FLAG_CERTIFICATE)) == 0) {
 +
 +    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) && major != GSS_S_CRED_UNAVAIL)
 +            goto cleanup;
 +
 +        /* If we have a caller-supplied password, the credential is resolved. */
++        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;
 +}