--- /dev/null
- 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
+
--- /dev/null
- 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
--- /dev/null
- 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
--- /dev/null
- @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]
--- /dev/null
- #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_ */
--- /dev/null
- * 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_ */
--- /dev/null
- 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;
+}
--- /dev/null
- 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
--- /dev/null
- 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_ */
--- /dev/null
- 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;
+}