dnl Based on the one from the Boinc project by Reinhard
++AC_DEFUN([AX_CHECK_WINDOWS],
++[AC_MSG_CHECKING(for windows)
++target_windows="no"
++AC_CHECK_HEADER(windows.h,[target_windows="yes"],[target_windows="no"])
++AC_MSG_RESULT($target_windows)
++AM_CONDITIONAL(TARGET_WINDOWS,test "x$target_windows" = "xyes")
++])dnl
++
AC_DEFUN([AX_CHECK_KRB5],
[AC_MSG_CHECKING(for GSS-API and Kerberos implementation)
KRB5_DIR=
[Use krb5 (in specified installation directory)]),
[check_krb5_dir="$withval"],
[check_krb5_dir=])
-AM_COND_IF(TARGET_WINDOWS,[
- found_krb5="yes"
- krb5dir=$check_krb5_dir
- KRB5_CFLAGS=-I"$check_krb5_dir/include"
- KRB5_LIBS="-L$check_krb5_dir/lib/ -lkrb5_32 -lgssapi32"
- COMPILE_ET=
-],
-[for dir in $check_krb5_dir $prefix /usr /usr/local ; do
+for dir in $check_krb5_dir $prefix /usr /usr/local ; do
krb5dir="$dir"
if test -x "$dir/bin/krb5-config"; then
found_krb5="yes";
-- KRB5_CFLAGS=`$dir/bin/krb5-config gssapi --cflags`;
-- KRB5_LIBS=`$dir/bin/krb5-config gssapi --libs`;
-- COMPILE_ET="$dir/bin/compile_et";
++ if test "x$target_windows" = "xyes"; then
++ KRB5_CFLAGS=-I"$check_krb5_dir/include";
++ KRB5_LIBS="-L$check_krb5_dir/lib/ -lkrb5_32 -lgssapi32";
++ COMPILE_ET="$check_krb5_dir/bin/compile_et";
++ else
++ KRB5_CFLAGS=`$dir/bin/krb5-config gssapi --cflags`;
++ KRB5_LIBS=`$dir/bin/krb5-config gssapi --libs`;
++ COMPILE_ET="$dir/bin/compile_et";
++ fi
break;
fi
-done])
+done
AC_MSG_RESULT($found_krb5)
if test x_$found_krb5 != x_yes; then
AC_MSG_ERROR([
if test x_$found_shibsp != x_yes; then
AC_MSG_ERROR([
----------------------------------------------------------------------
- Cannot find Shibboleth/OpenSAML libraries.
+ Cannot find Shibboleth libraries.
Please install Shibboleth or specify installation directory with
--with-shibsp=(dir).
])
else
printf "Shibboleth found in $shibspdir\n";
- SHIBSP_LIBS="-lshibsp -lsaml -lxml-security-c -lxmltooling -lxerces-c";
+ SHIBSP_LIBS="-lshibsp -lsaml -lxml-security-c -lxmltooling -lxerces-c";
SHIBSP_LDFLAGS="-L$shibspdir/lib";
AC_SUBST(SHIBSP_CXXFLAGS)
AC_SUBST(SHIBSP_LDFLAGS)
AC_SUBST(SHIBSP_LIBS)
+ AC_DEFINE_UNQUOTED([HAVE_SHIBSP], 1, [Define is Shibboleth SP is available])
fi
])dnl
[Use Shibboleth resolver (in specified installation directory)]),
[check_shibresolver_dir="$withval"],
[check_shibresolver_dir=])
+if test x_$check_shibresolver_dir != x_no; then
for dir in $check_shibresolver_dir $prefix /usr /usr/local ; do
shibresolverdir="$dir"
if test -f "$dir/include/shibresolver/resolver.h"; then
break;
fi
done
+fi
AC_MSG_RESULT($found_shibresolver)
+if test x_$check_shibresolver_dir != x_no; then
if test x_$found_shibresolver != x_yes; then
- AC_MSG_ERROR([
+ AC_MSG_WARN([
----------------------------------------------------------------------
- Cannot find Shibboleth resolver libraries.
+ Cannot find Shibboleth resolver libraries, building without
+ Shibboleth support.
Please install Shibboleth or specify installation directory with
--with-shibresolver=(dir).
AC_SUBST(SHIBRESOLVER_CXXFLAGS)
AC_SUBST(SHIBRESOLVER_LDFLAGS)
AC_SUBST(SHIBRESOLVER_LIBS)
+ AC_DEFINE_UNQUOTED([HAVE_SHIBRESOLVER], 1, [Define is Shibboleth resolver is available])
+fi
fi
])dnl
-AC_DEFUN([AX_CHECK_WINDOWS],
-[AC_MSG_CHECKING(for windows)
-target_windows="no"
-AC_CHECK_HEADER(windows.h,[target_windows="yes"],[target_windows="no"])
-AC_MSG_RESULT($target_windows)
-AM_CONDITIONAL(TARGET_WINDOWS,test "x$target_windows" = "xyes")
-])dnl
+AC_DEFUN([AX_CHECK_OPENSAML],
+[AC_MSG_CHECKING(for OpenSAML implementation)
+OPENSAML_DIR=
+found_opensaml="no"
+AC_ARG_WITH(opensaml,
+ AC_HELP_STRING([--with-opensaml],
+ [Use OpenSAML (in specified installation directory)]),
+ [check_opensaml_dir="$withval"],
+ [check_opensaml_dir=])
+if test x_$check_opensaml_dir != x_no; then
+for dir in $check_opensaml_dir $prefix /usr /usr/local ; do
+ opensamldir="$dir"
+ if test -f "$dir/include/saml/Assertion.h"; then
+ found_opensaml="yes";
+ OPENSAML_DIR="${opensamldir}"
+ OPENSAML_CXXFLAGS="-I$opensamldir/include";
+ break;
+ fi
+done
+fi
+AC_MSG_RESULT($found_opensaml)
+if test x_$check_opensaml_dir != x_no; then
+if test x_$found_opensaml != x_yes; then
+ AC_MSG_WARN([
+----------------------------------------------------------------------
+ Cannot find OpenSAML libraries, building without OpenSAML support.
+ Please install OpenSAML or specify installation directory with
+ --with-opensaml=(dir).
+----------------------------------------------------------------------
+])
+else
+ printf "OpenSAML found in $opensamldir\n";
+ OPENSAML_LIBS="-lsaml -lxml-security-c -lxmltooling -lxerces-c";
+ OPENSAML_LDFLAGS="-L$opensamldir/lib";
+ AC_SUBST(OPENSAML_CXXFLAGS)
+ AC_SUBST(OPENSAML_LDFLAGS)
+ AC_SUBST(OPENSAML_LIBS)
+ AC_DEFINE_UNQUOTED([HAVE_OPENSAML], 1, [Define is OpenSAML is available])
+fi
+fi
+])dnl
AC_DEFUN([AX_CHECK_RADSEC],
[AC_MSG_CHECKING(for radsec)
AC_SUBST(JANSSON_LIBS)
fi
])dnl
+
+AC_DEFUN([AX_CHECK_LIBMOONSHOT],
+[AC_MSG_CHECKING(for Moonshot identity selector implementation)
+LIBMOONSHOT_DIR=
+found_libmoonshot="no"
+AC_ARG_WITH(libmoonshot,
+ AC_HELP_STRING([--with-libmoonshot],
+ [Use libmoonshot (in specified installation directory)]),
+ [check_libmoonshot_dir="$withval"],
+ [check_libmoonshot_dir=])
+for dir in $check_libmoonshot_dir $prefix /usr /usr/local ../../moonshot-ui/libmoonshot ; do
+ libmoonshotdir="$dir"
+ if test -f "$dir/include/libmoonshot.h"; then
+ found_libmoonshot="yes";
+ LIBMOONSHOT_DIR="${libmoonshotdir}"
+ LIBMOONSHOT_CFLAGS="-I$libmoonshotdir/include";
+ break;
+ fi
+done
+AC_MSG_RESULT($found_libmoonshot)
+if test x_$found_libmoonshot != x_yes; then
+ AC_MSG_ERROR([
+----------------------------------------------------------------------
+ Cannot find Moonshot identity selector libraries.
+
+ Please install wpa_supplicant or specify installation directory with
+ --with-libmoonshot=(dir).
+----------------------------------------------------------------------
+])
+else
+ printf "libmoonshot found in $libmoonshotdir\n";
+ LIBMOONSHOT_LIBS="-lmoonshot";
+ LIBMOONSHOT_LDFLAGS="-L$libmoonshot/lib";
+ AC_SUBST(LIBMOONSHOT_CFLAGS)
+ AC_SUBST(LIBMOONSHOT_LDFLAGS)
+ AC_SUBST(LIBMOONSHOT_LIBS)
+ AC_CHECK_LIB(moonshot, moonshot_get_identity, [AC_DEFINE_UNQUOTED([HAVE_MOONSHOT_GET_IDENTITY], 1, [Define if Moonshot identity selector is available])], [], "$LIBMOONSHOT_LIBS")
+fi
+])dnl
+
AC_INIT([mech_eap], [0.1], [bugs@project-moonshot.org])
dnl AC_CONFIG_MACRO_DIR([m4])
dnl AM_INIT_AUTOMAKE([silent-rules])
+ AC_USE_SYSTEM_EXTENSIONS
+ AC_GNU_SOURCE
AM_INIT_AUTOMAKE
-LT_PREREQ([2.4])
+ AM_PROG_CC_C_O
+ AM_MAINTAINER_MODE()
- LT_INIT([dlopen disable-static])
+LT_PREREQ([2.2])
+ LT_INIT([dlopen disable-static win32-dll])
- AC_PROG_CC
+ 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)
- AC_GNU_SOURCE
dnl Check if we're on Solaris and set CFLAGS accordingly
dnl AC_CANONICAL_TARGET
AC_SUBST(TARGET_CFLAGS)
AC_SUBST(TARGET_LDFLAGS)
+ AX_CHECK_WINDOWS
AX_CHECK_KRB5
-AM_CONDITIONAL(HEIMDAL, test "x$heimdal" != "xno")
-dnl AX_CHECK_EAP
-if test "x$acceptor" = "xyes" ; then
+AX_CHECK_OPENSAML
+AM_CONDITIONAL(OPENSAML, test "x_$check_opensaml_dir" != "x_no")
+
+AX_CHECK_SHIBRESOLVER
+AM_CONDITIONAL(SHIBRESOLVER, test "x_$check_shibresolver_dir" != "x_no")
+if test x_$found_shibresolver = x_yes; then
AX_CHECK_SHIBSP
- AX_CHECK_SHIBRESOLVER
+fi
+
+if test "x$acceptor" = "xyes" ; then
AX_CHECK_RADSEC
AX_CHECK_JANSSON
fi
+
+AX_CHECK_LIBMOONSHOT
AC_CONFIG_FILES([Makefile libeap/Makefile mech_eap/Makefile])
AC_OUTPUT
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 \
- -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
+ -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_CPPFLAGS = -DBUILD_GSSEAP_LIB -DSYSCONFDIR=\"${sysconfdir}\" -DDATAROOTDIR=\"${datarootdir}\"
-mech_eap_la_CFLAGS += @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
-mech_eap_la_CXXFLAGS += @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @SHIBRESOLVER_CXXFLAGS@ @SHIBSP_CXXFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
+mech_eap_la_CFLAGS = -Werror -Wall -Wunused-parameter \
+ @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
+mech_eap_la_CXXFLAGS = -Werror -Wall -Wunused-parameter \
+ @KRB5_CFLAGS@ @RADSEC_CFLAGS@ \
+ @OPENSAML_CXXFLAGS@ @SHIBRESOLVER_CXXFLAGS@ @SHIBSP_CXXFLAGS@ \
+ @TARGET_CFLAGS@ $(EAP_CFLAGS)
mech_eap_la_LDFLAGS = -avoid-version -module \
- -export-symbols $(srcdir)/mech_eap.exports -no-undefined \
+ -export-symbols $(GSSEAP_EXPORTS) -no-undefined \
@RADSEC_LDFLAGS@ @TARGET_LDFLAGS@
-mech_eap_la_LIBADD = @KRB5_LIBS@ ../libeap/libeap.la @RADSEC_LIBS@ \
- @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@ $(OS_LIBS) $(LTLIBOBJS)
++if TARGET_WINDOWS
++mech_eap_la_LDFLAGS += -debug
++endif
+
+mech_eap_la_LIBADD = @KRB5_LIBS@ ../libeap/libeap.la @RADSEC_LIBS@ \
+ @OPENSAML_LIBS@ @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@
-
mech_eap_la_SOURCES = \
- accept_sec_context.c \
acquire_cred.c \
acquire_cred_with_password.c \
add_cred.c \
canonicalize_name.c \
compare_name.c \
context_time.c \
- delete_name_attribute.c \
delete_sec_context.c \
display_name.c \
display_name_ext.c \
duplicate_name.c \
eap_mech.c \
export_name.c \
- export_name_composite.c \
export_sec_context.c \
get_mic.c \
- get_name_attribute.c \
gsseap_err.c \
import_name.c \
import_sec_context.c \
inquire_names_for_mech.c \
inquire_saslname_for_mech.c \
inquire_sec_context_by_oid.c \
- map_name_to_any.c \
process_context_token.c \
pseudo_random.c \
radsec_err.c \
- release_any_name_mapping.c \
release_cred.c \
release_name.c \
release_oid.c \
- set_name_attribute.c \
set_cred_option.c \
set_sec_context_option.c \
store_cred.c \
unwrap.c \
unwrap_iov.c \
- util_base64.c \
util_buffer.c \
util_context.c \
util_cksum.c \
util_krb.c \
util_lucid.c \
util_mech.c \
+ util_moonshot.c \
util_name.c \
util_oid.c \
util_ordering.c \
wrap_iov_length.c \
wrap_size_limit.c
-BUILT_SOURCES = gsseap_err.c radsec_err.c
-
if GSSEAP_ENABLE_ACCEPTOR
-mech_eap_la_SOURCES += util_attr.cpp util_json.cpp util_radius.cpp util_shib.cpp util_saml.cpp
+
+mech_eap_la_SOURCES += \
+ accept_sec_context.c \
+ delete_name_attribute.c \
+ export_name_composite.c \
+ get_name_attribute.c \
+ map_name_to_any.c \
+ release_any_name_mapping.c \
+ set_name_attribute.c \
+ util_attr.cpp \
+ util_base64.c \
+ util_json.cpp \
+ util_radius.cpp
+
+if OPENSAML
+mech_eap_la_SOURCES += util_saml.cpp
endif
+if SHIBRESOLVER
+mech_eap_la_SOURCES += util_shib.cpp
+endif
+
+endif
+
+BUILT_SOURCES = gsseap_err.c radsec_err.c
+
if GSSEAP_ENABLE_REAUTH
mech_eap_la_SOURCES += util_reauth.c
endif
endif
-if TARGET_WINDOWS
-mech_eap_la_LDFLAGS += -debug
-else
gsseap_err.h gsseap_err.c: gsseap_err.et
$(COMPILE_ET) $<
clean-generic:
rm -f gsseap_err.[ch] radsec_err.[ch]
-
-endif
#include "gssapiP_eap.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_delete_sec_context(OM_uint32 *minor,
gss_ctx_id_t *context_handle,
gss_buffer_t output_token)
iov[1].buffer.value = NULL;
iov[1].buffer.length = 0;
- major = gssEapWrapOrGetMIC(minor, ctx, FALSE, FALSE,
+ major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
iov, 2, TOK_TYPE_DELETE_CONTEXT);
if (GSS_ERROR(major)) {
GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
};
void
-gssEapDestroyStatusInfo(struct gss_eap_status_info* p)
+gssEapDestroyStatusInfo(struct gss_eap_status_info *p)
{
struct gss_eap_status_info *next;
saveStatusInfoNoCopy(OM_uint32 minor, char *message)
{
struct gss_eap_status_info **next = NULL, *p=NULL;
+ struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
- struct gss_eap_thread_local_data* tld = gssEapGetThreadLocalData();
if (tld != NULL) {
- for (p = tld->status_info; p != NULL; p = p->next) {
+ for (p = tld->statusInfo; p != NULL; p = p->next) {
if (p->code == minor) {
/* Set message in-place */
if (p->message != NULL)
}
next = &p->next;
}
-
p = GSSEAP_CALLOC(1, sizeof(*p));
}
+
if (p == NULL) {
if (message != NULL)
GSSEAP_FREE(message);
if (next != NULL)
*next = p;
else
- tld->status_info = p;
+ tld->statusInfo = p;
}
static const char *
getStatusInfo(OM_uint32 minor)
{
struct gss_eap_status_info *p;
- struct gss_eap_thread_local_data *tld=gssEapGetThreadLocalData();
+ struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
+
if (tld != NULL) {
- for (p = tld->status_info;
- p != NULL;
- p = p->next) {
+ for (p = tld->statusInfo; p != NULL; p = p->next) {
if (p->code == minor)
return p->message;
}
}
-
return NULL;
}
void
gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...)
{
+#ifdef WIN32
+ OM_uint32 tmpMajor, tmpMinor;
+ char buf[BUFSIZ];
+ gss_buffer_desc s = GSS_C_EMPTY_BUFFER;
+ va_list ap;
+
+ if (format != NULL) {
+ va_start(ap, format);
+ snprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+ }
+
+ tmpMajor = makeStringBuffer(&tmpMinor, buf, &s);
+ if (!GSS_ERROR(tmpMajor))
+ saveStatusInfoNoCopy(minor, (char *)s.value);
+#else
char *s = NULL;
int n;
va_list ap;
if (format != NULL) {
va_start(ap, format);
n = vasprintf(&s, format, ap);
+ if (n == -1)
+ s = NULL;
va_end(ap);
}
saveStatusInfoNoCopy(minor, s);
+#endif /* WIN32 */
}
-OM_uint32 KRB5_CALLCONV
-gss_display_status(OM_uint32 *minor,
- OM_uint32 status_value,
- int status_type,
- gss_OID mech_type,
- OM_uint32 *message_context,
- gss_buffer_t status_string)
+OM_uint32
+gssEapDisplayStatus(OM_uint32 *minor,
+ OM_uint32 status_value,
+ gss_buffer_t status_string)
{
OM_uint32 major;
krb5_context krbContext = NULL;
status_string->length = 0;
status_string->value = NULL;
- if (!gssEapIsMechanismOid(mech_type)) {
- *minor = GSSEAP_WRONG_MECH;
- return GSS_S_BAD_MECH;
- }
-
- if (status_type != GSS_C_MECH_CODE ||
- *message_context != 0) {
- /* we rely on the mechglue for GSS_C_GSS_CODE */
- *minor = 0;
- return GSS_S_BAD_STATUS;
- }
-
errMsg = getStatusInfo(status_value);
if (errMsg == NULL) {
GSSEAP_KRB_INIT(&krbContext);
return major;
}
+
+OM_uint32 GSSAPI_CALLCONV
+gss_display_status(OM_uint32 *minor,
+ OM_uint32 status_value,
+ int status_type,
+ gss_OID mech_type,
+ OM_uint32 *message_context,
+ gss_buffer_t status_string)
+{
+ if (!gssEapIsMechanismOid(mech_type)) {
+ *minor = GSSEAP_WRONG_MECH;
+ return GSS_S_BAD_MECH;
+ }
+
+ if (status_type != GSS_C_MECH_CODE ||
+ *message_context != 0) {
+ /* we rely on the mechglue for GSS_C_GSS_CODE */
+ *minor = 0;
+ return GSS_S_BAD_STATUS;
+ }
+
+ return gssEapDisplayStatus(minor, status_value, status_string);
+}
*/
#include "gssapiP_eap.h"
+
#ifdef GSSEAP_ENABLE_ACCEPTOR
static OM_uint32
gssEapExportPartialContext(OM_uint32 *minor,
size_t length, serverLen = 0;
unsigned char *p;
char serverBuf[MAXHOSTNAMELEN];
-
if (ctx->acceptorCtx.radConn != NULL) {
if (rs_conn_get_current_peer(ctx->acceptorCtx.radConn,
serverBuf, sizeof(serverBuf)) != 0) {
}
serverLen = strlen(serverBuf);
}
-
length = 4 + serverLen + 4 + ctx->acceptorCtx.state.length;
token->value = GSSEAP_MALLOC(length);
if (GSS_ERROR(major))
goto cleanup;
}
+
#ifdef GSSEAP_ENABLE_ACCEPTOR
/*
* The partial context is only transmitted for unestablished acceptor
return major;
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_export_sec_context(OM_uint32 *minor,
gss_ctx_id_t *context_handle,
gss_buffer_t interprocess_token)
#include <assert.h>
#include <string.h>
#include <errno.h>
-#if defined(HAVE_UNISTD_H)
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STDARG_H
#include <stdarg.h>
+#endif
#include <time.h>
-#if defined(HAVE_SYS_PARAM_H)
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
+#ifdef WIN32
+#ifndef MAXHOSTNAMELEN
+# include <WinSock2.h>
+# define MAXHOSTNAMELEN NI_MAXHOST
+#endif
+#endif
+
/* GSS headers */
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_krb5.h>
#include <eap_common/eap_common.h>
#include <wpabuf.h>
- /* FreeRADIUS headers */
#ifdef GSSEAP_ENABLE_ACCEPTOR
+ /* FreeRADIUS headers */
#ifdef __cplusplus
extern "C" {
#define operator fr_operator
#endif
#include <freeradius/libradius.h>
#include <freeradius/radius.h>
-////Because freeradius/autoconf.h is evil!
-////#undef uint16_t
-////#undef uint32_t
-////#undef uint8_t
+
+ #undef pid_t
+
++/* libradsec headers */
#include <radsec/radsec.h>
#include <radsec/request.h>
#ifdef __cplusplus
#undef operator
}
#endif
-#endif /*GSSEAP_ENABLE_ACCEPTOR*/
+#endif /* GSSEAP_ENABLE_ACCEPTOR */
#include "gsseap_err.h"
#include "radsec_err.h"
OM_uint32 flags;
gss_OID mechanismUsed; /* this is immutable */
krb5_principal krbPrincipal; /* this is immutable */
+#ifdef GSSEAP_ENABLE_ACCEPTOR
struct gss_eap_attr_ctx *attrCtx;
+#endif
};
#define CRED_FLAG_INITIATE 0x00010000
#define CRED_FLAG_ACCEPT 0x00020000
-#define CRED_FLAG_DEFAULT_IDENTITY 0x00040000
-#define CRED_FLAG_PASSWORD 0x00080000
-#define CRED_FLAG_DEFAULT_CCACHE 0x00100000
+#define CRED_FLAG_PASSWORD 0x00040000
+#define CRED_FLAG_DEFAULT_CCACHE 0x00080000
+#define CRED_FLAG_RESOLVED 0x00100000
#define CRED_FLAG_PUBLIC_MASK 0x0000FFFF
#ifdef HAVE_HEIMDAL_VERSION
GSSEAP_MUTEX mutex;
OM_uint32 flags;
gss_name_t name;
+ gss_name_t target; /* for initiator */
gss_buffer_desc password;
gss_OID_set mechanisms;
time_t expiryTime;
- char *radiusConfigFile;
- char *radiusConfigStanza;
+ gss_buffer_desc radiusConfigFile;
+ gss_buffer_desc radiusConfigStanza;
+ gss_buffer_desc caCertificate;
+ gss_buffer_desc subjectNameConstraint;
+ gss_buffer_desc subjectAltNameConstraint;
#ifdef GSSEAP_ENABLE_REAUTH
krb5_ccache krbCredCache;
gss_cred_id_t reauthCred;
time_t expiryTime;
uint64_t sendSeq, recvSeq;
void *seqState;
- gss_cred_id_t defaultCred;
+ gss_cred_id_t cred;
union {
struct gss_eap_initiator_ctx initiator;
#define initiatorCtx ctxU.initiator
#define reauthCtx ctxU.reauth
#endif
} ctxU;
+ const struct gss_eap_token_buffer_set *inputTokens;
+ const struct gss_eap_token_buffer_set *outputTokens;
};
#define TOK_FLAG_SENDER_IS_ACCEPTOR 0x01
#define KEY_USAGE_INITIATOR_SEAL 24
#define KEY_USAGE_INITIATOR_SIGN 25
+/* accept_sec_context.c */
+OM_uint32
+gssEapAcceptSecContext(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t input_token,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle);
+
+/* init_sec_context.c */
+OM_uint32
+gssEapInitSecContext(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t ctx,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec);
+
/* wrap_iov.c */
OM_uint32
gssEapWrapOrGetMIC(OM_uint32 *minor,
void
gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...);
+OM_uint32
+gssEapDisplayStatus(OM_uint32 *minor,
+ OM_uint32 status_value,
+ gss_buffer_t status_string);
+
#define IS_WIRE_ERROR(err) ((err) > GSSEAP_RESERVED && \
(err) <= GSSEAP_RADIUS_PROT_FAILURE)
+/* upper bound of RADIUS error range must be kept in sync with radsec.h */
+#define IS_RADIUS_ERROR(err) ((err) >= ERROR_TABLE_BASE_rse && \
+ (err) <= ERROR_TABLE_BASE_rse + 20)
+
/* export_sec_context.c */
OM_uint32
gssEapExportSecContext(OM_uint32 *minor,
gss_buffer_t token);
+/* eap_mech.c */
+void
+gssEapInitiatorInit(void);
+
+void
+gssEapFinalize(void);
+
#ifdef __cplusplus
}
#endif
return GSS_S_COMPLETE;
}
- #endif
+ #endif /* GSSEAP_ENABLE_ACCEPTOR */
static OM_uint32
importMechanismOid(OM_uint32 *minor,
major = sequenceInternalize(minor, &ctx->seqState, &p, &remain);
if (GSS_ERROR(major))
return major;
+
#ifdef GSSEAP_ENABLE_ACCEPTOR
/*
* The partial context should only be expected for unestablished
if (GSS_ERROR(major))
return major;
}
-#endif
#ifdef GSSEAP_DEBUG
assert(remain == 0);
#endif
- #endif
++#endif /* GSSEAP_ENABLE_ACCEPTOR */
major = GSS_S_COMPLETE;
*minor = 0;
return major;
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32 GSSAPI_CALLCONV
gss_import_sec_context(OM_uint32 *minor,
gss_buffer_t interprocess_token,
gss_ctx_id_t *context_handle)
#ifndef _UTIL_H_
#define _UTIL_H_ 1
-#if defined(HAVE_SYS_PARAM_H)
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
-#if defined(HAVE_STDINT_H)
+#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <string.h>
#include <krb5.h>
-#if defined(WIN32)
-#define inline __inline
+#ifdef WIN32
+#define inline __inline
+#define snprintf _snprintf
#endif
#ifdef __cplusplus
#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
#endif
- #if !defined(WIN32) && (!(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)))
+ #if !defined(WIN32) && !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#define GSSEAP_UNUSED __attribute__ ((__unused__))
+#define GSSEAP_UNUSED __attribute__ ((__unused__))
#else
#define GSSEAP_UNUSED
#endif
-#if !defined(WIN32)
-#define GSSEAP_CONSTRUCTOR __attribute__((constructor))
-#define GSSEAP_DESTRUCTOR __attribute__((destructor))
-#else
-#define GSSEAP_CONSTRUCTOR
-#define GSSEAP_DESTRUCTOR
-#endif
-
-/* thread local storage */
-struct gss_eap_status_info;
-
-struct gss_eap_thread_local_data
-{
- krb5_context context;
- struct gss_eap_status_info* status_info;
-};
-
-struct gss_eap_thread_local_data*
-gssEapGetThreadLocalData();
-
-void
-gssEapDestroyStatusInfo(struct gss_eap_status_info* status);
-
-void
-gssEapDestroyKrbContext(krb5_context context);
-
/* util_buffer.c */
OM_uint32
makeStringBuffer(OM_uint32 *minor,
const char *string,
gss_buffer_t buffer);
+#define makeStringBufferOrCleanup(src, dst) \
+ do { \
+ major = makeStringBuffer((minor), (src), (dst));\
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
OM_uint32
bufferToString(OM_uint32 *minor,
const gss_buffer_t buffer,
const gss_buffer_t src,
gss_buffer_t dst);
+#define duplicateBufferOrCleanup(src, dst) \
+ do { \
+ major = duplicateBuffer((minor), (src), (dst)); \
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
static inline int
bufferEqual(const gss_buffer_t b1, const gss_buffer_t b2)
{
#define ITOK_TYPE_REAUTH_RESP 0x00000009 /* optional */
#define ITOK_TYPE_VERSION_INFO 0x0000000A /* optional */
#define ITOK_TYPE_VENDOR_INFO 0x0000000B /* optional */
+#define ITOK_TYPE_GSS_FLAGS 0x0000000C /* optional */
+#define ITOK_TYPE_INITIATOR_MIC 0x0000000D /* critical, required, if not reauth */
+#define ITOK_TYPE_ACCEPTOR_MIC 0x0000000E /* TBD */
#define ITOK_FLAG_CRITICAL 0x80000000 /* critical, wire flag */
#define ITOK_FLAG_VERIFIED 0x40000000 /* verified, API flag */
#define ITOK_TYPE_MASK (~(ITOK_FLAG_CRITICAL | ITOK_FLAG_VERIFIED))
+#define GSSEAP_WIRE_FLAGS_MASK GSS_C_MUTUAL_FLAG
+
OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
gss_ctx_id_t context_handle,
OM_uint32 *time_rec);
+OM_uint32
+gssEapMakeTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC);
+
+OM_uint32
+gssEapVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t tokenMIC);
+
/* util_cred.c */
OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
+gss_OID
+gssEapPrimaryMechForCred(gss_cred_id_t cred);
+
OM_uint32
gssEapAcquireCred(OM_uint32 *minor,
const gss_name_t desiredName,
- const gss_buffer_t password,
OM_uint32 timeReq,
const gss_OID_set desiredMechs,
int cred_usage,
gss_OID_set *pActualMechs,
OM_uint32 *timeRec);
+OM_uint32
+gssEapSetCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t password);
+
+OM_uint32
+gssEapSetCredService(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t target);
+
+OM_uint32
+gssEapResolveInitiatorCred(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ const gss_name_t target,
+ gss_cred_id_t *resolvedCred);
+
int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech);
OM_uint32
gss_OID
gssEapSaslNameToOid(const gss_buffer_t name);
+/* util_moonshot.c */
+OM_uint32
+libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName);
+
+OM_uint32
+libMoonshotResolveInitiatorCred(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t targetName);
+
/* util_name.c */
#define EXPORT_NAME_FLAG_OID 0x1
#define EXPORT_NAME_FLAG_COMPOSITE 0x2
gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
/* util_token.c */
+struct gss_eap_token_buffer_set {
+ gss_buffer_set_desc buffers; /* pointers only */
+ OM_uint32 *types;
+};
+
OM_uint32
gssEapEncodeInnerTokens(OM_uint32 *minor,
- gss_buffer_set_t extensions,
- OM_uint32 *types,
+ struct gss_eap_token_buffer_set *tokens,
gss_buffer_t buffer);
OM_uint32
gssEapDecodeInnerTokens(OM_uint32 *minor,
const gss_buffer_t buffer,
- gss_buffer_set_t *pExtensions,
- OM_uint32 **pTypes);
+ struct gss_eap_token_buffer_set *tokens);
+
+OM_uint32
+gssEapReleaseInnerTokens(OM_uint32 *minor,
+ struct gss_eap_token_buffer_set *tokens,
+ int freeBuffers);
+
+OM_uint32
+gssEapAllocInnerTokens(OM_uint32 *minor,
+ size_t count,
+ struct gss_eap_token_buffer_set *tokens);
size_t
tokenSize(const gss_OID_desc *mech, size_t body_size);
#define GSSEAP_FREE free
#define GSSEAP_REALLOC realloc
+#ifndef GSSAPI_CALLCONV
+#define GSSAPI_CALLCONV KRB5_CALLCONV
+#endif
+
+#ifdef WIN32
+#define GSSEAP_CONSTRUCTOR
+#define GSSEAP_DESTRUCTOR
+#else
+#define GSSEAP_CONSTRUCTOR __attribute__((constructor))
+#define GSSEAP_DESTRUCTOR __attribute__((destructor))
+#endif
+
#define GSSEAP_NOT_IMPLEMENTED do { \
assert(0 && "not implemented"); \
*minor = ENOSYS; \
} while (0)
#ifdef WIN32
+
#include <winbase.h>
-#define GSSEAP_MUTEX CRITICAL_SECTION
-// wrapper for EnterCriticalSection() to provide return value
-inline int win32_mutex_init(CRITICAL_SECTION* m)
-{
- EnterCriticalSection(m);
- return 0;
-}
-#define GSSEAP_MUTEX_INIT(m) win32_mutex_init((m))
+#define GSSEAP_GET_LAST_ERROR() (GetLastError())
+
+#define GSSEAP_MUTEX CRITICAL_SECTION
-
+#define GSSEAP_MUTEX_INIT(m) (InitializeCriticalSection((m)), 0)
#define GSSEAP_MUTEX_DESTROY(m) DeleteCriticalSection((m))
#define GSSEAP_MUTEX_LOCK(m) EnterCriticalSection((m))
#define GSSEAP_MUTEX_UNLOCK(m) LeaveCriticalSection((m))
- /* XXX yet to implement thread-local wrappers */
++/* Thread-local is handled separately */
+
+#define GSSEAP_THREAD_ONCE INIT_ONCE
+#define GSSEAP_ONCE(o, i) InitOnceExecuteOnce((o), (i))
+#define GSSEAP_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
+
#else
+
#include <pthread.h>
-#define GSSEAP_MUTEX pthread_mutex_t
-#define GSSEAP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define GSSEAP_GET_LAST_ERROR() (errno)
-
+#define GSSEAP_MUTEX pthread_mutex_t
#define GSSEAP_MUTEX_INIT(m) pthread_mutex_init((m), NULL)
#define GSSEAP_MUTEX_DESTROY(m) pthread_mutex_destroy((m))
#define GSSEAP_MUTEX_LOCK(m) pthread_mutex_lock((m))
#define GSSEAP_THREAD_ONCE pthread_once_t
#define GSSEAP_ONCE(o, i) pthread_once((o), (i))
#define GSSEAP_ONCE_INITIALIZER PTHREAD_ONCE_INIT
-#endif
+
+#endif /* WIN32 */
/* Helper functions */
static inline void
data->length = buffer->length;
}
+/* util_tld.c */
+struct gss_eap_status_info;
+
+struct gss_eap_thread_local_data {
+ krb5_context krbContext;
+ struct gss_eap_status_info *statusInfo;
+};
+
+struct gss_eap_thread_local_data *
+gssEapGetThreadLocalData(void);
+
+void
+gssEapDestroyStatusInfo(struct gss_eap_status_info *status);
+
+void
+gssEapDestroyKrbContext(krb5_context context);
+
#ifdef __cplusplus
}
#endif
#ifdef GSSEAP_ENABLE_ACCEPTOR
#include "util_json.h"
#include "util_attr.h"
-#endif
#include "util_base64.h"
- #endif
++#endif /* GSSEAP_ENABLE_ACCEPTOR */
#ifdef GSSEAP_ENABLE_REAUTH
#include "util_reauth.h"
#endif
}
if (GSSEAP_MUTEX_INIT(&ctx->mutex) != 0) {
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
gssEapReleaseContext(&tmpMinor, &ctx);
return GSS_S_FAILURE;
}
ctx->state = GSSEAP_STATE_INITIAL;
+ ctx->mechanismUsed = GSS_C_NO_OID;
/*
* Integrity, confidentiality, sequencing and replay detection are
GSS_C_INTEG_FLAG | /* integrity */
GSS_C_CONF_FLAG | /* confidentiality */
GSS_C_SEQUENCE_FLAG | /* sequencing */
- GSS_C_REPLAY_FLAG| /* replay detection */
- GSS_C_MUTUAL_FLAG; /*xxx big hack */
+ GSS_C_REPLAY_FLAG; /* replay detection */
*pCtx = ctx;
if (ctx->vps != NULL)
gssEapRadiusFreeAvps(&tmpMinor, &ctx->vps);
}
- #endif
+ #endif /* GSSEAP_ENABLE_ACCEPTOR */
OM_uint32
gssEapReleaseContext(OM_uint32 *minor,
if (ctx->flags & CTX_FLAG_KRB_REAUTH) {
gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
} else
--#endif
++#endif /* GSSEAP_ENABLE_REAUTH */
if (CTX_IS_INITIATOR(ctx)) {
releaseInitiatorContext(&ctx->initiatorCtx);
- } else {
+ }
#ifdef GSSEAP_ENABLE_ACCEPTOR
+ else {
releaseAcceptorContext(&ctx->acceptorCtx);
-#endif
}
- #endif
++#endif /* GSSEAP_ENABLE_ACCEPTOR */
krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key);
gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
sequenceFree(&tmpMinor, &ctx->seqState);
- gssEapReleaseCred(&tmpMinor, &ctx->defaultCred);
+ gssEapReleaseCred(&tmpMinor, &ctx->cred);
GSSEAP_MUTEX_DESTROY(&ctx->mutex);
{
unsigned char *p;
+ assert(ctx->mechanismUsed != GSS_C_NO_OID);
+
outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length);
outputToken->value = GSSEAP_MALLOC(outputToken->length);
if (outputToken->value == NULL) {
return GSS_S_COMPLETE;
}
+
+static OM_uint32
+gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC,
+ int verifyMIC)
+{
+ OM_uint32 major;
+ gss_iov_buffer_desc *iov = NULL;
+ size_t i = 0, j;
+ enum gss_eap_token_type tokType;
+ OM_uint32 micTokType;
+ unsigned char wireTokType[2];
+ unsigned char *innerTokTypes = NULL, *innerTokLengths = NULL;
+ const struct gss_eap_token_buffer_set *tokens;
+
+ tokens = verifyMIC ? ctx->inputTokens : ctx->outputTokens;
+
+ assert(tokens != NULL);
+
+ iov = GSSEAP_CALLOC(2 + (3 * tokens->buffers.count) + 1, sizeof(*iov));
+ if (iov == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ innerTokTypes = GSSEAP_MALLOC(4 * tokens->buffers.count);
+ if (innerTokTypes == NULL) {
+ *minor = ENOMEM;
+ major = GSS_S_FAILURE;
+ goto cleanup;
+ }
+
+ innerTokLengths = GSSEAP_MALLOC(4 * tokens->buffers.count);
+ if (innerTokLengths == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Mechanism OID */
+ assert(ctx->mechanismUsed != GSS_C_NO_OID);
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = ctx->mechanismUsed->length;
+ iov[i].buffer.value = ctx->mechanismUsed->elements;
+ i++;
+
+ /* Token type */
+ if (CTX_IS_INITIATOR(ctx) ^ verifyMIC) {
+ tokType = TOK_TYPE_INITIATOR_CONTEXT;
+ micTokType = ITOK_TYPE_INITIATOR_MIC;
+ } else {
+ tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
+ micTokType = ITOK_TYPE_ACCEPTOR_MIC;
+ }
+ store_uint16_be(tokType, wireTokType);
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = sizeof(wireTokType);
+ iov[i].buffer.value = wireTokType;
+ i++;
+
+ for (j = 0; j < tokens->buffers.count; j++) {
+ if (verifyMIC &&
+ (tokens->types[j] & ITOK_TYPE_MASK) == micTokType)
+ continue; /* will use this slot for trailer */
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = 4;
+ iov[i].buffer.value = &innerTokTypes[j * 4];
+ store_uint32_be(tokens->types[j] & ~(ITOK_FLAG_VERIFIED),
+ iov[i].buffer.value);
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer.length = 4;
+ iov[i].buffer.value = &innerTokLengths[j * 4];
+ store_uint32_be(tokens->buffers.elements[j].length,
+ iov[i].buffer.value);
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[i].buffer = tokens->buffers.elements[j];
+ i++;
+ }
+
+ if (verifyMIC) {
+ assert(tokenMIC->length >= 16);
+
+ assert(i < 2 + (3 * tokens->buffers.count));
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER;
+ iov[i].buffer.length = 16;
+ iov[i].buffer.value = tokenMIC->value;
+ i++;
+
+ iov[i].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+ iov[i].buffer.length = tokenMIC->length - 16;
+ iov[i].buffer.value = (unsigned char *)tokenMIC->value + 16;
+ i++;
+
+ major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
+ iov, i, TOK_TYPE_MIC);
+ } else {
+ iov[i++].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+ major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
+ iov, i, TOK_TYPE_MIC);
+ if (!GSS_ERROR(major))
+ *tokenMIC = iov[i - 1].buffer;
+ }
+
+cleanup:
+ if (iov != NULL)
+ gssEapReleaseIov(iov, tokens->buffers.count);
+ if (innerTokTypes != NULL)
+ GSSEAP_FREE(innerTokTypes);
+ if (innerTokLengths != NULL)
+ GSSEAP_FREE(innerTokLengths);
+
+ return major;
+}
+
+OM_uint32
+gssEapMakeTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t tokenMIC)
+{
+ tokenMIC->length = 0;
+ tokenMIC->value = NULL;
+
+ return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, FALSE);
+}
+
+OM_uint32
+gssEapVerifyTokenMIC(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ const gss_buffer_t tokenMIC)
+{
+ if (tokenMIC->length < 16) {
+ *minor = GSSEAP_TOK_TRUNC;
+ return GSS_S_BAD_SIG;
+ }
+
+ return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, TRUE);
+}
#include "gssapiP_eap.h"
-#if defined(WIN32)
-/*This didn't work for me(Alexey) when Visual Studio 2005 Express is used: */
-#include <Shlobj.h>
-/*This didn't work for me(Kevin) when Visual Studio 2010 Express is used: */
-/*#include <ShFolder.h>*/
-
-#if !defined(snprintf)
-#define snprintf _snprintf
-#endif
-
+#ifdef WIN32
- #include <shlobj.h>
++# include <shlobj.h> /* may need to use ShFolder.h instead */
++# include <stdio.h>
#else
--#include <pwd.h>
++# include <pwd.h>
#endif
-#include <stdio.h> /* for BUFSIZ */
OM_uint32
gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
}
if (GSSEAP_MUTEX_INIT(&cred->mutex) != 0) {
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
gssEapReleaseCred(&tmpMinor, &cred);
return GSS_S_FAILURE;
}
return GSS_S_COMPLETE;
}
+static void
+zeroAndReleasePassword(gss_buffer_t password)
+{
+ if (password->value != NULL) {
+ memset(password->value, 0, password->length);
+ GSSEAP_FREE(password->value);
+ }
+
+ password->value = NULL;
+ password->length = 0;
+}
+
OM_uint32
gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
{
GSSEAP_KRB_INIT(&krbContext);
gssEapReleaseName(&tmpMinor, &cred->name);
+ gssEapReleaseName(&tmpMinor, &cred->target);
- if (cred->password.value != NULL) {
- memset(cred->password.value, 0, cred->password.length);
- GSSEAP_FREE(cred->password.value);
- }
+ zeroAndReleasePassword(&cred->password);
- if (cred->radiusConfigFile != NULL)
- GSSEAP_FREE(cred->radiusConfigFile);
- if (cred->radiusConfigStanza != NULL)
- GSSEAP_FREE(cred->radiusConfigStanza);
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
+ gss_release_buffer(&tmpMinor, &cred->caCertificate);
+ gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
+ gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
#ifdef GSSEAP_ENABLE_REAUTH
if (cred->krbCredCache != NULL) {
}
static OM_uint32
-readDefaultIdentityAndCreds(OM_uint32 *minor,
- gss_buffer_t defaultIdentity,
- gss_buffer_t defaultCreds)
+readStaticIdentityFile(OM_uint32 *minor,
+ gss_buffer_t defaultIdentity,
+ gss_buffer_t defaultPassword)
{
OM_uint32 major, tmpMinor;
FILE *fp = NULL;
char buf[BUFSIZ];
char *ccacheName;
-#if !defined(WIN32)
- char pwbuf[BUFSIZ];
+ int i = 0;
+#ifndef WIN32
struct passwd *pw = NULL, pwd;
+ char pwbuf[BUFSIZ];
#endif
defaultIdentity->length = 0;
defaultIdentity->value = NULL;
- defaultCreds->length = 0;
- defaultCreds->value = NULL;
+ if (defaultPassword != GSS_C_NO_BUFFER) {
+ defaultPassword->length = 0;
+ defaultPassword->value = NULL;
+ }
ccacheName = getenv("GSSEAP_IDENTITY");
if (ccacheName == NULL) {
-#if !defined(WIN32)
- if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
- pw == NULL || pw->pw_dir == NULL) {
+#ifdef WIN32
+ TCHAR szPath[MAX_PATH];
+
+ if (!SUCCEEDED(SHGetFolderPath(NULL,
+ CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
+ NULL, /* User access token */
- 0,
++ 0, /* SHGFP_TYPE_CURRENT */
+ szPath))) {
major = GSS_S_CRED_UNAVAIL;
- *minor = GetLastError();
- *minor = errno;
++ *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */
goto cleanup;
}
- snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
- ccacheName = buf;
+ snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
#else
- TCHAR szPath[MAX_PATH];
-
- if(!SUCCEEDED(SHGetFolderPath(NULL,
- CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
- NULL, /* User access token */
- 0, /* == SHGFP_TYPE_CURRENT from ShlObj.h */
- szPath))) {
+ if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
+ pw == NULL || pw->pw_dir == NULL) {
major = GSS_S_CRED_UNAVAIL;
-////Needs to be correctly converted from the GetLastError();
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
goto cleanup;
- }
+ }
- snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
+ snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
+#endif /* WIN32 */
ccacheName = buf;
-#endif
}
fp = fopen(ccacheName, "r");
break;
}
- if (defaultIdentity->value == NULL)
+ if (i == 0)
dst = defaultIdentity;
- else if (defaultCreds->value == NULL)
- dst = defaultCreds;
+ else if (i == 1)
+ dst = defaultPassword;
else
break;
- major = duplicateBuffer(minor, &src, dst);
- if (GSS_ERROR(major))
- goto cleanup;
+ if (dst != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, &src, dst);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ i++;
}
if (defaultIdentity->length == 0) {
if (GSS_ERROR(major)) {
gss_release_buffer(&tmpMinor, defaultIdentity);
- gss_release_buffer(&tmpMinor, defaultCreds);
+ zeroAndReleasePassword(defaultPassword);
}
+ memset(buf, 0, sizeof(buf));
+
return major;
}
+gss_OID
+gssEapPrimaryMechForCred(gss_cred_id_t cred)
+{
+ gss_OID nameMech = GSS_C_NO_OID;
+
+ if (cred->mechanisms != GSS_C_NO_OID_SET &&
+ cred->mechanisms->count == 1)
+ nameMech = &cred->mechanisms->elements[0];
+
+ return nameMech;
+}
+
OM_uint32
gssEapAcquireCred(OM_uint32 *minor,
const gss_name_t desiredName,
- const gss_buffer_t password,
OM_uint32 timeReq GSSEAP_UNUSED,
const gss_OID_set desiredMechs,
int credUsage,
{
OM_uint32 major, tmpMinor;
gss_cred_id_t cred;
- gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
- gss_name_t defaultIdentityName = GSS_C_NO_NAME;
- gss_buffer_desc defaultCreds = GSS_C_EMPTY_BUFFER;
- gss_OID nameMech = GSS_C_NO_OID;
/* XXX TODO validate with changed set_cred_option API */
*pCred = GSS_C_NO_CREDENTIAL;
if (GSS_ERROR(major))
goto cleanup;
- if (cred->mechanisms != GSS_C_NO_OID_SET &&
- cred->mechanisms->count == 1)
- nameMech = &cred->mechanisms->elements[0];
-
- if (cred->flags & CRED_FLAG_INITIATE) {
- major = readDefaultIdentityAndCreds(minor, &defaultIdentity, &defaultCreds);
- if (major == GSS_S_COMPLETE) {
- major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
- nameMech, &defaultIdentityName);
- if (GSS_ERROR(major))
- goto cleanup;
- } else if (major != GSS_S_CRED_UNAVAIL)
- goto cleanup;
- }
-
if (desiredName != GSS_C_NO_NAME) {
GSSEAP_MUTEX_LOCK(&desiredName->mutex);
}
GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
-
- if (defaultIdentityName != GSS_C_NO_NAME) {
- int nameEqual;
-
- major = gssEapCompareName(minor, desiredName,
- defaultIdentityName, &nameEqual);
- if (GSS_ERROR(major))
- goto cleanup;
- else if (nameEqual)
- cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
- }
- } else {
- if (cred->flags & CRED_FLAG_ACCEPT) {
- gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
- char serviceName[5 + MAXHOSTNAMELEN];
-
- /* default host-based service is host@localhost */
- memcpy(serviceName, "host@", 5);
- if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
- major = GSS_S_FAILURE;
- *minor = GSSEAP_NO_HOSTNAME;
- goto cleanup;
- }
-
- nameBuf.value = serviceName;
- nameBuf.length = strlen((char *)nameBuf.value);
-
- major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
- nameMech, &cred->name);
- if (GSS_ERROR(major))
- goto cleanup;
- } else if (cred->flags & CRED_FLAG_INITIATE) {
- if (defaultIdentityName == GSS_C_NO_NAME) {
- major = GSS_S_CRED_UNAVAIL;
- *minor = GSSEAP_NO_DEFAULT_IDENTITY;
- goto cleanup;
- }
-
- cred->name = defaultIdentityName;
- defaultIdentityName = GSS_C_NO_NAME;
- }
- cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
- }
-
- assert(cred->name != GSS_C_NO_NAME);
-
- if (password != GSS_C_NO_BUFFER) {
- major = duplicateBuffer(minor, password, &cred->password);
- if (GSS_ERROR(major))
- goto cleanup;
-
- cred->flags |= CRED_FLAG_PASSWORD;
- } else if (defaultCreds.value != NULL &&
- (cred->flags & CRED_FLAG_DEFAULT_IDENTITY)) {
- cred->password = defaultCreds;
-
- defaultCreds.length = 0;
- defaultCreds.value = NULL;
-
- cred->flags |= CRED_FLAG_PASSWORD;
- } else if (cred->flags & CRED_FLAG_INITIATE) {
- /*
- * OK, here we need to ask the supplicant if we have creds or it
- * will acquire them, so GS2 can know whether to prompt for a
- * password or not.
- */
-#if 0
- && !gssEapCanReauthP(cred, GSS_C_NO_NAME, timeReq)
-#endif
- major = GSS_S_CRED_UNAVAIL;
- *minor = GSSEAP_NO_DEFAULT_CRED;
- goto cleanup;
}
if (pActualMechs != NULL) {
cleanup:
if (GSS_ERROR(major))
gssEapReleaseCred(&tmpMinor, &cred);
- gssEapReleaseName(&tmpMinor, &defaultIdentityName);
- gss_release_buffer(&tmpMinor, &defaultIdentity);
- if (defaultCreds.value != NULL) {
- memset(defaultCreds.value, 0, defaultCreds.length);
- gss_release_buffer(&tmpMinor, &defaultCreds);
- }
return major;
}
return present;
}
+static OM_uint32
+staticIdentityFileResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+ gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
+
+ *pName = GSS_C_NO_NAME;
+
+ major = readStaticIdentityFile(minor, &defaultIdentity, GSS_C_NO_BUFFER);
+ if (major == GSS_S_COMPLETE) {
+ major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
+ nameMech, pName);
+ }
+
+ gss_release_buffer(&tmpMinor, &defaultIdentity);
+
+ return major;
+}
+
+static OM_uint32
+gssEapResolveCredIdentity(OM_uint32 *minor,
+ gss_cred_id_t cred)
+{
+ OM_uint32 major;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+
+ if (cred->name != GSS_C_NO_NAME) {
+ *minor = 0;
+ return GSS_S_COMPLETE;
+ }
+
+ if (cred->flags & CRED_FLAG_ACCEPT) {
+ gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
+ char serviceName[5 + MAXHOSTNAMELEN];
+
+ /* default host-based service is host@localhost */
+ memcpy(serviceName, "host@", 5);
+ if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
+ *minor = GSSEAP_NO_HOSTNAME;
+ return GSS_S_FAILURE;
+ }
+
+ nameBuf.value = serviceName;
+ nameBuf.length = strlen((char *)nameBuf.value);
+
+ major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
+ nameMech, &cred->name);
+ if (GSS_ERROR(major))
+ return major;
+ } else if (cred->flags & CRED_FLAG_INITIATE) {
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+ major = libMoonshotResolveDefaultIdentity(minor, cred, &cred->name);
+ if (major == GSS_S_CRED_UNAVAIL)
+#endif
+ major = staticIdentityFileResolveDefaultIdentity(minor, cred, &cred->name);
+ if (major != GSS_S_CRED_UNAVAIL)
+ return major;
+ }
+
+ *minor = 0;
+ return GSS_S_COMPLETE;
+}
+
OM_uint32
gssEapInquireCred(OM_uint32 *minor,
gss_cred_id_t cred,
time_t now, lifetime;
if (name != NULL) {
- major = gssEapDuplicateName(minor, cred->name, name);
+ major = gssEapResolveCredIdentity(minor, cred);
if (GSS_ERROR(major))
- return major;
+ goto cleanup;
+
+ if (cred->name != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, cred->name, name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ } else
+ *name = GSS_C_NO_NAME;
}
if (cred_usage != NULL) {
else
major = gssEapIndicateMechs(minor, mechanisms);
if (GSS_ERROR(major))
- return major;
+ goto cleanup;
}
if (cred->expiryTime == 0) {
}
if (lifetime == 0) {
+ major = GSS_S_CREDENTIALS_EXPIRED;
*minor = GSSEAP_CRED_EXPIRED;
- return GSS_S_CREDENTIALS_EXPIRED;
+ goto cleanup;
}
major = GSS_S_COMPLETE;
*minor = 0;
+cleanup:
+ return major;
+}
+
+OM_uint32
+gssEapSetCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t password)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc newPassword = GSS_C_EMPTY_BUFFER;
+
+ if (cred->flags & CRED_FLAG_RESOLVED) {
+ major = GSS_S_FAILURE;
+ *minor = GSSEAP_CRED_RESOLVED;
+ goto cleanup;
+ }
+
+ if (password != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, password, &newPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ cred->flags |= CRED_FLAG_PASSWORD;
+ } else {
+ cred->flags &= ~(CRED_FLAG_PASSWORD);
+ }
+
+ gss_release_buffer(&tmpMinor, &cred->password);
+ cred->password = newPassword;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ return major;
+}
+
+OM_uint32
+gssEapSetCredService(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t target)
+{
+ OM_uint32 major, tmpMinor;
+ gss_name_t newTarget = GSS_C_NO_NAME;
+
+ if (cred->flags & CRED_FLAG_RESOLVED) {
+ major = GSS_S_FAILURE;
+ *minor = GSSEAP_CRED_RESOLVED;
+ goto cleanup;
+ }
+
+ if (target != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, target, &newTarget);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ gssEapReleaseName(&tmpMinor, &cred->target);
+ cred->target = newTarget;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ return major;
+}
+
+static OM_uint32
+gssEapDuplicateCred(OM_uint32 *minor,
+ const gss_cred_id_t src,
+ gss_cred_id_t *pDst)
+{
+ OM_uint32 major, tmpMinor;
+ gss_cred_id_t dst = GSS_C_NO_CREDENTIAL;
+
+ *pDst = GSS_C_NO_CREDENTIAL;
+
+ major = gssEapAllocCred(minor, &dst);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ dst->flags = src->flags;
+
+ if (src->name != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, src->name, &dst->name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (src->target != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, src->target, &dst->target);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (src->password.value != NULL) {
+ major = duplicateBuffer(minor, &src->password, &dst->password);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ major = duplicateOidSet(minor, src->mechanisms, &dst->mechanisms);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ dst->expiryTime = src->expiryTime;
+
+ if (src->radiusConfigFile.value != NULL)
+ duplicateBufferOrCleanup(&src->radiusConfigFile, &dst->radiusConfigFile);
+ if (src->radiusConfigStanza.value != NULL)
+ duplicateBufferOrCleanup(&src->radiusConfigStanza, &dst->radiusConfigStanza);
+ if (src->caCertificate.value != NULL)
+ duplicateBufferOrCleanup(&src->caCertificate, &dst->caCertificate);
+ if (src->subjectNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint);
+ if (src->subjectAltNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint);
+
+#ifdef GSSEAP_ENABLE_REAUTH
+ /* XXX krbCredCache, reauthCred */
+#endif
+
+ *pDst = dst;
+ dst = GSS_C_NO_CREDENTIAL;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ gssEapReleaseCred(&tmpMinor, &dst);
+
+ return major;
+}
+
+static OM_uint32
+staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
+ gss_name_t defaultIdentityName = GSS_C_NO_NAME;
+ gss_buffer_desc defaultPassword = GSS_C_EMPTY_BUFFER;
+ int isDefaultIdentity = FALSE;
+
+ major = readStaticIdentityFile(minor, &defaultIdentity, &defaultPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
+ gssEapPrimaryMechForCred(cred), &defaultIdentityName);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ if (defaultIdentityName == GSS_C_NO_NAME) {
+ if (cred->name == GSS_C_NO_NAME) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_IDENTITY;
+ goto cleanup;
+ }
+ } else {
+ if (cred->name == GSS_C_NO_NAME) {
+ cred->name = defaultIdentityName;
+ defaultIdentityName = GSS_C_NO_NAME;
+ isDefaultIdentity = TRUE;
+ } else {
+ major = gssEapCompareName(minor, cred->name,
+ defaultIdentityName, &isDefaultIdentity);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+ }
+
+ if (isDefaultIdentity &&
+ (cred->flags & CRED_FLAG_PASSWORD) == 0) {
+ major = gssEapSetCredPassword(minor, cred, &defaultPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+cleanup:
+ gssEapReleaseName(&tmpMinor, &defaultIdentityName);
+ zeroAndReleasePassword(&defaultPassword);
+ gss_release_buffer(&tmpMinor, &defaultIdentity);
+
+ return major;
+}
+
+OM_uint32
+gssEapResolveInitiatorCred(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ const gss_name_t targetName
+#ifndef HAVE_MOONSHOT_GET_IDENTITY
+ GSSEAP_UNUSED
+#endif
+ ,
+ gss_cred_id_t *pResolvedCred)
+{
+ OM_uint32 major, tmpMinor;
+ gss_cred_id_t resolvedCred = GSS_C_NO_CREDENTIAL;
+
+ if (cred == GSS_C_NO_CREDENTIAL) {
+ major = gssEapAcquireCred(minor,
+ GSS_C_NO_NAME,
+ GSS_C_INDEFINITE,
+ GSS_C_NO_OID_SET,
+ GSS_C_INITIATE,
+ &resolvedCred,
+ NULL,
+ NULL);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ } else {
+ if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
+ major = GSS_S_NO_CRED;
+ *minor = GSSEAP_CRED_USAGE_MISMATCH;
+ goto cleanup;
+ }
+
+ major = gssEapDuplicateCred(minor, cred, &resolvedCred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if ((resolvedCred->flags & CRED_FLAG_RESOLVED) == 0) {
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+ major = libMoonshotResolveInitiatorCred(minor, resolvedCred, targetName);
+ if (major == GSS_S_CRED_UNAVAIL)
+#endif
+ major = staticIdentityFileResolveInitiatorCred(minor, resolvedCred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ if ((resolvedCred->flags & CRED_FLAG_PASSWORD) == 0) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_CRED;
+ goto cleanup;
+ }
+
+ resolvedCred->flags |= CRED_FLAG_RESOLVED;
+ }
+
+ *pResolvedCred = resolvedCred;
+ resolvedCred = GSS_C_NO_CREDENTIAL;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ gssEapReleaseCred(&tmpMinor, &resolvedCred);
+
return major;
}
OM_uint32
gssEapKerberosInit(OM_uint32 *minor, krb5_context *context)
{
- struct gss_eap_thread_local_data* tld;
+ struct gss_eap_thread_local_data *tld;
+
*minor = 0;
tld = gssEapGetThreadLocalData();
- if (tld)
- {
- *context = tld->context;
+ if (tld != NULL) {
+ *context = tld->krbContext;
if (*context == NULL) {
*minor = initKrbContext(context);
- if (*minor == 0) {
- tld->context = *context;
- }
+ if (*minor == 0)
+ tld->krbContext = *context;
}
}
-
return *minor == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
}
#endif /* HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE */
if (!krb5_c_is_keyed_cksum(*cksumtype)) {
- *minor = KRB5KRB_AP_ERR_INAPP_CKSUM;
+ *minor = (OM_uint32)KRB5KRB_AP_ERR_INAPP_CKSUM;
return GSS_S_FAILURE;
}
}
if (GSSEAP_MUTEX_INIT(&name->mutex) != 0) {
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
gssEapReleaseName(&tmpMinor, &name);
return GSS_S_FAILURE;
}
GSSEAP_KRB_INIT(&krbContext);
krb5_free_principal(krbContext, name->krbPrincipal);
gssEapReleaseOid(&tmpMinor, &name->mechanismUsed);
-
#ifdef GSSEAP_ENABLE_ACCEPTOR
gssEapReleaseAttrContext(&tmpMinor, name);
#endif
name->mechanismUsed = mechanismUsed;
mechanismUsed = GSS_C_NO_OID;
+#ifdef GSSEAP_ENABLE_ACCEPTOR
if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
gss_buffer_desc buf;
buf.length = remain;
buf.value = p;
-#ifdef GSSEAP_ENABLE_ACCEPTOR
+
major = gssEapImportAttrContext(minor, &buf, name);
-#else
- major = GSS_S_UNAVAILABLE;
-#endif
if (GSS_ERROR(major))
goto cleanup;
}
+#endif
major = GSS_S_COMPLETE;
*minor = 0;
exportedNameLen += 6 + mech->length;
}
exportedNameLen += 4 + nameBuf.length;
- if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
#ifdef GSSEAP_ENABLE_ACCEPTOR
+ if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
major = gssEapExportAttrContext(minor, name, &attrs);
-#else
- major = GSS_S_UNAVAILABLE;
-#endif
if (GSS_ERROR(major))
goto cleanup;
exportedNameLen += attrs.length;
}
+#endif
exportedName->value = GSSEAP_MALLOC(exportedNameLen);
if (exportedName->value == NULL) {
goto cleanup;
}
- if (input_name->attrCtx != NULL) {
#ifdef GSSEAP_ENABLE_ACCEPTOR
+ if (input_name->attrCtx != NULL) {
major = gssEapDuplicateAttrContext(minor, input_name, name);
-#else
- major = GSS_S_UNAVAILABLE;
-#endif
if (GSS_ERROR(major))
goto cleanup;
}
+#endif
*dest_name = name;
gssEapRadiusMapError(OM_uint32 *minor,
struct rs_error *err);
-////This really need to be a function call on Windows
++/* This really needs to be a function call on Windows */
#define RS_CONFIG_FILE SYSCONFDIR "/radsec.conf"
#define VENDORPEC_MS 311 /* RFC 2548 */
#define PW_SAML_AAA_ASSERTION 132
#define PW_MS_WINDOWS_AUTH_DATA 133
-#define IS_RADIUS_ERROR(code) ((code) >= ERROR_TABLE_BASE_rse && \
- (code) <= ERROR_TABLE_BASE_rse + RSE_TIMEOUT_IO)
-
#ifdef __cplusplus
}
#endif
* SUCH DAMAGE.
*/
-/* Access all thread-local data through these methods which
- * use pthreads to manage thread-local memory on Unix and TlsFoo() on Windows.
- * This would be more flexible, scalable, and extensible
- * if implemented through a callback interface, but given that
- * there are currently only two 'clients', hard-coding seems more
- * straightforward
+/*
- * Thread local data abstraction.
++ * Thread local data abstraction, using pthreads on Unix and the TlsXXX
++ * APIs on Windows.
*/
+
#include "gssapiP_eap.h"
/* Clean up thread-local data; called on thread detach */
static void
-destroyThreadLocalData(struct gss_eap_thread_local_data* tld)
+destroyThreadLocalData(struct gss_eap_thread_local_data *tld)
{
- if (tld->status_info)
- gssEapDestroyStatusInfo(tld->status_info);
- if (tld->context)
- gssEapDestroyKrbContext(tld->context);
+ if (tld->statusInfo != NULL)
+ gssEapDestroyStatusInfo(tld->statusInfo);
+ if (tld->krbContext != NULL)
+ gssEapDestroyKrbContext(tld->krbContext);
GSSEAP_FREE(tld);
}
#ifdef WIN32
-/* This is the tls index returned by TlsAlloc() on process init.
- * Each thread, on thread attach in DllMain(), allocates its thread-local data and uses this index with TlsSetValue() to store it.
- * It can then subsequently be retrieved with TlsGetValue()
+/*
+ * This is the tls index returned by TlsAlloc() on process init.
+ * Each thread, on thread attach in DllMain(), allocates its thread-local
+ * data and uses this index with TlsSetValue() to store it.
+ * It can then subsequently be retrieved with TlsGetValue().
*/
static DWORD tlsIndex;
/* Access thread-local data */
struct gss_eap_thread_local_data *
-gssEapGetThreadLocalData()
+gssEapGetThreadLocalData(void)
{
return TlsGetValue(tlsIndex);
}
-
-/* DllMain() is the entry-point function for this DLL. */
-BOOL WINAPI DllMain(HINSTANCE hDLL, /* DLL module handle */
- DWORD reason, /* reason called */
- LPVOID reserved) /* reserved */
-{
+
+BOOL WINAPI
+DllMain(HINSTANCE hDLL, /* DLL module handle */
+ DWORD reason, /* reason called */
+ LPVOID reserved) /* reserved */
+{
struct gss_eap_thread_local_data *tlsData;
- switch (reason)
- {
- // The DLL is loading due to process
- // initialization or a call to LoadLibrary.
- case DLL_PROCESS_ATTACH:
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
/* Allocate a TLS index. */
- if ((tlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
- return FALSE;
+ gssEapInitiatorInit();
+ tlsIndex = TlsAlloc();
+ if (tlsIndex == TLS_OUT_OF_INDEXES)
+ return FALSE;
/* No break: Initialize the index for first thread.*/
-
- /* The attached process creates a new thread. */
- case DLL_THREAD_ATTACH:
+ case DLL_THREAD_ATTACH:
/* Initialize the TLS index for this thread. */
tlsData = GSSEAP_CALLOC(1, sizeof(*tlsData));
- if (tlsData != NULL)
- TlsSetValue(tlsIndex, tlsData);
-
- break;
-
- /* The thread of the attached process terminates. */
- case DLL_THREAD_DETACH:
+ if (tlsData != NULL)
+ TlsSetValue(tlsIndex, tlsData);
+ break;
+ case DLL_THREAD_DETACH:
/* Release the allocated memory for this thread. */
- tlsData = TlsGetValue(tlsIndex);
- if (tlsData != NULL)
- {
- destroyThreadLocalData(tlsData);
+ tlsData = TlsGetValue(tlsIndex);
+ if (tlsData != NULL) {
+ destroyThreadLocalData(tlsData);
TlsSetValue(tlsIndex, NULL);
}
-
- break;
-
- /* DLL unload due to process termination or FreeLibrary. */
- case DLL_PROCESS_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
/* Release the allocated memory for this thread. */
- tlsData = TlsGetValue(tlsIndex);
- if (tlsData != NULL)
- destroyThreadLocalData(tlsData);
+ tlsData = TlsGetValue(tlsIndex);
+ if (tlsData != NULL)
+ destroyThreadLocalData(tlsData);
/* Release the TLS index. */
- TlsFree(tlsIndex);
- break;
-
- default:
- break;
- }
-
- return TRUE;
- UNREFERENCED_PARAMETER(hDLL);
- UNREFERENCED_PARAMETER(reserved);
+ TlsFree(tlsIndex);
+ gssEapFinalize();
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+ UNREFERENCED_PARAMETER(hDLL);
+ UNREFERENCED_PARAMETER(reserved);
}
#else /* WIN32 */
-/* PTHREAD implementation */
+/* pthreads implementation */
+
static GSSEAP_THREAD_ONCE tldKeyOnce = GSSEAP_ONCE_INITIALIZER;
static GSSEAP_THREAD_KEY tldKey;
-static void
-pthreadDestroyThreadLocalData(void* arg)
+
+static void
+pthreadDestroyThreadLocalData(void *arg)
{
struct gss_eap_thread_local_data* tld = arg;
- if (tld)
- {
+
+ if (tld != NULL)
destroyThreadLocalData(tld);
- }
}
-static void
+static void
createThreadLocalDataKey(void)
{
GSSEAP_KEY_CREATE(&tldKey, pthreadDestroyThreadLocalData);
}
-struct gss_eap_thread_local_data *
+struct gss_eap_thread_local_data *
gssEapGetThreadLocalData()
{
struct gss_eap_thread_local_data *tld;
+
GSSEAP_ONCE(&tldKeyOnce, createThreadLocalDataKey);
+
tld = GSSEAP_GETSPECIFIC(tldKey);
- if (!tld)
- {
+ if (tld == NULL) {
tld = GSSEAP_CALLOC(1, sizeof(*tld));
+ if (tld == NULL)
+ return NULL;
+
GSSEAP_SETSPECIFIC(tldKey, tld);
}
+
return tld;
}
+
#endif /* WIN32 */