summaryrefslogtreecommitdiffstats
path: root/src/modules/rlm_eap
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/rlm_eap')
-rw-r--r--src/modules/rlm_eap/.gitignore1
-rw-r--r--src/modules/rlm_eap/README.md11
-rw-r--r--src/modules/rlm_eap/all.mk1
-rwxr-xr-xsrc/modules/rlm_eap/configure3557
-rw-r--r--src/modules/rlm_eap/configure.ac42
-rw-r--r--src/modules/rlm_eap/eap.c1270
-rw-r--r--src/modules/rlm_eap/eap.h154
-rw-r--r--src/modules/rlm_eap/libeap/all.mk10
-rw-r--r--src/modules/rlm_eap/libeap/comp128.c460
-rw-r--r--src/modules/rlm_eap/libeap/comp128.h11
-rw-r--r--src/modules/rlm_eap/libeap/eap_chbind.c290
-rw-r--r--src/modules/rlm_eap/libeap/eap_chbind.h64
-rw-r--r--src/modules/rlm_eap/libeap/eap_sim.h122
-rw-r--r--src/modules/rlm_eap/libeap/eap_tls.c1206
-rw-r--r--src/modules/rlm_eap/libeap/eap_tls.h109
-rw-r--r--src/modules/rlm_eap/libeap/eap_types.h162
-rw-r--r--src/modules/rlm_eap/libeap/eapclient.h8
-rw-r--r--src/modules/rlm_eap/libeap/eapcommon.c401
-rw-r--r--src/modules/rlm_eap/libeap/eapcrypto.c301
-rw-r--r--src/modules/rlm_eap/libeap/eapsimlib.c508
-rw-r--r--src/modules/rlm_eap/libeap/fips186prf.c270
-rw-r--r--src/modules/rlm_eap/libeap/mppe_keys.c384
-rw-r--r--src/modules/rlm_eap/mem.c503
-rw-r--r--src/modules/rlm_eap/radeapclient.c2315
-rw-r--r--src/modules/rlm_eap/radeapclient.mk29
-rw-r--r--src/modules/rlm_eap/rlm_eap.c859
-rw-r--r--src/modules/rlm_eap/rlm_eap.h116
-rw-r--r--src/modules/rlm_eap/rlm_eap.mk6
-rw-r--r--src/modules/rlm_eap/types/all.mk1
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/.gitignore1
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/README.md10
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/all.mk.in12
-rwxr-xr-xsrc/modules/rlm_eap/types/rlm_eap_fast/configure4512
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/configure.ac86
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c1315
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.h260
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c198
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.h39
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c659
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_gtc/README.md12
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_gtc/all.mk12
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c250
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/.gitignore1
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/README.md11
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/all.mk.in13
-rwxr-xr-xsrc/modules/rlm_eap/types/rlm_eap_ikev2/configure4206
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/configure.ac99
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.c420
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.h48
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.c52
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.h35
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ikev2/rlm_eap_ikev2.c526
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_md5/README.md12
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_md5/all.mk12
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.c229
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.h52
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_md5/rlm_eap_md5.c168
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_mschapv2/README.md13
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_mschapv2/all.mk12
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_mschapv2/eap_mschapv2.h51
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c757
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_peap/README.md13
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_peap/all.mk10
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_peap/eap_peap.h76
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_peap/peap.c1316
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c429
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/.gitignore1
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/README.md11
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/all.mk.in16
-rwxr-xr-xsrc/modules/rlm_eap/types/rlm_eap_pwd/configure4271
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/configure.ac80
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/const_time.h190
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c933
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.h126
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c972
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.h51
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_sim/.gitignore1
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_sim/README.md9
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_sim/all.mk.in12
-rwxr-xr-xsrc/modules/rlm_eap/types/rlm_eap_sim/configure2929
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_sim/configure.ac18
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c697
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tls/README.md9
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tls/all.mk10
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c303
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h52
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tnc/.gitignore1
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tnc/README.md9
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tnc/all.mk.in14
-rwxr-xr-xsrc/modules/rlm_eap/types/rlm_eap_tnc/configure4199
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tnc/configure.ac90
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_tnc/rlm_eap_tnc.c357
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ttls/README.md10
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ttls/all.mk10
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ttls/eap_ttls.h46
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c392
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c1321
97 files changed, 46238 insertions, 0 deletions
diff --git a/src/modules/rlm_eap/.gitignore b/src/modules/rlm_eap/.gitignore
new file mode 100644
index 0000000..e713fa7
--- /dev/null
+++ b/src/modules/rlm_eap/.gitignore
@@ -0,0 +1 @@
+radeapclient
diff --git a/src/modules/rlm_eap/README.md b/src/modules/rlm_eap/README.md
new file mode 100644
index 0000000..54cce8f
--- /dev/null
+++ b/src/modules/rlm_eap/README.md
@@ -0,0 +1,11 @@
+# rlm_eap
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+
+Implements the base protocol for EAP (Extensible Authentication Protocol).
+
+EAP is commonly used to authenticate 802.1X and PPP (Point to Point Protocol) sessions.
diff --git a/src/modules/rlm_eap/all.mk b/src/modules/rlm_eap/all.mk
new file mode 100644
index 0000000..f2cb44b
--- /dev/null
+++ b/src/modules/rlm_eap/all.mk
@@ -0,0 +1 @@
+SUBMAKEFILES := libeap/all.mk rlm_eap.mk types/all.mk radeapclient.mk
diff --git a/src/modules/rlm_eap/configure b/src/modules/rlm_eap/configure
new file mode 100755
index 0000000..a87f8b0
--- /dev/null
+++ b/src/modules/rlm_eap/configure
@@ -0,0 +1,3557 @@
+#! /bin/sh
+# From configure.ac Revision.
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="rlm_eap.c"
+enable_option_checking=no
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+eaptypes
+mod_cflags
+mod_ldflags
+targetname
+subdirs
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_rlm_eap
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS'
+ac_subdirs_all='$eapsubdirs'
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-rlm_eap build without rlm_eap
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+echo
+echo Running tests for rlm_eap
+echo
+
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+# Check whether --with-rlm_eap was given.
+if test "${with_rlm_eap+set}" = set; then :
+ withval=$with_rlm_eap;
+fi
+
+
+
+SMART_LIBS=
+SMART_CLFAGS=
+
+
+fail=
+fr_status=
+fr_features=
+: > "config.report"
+: > "config.report.tmp"
+
+
+
+if test x"$with_rlm_eap" != xno; then
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+eapsubdirs=
+for foo in `find ./types -name configure -print`; do
+ bar=`echo $foo | sed 's%/configure$%%g'`
+ eapsubdirs="$eapsubdirs $bar"
+done
+
+ln -s ../../../install-sh install-sh
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+
+
+subdirs="$subdirs $eapsubdirs"
+
+rm install-sh
+
+
+ targetname=rlm_eap
+else
+ targetname=
+ echo \*\*\* module rlm_eap is disabled.
+
+
+fr_status="disabled"
+
+fi
+
+if test x"$fail" != x""; then
+ targetname=""
+
+
+ if test x"${enable_strict_dependencies}" = x"yes"; then
+ as_fn_error $? "set --without-rlm_eap to disable it explicitly." "$LINENO" 5
+ else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: silently not building rlm_eap." >&5
+$as_echo "$as_me: WARNING: silently not building rlm_eap." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: FAILURE: rlm_eap requires: $fail." >&5
+$as_echo "$as_me: WARNING: FAILURE: rlm_eap requires: $fail." >&2;};
+ fail="$(echo $fail)"
+
+
+fr_status="skipping (requires $fail)"
+
+ fr_features=
+
+ fi
+
+else
+
+
+fr_status="OK"
+
+fi
+
+if test x"$fr_features" = x""; then
+ $as_echo "$fr_status" > "config.report"
+else
+ $as_echo_n "$fr_status ... " > "config.report"
+ cat "config.report.tmp" >> "config.report"
+fi
+
+rm "config.report.tmp"
+
+
+
+
+
+if test x"$fail" != x""; then :
+ eapsubdirs=""
+fi
+
+
+eaptypes=types
+if test x"$eapsubdirs" = x""; then
+ eaptypes=""
+fi
+
+mod_ldflags="$SMART_LIBS"
+mod_cflags="$SMART_CPPFLAGS"
+
+
+
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file, --srcdir, and --disable-option-checking arguments
+ # so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ eval "set x $ac_configure_args"
+ shift
+ for ac_arg
+ do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case $ac_arg in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+ | --c=*)
+ ;;
+ --config-cache | -C)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ ;;
+ --disable-option-checking)
+ ;;
+ *)
+ case $ac_arg in
+ *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_sub_configure_args " '$ac_arg'" ;;
+ esac
+ done
+
+ # Always prepend --prefix to ensure using the same prefix
+ # in subdir configurations.
+ ac_arg="--prefix=$prefix"
+ case $ac_arg in
+ *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args"
+
+ # Pass --silent
+ if test "$silent" = yes; then
+ ac_sub_configure_args="--silent $ac_sub_configure_args"
+ fi
+
+ # Always prepend --disable-option-checking to silence warnings, since
+ # different subdirs can have different --enable and --with options.
+ ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args"
+
+ ac_popdir=`pwd`
+ for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ test -d "$srcdir/$ac_dir" || continue
+
+ ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)"
+ $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5
+ $as_echo "$ac_msg" >&6
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ cd "$ac_dir"
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ ac_sub_configure=$ac_srcdir/configure.gnu
+ elif test -f "$ac_srcdir/configure"; then
+ ac_sub_configure=$ac_srcdir/configure
+ elif test -f "$ac_srcdir/configure.in"; then
+ # This should be Cygnus configure.
+ ac_sub_configure=$ac_aux_dir/configure
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5
+$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+ # Make the cache file name correct relative to the subdirectory.
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+ *) # Relative name.
+ ac_sub_cache_file=$ac_top_build_prefix$cache_file ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+ # The eval makes quoting arguments work.
+ eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \
+ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" ||
+ as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5
+ fi
+
+ cd "$ac_popdir"
+ done
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/src/modules/rlm_eap/configure.ac b/src/modules/rlm_eap/configure.ac
new file mode 100644
index 0000000..dfa13e9
--- /dev/null
+++ b/src/modules/rlm_eap/configure.ac
@@ -0,0 +1,42 @@
+AC_PREREQ([2.69])
+AC_INIT
+AC_CONFIG_SRCDIR([rlm_eap.c])
+AC_REVISION($Revision$)
+FR_INIT_MODULE([rlm_eap])
+
+SMART_LIBS=
+SMART_CLFAGS=
+
+FR_MODULE_START_TESTS
+
+AC_PROG_CC
+
+eapsubdirs=
+for foo in `find ./types -name configure -print`; do
+ bar=`echo $foo | sed 's%/configure$%%g'`
+ eapsubdirs="$eapsubdirs $bar"
+done
+
+dnl # don't ask... this is done to avoid autoconf stupidities.
+ln -s ../../../install-sh install-sh
+
+AC_CONFIG_SUBDIRS($eapsubdirs)
+rm install-sh
+
+FR_MODULE_END_TESTS
+
+FR_MODULE_TEST_FAIL_DO([eapsubdirs=""])
+
+eaptypes=types
+if test x"$eapsubdirs" = x""; then
+ eaptypes=""
+fi
+
+mod_ldflags="$SMART_LIBS"
+mod_cflags="$SMART_CPPFLAGS"
+
+AC_SUBST(mod_ldflags)
+AC_SUBST(mod_cflags)
+AC_SUBST(eaptypes)
+
+AC_OUTPUT
diff --git a/src/modules/rlm_eap/eap.c b/src/modules/rlm_eap/eap.c
new file mode 100644
index 0000000..1ece323
--- /dev/null
+++ b/src/modules/rlm_eap/eap.c
@@ -0,0 +1,1270 @@
+/*
+ * eap.c rfc2284 & rfc2869 implementation
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000-2003,2006 The FreeRADIUS server project
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ */
+/*
+ * EAP PACKET FORMAT
+ * --- ------ ------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Data ...
+ * +-+-+-+-+
+ *
+ *
+ * EAP Request and Response Packet Format
+ * --- ------- --- -------- ------ ------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Type-Data ...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+ *
+ *
+ * EAP Success and Failure Packet Format
+ * --- ------- --- ------- ------ ------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#include <freeradius-devel/modpriv.h>
+
+RCSID("$Id$")
+
+#include "rlm_eap.h"
+#include <ctype.h>
+
+static char const *eap_codes[] = {
+ "", /* 0 is invalid */
+ "Request",
+ "Response",
+ "Success",
+ "Failure"
+};
+
+static int _eap_module_free(eap_module_t *inst)
+{
+ /*
+ * We have to check inst->type as it's only allocated
+ * if we loaded the eap method.
+ */
+ if (inst->type && inst->type->detach) (inst->type->detach)(inst->instance);
+
+#ifndef NDEBUG
+ /*
+ * Don't dlclose() modules if we're doing memory
+ * debugging. This removes the symbols needed by
+ * valgrind.
+ */
+ if (!main_config.debug_memory)
+#endif
+ if (inst->handle) dlclose(inst->handle);
+
+ return 0;
+}
+
+/** Load required EAP sub-modules (methods)
+ *
+ */
+int eap_module_instantiate(rlm_eap_t *inst, eap_module_t **m_inst, eap_type_t num, CONF_SECTION *cs)
+{
+ eap_module_t *method;
+ char *mod_name, *p;
+
+ /* Make room for the EAP-Type */
+ *m_inst = method = talloc_zero(cs, eap_module_t);
+ if (!inst) return -1;
+
+ talloc_set_destructor(method, _eap_module_free);
+
+ /* fill in the structure */
+ method->cs = cs;
+ method->name = eap_type2name(num);
+
+ /*
+ * The name of the module were trying to load
+ */
+ mod_name = talloc_typed_asprintf(method, "rlm_eap_%s", method->name);
+
+ /*
+ * dlopen is case sensitive
+ */
+ p = mod_name;
+ while (*p) {
+ *p = tolower((uint8_t) *p);
+ p++;
+ }
+
+ /*
+ * Link the loaded EAP-Type
+ */
+ method->handle = fr_dlopenext(mod_name);
+ if (!method->handle) {
+ ERROR("rlm_eap (%s): Failed to link %s: %s", inst->xlat_name, mod_name, fr_strerror());
+
+ return -1;
+ }
+
+ method->type = dlsym(method->handle, mod_name);
+ if (!method->type) {
+ ERROR("rlm_eap (%s): Failed linking to structure in %s: %s", inst->xlat_name,
+ method->name, dlerror());
+
+ return -1;
+ }
+
+ cf_log_module(cs, "Linked to sub-module %s", mod_name);
+
+ /*
+ * Call the attach num in the EAP num module
+ */
+ if ((method->type->instantiate) && ((method->type->instantiate)(method->cs, &(method->instance)) < 0)) {
+ ERROR("rlm_eap (%s): Failed to initialise %s", inst->xlat_name, mod_name);
+
+ if (method->instance) {
+ (void) talloc_steal(method, method->instance);
+ }
+
+ return -1;
+ }
+
+ if (method->instance) {
+ (void) talloc_steal(method, method->instance);
+ }
+
+ return 0;
+}
+
+/*
+ * Call the appropriate handle with the right eap_method.
+ */
+static int eap_module_call(eap_module_t *module, eap_handler_t *handler)
+{
+ int rcode = 1;
+ REQUEST *request = handler->request;
+
+ char const *caller = request->module;
+
+ rad_assert(module != NULL);
+
+ RDEBUG2("Calling submodule %s to process data", module->type->name);
+
+ request->module = module->type->name;
+
+ switch (handler->stage) {
+ case INITIATE:
+ if (!module->type->session_init(module->instance, handler)) {
+ rcode = 0;
+ }
+
+ break;
+
+ case PROCESS:
+ /*
+ * The called function updates the EAP reply packet.
+ */
+ if (!module->type->process ||
+ !module->type->process(module->instance, handler)) {
+ rcode = 0;
+ }
+
+ break;
+
+ default:
+ /* Should never enter here */
+ RDEBUG("Internal sanity check failed on EAP");
+ rcode = 0;
+ break;
+ }
+
+ request->module = caller;
+ return rcode;
+}
+
+/** Process NAK data from EAP peer
+ *
+ */
+static eap_type_t eap_process_nak(rlm_eap_t *inst, REQUEST *request,
+ eap_type_t type,
+ eap_type_data_t *nak)
+{
+ unsigned int i;
+ VALUE_PAIR *vp;
+ eap_type_t method = PW_EAP_INVALID;
+
+ /*
+ * The NAK data is the preferred EAP type(s) of
+ * the client.
+ *
+ * RFC 3748 says to list one or more proposed
+ * alternative types, one per octet, or to use
+ * 0 for no alternative.
+ */
+ if (!nak->data) {
+ REDEBUG("Peer sent empty (invalid) NAK. "
+ "Can't select method to continue with");
+
+ return PW_EAP_INVALID;
+ }
+
+ /*
+ * Pick one type out of the one they asked for,
+ * as they may have asked for many.
+ */
+ vp = fr_pair_find_by_num(request->config, PW_EAP_TYPE, 0, TAG_ANY);
+ for (i = 0; i < nak->length; i++) {
+ /*
+ * Type 0 is valid, and means there are no
+ * common choices.
+ */
+ if (nak->data[i] == 0) {
+ RDEBUG("Peer NAK'd indicating it is not willing to "
+ "continue ");
+
+ return PW_EAP_INVALID;
+ }
+
+ /*
+ * It is invalid to request identity,
+ * notification & nak in nak.
+ */
+ if (nak->data[i] < PW_EAP_MD5) {
+ REDEBUG("Peer NAK'd asking for bad "
+ "type %s (%d)",
+ eap_type2name(nak->data[i]),
+ nak->data[i]);
+
+ return PW_EAP_INVALID;
+ }
+
+ if ((nak->data[i] >= PW_EAP_MAX_TYPES) ||
+ !inst->methods[nak->data[i]]) {
+ RDEBUG2("Peer NAK'd asking for "
+ "unsupported EAP type %s (%d), skipping...",
+ eap_type2name(nak->data[i]),
+ nak->data[i]);
+
+ continue;
+ }
+
+ /*
+ * Prevent a firestorm if the client is confused.
+ */
+ if (type == nak->data[i]) {
+ RDEBUG2("Peer NAK'd our request for "
+ "%s (%d) with a request for "
+ "%s (%d), skipping...",
+ eap_type2name(nak->data[i]),
+ nak->data[i],
+ eap_type2name(nak->data[i]),
+ nak->data[i]);
+
+ RWARN("!!! We requested to use an EAP type as normal.");
+ RWARN("!!! The supplicant rejected that, and requested to use the same EAP type.");
+ RWARN("!!! i.e. the supplicant said 'I don't like X, please use X instead.");
+ RWARN("!!! The supplicant software is broken and does not work properly.");
+ RWARN("!!! Please upgrade it to software that works.");
+
+ continue;
+ }
+
+ /*
+ * Enforce per-user configuration of EAP
+ * types.
+ */
+ if (vp && (vp->vp_integer != nak->data[i])) {
+ RDEBUG2("Peer wants %s (%d), while we "
+ "require %s (%d), skipping",
+ eap_type2name(nak->data[i]),
+ nak->data[i],
+ eap_type2name(vp->vp_integer),
+ vp->vp_integer);
+
+ continue;
+ }
+
+ RDEBUG("Found mutually acceptable type %s (%d)",
+ eap_type2name(nak->data[i]), nak->data[i]);
+
+ method = nak->data[i];
+
+ break;
+ }
+
+ if (method == PW_EAP_INVALID) {
+ REDEBUG("No mutually acceptable types found");
+ }
+
+ return method;
+}
+
+/** Select the correct callback based on a response
+ *
+ * Based on the EAP response from the supplicant, call the appropriate
+ * method callback.
+ *
+ * Default to the configured EAP-Type for all Unsupported EAP-Types.
+ *
+ * @param inst Configuration data for this instance of rlm_eap.
+ * @param handler State data that persists over multiple rounds of EAP.
+ * @return a status code.
+ */
+eap_rcode_t eap_method_select(rlm_eap_t *inst, eap_handler_t *handler)
+{
+ eap_type_data_t *type = &handler->eap_ds->response->type;
+ REQUEST *request = handler->request;
+
+ eap_type_t next = inst->default_method;
+ VALUE_PAIR *vp;
+
+ /*
+ * Don't trust anyone.
+ */
+ if ((type->num == 0) || (type->num >= PW_EAP_MAX_TYPES)) {
+ REDEBUG("Peer sent EAP method number %d, which is outside known range", type->num);
+
+ return EAP_INVALID;
+ }
+
+ /*
+ * Multiple levels of TLS nesting are invalid. But if
+ * the parent has a home_server defined, then this
+ * request is being processed through a virtual
+ * server... so that's OK.
+ *
+ * i.e. we're inside an EAP tunnel, which means we have a
+ * parent. If the outer session exists, and doesn't have
+ * a home server, then it's multiple layers of tunneling.
+ */
+ if (handler->request->parent &&
+ handler->request->parent->parent &&
+ !handler->request->parent->parent->home_server) {
+ RERROR("Multiple levels of TLS nesting are invalid");
+
+ return EAP_INVALID;
+ }
+
+ RDEBUG2("Peer sent packet with method EAP %s (%d)", eap_type2name(type->num), type->num);
+ /*
+ * Figure out what to do.
+ */
+ switch (type->num) {
+ case PW_EAP_IDENTITY:
+ /*
+ * Allow per-user configuration of EAP types.
+ */
+ vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TYPE, 0,
+ TAG_ANY);
+ if (vp) next = vp->vp_integer;
+
+ /*
+ * Ensure it's valid.
+ */
+ if ((next < PW_EAP_MD5) ||
+ (next >= PW_EAP_MAX_TYPES) ||
+ (!inst->methods[next])) {
+ REDEBUG2("Tried to start unsupported EAP type %s (%d)",
+ eap_type2name(next), next);
+
+ return EAP_INVALID;
+ }
+
+ do_initiate:
+ /*
+ * If any of these fail, we messed badly somewhere
+ */
+ rad_assert(next >= PW_EAP_MD5);
+ rad_assert(next < PW_EAP_MAX_TYPES);
+ rad_assert(inst->methods[next]);
+
+ handler->stage = INITIATE;
+ handler->type = next;
+
+ if (eap_module_call(inst->methods[next], handler) == 0) {
+ REDEBUG2("Failed starting EAP %s (%d) session. EAP sub-module failed",
+ eap_type2name(next), next);
+
+ return EAP_INVALID;
+ }
+ break;
+
+ case PW_EAP_NAK:
+ /*
+ * Delete old data, if necessary.
+ */
+ if (handler->opaque && handler->free_opaque) {
+ handler->free_opaque(handler->opaque);
+ handler->free_opaque = NULL;
+ handler->opaque = NULL;
+ }
+
+ /*
+ * We got a NAK after the peer started doing a
+ * particular EAP type. That's rude, tell the
+ * peer to go away.
+ */
+ if (handler->started) return EAP_INVALID;
+
+ next = eap_process_nak(inst, handler->request,
+ handler->type, type);
+
+ /*
+ * We probably want to return 'fail' here...
+ */
+ if (!next) {
+ return EAP_INVALID;
+ }
+
+ goto do_initiate;
+
+ /*
+ * Key off of the configured sub-modules.
+ */
+ default:
+ /*
+ * We haven't configured it, it doesn't exist.
+ */
+ if (!inst->methods[type->num]) {
+ REDEBUG2("Client asked for unsupported EAP type %s (%d)",
+ eap_type2name(type->num),
+ type->num);
+
+ return EAP_INVALID;
+ }
+
+ rad_assert(handler->stage == PROCESS);
+ handler->type = type->num;
+ if (eap_module_call(inst->methods[type->num],
+ handler) == 0) {
+ REDEBUG2("Failed continuing EAP %s (%d) session. EAP sub-module failed",
+ eap_type2name(type->num),
+ type->num);
+
+ return EAP_INVALID;
+ }
+ handler->started = true;
+ break;
+ }
+
+ return EAP_OK;
+}
+
+
+/*
+ * compose EAP reply packet in EAP-Message attr of RADIUS.
+ *
+ * Set the RADIUS reply codes based on EAP request codes. Append
+ * any additonal VPs to RADIUS reply
+ */
+rlm_rcode_t eap_compose(eap_handler_t *handler)
+{
+ VALUE_PAIR *vp;
+ eap_packet_raw_t *eap_packet;
+ REQUEST *request;
+ EAP_DS *eap_ds;
+ eap_packet_t *reply;
+ int rcode;
+
+#ifndef NDEBUG
+ handler = talloc_get_type_abort(handler, eap_handler_t);
+ request = talloc_get_type_abort(handler->request, REQUEST);
+ eap_ds = talloc_get_type_abort(handler->eap_ds, EAP_DS);
+ reply = talloc_get_type_abort(eap_ds->request, eap_packet_t);
+#else
+ request = handler->request;
+ eap_ds = handler->eap_ds;
+ reply = eap_ds->request;
+#endif
+
+ /*
+ * The Id for the EAP packet to the NAS wasn't set.
+ * Do so now.
+ */
+ if (!eap_ds->set_request_id) {
+ /*
+ * Id serves to suppport request/response
+ * retransmission in the EAP layer and as such
+ * must be different for 'adjacent' packets
+ * except in case of success/failure-replies.
+ *
+ * RFC2716 (EAP-TLS) requires this to be
+ * incremented, RFC2284 only makes the above-
+ * mentioned restriction.
+ */
+ reply->id = handler->eap_ds->response->id;
+
+ switch (reply->code) {
+ /*
+ * The Id is a simple "ack" for success
+ * and failure.
+ *
+ * RFC 3748 section 4.2 says
+ *
+ * ... The Identifier field MUST match
+ * the Identifier field of the Response
+ * packet that it is sent in response
+ * to.
+ */
+ case PW_EAP_SUCCESS:
+ case PW_EAP_FAILURE:
+ break;
+
+ /*
+ * We've sent a response to their
+ * request, the Id is incremented.
+ */
+ default:
+ ++reply->id;
+ }
+ }
+
+ /*
+ * For Request & Response packets, set the EAP sub-type,
+ * if the EAP sub-module didn't already set it.
+ *
+ * This allows the TLS module to be "morphic", and means
+ * that the TTLS and PEAP modules can call it to do most
+ * of their dirty work.
+ */
+ if (((eap_ds->request->code == PW_EAP_REQUEST) ||
+ (eap_ds->request->code == PW_EAP_RESPONSE)) &&
+ (eap_ds->request->type.num == 0)) {
+ rad_assert(handler->type >= PW_EAP_MD5);
+ rad_assert(handler->type < PW_EAP_MAX_TYPES);
+
+ eap_ds->request->type.num = handler->type;
+ }
+
+ if (eap_wireformat(reply) == EAP_INVALID) {
+ return RLM_MODULE_INVALID;
+ }
+ eap_packet = (eap_packet_raw_t *)reply->packet;
+
+ vp = radius_pair_create(request->reply, &request->reply->vps, PW_EAP_MESSAGE, 0);
+ if (!vp) return RLM_MODULE_INVALID;
+
+ vp->vp_length = eap_packet->length[0] * 256 + eap_packet->length[1];
+ vp->vp_octets = talloc_steal(vp, reply->packet);
+ reply->packet = NULL;
+
+ /*
+ * EAP-Message is always associated with
+ * Message-Authenticator but not vice-versa.
+ *
+ * Don't add a Message-Authenticator if it's already
+ * there.
+ */
+ vp = fr_pair_find_by_num(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+ if (!vp) {
+ vp = fr_pair_afrom_num(request->reply, PW_MESSAGE_AUTHENTICATOR, 0);
+ vp->vp_length = AUTH_VECTOR_LEN;
+ vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length);
+ fr_pair_add(&(request->reply->vps), vp);
+ }
+
+ /* Set request reply code, but only if it's not already set. */
+ rcode = RLM_MODULE_OK;
+ if (!request->reply->code) switch (reply->code) {
+ case PW_EAP_RESPONSE:
+ request->reply->code = PW_CODE_ACCESS_REJECT;
+ rcode = RLM_MODULE_REJECT;
+ break;
+ case PW_EAP_SUCCESS:
+ request->reply->code = PW_CODE_ACCESS_ACCEPT;
+ rcode = RLM_MODULE_OK;
+ break;
+ case PW_EAP_FAILURE:
+ request->reply->code = PW_CODE_ACCESS_REJECT;
+ rcode = RLM_MODULE_REJECT;
+ break;
+ case PW_EAP_REQUEST:
+ request->reply->code = PW_CODE_ACCESS_CHALLENGE;
+ rcode = RLM_MODULE_HANDLED;
+ break;
+ default:
+ /*
+ * When we're pulling MS-CHAPv2 out of EAP-MS-CHAPv2,
+ * we do so WITHOUT setting a reply code, as the
+ * request is being proxied.
+ */
+ if (request->options & RAD_REQUEST_OPTION_PROXY_EAP) {
+ return RLM_MODULE_HANDLED;
+ }
+
+ /* Should never enter here */
+ REDEBUG("Reply code %d is unknown, rejecting the request", reply->code);
+ request->reply->code = PW_CODE_ACCESS_REJECT;
+ reply->code = PW_EAP_FAILURE;
+ rcode = RLM_MODULE_REJECT;
+ break;
+ }
+
+ RDEBUG2("Sending EAP %s (code %i) ID %d length %i",
+ eap_codes[eap_packet->code], eap_packet->code, reply->id,
+ eap_packet->length[0] * 256 + eap_packet->length[1]);
+
+ return rcode;
+}
+
+/*
+ * Radius criteria, EAP-Message is invalid without Message-Authenticator
+ * For EAP_START, send Access-Challenge with EAP Identity request.
+ */
+int eap_start(rlm_eap_t *inst, REQUEST *request)
+{
+ VALUE_PAIR *vp, *proxy;
+ VALUE_PAIR *eap_msg;
+
+ eap_msg = fr_pair_find_by_num(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ if (!eap_msg) {
+ RDEBUG2("No EAP-Message, not doing EAP");
+ return EAP_NOOP;
+ }
+
+ /*
+ * Look for EAP-Type = None (FreeRADIUS specific attribute)
+ * this allows you to NOT do EAP for some users.
+ */
+ vp = fr_pair_find_by_num(request->packet->vps, PW_EAP_TYPE, 0, TAG_ANY);
+ if (vp && vp->vp_integer == 0) {
+ RDEBUG2("Found EAP-Message, but EAP-Type = None, so we're not doing EAP");
+ return EAP_NOOP;
+ }
+
+ /*
+ * http://www.freeradius.org/rfc/rfc2869.html#EAP-Message
+ *
+ * Checks for Message-Authenticator are handled by rad_recv().
+ */
+
+ /*
+ * Check for a Proxy-To-Realm. Don't get excited over LOCAL
+ * realms (sigh).
+ */
+ proxy = fr_pair_find_by_num(request->config, PW_PROXY_TO_REALM, 0, TAG_ANY);
+ if (proxy) {
+ REALM *realm;
+
+ /*
+ * If it's a LOCAL realm, then we're not proxying
+ * to it.
+ */
+ realm = realm_find(proxy->vp_strvalue);
+ if (!realm || (realm && (!realm->auth_pool))) {
+ proxy = NULL;
+ }
+ }
+
+ /*
+ * Check the length before de-referencing the contents.
+ *
+ * Lengths of zero are required by the RFC for EAP-Start,
+ * but we've never seen them in practice.
+ *
+ * Lengths of two are what we see in practice as
+ * EAP-Starts.
+ */
+ if ((eap_msg->vp_length == 0) || (eap_msg->vp_length == 2)) {
+ uint8_t *p;
+
+ /*
+ * It's a valid EAP-Start, but the request
+ * was marked as being proxied. So we don't
+ * do EAP, as the home server will do it.
+ */
+ if (proxy) {
+ do_proxy:
+ RDEBUG2("Request is supposed to be proxied to "
+ "Realm %s. Not doing EAP.", proxy->vp_strvalue);
+ return EAP_NOOP;
+ }
+
+ RDEBUG2("Got EAP_START message");
+ vp = fr_pair_afrom_num(request->reply, PW_EAP_MESSAGE, 0);
+ if (!vp) return EAP_FAIL;
+ fr_pair_add(&request->reply->vps, vp);
+
+ /*
+ * Manually create an EAP Identity request
+ */
+ vp->vp_length = 5;
+ vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
+
+ p[0] = PW_EAP_REQUEST;
+ p[1] = 0; /* ID */
+ p[2] = 0;
+ p[3] = 5; /* length */
+ p[4] = PW_EAP_IDENTITY;
+
+ request->reply->code = PW_CODE_ACCESS_CHALLENGE;
+ return EAP_FOUND;
+ } /* end of handling EAP-Start */
+
+ /*
+ * The EAP packet header is 4 bytes, plus one byte of
+ * EAP sub-type. Short packets are discarded, unless
+ * we're proxying.
+ */
+ if (eap_msg->vp_length < (EAP_HEADER_LEN + 1)) {
+ if (proxy) goto do_proxy;
+
+ RDEBUG2("Ignoring EAP-Message which is too short to be meaningful");
+ return EAP_FAIL;
+ }
+
+ /*
+ * Create an EAP-Type containing the EAP-type
+ * from the packet.
+ */
+ vp = fr_pair_afrom_num(request->packet, PW_EAP_TYPE, 0);
+ if (vp) {
+ vp->vp_integer = eap_msg->vp_octets[4];
+ fr_pair_add(&(request->packet->vps), vp);
+ }
+
+ /*
+ * If the request was marked to be proxied, do it now.
+ * This is done after checking for a valid length
+ * (which may not be good), and after adding the EAP-Type
+ * attribute. This lets other modules selectively cancel
+ * proxying based on EAP-Type.
+ */
+ if (proxy) goto do_proxy;
+
+ /*
+ * From now on, we're supposed to be handling the
+ * EAP packet. We better understand it...
+ */
+
+ /*
+ * We're allowed only a few codes. Request, Response,
+ * Success, or Failure.
+ */
+ if ((eap_msg->vp_octets[0] == 0) ||
+ (eap_msg->vp_octets[0] >= PW_EAP_MAX_CODES)) {
+ RDEBUG2("Peer sent EAP packet with unknown code %i", eap_msg->vp_octets[0]);
+ } else {
+ RDEBUG2("Peer sent EAP %s (code %i) ID %d length %zu",
+ eap_codes[eap_msg->vp_octets[0]],
+ eap_msg->vp_octets[0],
+ eap_msg->vp_octets[1],
+ eap_msg->vp_length);
+ }
+
+ /*
+ * We handle request and responses. The only other defined
+ * codes are success and fail. The client SHOULD NOT be
+ * sending success/fail packets to us, as it doesn't make
+ * sense.
+ */
+ if ((eap_msg->vp_octets[0] != PW_EAP_REQUEST) &&
+ (eap_msg->vp_octets[0] != PW_EAP_RESPONSE)) {
+ RDEBUG2("Ignoring EAP packet which we don't know how to handle");
+ return EAP_FAIL;
+ }
+
+ /*
+ * We've been told to ignore unknown EAP types, AND it's
+ * an unknown type. Return "NOOP", which will cause the
+ * mod_authorize() to return NOOP.
+ *
+ * EAP-Identity, Notification, and NAK are all handled
+ * internally, so they never have handlers.
+ */
+ if ((eap_msg->vp_octets[4] >= PW_EAP_MD5) &&
+ inst->ignore_unknown_types &&
+ ((eap_msg->vp_octets[4] == 0) ||
+ (eap_msg->vp_octets[4] >= PW_EAP_MAX_TYPES) ||
+ (!inst->methods[eap_msg->vp_octets[4]]))) {
+ RDEBUG2("Ignoring Unknown EAP type");
+ return EAP_NOOP;
+ }
+
+ /*
+ * They're NAKing the EAP type we wanted to use, and
+ * asking for one which we don't support.
+ *
+ * NAK is code + id + length1 + length + NAK
+ * + requested EAP type(s).
+ *
+ * We know at this point that we can't handle the
+ * request. We could either return an EAP-Fail here, but
+ * it's not too critical.
+ *
+ * By returning "noop", we can ensure that authorize()
+ * returns NOOP, and another module may choose to proxy
+ * the request.
+ */
+ if ((eap_msg->vp_octets[4] == PW_EAP_NAK) &&
+ (eap_msg->vp_length >= (EAP_HEADER_LEN + 2)) &&
+ inst->ignore_unknown_types &&
+ ((eap_msg->vp_octets[5] == 0) ||
+ (eap_msg->vp_octets[5] >= PW_EAP_MAX_TYPES) ||
+ (!inst->methods[eap_msg->vp_octets[5]]))) {
+ RDEBUG2("Ignoring NAK with request for unknown EAP type");
+ return EAP_NOOP;
+ }
+
+ if ((eap_msg->vp_octets[4] == PW_EAP_TTLS) ||
+ (eap_msg->vp_octets[4] == PW_EAP_PEAP)) {
+ RDEBUG2("Continuing tunnel setup");
+ return EAP_OK;
+ }
+ /*
+ * We return ok in response to EAP identity
+ * This means we can write:
+ *
+ * eap {
+ * ok = return
+ * }
+ * ldap
+ * sql
+ *
+ * ...in the inner-tunnel, to avoid expensive and unnecessary SQL/LDAP lookups
+ */
+ if (eap_msg->vp_octets[4] == PW_EAP_IDENTITY) {
+ RDEBUG2("EAP-Identity reply, returning 'ok' so we can short-circuit the rest of authorize");
+ return EAP_OK;
+ }
+
+ /*
+ * Later EAP messages are longer than the 'start'
+ * message, so if everything is OK, this function returns
+ * 'no start found', so that the rest of the EAP code can
+ * use the State attribute to match this EAP-Message to
+ * an ongoing conversation.
+ */
+ RDEBUG2("No EAP Start, assuming it's an on-going EAP conversation");
+
+ return EAP_NOTFOUND;
+}
+
+/*
+ * compose EAP FAILURE packet in EAP-Message
+ */
+void eap_fail(eap_handler_t *handler)
+{
+ /*
+ * Delete any previous replies.
+ */
+ fr_pair_delete_by_num(&handler->request->reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ fr_pair_delete_by_num(&handler->request->reply->vps, PW_STATE, 0, TAG_ANY);
+
+ talloc_free(handler->eap_ds->request);
+ handler->eap_ds->request = talloc_zero(handler->eap_ds, eap_packet_t);
+ handler->eap_ds->request->code = PW_EAP_FAILURE;
+ handler->finished = true;
+ eap_compose(handler);
+}
+
+/*
+ * compose EAP SUCCESS packet in EAP-Message
+ */
+void eap_success(eap_handler_t *handler)
+{
+ handler->eap_ds->request->code = PW_EAP_SUCCESS;
+ handler->finished = true;
+ eap_compose(handler);
+}
+
+/*
+ * Basic EAP packet verfications & validations
+ */
+static int eap_validation(REQUEST *request, eap_packet_raw_t **eap_packet_p)
+{
+ uint16_t len;
+ eap_packet_raw_t *eap_packet = *eap_packet_p;
+
+ memcpy(&len, eap_packet->length, sizeof(uint16_t));
+ len = ntohs(len);
+
+ /*
+ * High level EAP packet checks
+ */
+ if (len <= EAP_HEADER_LEN) {
+ RAUTH("EAP packet is too small: Ignoring it.");
+ return EAP_INVALID;
+ }
+
+ if (eap_packet->code == PW_EAP_REQUEST) {
+ VALUE_PAIR *vp;
+ RAUTH("Unexpected EAP-Request. NAKing it.");
+
+ vp = pair_make_reply("EAP-Message", "123456", T_OP_SET);
+ if (vp) {
+ uint8_t buffer[6];
+
+ buffer[0] = PW_EAP_RESPONSE;
+ buffer[1] = eap_packet->id;
+ buffer[2] = 0;
+ buffer[3] = 6;
+ buffer[4] = PW_EAP_NAK;
+ buffer[5] = 0; /* no overlapping EAP types */
+
+ fr_pair_value_memcpy(vp, buffer, 6);
+ }
+
+ /*
+ * Ensure that the Access-Reject has a Message-Authenticator
+ */
+ vp = fr_pair_find_by_num(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+ if (!vp) {
+ vp = fr_pair_afrom_num(request->reply, PW_MESSAGE_AUTHENTICATOR, 0);
+ vp->vp_length = AUTH_VECTOR_LEN;
+ vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length);
+ fr_pair_add(&(request->reply->vps), vp);
+ }
+ request->reply->code = PW_CODE_ACCESS_REJECT;
+
+ return EAP_INVALID;
+ }
+
+ /*
+ * We only allow responses from the peer. The peer
+ * CANNOT ask us to authenticate outselves.
+ */
+ if (eap_packet->code != PW_EAP_RESPONSE) {
+ RAUTH("Unexpected packet code %02x: Ignoring it.", eap_packet->code);
+ return EAP_INVALID;
+ }
+
+ if ((eap_packet->data[0] <= 0) ||
+ (eap_packet->data[0] >= PW_EAP_MAX_TYPES)) {
+ /*
+ * Handle expanded types by smashing them to
+ * normal types.
+ */
+ if (eap_packet->data[0] == PW_EAP_EXPANDED_TYPE) {
+ uint8_t *p, *q;
+
+ if (len <= (EAP_HEADER_LEN + 1 + 3 + 4)) {
+ RAUTH("Expanded EAP type is too short: ignoring the packet");
+ return EAP_INVALID;
+ }
+
+ if ((eap_packet->data[1] != 0) ||
+ (eap_packet->data[2] != 0) ||
+ (eap_packet->data[3] != 0)) {
+ RAUTH("Expanded EAP type has unknown Vendor-ID: ignoring the packet");
+ return EAP_INVALID;
+ }
+
+ if ((eap_packet->data[4] != 0) ||
+ (eap_packet->data[5] != 0) ||
+ (eap_packet->data[6] != 0)) {
+ RAUTH("Expanded EAP type has unknown Vendor-Type: ignoring the packet");
+ return EAP_INVALID;
+ }
+
+ if ((eap_packet->data[7] == 0) ||
+ (eap_packet->data[7] >= PW_EAP_MAX_TYPES)) {
+ RAUTH("Unsupported Expanded EAP type %s (%u): ignoring the packet",
+ eap_type2name(eap_packet->data[7]), eap_packet->data[7]);
+ return EAP_INVALID;
+ }
+
+ if (eap_packet->data[7] == PW_EAP_NAK) {
+ RAUTH("Unsupported Expanded EAP-NAK: ignoring the packet");
+ return EAP_INVALID;
+ }
+
+ /*
+ * Re-write the EAP packet to NOT have the expanded type.
+ */
+ q = (uint8_t *) eap_packet;
+ memmove(q + EAP_HEADER_LEN, q + EAP_HEADER_LEN + 7, len - 7 - EAP_HEADER_LEN);
+
+ p = talloc_realloc(talloc_parent(eap_packet), eap_packet, uint8_t, len - 7);
+ if (!p) {
+ RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
+ eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
+ return EAP_INVALID;
+ }
+
+ len -= 7;
+ p[2] = (len >> 8) & 0xff;
+ p[3] = len & 0xff;
+
+ *eap_packet_p = (eap_packet_raw_t *) p;
+ RWARN("Converting Expanded EAP to normal EAP.");
+ RWARN("Unnecessary use of Expanded EAP types is not recommended.");
+
+ return EAP_VALID;
+ }
+
+ RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
+ eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
+ return EAP_INVALID;
+ }
+
+ /* we don't expect notification, but we send it */
+ if (eap_packet->data[0] == PW_EAP_NOTIFICATION) {
+ RAUTH("Got NOTIFICATION, "
+ "Ignoring the packet");
+ return EAP_INVALID;
+ }
+
+ return EAP_VALID;
+}
+
+
+/*
+ * Get the user Identity only from EAP-Identity packets
+ */
+static char *eap_identity(REQUEST *request, eap_handler_t *handler, eap_packet_raw_t *eap_packet)
+{
+ int size;
+ uint16_t len;
+ char *identity;
+
+ if ((!eap_packet) ||
+ (eap_packet->code != PW_EAP_RESPONSE) ||
+ (eap_packet->data[0] != PW_EAP_IDENTITY)) {
+ return NULL;
+ }
+
+ memcpy(&len, eap_packet->length, sizeof(uint16_t));
+ len = ntohs(len);
+
+ if ((len <= 5) || (eap_packet->data[1] == 0x00)) {
+ REDEBUG("EAP-Identity Unknown");
+ return NULL;
+ }
+
+ if (len > 1024) {
+ REDEBUG("EAP-Identity too long");
+ return NULL;
+ }
+
+ size = len - 5;
+ identity = talloc_array(handler, char, size + 1);
+ memcpy(identity, &eap_packet->data[1], size);
+ identity[size] = '\0';
+
+ return identity;
+}
+
+
+/*
+ * Create our Request-Response data structure with the eap packet
+ */
+static EAP_DS *eap_buildds(eap_handler_t *handler,
+ eap_packet_raw_t **eap_packet_p)
+{
+ EAP_DS *eap_ds = NULL;
+ eap_packet_raw_t *eap_packet = *eap_packet_p;
+ int typelen;
+ uint16_t len;
+
+ if ((eap_ds = eap_ds_alloc(handler)) == NULL) {
+ return NULL;
+ }
+
+ eap_ds->response->packet = (uint8_t *) eap_packet;
+ (void) talloc_steal(eap_ds, eap_packet);
+ eap_ds->response->code = eap_packet->code;
+ eap_ds->response->id = eap_packet->id;
+ eap_ds->response->type.num = eap_packet->data[0];
+
+ memcpy(&len, eap_packet->length, sizeof(uint16_t));
+ len = ntohs(len);
+ eap_ds->response->length = len;
+
+ /*
+ * We've eaten the eap packet into the eap_ds.
+ */
+ *eap_packet_p = NULL;
+
+ /*
+ * First 5 bytes in eap, are code + id + length(2) + type.
+ *
+ * The rest is type-specific data. We skip type while
+ * getting typedata from data.
+ */
+ typelen = len - 5/*code + id + length + type */;
+ if (typelen > 0) {
+ /*
+ * Since the packet contains the complete
+ * eap_packet, typedata will be a ptr in packet
+ * to its typedata
+ */
+ eap_ds->response->type.data = eap_ds->response->packet + 5/*code+id+length+type*/;
+ eap_ds->response->type.length = typelen;
+ } else {
+ eap_ds->response->type.length = 0;
+ eap_ds->response->type.data = NULL;
+ }
+
+ return eap_ds;
+}
+
+
+/*
+ * If identity response then create a fresh handler & fill the identity
+ * else handler MUST be in our list, get that.
+ * This handler creation cannot fail
+ *
+ * username contains REQUEST->username which might have been stripped.
+ * identity contains the one sent in EAP-Identity response
+ */
+eap_handler_t *eap_handler(rlm_eap_t *inst, eap_packet_raw_t **eap_packet_p,
+ REQUEST *request)
+{
+ eap_handler_t *handler = NULL;
+ eap_packet_raw_t *eap_packet;
+ VALUE_PAIR *vp;
+
+ /*
+ * Ensure it's a valid EAP-Request, or EAP-Response.
+ */
+ if (eap_validation(request, eap_packet_p) == EAP_INVALID) {
+ error:
+ talloc_free(*eap_packet_p);
+ *eap_packet_p = NULL;
+ return NULL;
+ }
+
+ eap_packet = *eap_packet_p;
+
+ /*
+ * eap_handler_t MUST be found in the list if it is not
+ * EAP-Identity response
+ */
+ if (eap_packet->data[0] != PW_EAP_IDENTITY) {
+ handler = eaplist_find(inst, request, eap_packet);
+ if (!handler) {
+ /* Either send EAP_Identity or EAP-Fail */
+ RDEBUG("Either EAP-request timed out OR EAP-response to an unknown EAP-request");
+ goto error;
+ }
+
+ /*
+ * Even more paranoia. Without this, some weird
+ * clients could do crazy things.
+ *
+ * It's ok to send EAP sub-type NAK in response
+ * to a request for a particular type, but it's NOT
+ * OK to blindly return data for another type.
+ */
+ if ((eap_packet->data[0] != PW_EAP_NAK) &&
+ (eap_packet->data[0] != handler->type)) {
+ RERROR("Response appears to match a previous request, but the EAP type is wrong");
+ RERROR("We expected EAP type %s, but received type %s",
+ eap_type2name(handler->type),
+ eap_type2name(eap_packet->data[0]));
+ RERROR("Your Supplicant or NAS is probably broken");
+ goto error;
+ }
+
+ vp = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ if (!vp) {
+ /*
+ * NAS did not set the User-Name
+ * attribute, so we set it here and
+ * prepend it to the beginning of the
+ * request vps so that autz's work
+ * correctly
+ */
+ RDEBUG2("Broken NAS did not set User-Name, setting from EAP Identity");
+ vp = fr_pair_make(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
+ if (!vp) {
+ goto error;
+ }
+ } else {
+ /*
+ * A little more paranoia. If the NAS
+ * *did* set the User-Name, and it doesn't
+ * match the identity, (i.e. If they
+ * change their User-Name part way through
+ * the EAP transaction), then reject the
+ * request as the NAS is doing something
+ * funny.
+ */
+ if (strncmp(handler->identity, vp->vp_strvalue,
+ MAX_STRING_LEN) != 0) {
+ RDEBUG("Identity does not match User-Name. Authentication failed");
+ goto error;
+ }
+ }
+ } else { /* packet was EAP identity */
+ handler = eap_handler_alloc(inst);
+ if (!handler) {
+ goto error;
+ }
+
+ /*
+ * All fields in the handler are set to zero.
+ */
+ handler->identity = eap_identity(request, handler, eap_packet);
+ if (!handler->identity) {
+ RDEBUG("Identity Unknown, authentication failed");
+ error2:
+ talloc_free(handler);
+ goto error;
+ }
+
+ vp = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ if (!vp) {
+ /*
+ * NAS did not set the User-Name
+ * attribute, so we set it here and
+ * prepend it to the beginning of the
+ * request vps so that autz's work
+ * correctly
+ */
+ RWDEBUG2("NAS did not set User-Name. Setting it locally from EAP Identity");
+ vp = fr_pair_make(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
+ if (!vp) {
+ goto error2;
+ }
+ } else {
+ /*
+ * Paranoia. If the NAS *did* set the
+ * User-Name, and it doesn't match the
+ * identity, the NAS is doing something
+ * funny, so reject the request.
+ */
+ if (strncmp(handler->identity, vp->vp_strvalue,
+ MAX_STRING_LEN) != 0) {
+ RDEBUG("Identity does not match User-Name, setting from EAP Identity");
+ goto error2;
+ }
+ }
+ }
+
+ handler->eap_ds = eap_buildds(handler, eap_packet_p);
+ if (!handler->eap_ds) {
+ goto error2;
+ }
+
+ handler->timestamp = request->timestamp;
+ handler->request = request;
+ return handler;
+}
diff --git a/src/modules/rlm_eap/eap.h b/src/modules/rlm_eap/eap.h
new file mode 100644
index 0000000..b487c08
--- /dev/null
+++ b/src/modules/rlm_eap/eap.h
@@ -0,0 +1,154 @@
+/*
+ * eap.h Header file containing the interfaces for all EAP types.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _EAP_H
+#define _EAP_H
+
+RCSIDH(eap_h, "$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+
+#include "eap_types.h"
+
+/* TLS configuration name */
+#define TLS_CONFIG_SECTION "tls-config"
+
+/*
+ * EAP_DS contains all the received/sending information
+ * response = Received EAP packet
+ * request = Sending EAP packet
+ *
+ * Note: We are authentication server,
+ * we get ONLY EAP-Responses and
+ * we send EAP-Request/EAP-success/EAP-failure
+ */
+typedef struct eap_ds {
+ eap_packet_t *response;
+ eap_packet_t *request;
+ int set_request_id;
+} EAP_DS;
+
+/*
+ * Currently there are only 2 types
+ * of operations defined,
+ * apart from attach & detach for each EAP-Type.
+ */
+typedef enum operation_t {
+ INITIATE = 0,
+ PROCESS
+} operation_t;
+
+
+/*
+ * eap_handler_t is the interface for any EAP-Type.
+ * Each handler contains information for one specific EAP-Type.
+ * This way we don't need to change any interfaces in future.
+ * It is also a list of EAP-request handlers waiting for EAP-response
+ * eap_id = copy of the eap packet we sent to the
+ *
+ * next = pointer to next
+ * state = state attribute from the reply we sent
+ * state_len = length of data in the state attribute.
+ * src_ipaddr = client which sent us the RADIUS request containing
+ * this EAP conversation.
+ * eap_id = copy of EAP id we sent to the client.
+ * timestamp = timestamp when this handler was last used.
+ * identity = Identity, as obtained, from EAP-Identity response.
+ * request = RADIUS request data structure
+ * prev_eapds = Previous EAP request, for which eap_ds contains the response.
+ * eap_ds = Current EAP response.
+ * opaque = EAP-Type holds some data that corresponds to the current
+ * EAP-request/response
+ * free_opaque = To release memory held by opaque,
+ * when this handler is timedout & needs to be deleted.
+ * It is the responsibility of the specific EAP-TYPE
+ * to avoid any memory leaks in opaque
+ * Hence this pointer should be provided by the EAP-Type
+ * if opaque is not NULL
+ * status = finished/onhold/..
+ */
+#define EAP_STATE_LEN (AUTH_VECTOR_LEN)
+typedef struct _eap_handler {
+ struct _eap_handler *prev, *next;
+ uint8_t state[EAP_STATE_LEN];
+ fr_ipaddr_t src_ipaddr;
+
+ uint8_t eap_id; //!< EAP Identifier used to match
+ //!< requests and responses.
+ eap_type_t type; //!< EAP type number.
+
+ time_t timestamp;
+
+ REQUEST *request;
+
+ char *identity; //!< User name from EAP-Identity
+
+ EAP_DS *prev_eapds;
+ EAP_DS *eap_ds;
+
+ void *opaque;
+ void (*free_opaque)(void *opaque);
+ void *inst_holder;
+
+ int status;
+
+ int stage;
+
+ int trips;
+
+ bool tls;
+ bool started;
+ bool finished;
+ VALUE_PAIR *certs;
+} eap_handler_t;
+
+/*
+ * Interface to call EAP sub mdoules
+ */
+typedef struct rlm_eap_module {
+ char const *name; //!< The name of the sub-module
+ //!< (without rlm_ prefix).
+ int (*instantiate)(CONF_SECTION *conf, void **instance); //!< Create a new submodule instance.
+ int (*session_init)(void *instance, eap_handler_t *handler); //!< Initialise a new EAP session.
+ int (*process)(void *instance, eap_handler_t *handler); //!< Continue an EAP session.
+ int (*detach)(void *instance); //!< Destroy a submodule instance.
+} rlm_eap_module_t;
+
+#define REQUEST_DATA_EAP_HANDLER (1)
+#define REQUEST_DATA_EAP_TUNNEL_CALLBACK PW_EAP_MESSAGE
+#define REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK ((PW_EAP_MESSAGE << 16) | PW_EAP_MSCHAPV2)
+#define RAD_REQUEST_OPTION_PROXY_EAP (1 << 16)
+
+/*
+ * This is for tunneled callbacks
+ */
+typedef int (*eap_tunnel_callback_t)(eap_handler_t *handler, void *tls_session);
+
+typedef struct eap_tunnel_data_t {
+ void *tls_session;
+ eap_tunnel_callback_t callback;
+} eap_tunnel_data_t;
+
+#endif /*_EAP_H*/
diff --git a/src/modules/rlm_eap/libeap/all.mk b/src/modules/rlm_eap/libeap/all.mk
new file mode 100644
index 0000000..6a32129
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/all.mk
@@ -0,0 +1,10 @@
+TARGET := libfreeradius-eap.a
+
+SOURCES := eapcommon.c eapcrypto.c eap_chbind.c eapsimlib.c fips186prf.c comp128.c
+ifneq (${OPENSSL_LIBS},)
+SOURCES += eap_tls.c mppe_keys.c
+endif
+
+SRC_CFLAGS := -DEAPLIB
+
+SRC_INCDIRS := . ..
diff --git a/src/modules/rlm_eap/libeap/comp128.c b/src/modules/rlm_eap/libeap/comp128.c
new file mode 100644
index 0000000..e624877
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/comp128.c
@@ -0,0 +1,460 @@
+/*
+ * This program is is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file comp128.c
+ * @brief Implementations of comp128v1, comp128v2, comp128v3 algorithms
+ *
+ * Comp128v1 was inspired by code from:
+ * Marc Briceno <marc@scard.org>, Ian Goldberg <iang@cs.berkeley.edu>,
+ * and David Wagner <daw@cs.berkeley.edu>
+ *
+ * But it has been fully rewritten (Sylvain Munaut <tnt@246tNt.com>) from various PDFs found online
+ * describing the algorithm because the licence of the code referenced above was unclear.
+ * A comment snippet from the original code is included below, it describes where the doc came
+ * from and how the algorithm was reverse engineered.
+ *
+ * Comp128v2 & v3 is a port of the python code from:
+ * http://www.hackingprojects.net/
+ * The author of the original code is Tamas Jos <tamas.jos@skelsec.com>
+ *
+ * @note The above GPL license only applies to comp128v1, the license for comp128v2 and comp128v3 is unknown.
+ *
+ * @copyright 2013 The FreeRADIUS server project
+ * @copyright 2013 Hacking projects [http://www.hackingprojects.net/]
+ * @copyright 2009 Sylvain Munaut <tnt@246tNt.com>
+ */
+
+#include "comp128.h"
+#include <stdio.h>
+/* 512 bytes */
+static uint8_t const comp128v1_t0[] = {
+ 102, 177, 186, 162, 2, 156, 112, 75, 55, 25, 8, 12, 251, 193, 246, 188,
+ 109, 213, 151, 53, 42, 79, 191, 115, 233, 242, 164, 223, 209, 148, 108, 161,
+ 252, 37, 244, 47, 64, 211, 6, 237, 185, 160, 139, 113, 76, 138, 59, 70,
+ 67, 26, 13, 157, 63, 179, 221, 30, 214, 36, 166, 69, 152, 124, 207, 116,
+ 247, 194, 41, 84, 71, 1, 49, 14, 95, 35, 169, 21, 96, 78, 215, 225,
+ 182, 243, 28, 92, 201, 118, 4, 74, 248, 128, 17, 11, 146, 132, 245, 48,
+ 149, 90, 120, 39, 87, 230, 106, 232, 175, 19, 126, 190, 202, 141, 137, 176,
+ 250, 27, 101, 40, 219, 227, 58, 20, 51, 178, 98, 216, 140, 22, 32, 121,
+ 61, 103, 203, 72, 29, 110, 85, 212, 180, 204, 150, 183, 15, 66, 172, 196,
+ 56, 197, 158, 0, 100, 45, 153, 7, 144, 222, 163, 167, 60, 135, 210, 231,
+ 174, 165, 38, 249, 224, 34, 220, 229, 217, 208, 241, 68, 206, 189, 125, 255,
+ 239, 54, 168, 89, 123, 122, 73, 145, 117, 234, 143, 99, 129, 200, 192, 82,
+ 104, 170, 136, 235, 93, 81, 205, 173, 236, 94, 105, 52, 46, 228, 198, 5,
+ 57, 254, 97, 155, 142, 133, 199, 171, 187, 50, 65, 181, 127, 107, 147, 226,
+ 184, 218, 131, 33, 77, 86, 31, 44, 88, 62, 238, 18, 24, 43, 154, 23,
+ 80, 159, 134, 111, 9, 114, 3, 91, 16, 130, 83, 10, 195, 240, 253, 119,
+ 177, 102, 162, 186, 156, 2, 75, 112, 25, 55, 12, 8, 193, 251, 188, 246,
+ 213, 109, 53, 151, 79, 42, 115, 191, 242, 233, 223, 164, 148, 209, 161, 108,
+ 37, 252, 47, 244, 211, 64, 237, 6, 160, 185, 113, 139, 138, 76, 70, 59,
+ 26, 67, 157, 13, 179, 63, 30, 221, 36, 214, 69, 166, 124, 152, 116, 207,
+ 194, 247, 84, 41, 1, 71, 14, 49, 35, 95, 21, 169, 78, 96, 225, 215,
+ 243, 182, 92, 28, 118, 201, 74, 4, 128, 248, 11, 17, 132, 146, 48, 245,
+ 90, 149, 39, 120, 230, 87, 232, 106, 19, 175, 190, 126, 141, 202, 176, 137,
+ 27, 250, 40, 101, 227, 219, 20, 58, 178, 51, 216, 98, 22, 140, 121, 32,
+ 103, 61, 72, 203, 110, 29, 212, 85, 204, 180, 183, 150, 66, 15, 196, 172,
+ 197, 56, 0, 158, 45, 100, 7, 153, 222, 144, 167, 163, 135, 60, 231, 210,
+ 165, 174, 249, 38, 34, 224, 229, 220, 208, 217, 68, 241, 189, 206, 255, 125,
+ 54, 239, 89, 168, 122, 123, 145, 73, 234, 117, 99, 143, 200, 129, 82, 192,
+ 170, 104, 235, 136, 81, 93, 173, 205, 94, 236, 52, 105, 228, 46, 5, 198,
+ 254, 57, 155, 97, 133, 142, 171, 199, 50, 187, 181, 65, 107, 127, 226, 147,
+ 218, 184, 33, 131, 86, 77, 44, 31, 62, 88, 18, 238, 43, 24, 23, 154,
+ 159, 80, 111, 134, 114, 9, 91, 3, 130, 16, 10, 83, 240, 195, 119, 253};
+
+/* 256 bytes */
+static uint8_t const comp128v1_t1[] = {
+ 19, 11, 80, 114, 43, 1, 69, 94, 39, 18, 127, 117, 97, 3, 85, 43,
+ 27, 124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5,
+ 35, 107, 103, 68, 21, 86, 36, 91, 85, 126, 32, 50, 109, 94, 120, 6,
+ 53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55, 110, 125, 105, 20,
+ 90, 80, 76, 96, 23, 60, 89, 64, 121, 56, 14, 74, 101, 8, 19, 78,
+ 76, 66, 104, 46, 111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51,
+ 57, 65, 119, 116, 22, 109, 7, 86, 59, 93, 62, 110, 78, 99, 77, 67,
+ 12, 113, 87, 98, 102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75,
+ 95, 63, 28, 49, 123, 120, 20, 112, 44, 30, 15, 98, 106, 2, 103, 29,
+ 82, 107, 42, 124, 24, 30, 41, 16, 108, 100, 117, 40, 73, 40, 7, 114,
+ 82, 115, 36, 112, 12, 102, 100, 84, 92, 48, 72, 97, 9, 54, 55, 74,
+ 113, 123, 17, 26, 53, 58, 4, 9, 69, 122, 21, 118, 42, 60, 27, 73,
+ 118, 125, 34, 15, 65, 115, 84, 64, 62, 81, 70, 1, 24, 111, 121, 83,
+ 104, 81, 49, 127, 48, 105, 31, 10, 6, 91, 87, 37, 16, 54, 116, 126,
+ 31, 38, 13, 0, 72, 106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52,
+ 101, 17, 44, 108, 71, 52, 66, 57, 33, 51, 25, 90, 2, 119, 122, 35};
+
+/* 128 bytes */
+static uint8_t const comp128v1_t2[] = {
+ 52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43,
+ 37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18,
+ 55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59,
+ 62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56,
+ 48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61,
+ 29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0,
+ 20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27,
+ 31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7};
+
+/* 64 bytes */
+static uint8_t const comp128v1_t3[] = {
+ 1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31,
+ 28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9,
+ 20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10,
+ 17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19};
+
+/* 32 bytes */
+static uint8_t const comp128v1_t4[] = {
+ 15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8,
+ 10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12};
+
+static uint8_t const *_comp128_table[] = { comp128v1_t0, comp128v1_t1, comp128v1_t2, comp128v1_t3, comp128v1_t4 };
+
+/* 256 bytes */
+static uint8_t const comp128v23_t0[] = {
+ 197, 235, 60, 151, 98, 96, 3, 100, 248, 118, 42, 117, 172, 211, 181, 203,
+ 61, 126, 156, 87, 149, 224, 55, 132, 186, 63, 238, 255, 85, 83, 152, 33,
+ 160, 184, 210, 219, 159, 11, 180, 194, 130, 212, 147, 5, 215, 92, 27, 46,
+ 113, 187, 52, 25, 185, 79, 221, 48, 70, 31, 101, 15, 195, 201, 50, 222,
+ 137, 233, 229, 106, 122, 183, 178, 177, 144, 207, 234, 182, 37, 254, 227, 231,
+ 54, 209, 133, 65, 202, 69, 237, 220, 189, 146, 120, 68, 21, 125, 38, 30,
+ 2, 155, 53, 196, 174, 176, 51, 246, 167, 76, 110, 20, 82, 121, 103, 112,
+ 56, 173, 49, 217, 252, 0, 114, 228, 123, 12, 93, 161, 253, 232, 240, 175,
+ 67, 128, 22, 158, 89, 18, 77, 109, 190, 17, 62, 4, 153, 163, 59, 145,
+ 138, 7, 74, 205, 10, 162, 80, 45, 104, 111, 150, 214, 154, 28, 191, 169,
+ 213, 88, 193, 198, 200, 245, 39, 164, 124, 84, 78, 1, 188, 170, 23, 86,
+ 226, 141, 32, 6, 131, 127, 199, 40, 135, 16, 57, 71, 91, 225, 168, 242,
+ 206, 97, 166, 44, 14, 90, 236, 239, 230, 244, 223, 108, 102, 119, 148, 251,
+ 29, 216, 8, 9, 249, 208, 24, 105, 94, 34, 64, 95, 115, 72, 134, 204,
+ 43, 247, 243, 218, 47, 58, 73, 107, 241, 179, 116, 66, 36, 143, 81, 250,
+ 139, 19, 13, 142, 140, 129, 192, 99, 171, 157, 136, 41, 75, 35, 165, 26};
+
+/* 256 bytes */
+static uint8_t const comp128v23_t1[] = {
+ 170, 42, 95, 141, 109, 30, 71, 89, 26, 147, 231, 205, 239, 212, 124, 129,
+ 216, 79, 15, 185, 153, 14, 251, 162, 0, 241, 172, 197, 43, 10, 194, 235,
+ 6, 20, 72, 45, 143, 104, 161, 119, 41, 136, 38, 189, 135, 25, 93, 18,
+ 224, 171, 252, 195, 63, 19, 58, 165, 23, 55, 133, 254, 214, 144, 220, 178,
+ 156, 52, 110, 225, 97, 183, 140, 39, 53, 88, 219, 167, 16, 198, 62, 222,
+ 76, 139, 175, 94, 51, 134, 115, 22, 67, 1, 249, 217, 3, 5, 232, 138,
+ 31, 56, 116, 163, 70, 128, 234, 132, 229, 184, 244, 13, 34, 73, 233, 154,
+ 179, 131, 215, 236, 142, 223, 27, 57, 246, 108, 211, 8, 253, 85, 66, 245,
+ 193, 78, 190, 4, 17, 7, 150, 127, 152, 213, 37, 186, 2, 243, 46, 169,
+ 68, 101, 60, 174, 208, 158, 176, 69, 238, 191, 90, 83, 166, 125, 77, 59,
+ 21, 92, 49, 151, 168, 99, 9, 50, 146, 113, 117, 228, 65, 230, 40, 82,
+ 54, 237, 227, 102, 28, 36, 107, 24, 44, 126, 206, 201, 61, 114, 164, 207,
+ 181, 29, 91, 64, 221, 255, 48, 155, 192, 111, 180, 210, 182, 247, 203, 148,
+ 209, 98, 173, 11, 75, 123, 250, 118, 32, 47, 240, 202, 74, 177, 100, 80,
+ 196, 33, 248, 86, 157, 137, 120, 130, 84, 204, 122, 81, 242, 188, 200, 149,
+ 226, 218, 160, 187, 106, 35, 87, 105, 96, 145, 199, 159, 12, 121, 103, 112};
+
+static inline void _comp128_compression_round(uint8_t *x, int n, const uint8_t *tbl)
+{
+ int i, j, m, a, b, y, z;
+ m = 4 - n;
+ for (i = 0; i < (1 << n); i++) {
+ for (j = 0; j < (1 << m); j++) {
+ a = j + i * (2 << m);
+ b = a + (1 << m);
+ y = (x[a] + (x[b] << 1)) & ((32 << m) - 1);
+ z = ((x[a] << 1) + x[b]) & ((32 << m) - 1);
+ x[a] = tbl[y];
+ x[b] = tbl[z];
+ }
+ }
+}
+
+static inline void _comp128_compression(uint8_t *x)
+{
+ int n;
+ for (n = 0; n < 5; n++) {
+ _comp128_compression_round(x, n, _comp128_table[n]);
+ }
+}
+
+static inline void _comp128_bitsfrombytes(uint8_t *x, uint8_t *bits)
+{
+ int i;
+
+ memset(bits, 0x00, 128);
+ for (i = 0; i < 128; i++) {
+ if (x[i >> 2] & (1 << (3 - (i & 3)))) {
+ bits[i] = 1;
+ }
+ }
+}
+
+static inline void _comp128_permutation(uint8_t *x, uint8_t *bits)
+{
+ int i;
+ memset(&x[16], 0x00, 16);
+ for (i = 0; i < 128; i++) {
+ x[(i >> 3) + 16] |= bits[(i * 17) & 127] << (7 - (i & 7));
+ }
+}
+
+/** Calculate comp128v1 sres and kc from ki and rand
+ *
+ * This code derived from a leaked document from the GSM standards.
+ * Some missing pieces were filled in by reverse-engineering a working SIM.
+ * We have verified that this is the correct COMP128 algorithm.
+ *
+ * The first page of the document identifies it as
+ * _Technical Information: GSM System Security Study_.
+ * 10-1617-01, 10th June 1988.
+ * The bottom of the title page is marked
+ * Racal Research Ltd.
+ * Worton Drive, Worton Grange Industrial Estate,
+ * Reading, Berks. RG2 0SB, England.
+ * Telephone: Reading (0734) 868601 Telex: 847152
+ * The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy!
+ *
+ * Note: There are three typos in the spec (discovered by reverse-engineering).
+ * First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read
+ * "z = (2 * x[m] + x[n]) mod 2^(9-j)".
+ * Second, the "k" loop in the "Form bits from bytes" section is severely
+ * botched: the k index should run only from 0 to 3, and clearly the range
+ * on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8,
+ * to be consistent with the subsequent section).
+ * Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as
+ * claimed in the document. (And the document doesn't specify how Kc is
+ * derived, but that was also easily discovered with reverse engineering.)
+ * All of these typos have been corrected in the following code.
+ *
+ * @param[out] sres 4 byte value derived from ki and rand.
+ * @param[out] kc 12 byte value derived from ki and rand.
+ * @param[in] ki known only by the SIM and AuC (us in this case).
+ * @param[in] rand 16 bytes of randomness.
+ */
+void comp128v1(uint8_t *sres, uint8_t *kc, uint8_t const *ki, uint8_t const *rand)
+{
+ int i;
+ uint8_t x[32], bits[128];
+
+ /* x[16-31] = RAND */
+ memcpy(&x[16], rand, 16);
+
+ /*
+ * Round 1-7
+ */
+ for (i=0; i < 7; i++) {
+ /* x[0-15] = Ki */
+ memcpy(x, ki, 16);
+
+ /* Compression */
+ _comp128_compression(x);
+
+ /* FormBitFromBytes */
+ _comp128_bitsfrombytes(x, bits);
+
+ /* Permutation */
+ _comp128_permutation(x, bits);
+ }
+
+ /*
+ * Round 8 (final)
+ * x[0-15] = Ki
+ */
+ memcpy(x, ki, 16);
+
+ /* Compression */
+ _comp128_compression(x);
+
+ /* Output stage */
+ for (i = 0; i < 8; i += 2) {
+ sres[i >> 1] = x[i] << 4 | x[i + 1];
+ }
+
+ for (i = 0; i < 12; i += 2) {
+ kc[i>>1] = (x[i + 18] << 6) |
+ (x[i + 19] << 2) |
+ (x[i + 20] >> 2);
+ }
+
+ kc[6] = (x[30] << 6) | (x[31] << 2);
+ kc[7] = 0;
+}
+
+static void _comp128v23(uint8_t *rand, uint8_t const *kxor)
+{
+ uint8_t temp[16];
+ uint8_t km_rm[32];
+
+ int j, i, k, z;
+
+ memset(&temp, 0, sizeof(temp));
+ memcpy(km_rm, rand, 16);
+ memcpy(km_rm + 16, kxor, 16);
+ memset(rand, 0, 16);
+
+ for (i = 0; i < 5; i++) {
+ j = 0;
+
+ for (z = 0; z < 16; z++) {
+ temp[z] = comp128v23_t0[comp128v23_t1[km_rm[16 + z]] ^ km_rm[z]];
+ }
+
+ while ((1 << i) > j) {
+ k = 0;
+
+ while ((1 << (4 - i)) > k) {
+ km_rm[(((2 * k) + 1) << i) + j] =
+ comp128v23_t0[comp128v23_t1[temp[(k << i) + j]] ^ (km_rm[(k << i) + 16 + j])];
+ km_rm[(k << (i + 1)) + j] = temp[(k << i) + j];
+ k++;
+ }
+ j++;
+ }
+ }
+
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 8; j++) {
+ rand[i] = rand[i] ^ (((km_rm[(19 * (j + 8 * i) + 19) % 256 / 8] >> (3 * j + 3) % 8) & 1) << j);
+ }
+ }
+}
+
+/** Calculate comp128v2 or comp128v3 sres and kc from ki and rand
+ *
+ * @param[out] sres 4 byte value derived from ki and rand.
+ * @param[out] kc 8 byte value derived from ki and rand.
+ * @param[in] ki known only by the SIM and AuC (us in this case).
+ * @param[in] rand 16 bytes of randomness.
+ * @param[in] v2 if true we use version comp128-2 else we use comp128-3.
+
+ */
+void comp128v23(uint8_t *sres, uint8_t *kc, uint8_t const *ki, uint8_t const *rand, bool v2)
+{
+ uint8_t k_mix[16];
+ uint8_t rand_mix[16];
+ uint8_t katyvasz[16];
+ uint8_t buffer[16];
+
+ /* Every day IM suffling... */
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ k_mix[i] = ki[15 - i];
+ k_mix[15 - i] = ki[i];
+ }
+
+ for (i = 0; i < 8; i++) {
+ rand_mix[i] = rand[15 - i];
+ rand_mix[15 - i] = rand[i];
+ }
+
+ for (i = 0; i < 16; i++) {
+ katyvasz[i] = k_mix[i] ^ rand_mix[i];
+ }
+
+ for (i = 0; i < 8; i++) {
+ _comp128v23(rand_mix, katyvasz);
+ }
+
+ for (i = 0; i < 16; i++) {
+ buffer[i] = rand_mix[15 - i];
+ }
+
+ if (v2) {
+ buffer[15] = 0x00;
+ buffer[14] = 4 * (buffer[14] >> 2);
+ }
+
+ for (i = 0; i < 4; i++) {
+ buffer[8 + i - 4] = buffer[8 + i];
+ buffer[8 + i] = buffer[8 + i + 4];
+ }
+
+ /*
+ * The algorithm uses 16 bytes until this point, but only 12 bytes are effective
+ * also 12 bytes coming out from the SIM card.
+ */
+ memcpy(sres, buffer, 4);
+ memcpy(kc, buffer + 4, 8);
+}
+
+#if 0
+#include <stdlib.h>
+#include <ctype.h>
+static int hextoint(char x)
+{
+ x = toupper(x);
+ if (x >= 'A' && x <= 'F') {
+ return x-'A' + 10;
+ } else if (x >= '0' && x <= '9') {
+ return x-'0';
+ }
+
+ fprintf(stderr, "Bad input.\n");
+
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ uint8_t rand[16], key[16], sres[4], kc[8];
+ int version;
+ int i;
+
+ if ((argc != 4) ||
+ (strlen(argv[1]) != 34) || (strlen(argv[2]) != 34) ||
+ (strncmp(argv[1], "0x", 2) != 0) || (strncmp(argv[2], "0x", 2) != 0) ||
+ !(version = atoi(argv[3]))) {
+ error:
+ fprintf(stderr, "Usage: %s 0x<key> 0x<rand> [1|2|3]\n", argv[0]);
+ exit(1);
+ }
+
+ for (i = 0; i < 16; i++) {
+ key[i] = (hextoint(argv[1][(2 * i) + 2]) << 4) | hextoint(argv[1][(2 * i) + 3]);
+ }
+
+ for (i = 0; i < 16; i++) {
+ rand[i] = (hextoint(argv[2][(2 * i) + 2]) << 4) | hextoint(argv[2][(2 * i) + 3]);
+ }
+
+ switch (version) {
+ case 3:
+ comp128v23(sres, kc, key, rand, false);
+ break;
+ case 2:
+ comp128v23(sres, kc, key, rand, true);
+ break;
+ case 1:
+ comp128v1(sres, kc, key, rand);
+ break;
+ default:
+ fprintf(stderr, "Invalid version, must be 1,2 or 3");
+ goto error;
+ }
+
+ /* Output in vector format <Ki>,<rand>,<sres><Kc> */
+ for (i = 0; i < 16; i++) {
+ printf("%02X", key[i]);
+ }
+ printf(",");
+ for (i = 0; i < 16; i++) {
+ printf("%02X", rand[i]);
+ }
+ printf(",");
+ for (i = 0; i < 4; i++) {
+ printf("%02X", sres[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ printf("%02X", kc[i]);
+ }
+ printf("\n");
+
+ return 0;
+}
+#endif
diff --git a/src/modules/rlm_eap/libeap/comp128.h b/src/modules/rlm_eap/libeap/comp128.h
new file mode 100644
index 0000000..4cd2199
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/comp128.h
@@ -0,0 +1,11 @@
+#ifndef _COMP128_H
+#define _COMP128_H
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+void comp128v1(uint8_t *sres, uint8_t *kc, const uint8_t *ki, const uint8_t *rand);
+void comp128v23(uint8_t *sres, uint8_t *kc, uint8_t const *ki, uint8_t const *rand, bool v2);
+
+#endif
diff --git a/src/modules/rlm_eap/libeap/eap_chbind.c b/src/modules/rlm_eap/libeap/eap_chbind.c
new file mode 100644
index 0000000..21b2584
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eap_chbind.c
@@ -0,0 +1,290 @@
+/*
+ * eap_chbind.c
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2014 Network RADIUS SARL
+ * Copyright 2014 The FreeRADIUS server project
+ */
+
+
+RCSID("$Id$")
+
+#include "eap_chbind.h"
+
+static bool chbind_build_response(REQUEST *request, CHBIND_REQ *chbind)
+{
+ int length;
+ size_t total;
+ uint8_t *ptr, *end;
+ VALUE_PAIR const *vp;
+ vp_cursor_t cursor;
+
+ total = 0;
+ for (vp = fr_cursor_init(&cursor, &request->reply->vps);
+ vp != NULL;
+ vp = fr_cursor_next(&cursor)) {
+ /*
+ * Skip things which shouldn't be in channel bindings.
+ */
+ if (vp->da->flags.encrypt != FLAG_ENCRYPT_NONE) continue;
+ if (!vp->da->vendor && (vp->da->attr == PW_MESSAGE_AUTHENTICATOR)) continue;
+
+ total += 2 + vp->vp_length;
+ }
+
+ /*
+ * No attributes: just send a 1-byte response code.
+ */
+ if (!total) {
+ ptr = talloc_zero_array(chbind, uint8_t, 1);
+ } else {
+ ptr = talloc_zero_array(chbind, uint8_t, total + 4);
+ }
+ if (!ptr) return false;
+ chbind->response = (chbind_packet_t *) ptr;
+
+ /*
+ * Set the response code. Default to "fail" if none was
+ * specified.
+ */
+ vp = fr_pair_find_by_num(request->config, PW_CHBIND_RESPONSE_CODE, 0, TAG_ANY);
+ if (vp) {
+ ptr[0] = vp->vp_integer;
+ } else {
+ ptr[0] = CHBIND_CODE_FAILURE;
+ }
+
+ if (!total) return true; /* nothing to encode */
+
+ /* Write the length field into the header */
+ ptr[1] = (total >> 8) & 0xff;
+ ptr[2] = total & 0xff;
+ ptr[3] = CHBIND_NSID_RADIUS;
+
+ RDEBUG("Sending chbind response: code %i", (int )(ptr[0]));
+ rdebug_pair_list(L_DBG_LVL_1, request, request->reply->vps, NULL);
+
+ /* Encode the chbind attributes into the response */
+ ptr += 4;
+ end = ptr + total;
+ for (vp = fr_cursor_init(&cursor, &request->reply->vps);
+ vp != NULL;
+ vp = fr_cursor_next(&cursor)) {
+ /*
+ * Skip things which shouldn't be in channel bindings.
+ */
+ if (vp->da->flags.encrypt != FLAG_ENCRYPT_NONE) continue;
+ if (!vp->da->vendor && (vp->da->attr == PW_MESSAGE_AUTHENTICATOR)) continue;
+
+ length = rad_vp2attr(NULL, NULL, NULL, &vp, ptr, end - ptr);
+ if (length < 0) continue;
+ ptr += length;
+ }
+
+ return true;
+}
+
+
+/*
+ * Parse channel binding packet to obtain data for a specific
+ * NSID.
+ *
+ * See:
+ * http://tools.ietf.org/html/draft-ietf-emu-chbind-13#section-5.3.2
+ */
+static size_t chbind_get_data(chbind_packet_t const *packet,
+ int desired_nsid,
+ uint8_t const **data)
+{
+ uint8_t const *ptr;
+ uint8_t const *end;
+
+ if (packet->code != CHBIND_CODE_REQUEST) {
+ return 0;
+ }
+
+ ptr = (uint8_t const *) packet;
+ end = ptr + talloc_array_length((uint8_t const *) packet);
+
+ ptr++; /* skip the code at the start of the packet */
+ while (ptr < end) {
+ uint8_t nsid;
+ size_t length;
+
+ /*
+ * Need room for length(2) + NSID + data.
+ */
+ if ((end - ptr) < 4) return 0;
+
+ length = (ptr[0] << 8) | ptr[1];
+ if (length == 0) return 0;
+
+ if ((ptr + length + 3) > end) return 0;
+
+ nsid = ptr[2];
+ if (nsid == desired_nsid) {
+ ptr += 3;
+ *data = ptr;
+ return length;
+ }
+
+ ptr += 3 + length;
+ }
+
+ return 0;
+}
+
+
+PW_CODE chbind_process(REQUEST *request, CHBIND_REQ *chbind)
+{
+ PW_CODE rcode;
+ REQUEST *fake = NULL;
+ VALUE_PAIR *vp = NULL;
+ uint8_t const *attr_data;
+ size_t data_len = 0;
+
+ /* check input parameters */
+ rad_assert((request != NULL) &&
+ (chbind != NULL) &&
+ (chbind->request != NULL) &&
+ (chbind->response == NULL));
+
+ /* Set-up the fake request */
+ fake = request_alloc_fake(request);
+ fr_pair_make(fake->packet, &fake->packet->vps, "Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
+
+ /* Add the username to the fake request */
+ if (chbind->username) {
+ vp = fr_pair_copy(fake->packet, chbind->username);
+ fr_pair_add(&fake->packet->vps, vp);
+ fake->username = vp;
+ }
+
+ /*
+ * Maybe copy the State over, too?
+ */
+
+ /* Add the channel binding attributes to the fake packet */
+ data_len = chbind_get_data(chbind->request, CHBIND_NSID_RADIUS, &attr_data);
+ if (data_len) {
+ rad_assert(data_len <= talloc_array_length((uint8_t const *) chbind->request));
+
+ while (data_len > 0) {
+ int attr_len = rad_attr2vp(fake->packet, NULL, NULL, NULL, attr_data, data_len, &vp);
+ if (attr_len <= 0) {
+ /* If radaddr2vp fails, return NULL string for
+ channel binding response */
+ talloc_free(fake);
+ return PW_CODE_ACCESS_ACCEPT;
+ }
+ if (vp) {
+ fr_pair_add(&fake->packet->vps, vp);
+ }
+ attr_data += attr_len;
+ data_len -= attr_len;
+ }
+ }
+
+ /*
+ * Set virtual server based on configuration for channel
+ * bindings, this is hard-coded for now.
+ */
+ fake->server = "channel_bindings";
+ fake->packet->code = PW_CODE_ACCESS_REQUEST;
+
+ switch (rad_virtual_server(fake)) {
+ /* If rad_authenticate succeeded, build a reply */
+ case RLM_MODULE_OK:
+ case RLM_MODULE_HANDLED:
+ if (chbind_build_response(fake, chbind)) {
+ rcode = PW_CODE_ACCESS_ACCEPT;
+ break;
+ }
+ /* FALL-THROUGH */
+
+ /* If we got any other response from rad_authenticate, it maps to a reject */
+ default:
+ rcode = PW_CODE_ACCESS_REJECT;
+ break;
+ }
+
+ talloc_free(fake);
+
+ return rcode;
+}
+
+/*
+ * Handles multiple EAP-channel-binding Message attrs
+ * ie concatenates all to get the complete EAP-channel-binding packet.
+ */
+chbind_packet_t *eap_chbind_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps)
+{
+ size_t length;
+ uint8_t *ptr;
+ VALUE_PAIR *first, *vp;
+ chbind_packet_t *packet;
+ vp_cursor_t cursor;
+
+ first = fr_pair_find_by_num(vps, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY);
+ if (!first) return NULL;
+
+ /*
+ * Compute the total length of the channel binding data.
+ */
+ length = 0;
+ fr_cursor_init(&cursor, &first);
+ while ((vp = fr_cursor_next_by_num(&cursor, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY))) {
+ length += vp->vp_length;
+ }
+
+ if (length < 4) {
+ DEBUG("Invalid length %u for channel binding data", (unsigned int) length);
+ return NULL;
+ }
+
+ /*
+ * Now that we know the length, allocate memory for the packet.
+ */
+ ptr = talloc_zero_array(ctx, uint8_t, length);
+ if (!ptr) return NULL;
+
+ /*
+ * Copy the data over to our packet.
+ */
+ packet = (chbind_packet_t *) ptr;
+ fr_cursor_init(&cursor, &first);
+ while ((vp = fr_cursor_next_by_num(&cursor, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY))) {
+ memcpy(ptr, vp->vp_octets, vp->vp_length);
+ ptr += vp->vp_length;
+ }
+
+ return packet;
+}
+
+VALUE_PAIR *eap_chbind_packet2vp(RADIUS_PACKET *packet, chbind_packet_t *chbind)
+{
+ VALUE_PAIR *vp;
+
+ if (!chbind) return NULL; /* don't produce garbage */
+
+ vp = fr_pair_afrom_num(packet, PW_UKERNA_CHBIND, VENDORPEC_UKERNA);
+ if (!vp) return NULL;
+ fr_pair_value_memcpy(vp, (uint8_t *) chbind, talloc_array_length((uint8_t *)chbind));
+
+ return vp;
+}
diff --git a/src/modules/rlm_eap/libeap/eap_chbind.h b/src/modules/rlm_eap/libeap/eap_chbind.h
new file mode 100644
index 0000000..346b712
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eap_chbind.h
@@ -0,0 +1,64 @@
+/*
+ * eap_chbind.c
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2014 Network RADIUS SARL
+ * Copyright 2014 The FreeRADIUS server project
+ */
+
+#ifndef _EAP_CHBIND_H
+#define _EAP_CHBIND_H
+
+RCSIDH(eap_chbind_h, "$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ctype.h>
+
+#include <freeradius-devel/radiusd.h>
+
+#include "eap.h"
+
+/* Structure to represent eap channel binding packet format */
+typedef struct chbind_packet_t {
+ uint8_t code;
+ uint8_t data[1];
+} chbind_packet_t;
+
+/* Structure to hold channel bindings req/resp information */
+typedef struct CHBIND_REQ {
+ VALUE_PAIR *username; /* the username */
+ chbind_packet_t *request; /* channel binding request buffer */
+ chbind_packet_t *response; /* channel binding response buffer */
+} CHBIND_REQ;
+
+/* Protocol constants */
+#define CHBIND_NSID_RADIUS 1
+
+#define CHBIND_CODE_REQUEST 1
+#define CHBIND_CODE_SUCCESS 2
+#define CHBIND_CODE_FAILURE 3
+
+/* Channel binding function prototypes */
+PW_CODE chbind_process(REQUEST *request, CHBIND_REQ *chbind_req);
+
+VALUE_PAIR *eap_chbind_packet2vp(RADIUS_PACKET *packet, chbind_packet_t *chbind);
+chbind_packet_t *eap_chbind_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps);
+
+#endif /*_EAP_CHBIND_H*/
diff --git a/src/modules/rlm_eap/libeap/eap_sim.h b/src/modules/rlm_eap/libeap/eap_sim.h
new file mode 100644
index 0000000..0d92f67
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eap_sim.h
@@ -0,0 +1,122 @@
+/*
+ * eap_sim.h Header file containing the EAP-SIM types
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ * Copyright 2006 The FreeRADIUS server project
+ *
+ */
+#ifndef _EAP_SIM_H
+#define _EAP_SIM_H
+
+RCSIDH(eap_sim_h, "$Id$")
+
+#include "eap_types.h"
+
+#define EAP_SIM_VERSION 0x0001
+
+enum eapsim_subtype {
+ EAPSIM_START = 10,
+ EAPSIM_CHALLENGE = 11,
+ EAPSIM_NOTIFICATION = 12,
+ EAPSIM_REAUTH = 13,
+ EAPSIM_CLIENT_ERROR = 14,
+ EAPSIM_MAX_SUBTYPE = 15
+};
+
+enum eapsim_clientstates {
+ EAPSIM_CLIENT_INIT = 0,
+ EAPSIM_CLIENT_START = 1,
+ EAPSIM_CLIENT_MAXSTATES
+};
+
+/* server states
+ *
+ * in server_start, we send a EAP-SIM Start message.
+ *
+ */
+enum eapsim_serverstates {
+ EAPSIM_SERVER_START = 0,
+ EAPSIM_SERVER_CHALLENGE = 1,
+ EAPSIM_SERVER_SUCCESS = 10,
+ EAPSIM_SERVER_MAXSTATES
+};
+
+
+/*
+ * interfaces in eapsimlib.c
+ */
+int map_eapsim_basictypes(RADIUS_PACKET *r, eap_packet_t *ep);
+char const *sim_state2name(enum eapsim_clientstates state, char *buf, int buflen);
+char const *sim_subtype2name(enum eapsim_subtype subtype, char *buf, int buflen);
+int unmap_eapsim_basictypes(RADIUS_PACKET *r, uint8_t *attr, unsigned int attrlen);
+
+
+/************************/
+/* CRYPTO FUNCTIONS */
+/************************/
+
+/*
+ * key derivation functions/structures
+ *
+ */
+
+#define EAPSIM_SRES_SIZE 4
+#define EAPSIM_RAND_SIZE 16
+#define EAPSIM_KC_SIZE 8
+#define EAPSIM_CALCMAC_SIZE 20
+#define EAPSIM_NONCEMT_SIZE 16
+#define EAPSIM_AUTH_SIZE 16
+
+struct eapsim_keys {
+ /* inputs */
+ uint8_t identity[MAX_STRING_LEN];
+ unsigned int identitylen;
+ uint8_t nonce_mt[EAPSIM_NONCEMT_SIZE];
+ uint8_t rand[3][EAPSIM_RAND_SIZE];
+ uint8_t sres[3][EAPSIM_SRES_SIZE];
+ uint8_t Kc[3][EAPSIM_KC_SIZE];
+ uint8_t versionlist[MAX_STRING_LEN];
+ uint8_t versionlistlen;
+ uint8_t versionselect[2];
+
+ /* outputs */
+ uint8_t master_key[20];
+ uint8_t K_aut[EAPSIM_AUTH_SIZE];
+ uint8_t K_encr[16];
+ uint8_t msk[64];
+ uint8_t emsk[64];
+};
+
+
+/*
+ * interfaces in eapsimlib.c
+ */
+int eapsim_checkmac(TALLOC_CTX *ctx, VALUE_PAIR *rvps,
+ uint8_t key[EAPSIM_AUTH_SIZE],
+ uint8_t *extra, int extralen,
+ uint8_t calcmac[20]);
+
+/*
+ * in eapcrypto.c
+ */
+void eapsim_calculate_keys(struct eapsim_keys *ek);
+void eapsim_dump_mk(struct eapsim_keys *ek);
+
+
+#endif /* _EAP_SIM_H */
diff --git a/src/modules/rlm_eap/libeap/eap_tls.c b/src/modules/rlm_eap/libeap/eap_tls.c
new file mode 100644
index 0000000..2f37663
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eap_tls.c
@@ -0,0 +1,1206 @@
+
+/*
+ * eap_tls.c
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+/*
+ *
+ * TLS Packet Format in EAP
+ * --- ------ ------ -- ---
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Flags | TLS Message Length
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | TLS Message Length | TLS Data...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include <assert.h>
+
+#include "eap_tls.h"
+/*
+ * Send an initial eap-tls request to the peer.
+ *
+ * Frame eap reply packet.
+ * len = header + type + tls_typedata
+ * tls_typedata = flags(Start (S) bit set, and no data)
+ *
+ * Once having received the peer's Identity, the EAP server MUST
+ * respond with an EAP-TLS/Start packet, which is an
+ * EAP-Request packet with EAP-Type=EAP-TLS, the Start (S) bit
+ * set, and no data. The EAP-TLS conversation will then begin,
+ * with the peer sending an EAP-Response packet with
+ * EAP-Type = EAP-TLS. The data field of that packet will
+ * be the TLS data.
+ *
+ * Fragment length is Framed-MTU - 4.
+ */
+tls_session_t *eaptls_session(eap_handler_t *handler, fr_tls_server_conf_t *tls_conf, bool client_cert, bool allow_tls13)
+{
+ tls_session_t *ssn;
+ REQUEST *request = handler->request;
+
+ handler->tls = true;
+
+ /*
+ * Every new session is started only from EAP-TLS-START.
+ * Before Sending EAP-TLS-START, open a new SSL session.
+ * Create all the required data structures & store them
+ * in Opaque. So that we can use these data structures
+ * when we get the response
+ */
+ ssn = tls_new_session(handler, tls_conf, request, client_cert, allow_tls13);
+ if (!ssn) {
+ return NULL;
+ }
+
+ /*
+ * Create a structure for all the items required to be
+ * verified for each client and set that as opaque data
+ * structure.
+ *
+ * NOTE: If we want to set each item sepearately then
+ * this index should be global.
+ */
+ SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_HANDLER, (void *)handler);
+ SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_CONF, (void *)tls_conf);
+ SSL_set_ex_data(ssn->ssl, fr_tls_ex_index_certs, (void *)&(handler->certs));
+ SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(handler->identity));
+#ifdef HAVE_OPENSSL_OCSP_H
+ SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_STORE, (void *)tls_conf->ocsp_store);
+#endif
+ SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_SSN, (void *)ssn);
+ SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_TALLOC, handler);
+
+ return talloc_steal(handler, ssn); /* ssn */
+}
+
+/*
+ The S flag is set only within the EAP-TLS start message
+ sent from the EAP server to the peer.
+*/
+int eaptls_start(EAP_DS *eap_ds, int peap_flag)
+{
+ EAPTLS_PACKET reply;
+
+ reply.code = FR_TLS_START;
+ reply.length = TLS_HEADER_LEN + 1/*flags*/;
+
+ reply.flags = peap_flag;
+ reply.flags = SET_START(reply.flags);
+
+ reply.data = NULL;
+ reply.dlen = 0;
+
+ eaptls_compose(eap_ds, &reply);
+
+ return 1;
+}
+
+
+/** Send an EAP-TLS success
+ *
+ * Composes an EAP-TLS-Success. This is a message with code EAP_TLS_ESTABLISHED.
+ * It contains no cryptographic material, and is not protected.
+ *
+ * We add the MPPE keys here. These are used by the NAS. The supplicant
+ * will derive the same keys separately.
+ *
+ * @param handler handler of eap session that completed successfully.
+ * @param peap_flag to indicate PEAP version
+ * @return
+ * - 1 on success.
+ */
+int eaptls_success(eap_handler_t *handler, int peap_flag)
+{
+ EAPTLS_PACKET reply;
+ REQUEST *request = handler->request;
+ tls_session_t *tls_session = handler->opaque;
+
+ handler->finished = true;
+ reply.code = FR_TLS_SUCCESS;
+ reply.length = TLS_HEADER_LEN;
+ reply.flags = peap_flag;
+ reply.data = NULL;
+ reply.dlen = 0;
+
+ tls_success(tls_session, request);
+
+ /*
+ * Call compose AFTER checking for cached data.
+ */
+ eaptls_compose(handler->eap_ds, &reply);
+
+ /*
+ * Automatically generate MPPE keying material.
+ */
+ if (tls_session->label) {
+ uint8_t const *context = NULL;
+ size_t context_size = 0;
+#ifdef TLS1_3_VERSION
+ uint8_t const context_tls13[] = { handler->type };
+#endif
+
+ switch (SSL_version(tls_session->ssl)) {
+#ifdef TLS1_3_VERSION
+ case TLS1_3_VERSION:
+ context = context_tls13;
+ context_size = sizeof(context_tls13);
+ tls_session->label = "EXPORTER_EAP_TLS_Key_Material";
+ break;
+#endif
+ case TLS1_2_VERSION:
+ case TLS1_1_VERSION:
+ case TLS1_VERSION:
+ break;
+ case SSL2_VERSION:
+ case SSL3_VERSION:
+ default:
+ /* Should never happen */
+ rad_assert(0);
+ return 0;
+ break;
+ }
+ eaptls_gen_mppe_keys(request,
+ tls_session->ssl, tls_session->label,
+ context, context_size);
+ } else if (handler->type != PW_EAP_FAST) {
+ RWDEBUG("(TLS) EAP Not adding MPPE keys because there is no PRF label");
+ }
+
+ eaptls_gen_eap_key(handler);
+
+ return 1;
+}
+
+int eaptls_fail(eap_handler_t *handler, int peap_flag)
+{
+ EAPTLS_PACKET reply;
+ tls_session_t *tls_session = handler->opaque;
+
+ handler->finished = true;
+ reply.code = FR_TLS_FAIL;
+ reply.length = TLS_HEADER_LEN;
+ reply.flags = peap_flag;
+ reply.data = NULL;
+ reply.dlen = 0;
+
+ tls_fail(tls_session);
+
+ eaptls_compose(handler->eap_ds, &reply);
+
+ return 1;
+}
+
+/*
+ A single TLS record may be up to 16384 octets in length, but a TLS
+ message may span multiple TLS records, and a TLS certificate message
+ may in principle be as long as 16MB.
+*/
+
+/*
+ * Frame the Dirty data that needs to be send to the client in an
+ * EAP-Request. We always embed the TLS-length in all EAP-TLS
+ * packets that we send, for easy reference purpose. Handle
+ * fragmentation and sending the next fragment etc.
+ */
+int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn)
+{
+ EAPTLS_PACKET reply;
+ unsigned int size;
+ unsigned int nlen;
+ unsigned int lbit = 0;
+
+ /* This value determines whether we set (L)ength flag for
+ EVERY packet we send and add corresponding
+ "TLS Message Length" field.
+
+ length_flag = true;
+ This means we include L flag and "TLS Msg Len" in EVERY
+ packet we send out.
+
+ length_flag = false;
+ This means we include L flag and "TLS Msg Len" **ONLY**
+ in First packet of a fragment series. We do not use
+ it anywhere else.
+
+ Having L flag in every packet is prefered.
+
+ */
+ if (ssn->length_flag) {
+ lbit = 4;
+ }
+ if (ssn->fragment == 0) {
+ ssn->tls_msg_len = ssn->dirty_out.used;
+ }
+
+ reply.code = FR_TLS_REQUEST;
+ reply.flags = ssn->peap_flag;
+
+ /* Send data, NOT more than the FRAGMENT size */
+ if (ssn->dirty_out.used > ssn->mtu) {
+ size = ssn->mtu;
+ reply.flags = SET_MORE_FRAGMENTS(reply.flags);
+ /* Length MUST be included if it is the First Fragment */
+ if (ssn->fragment == 0) {
+ lbit = 4;
+ }
+ ssn->fragment = 1;
+ } else {
+ size = ssn->dirty_out.used;
+ ssn->fragment = 0;
+ }
+
+ reply.dlen = lbit + size;
+ reply.length = TLS_HEADER_LEN + 1/*flags*/ + reply.dlen;
+
+ reply.data = talloc_array(eap_ds, uint8_t, reply.length);
+ if (!reply.data) return 0;
+
+ if (lbit) {
+ nlen = htonl(ssn->tls_msg_len);
+ memcpy(reply.data, &nlen, lbit);
+ reply.flags = SET_LENGTH_INCLUDED(reply.flags);
+ }
+ (ssn->record_minus)(&ssn->dirty_out, reply.data + lbit, size);
+
+ eaptls_compose(eap_ds, &reply);
+ talloc_free(reply.data);
+ reply.data = NULL;
+
+ return 1;
+}
+
+
+/*
+ * Similarly, when the EAP server receives an EAP-Response with
+ * the M bit set, it MUST respond with an EAP-Request with
+ * EAP-Type=EAP-TLS and no data. This serves as a fragment ACK.
+ *
+ * In order to prevent errors in the processing of fragments, the
+ * EAP server MUST use increment the Identifier value for each
+ * fragment ACK contained within an EAP-Request, and the peer
+ * MUST include this Identifier value in the subsequent fragment
+ * contained within an EAP- Reponse.
+ *
+ * EAP server sends an ACK when it determines there are More
+ * fragments to receive to make the complete
+ * TLS-record/TLS-Message
+ */
+static int eaptls_send_ack(eap_handler_t *handler, int peap_flag)
+{
+ EAPTLS_PACKET reply;
+ REQUEST *request = handler->request;
+
+ RDEBUG2("(TLS) EAP ACKing fragment, the peer should send more data.");
+ reply.code = FR_TLS_ACK;
+ reply.length = TLS_HEADER_LEN + 1/*flags*/;
+ reply.flags = peap_flag;
+ reply.data = NULL;
+ reply.dlen = 0;
+
+ eaptls_compose(handler->eap_ds, &reply);
+
+ return 1;
+}
+
+/*
+ * The S flag is set only within the EAP-TLS start message sent
+ * from the EAP server to the peer.
+ *
+ * Similarly, when the EAP server receives an EAP-Response with
+ * the M bit set, it MUST respond with an EAP-Request with
+ * EAP-Type=EAP-TLS and no data. This serves as a fragment
+ * ACK. The EAP peer MUST wait.
+ */
+static fr_tls_status_t eaptls_verify(eap_handler_t *handler)
+{
+ EAP_DS *eap_ds = handler->eap_ds;
+ tls_session_t *tls_session = handler->opaque;
+ EAP_DS *prev_eap_ds = handler->prev_eapds;
+ eaptls_packet_t *eaptls_packet, *eaptls_prev = NULL;
+ REQUEST *request = handler->request;
+ size_t frag_len;
+
+ /*
+ * We don't check ANY of the input parameters. It's all
+ * code which works together, so if something is wrong,
+ * we SHOULD core dump.
+ *
+ * e.g. if eap_ds is NULL, of if eap_ds->response is
+ * NULL, of if it's NOT an EAP-Response, or if the packet
+ * is too short. See eap_validation()., in ../../eap.c
+ *
+ * Also, eap_method_select() takes care of selecting the
+ * appropriate type, so we don't need to check
+ * eap_ds->response->type.num == PW_EAP_TLS, or anything
+ * else.
+ */
+ eaptls_packet = (eaptls_packet_t *)eap_ds->response->type.data;
+ if (prev_eap_ds && prev_eap_ds->response)
+ eaptls_prev = (eaptls_packet_t *)prev_eap_ds->response->type.data;
+
+ if (eaptls_packet) {
+ /*
+ * First output the flags (for debugging)
+ */
+ RDEBUG3("(TLS) EAP Peer sent flags %c%c%c",
+ TLS_START(eaptls_packet->flags) ? 'S' : '-',
+ TLS_MORE_FRAGMENTS(eaptls_packet->flags) ? 'M' : '-',
+ TLS_LENGTH_INCLUDED(eaptls_packet->flags) ? 'L' : '-');
+ }
+
+ /*
+ * check for ACK
+ *
+ * If there's no TLS data, or there's 1 byte of TLS data,
+ * with the flags set to zero, then it's an ACK.
+ *
+ * Find if this is a reply to the previous request sent
+ */
+ if ((!eaptls_packet) ||
+ ((eap_ds->response->length == EAP_HEADER_LEN + 2) &&
+ ((eaptls_packet->flags & 0xc0) == 0x00))) {
+
+ if (prev_eap_ds && (prev_eap_ds->request->id == eap_ds->response->id)) {
+ return tls_ack_handler(handler->opaque, request);
+ } else {
+ REDEBUG("(TLS) EAP Received Unexpected ACK - rejection the connection");
+ return FR_TLS_INVALID;
+ }
+ }
+
+ /*
+ * We send TLS_START, but do not receive it.
+ */
+ if (TLS_START(eaptls_packet->flags)) {
+ REDEBUG("(TLS) EAP Peer sent EAP-TLS Start message (only the server is allowed to do this)");
+ return FR_TLS_INVALID;
+ }
+
+ /*
+ * Calculate this fragment's length
+ */
+ frag_len = eap_ds->response->length -
+ (EAP_HEADER_LEN + (TLS_LENGTH_INCLUDED(eaptls_packet->flags) ? 6 : 2));
+
+ /*
+ * The L bit (length included) is set to indicate the
+ * presence of the four octet TLS Message Length field,
+ * and MUST be set for the first fragment of a fragmented
+ * TLS message or set of messages.
+ *
+ * The M bit (more fragments) is set on all but the last
+ * fragment.
+ *
+ * The S bit (EAP-TLS start) is set in an EAP-TLS Start
+ * message. This differentiates the EAP-TLS Start message
+ * from a fragment acknowledgement.
+ */
+ if (TLS_LENGTH_INCLUDED(eaptls_packet->flags)) {
+ size_t total_len = eaptls_packet->data[2] * 256 | eaptls_packet->data[3];
+
+ if (frag_len > total_len) {
+ RWDEBUG("(TLS) EAP Fragment length (%zu bytes) is greater than TLS record length (%zu bytes)", frag_len,
+ total_len);
+ }
+
+ RDEBUG2("(TLS) EAP Peer says that the final record size will be %zu bytes", total_len);
+ if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
+ /*
+ * The supplicant is free to send fragments of wildly varying
+ * lengths, but the vast majority won't.
+ *
+ * In this calculation we take into account the fact that the future
+ * fragments are likely to be 4 bytes larger than the initial one
+ * as they won't contain the length field.
+ */
+ if (frag_len + 4) { /* check for wrap, else clang scan gets excited */
+ RDEBUG2("(TLS) EAP Expecting %i fragments",
+ (int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
+ }
+
+ /*
+ * FIRST_FRAGMENT is identified
+ * 1. If there is no previous EAP-response received.
+ * 2. If EAP-response received, then its M bit not set.
+ * (It is because Last fragment will not have M bit set)
+ */
+ if (!prev_eap_ds || (!prev_eap_ds->response) || (!eaptls_prev) ||
+ !TLS_MORE_FRAGMENTS(eaptls_prev->flags)) {
+ RDEBUG2("(TLS) EAP Got first TLS fragment (%zu bytes). Peer says more fragments "
+ "will follow", frag_len);
+ tls_session->tls_record_in_total_len = total_len;
+ tls_session->tls_record_in_recvd_len = frag_len;
+
+ return FR_TLS_FIRST_FRAGMENT;
+ }
+
+ RDEBUG2("(TLS) EAP Got additional fragment with length (%zu bytes). "
+ "Peer says more fragments will follow", frag_len);
+
+ /*
+ * Check we've not exceeded the originally indicated TLS record size.
+ */
+ tls_session->tls_record_in_recvd_len += frag_len;
+ if (tls_session->tls_record_in_recvd_len > tls_session->tls_record_in_total_len) {
+ RWDEBUG("(TLS) EAP Total received fragments (%zu bytes), exceeds "
+ "total data length (%zu bytes)", frag_len, total_len);
+ }
+
+ return FR_TLS_MORE_FRAGMENTS_WITH_LENGTH;
+ }
+
+ /*
+ * If it's a complete record, our fragment size should match the
+ * value of the four octet TLS length field.
+ */
+ if (total_len != frag_len) {
+ RWDEBUG("(TLS) EAP Peer says no more fragments, but expected data length (%zu bytes) "
+ "does not match expected data length (%zu bytes)", total_len, frag_len);
+ }
+
+ tls_session->tls_record_in_total_len = total_len;
+ tls_session->tls_record_in_recvd_len = frag_len;
+ RDEBUG2("(TLS) EAP Got all data (%zu bytes)", frag_len);
+ return FR_TLS_LENGTH_INCLUDED;
+ }
+
+ /*
+ * The previous packet had the M flags set, but this one doesn't,
+ * this must be the final record fragment
+ */
+ if ((eaptls_prev && TLS_MORE_FRAGMENTS(eaptls_prev->flags)) && !TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
+ RDEBUG2("(TLS) EAP Got final fragment (%zu bytes)", frag_len);
+ tls_session->tls_record_in_recvd_len += frag_len;
+ if (tls_session->tls_record_in_recvd_len != tls_session->tls_record_in_total_len) {
+ RWDEBUG("(TLS) EAP Total received record fragments (%zu bytes), does not equal expected "
+ "expected data length (%zu bytes)",
+ tls_session->tls_record_in_recvd_len, tls_session->tls_record_in_total_len);
+ }
+ }
+
+ if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
+ RDEBUG2("(TLS) EAP Got additional fragment (%zu bytes). Peer says more fragments will follow",
+ frag_len);
+ tls_session->tls_record_in_recvd_len += frag_len;
+ if (tls_session->tls_record_in_recvd_len > tls_session->tls_record_in_total_len) {
+ RWDEBUG("(TLS) EAP Total received fragments (%zu bytes), exceeds "
+ "expected length (%zu bytes)",
+ tls_session->tls_record_in_recvd_len, tls_session->tls_record_in_total_len);
+ }
+ return FR_TLS_MORE_FRAGMENTS;
+ }
+
+ /*
+ * None of the flags are set, but it's still a valid EAP-TLS packet.
+ */
+ return FR_TLS_OK;
+}
+
+/*
+ * EAPTLS_PACKET
+ * code = EAP-code
+ * id = EAP-id
+ * length = code + id + length + flags + tlsdata
+ * = 1 + 1 + 2 + 1 + X
+ * length = EAP-length - 1(EAP-Type = 1 octet)
+ * flags = EAP-typedata[0] (1 octet)
+ * dlen = EAP-typedata[1-4] (4 octets), if L flag set
+ * = length - 5(code+id+length+flags), otherwise
+ * data = EAP-typedata[5-n], if L flag set
+ * = EAP-typedata[1-n], otherwise
+ * packet = EAP-typedata (complete typedata)
+ *
+ * Points to consider during EAP-TLS data extraction
+ * 1. In the received packet, No data will be present incase of ACK-NAK
+ * 2. Incase if more fragments need to be received then ACK after retreiving this fragment.
+ *
+ * RFC 2716 Section 4.2. PPP EAP TLS Request Packet
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Flags | TLS Message Length
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | TLS Message Length | TLS Data...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * The Length field is two octets and indicates the length of the EAP
+ * packet including the Code, Identifir, Length, Type, and TLS data
+ * fields.
+ */
+static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_status_t status)
+{
+ EAPTLS_PACKET *tlspacket;
+ uint32_t data_len = 0;
+ uint32_t len = 0;
+ uint8_t *data = NULL;
+
+ if (status == FR_TLS_INVALID) return NULL;
+
+ /*
+ * The main EAP code & eaptls_verify() take care of
+ * ensuring that the packet is OK, and that we can
+ * extract the various fields we want.
+ *
+ * e.g. a TLS packet with zero data is allowed as an ACK,
+ * but we will never see it here, as we will simply
+ * send another fragment, instead of trying to extract
+ * the data.
+ *
+ * MUST have TLS type octet, followed by flags, followed
+ * by data.
+ */
+ assert(eap_ds->response->length > 2);
+
+ tlspacket = talloc(eap_ds, EAPTLS_PACKET);
+ if (!tlspacket) return NULL;
+
+ /*
+ * Code & id for EAPTLS & EAP are same
+ * but eaptls_length = eap_length - 1(EAP-Type = 1 octet)
+ *
+ * length = code + id + length + type + tlsdata
+ * = 1 + 1 + 2 + 1 + X
+ */
+ tlspacket->code = eap_ds->response->code;
+ tlspacket->id = eap_ds->response->id;
+ tlspacket->length = eap_ds->response->length - 1; /* EAP type */
+ tlspacket->flags = eap_ds->response->type.data[0];
+
+ /*
+ * A quick sanity check of the flags. If we've been told
+ * that there's a length, and there isn't one, then stop.
+ */
+ if (TLS_LENGTH_INCLUDED(tlspacket->flags) &&
+ (tlspacket->length < 5)) { /* flags + TLS message length */
+ REDEBUG("(TLS) EAP Invalid packet received: Length bit is set,"
+ "but packet too short to contain length field");
+ talloc_free(tlspacket);
+ return NULL;
+ }
+
+ /*
+ * If the final TLS packet is larger than we can handle, die
+ * now.
+ *
+ * Likewise, if the EAP packet says N bytes, and the TLS
+ * packet says there's fewer bytes, it's a problem.
+ */
+ if (TLS_LENGTH_INCLUDED(tlspacket->flags)) {
+ memcpy(&data_len, &eap_ds->response->type.data[1], 4);
+ data_len = ntohl(data_len);
+ if (data_len > MAX_RECORD_SIZE) {
+ REDEBUG("(TLS) EAP Reassembled data will be %u bytes, "
+ "greater than the size that we can handle (" STRINGIFY(MAX_RECORD_SIZE) " bytes)",
+ data_len);
+ talloc_free(tlspacket);
+ return NULL;
+ }
+ }
+
+ switch (status) {
+ /*
+ * The TLS Message Length field is four octets, and
+ * provides the total length of the TLS message or set of
+ * messages that is being fragmented; this simplifies
+ * buffer allocation.
+ *
+ * Dynamic allocation of buffers as & when we know the
+ * length should solve the problem.
+ */
+ case FR_TLS_FIRST_FRAGMENT:
+ case FR_TLS_LENGTH_INCLUDED:
+ case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH:
+ if (tlspacket->length < 5) { /* flags + TLS message length */
+ REDEBUG("(TLS) EAP Invalid packet received: Expected length, got none");
+ talloc_free(tlspacket);
+ return NULL;
+ }
+
+ /*
+ * Extract all the TLS fragments from the
+ * previous eap_ds Start appending this
+ * fragment to the above ds
+ */
+ memcpy(&data_len, &eap_ds->response->type.data[1], sizeof(uint32_t));
+ data_len = ntohl(data_len);
+ data = (eap_ds->response->type.data + 5/*flags+TLS-Length*/);
+ len = eap_ds->response->type.length - 5/*flags+TLS-Length*/;
+
+ /*
+ * Hmm... this should be an error, too.
+ */
+ if (data_len > len) {
+ data_len = len;
+ }
+ break;
+
+ /*
+ * Data length is implicit, from the EAP header.
+ */
+ case FR_TLS_MORE_FRAGMENTS:
+ case FR_TLS_OK:
+ data_len = eap_ds->response->type.length - 1/*flags*/;
+ data = eap_ds->response->type.data + 1/*flags*/;
+ break;
+
+ default:
+ REDEBUG("(TLS) EAP Invalid packet received");
+ talloc_free(tlspacket);
+ return NULL;
+ }
+
+ tlspacket->dlen = data_len;
+ if (data_len) {
+ tlspacket->data = talloc_array(tlspacket, uint8_t,
+ data_len);
+ if (!tlspacket->data) {
+ talloc_free(tlspacket);
+ return NULL;
+ }
+ memcpy(tlspacket->data, data, data_len);
+ }
+
+ return tlspacket;
+}
+
+
+
+/*
+ * To process the TLS,
+ * INCOMING DATA:
+ * 1. EAP-TLS should get the compelete TLS data from the peer.
+ * 2. Store that data in a data structure with any other required info
+ * 3. Handle that data structure to the TLS module.
+ * 4. TLS module will perform its operations on the data and
+ * handle back to EAP-TLS
+ *
+ * OUTGOING DATA:
+ * 1. EAP-TLS if necessary will fragment it and send it to the
+ * destination.
+ *
+ * During EAP-TLS initialization, TLS Context object will be
+ * initialized and stored. For every new authentication
+ * requests, TLS will open a new session object and that session
+ * object should be maintained even after the session is
+ * completed for session resumption. (Probably later as a feature
+ * as we donot know who maintains these session objects ie,
+ * SSL_CTX (internally) or TLS module(explicitly). If TLS module,
+ * then how to let SSL API know about these sessions.)
+ */
+static fr_tls_status_t eaptls_operation(fr_tls_status_t status, eap_handler_t *handler)
+{
+ REQUEST *request = handler->request;
+ tls_session_t *tls_session = handler->opaque;
+
+ if ((status == FR_TLS_MORE_FRAGMENTS) ||
+ (status == FR_TLS_MORE_FRAGMENTS_WITH_LENGTH) ||
+ (status == FR_TLS_FIRST_FRAGMENT)) {
+ /*
+ * Send the ACK.
+ */
+ eaptls_send_ack(handler, tls_session->peap_flag);
+ return FR_TLS_HANDLED;
+
+ }
+
+ /*
+ * We have the complete TLS-data or TLS-message.
+ *
+ * Clean the dirty message.
+ *
+ * Authenticate the user and send
+ * Success/Failure.
+ *
+ * If more info
+ * is required then send another request.
+ */
+ if (!tls_handshake_recv(handler->request, tls_session)) {
+ REDEBUG("(TLS) EAP Receive handshake failed during operation");
+ tls_fail(tls_session);
+ return FR_TLS_FAIL;
+ }
+
+#ifdef TLS1_3_VERSION
+ /*
+ * https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5
+ *
+ * We need to signal the other end that TLS negotiation
+ * is done. We can't send a zero-length application data
+ * message, so we send application data which is one byte
+ * of zero.
+ *
+ * Note this is only done for when there is no application
+ * data to be sent. So this is done always for EAP-TLS but
+ * notibly not for PEAP even on resumption.
+ */
+ if ((SSL_version(tls_session->ssl) == TLS1_3_VERSION) &&
+ (tls_session->client_cert_ok || tls_session->authentication_success || SSL_session_reused(tls_session->ssl))) {
+ if ((handler->type == PW_EAP_TLS) || SSL_session_reused(tls_session->ssl)) {
+ tls_session->authentication_success = true;
+
+ RDEBUG("(TLS) EAP Sending final Commitment Message.");
+ tls_session->record_plus(&tls_session->clean_in, "\0", 1);
+ }
+
+ tls_handshake_send(request, tls_session);
+ }
+#endif
+
+ /*
+ * FIXME: return success/fail.
+ *
+ * TLS proper can decide what to do, then.
+ */
+ if (tls_session->dirty_out.used > 0) {
+ eaptls_request(handler->eap_ds, tls_session);
+ return FR_TLS_HANDLED;
+ }
+
+ /*
+ * If there is no data to send i.e
+ * dirty_out.used <=0 and if the SSL
+ * handshake is finished.
+ */
+ if (tls_session->is_init_finished) return FR_TLS_SUCCESS;
+
+ /*
+ * If session is established, skip round-trip and
+ * try to process any inner tunnel data if present.
+ *
+ * This occurs for EAP-TTLS/PAP with TLSv1.3.
+ */
+ if (!tls_session->is_init_finished && SSL_is_init_finished(tls_session->ssl)) {
+ /*
+ * Don't set is_init_finished, as that causes the
+ * rest of the code to make too many assumptions.
+ */
+ return FR_TLS_OK;
+ }
+
+ /*
+ * Who knows what happened...
+ */
+ REDEBUG("(TLS) Cannot continue, as the peer is misbehaving.");
+ return FR_TLS_FAIL;
+}
+
+
+/*
+ * In the actual authentication first verify the packet and then create the data structure
+ */
+/*
+ * To process the TLS,
+ * INCOMING DATA:
+ * 1. EAP-TLS should get the compelete TLS data from the peer.
+ * 2. Store that data in a data structure with any other required info
+ * 3. Hand this data structure to the TLS module.
+ * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
+ * OUTGOING DATA:
+ * 1. EAP-TLS if necessary will fragment it and send it to the destination.
+ *
+ * During EAP-TLS initialization, TLS Context object will be
+ * initialized and stored. For every new authentication
+ * requests, TLS will open a new session object and that
+ * session object SHOULD be maintained even after the session
+ * is completed, for session resumption. (Probably later as a
+ * feature, as we do not know who maintains these session
+ * objects ie, SSL_CTX (internally) or TLS module (explicitly). If
+ * TLS module, then how to let SSL API know about these
+ * sessions.)
+ */
+
+/*
+ * Process an EAP request
+ */
+fr_tls_status_t eaptls_process(eap_handler_t *handler)
+{
+ tls_session_t *tls_session = (tls_session_t *) handler->opaque;
+ EAPTLS_PACKET *tlspacket;
+ fr_tls_status_t status;
+ REQUEST *request = handler->request;
+
+ if (!request) return FR_TLS_FAIL;
+
+ RDEBUG3("(TLS) EAP Continuing ...");
+
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
+
+ if (handler->certs) fr_pair_add(&request->packet->vps,
+ fr_pair_list_copy(request->packet, handler->certs));
+
+ /*
+ * This case is when SSL generates Alert then we
+ * send that alert to the client and then send the EAP-Failure
+ */
+ status = eaptls_verify(handler);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("(TLS) EAP Verification failed with %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("(TLS) EAP Verification says %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+
+ switch (status) {
+ default:
+ case FR_TLS_INVALID:
+ case FR_TLS_FAIL:
+
+ /*
+ * Success means that we're done the initial
+ * handshake. For TTLS, this means send stuff
+ * back to the client, and the client sends us
+ * more tunneled data.
+ */
+ case FR_TLS_SUCCESS:
+ goto done;
+
+ /*
+ * Normal TLS request, continue with the "get rest
+ * of fragments" phase.
+ */
+ case FR_TLS_REQUEST:
+ eaptls_request(handler->eap_ds, tls_session);
+ status = FR_TLS_HANDLED;
+ goto done;
+
+ /*
+ * The handshake is done, and we're in the "tunnel
+ * data" phase.
+ */
+ case FR_TLS_OK:
+ RDEBUG2("(TLS) EAP Done initial handshake");
+
+ /*
+ * Get the rest of the fragments.
+ */
+ case FR_TLS_FIRST_FRAGMENT:
+ case FR_TLS_MORE_FRAGMENTS:
+ case FR_TLS_LENGTH_INCLUDED:
+ case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH:
+ break;
+ }
+
+ /*
+ * Extract the TLS packet from the buffer.
+ */
+ if ((tlspacket = eaptls_extract(request, handler->eap_ds, status)) == NULL) {
+ REDEBUG("(TLS) EAP Failed extracting TLS packet from EAP-Message");
+ status = FR_TLS_FAIL;
+ goto done;
+ }
+
+ /*
+ * Get the session struct from the handler
+ *
+ * update the dirty_in buffer
+ *
+ * NOTE: This buffer will contain partial data when M bit is set.
+ *
+ * CAUTION while reinitializing this buffer, it should be
+ * reinitialized only when this M bit is NOT set.
+ */
+ if (tlspacket->dlen !=
+ (tls_session->record_plus)(&tls_session->dirty_in, tlspacket->data, tlspacket->dlen)) {
+ talloc_free(tlspacket);
+ REDEBUG("(TLS) EAP Exceeded maximum record size");
+ status = FR_TLS_FAIL;
+ goto done;
+ }
+
+ /*
+ * No longer needed.
+ */
+ talloc_free(tlspacket);
+
+ /*
+ * SSL initalization is done. Return.
+ *
+ * The TLS data will be in the tls_session structure.
+ */
+ if (tls_session->is_init_finished) {
+ /*
+ * The initialization may be finished, but if
+ * there more fragments coming, then send ACK,
+ * and get the caller to continue the
+ * conversation.
+ */
+ if ((status == FR_TLS_MORE_FRAGMENTS) ||
+ (status == FR_TLS_MORE_FRAGMENTS_WITH_LENGTH) ||
+ (status == FR_TLS_FIRST_FRAGMENT)) {
+ /*
+ * Send the ACK.
+ */
+ eaptls_send_ack(handler, tls_session->peap_flag);
+ RDEBUG2("(TLS) EAP Init is done, but tunneled data is fragmented");
+ status = FR_TLS_HANDLED;
+ goto done;
+ }
+
+ status = tls_application_data(tls_session, request);
+ goto done;
+ }
+
+ /*
+ * Continue the handshake.
+ */
+ status = eaptls_operation(status, handler);
+ if (status == FR_TLS_SUCCESS) {
+#define MAX_SESSION_SIZE (256)
+ VALUE_PAIR *vps;
+ char buffer[2 * MAX_SESSION_SIZE + 1];
+
+ /*
+ * Restore the cached VPs before processing the
+ * application data.
+ */
+ tls_session_id(tls_session->ssl_session, buffer, MAX_SESSION_SIZE);
+
+ vps = SSL_SESSION_get_ex_data(tls_session->ssl_session, fr_tls_ex_index_vps);
+ if (!vps) {
+ RWDEBUG("(TLS) EAP No information in cached session %s", buffer);
+ } else {
+ vp_cursor_t cursor;
+ VALUE_PAIR *vp;
+ fr_tls_server_conf_t *conf;
+
+ RDEBUG("(TLS) EAP Adding cached attributes from session %s", buffer);
+
+ conf = (fr_tls_server_conf_t *)SSL_get_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF);
+ rad_assert(conf != NULL);
+
+ /*
+ * The cbtls_get_session() function doesn't have
+ * access to sock->certs or handler->certs, which
+ * is where the certificates normally live. So
+ * the certs are all in the VPS list here, and
+ * have to be manually extracted.
+ */
+ RINDENT();
+ for (vp = fr_cursor_init(&cursor, &vps);
+ vp;
+ vp = fr_cursor_next(&cursor)) {
+ if (conf->cache_ht && fr_hash_table_finddata(conf->cache_ht, vp->da)) {
+ rdebug_pair(L_DBG_LVL_2, request, vp, "&session-state:");
+ fr_pair_add(&request->state, fr_pair_copy(request->state_ctx, vp));
+ continue;
+ }
+
+ /*
+ * TLS-* attrs get added back to
+ * the request list.
+ */
+ if ((vp->da->vendor == 0) &&
+ (vp->da->attr >= PW_TLS_CERT_SERIAL) &&
+ (vp->da->attr <= PW_TLS_CLIENT_CERT_SUBJECT_ALT_NAME_UPN)) {
+ /*
+ * Certs already exist. Don't re-add them.
+ */
+ if (!handler->certs) {
+ rdebug_pair(L_DBG_LVL_2, request, vp, "&request:");
+ fr_pair_add(&request->packet->vps, fr_pair_copy(request->packet, vp));
+ }
+
+ } else if ((vp->da->vendor == 0) &&
+ (vp->da->attr == PW_EAP_TYPE)) {
+ /*
+ * EAP-Type gets added to
+ * the control list, so
+ * that we can sanity check it.
+ */
+ rdebug_pair(L_DBG_LVL_2, request, vp, "&control:");
+ fr_pair_add(&request->config, fr_pair_copy(request, vp));
+
+ } else {
+
+ rdebug_pair(L_DBG_LVL_2, request, vp, "&reply:");
+ fr_pair_add(&request->reply->vps, fr_pair_copy(request->reply, vp));
+ }
+ }
+ REXDENT();
+ }
+ }
+
+ done:
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
+
+ return status;
+}
+
+
+/*
+ * compose the TLS reply packet in the EAP reply typedata
+ */
+int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply)
+{
+ uint8_t *ptr;
+
+ /*
+ * Don't set eap_ds->request->type.num, as the main EAP
+ * handler will do that for us. This allows the TLS
+ * module to be called from TTLS & PEAP.
+ */
+
+ /*
+ * When the EAP server receives an EAP-Response with the
+ * M bit set, it MUST respond with an EAP-Request with
+ * EAP-Type=EAP-TLS and no data. This serves as a
+ * fragment ACK. The EAP peer MUST wait until it receives
+ * the EAP-Request before sending another fragment.
+ *
+ * In order to prevent errors in the processing of
+ * fragments, the EAP server MUST use increment the
+ * Identifier value for each fragment ACK contained
+ * within an EAP-Request, and the peer MUST include this
+ * Identifier value in the subsequent fragment contained
+ * within an EAP- Reponse.
+ */
+ eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t,
+ reply->length - TLS_HEADER_LEN + 1);
+ if (!eap_ds->request->type.data) return 0;
+
+ /* EAPTLS Header length is excluded while computing EAP typelen */
+ eap_ds->request->type.length = reply->length - TLS_HEADER_LEN;
+
+ ptr = eap_ds->request->type.data;
+ *ptr++ = (uint8_t)(reply->flags & 0xFF);
+
+ if (reply->dlen) memcpy(ptr, reply->data, reply->dlen);
+
+ switch (reply->code) {
+ case FR_TLS_ACK:
+ case FR_TLS_START:
+ case FR_TLS_REQUEST:
+ eap_ds->request->code = PW_EAP_REQUEST;
+ break;
+
+ case FR_TLS_SUCCESS:
+ eap_ds->request->code = PW_EAP_SUCCESS;
+ break;
+
+ case FR_TLS_FAIL:
+ eap_ds->request->code = PW_EAP_FAILURE;
+ break;
+
+ default:
+ /* Should never enter here */
+ rad_assert(0);
+ break;
+ }
+
+ return 1;
+}
+
+/*
+ * Parse TLS configuration
+ *
+ * If the option given by 'attr' is set, we find the config section
+ * of that name and use that for the TLS configuration. If not, we
+ * fall back to compatibility mode and read the TLS options from
+ * the 'tls' section.
+ */
+fr_tls_server_conf_t *eaptls_conf_parse(CONF_SECTION *cs, char const *attr)
+{
+ char const *tls_conf_name;
+ CONF_PAIR *cp;
+ CONF_SECTION *parent;
+ CONF_SECTION *tls_cs;
+ fr_tls_server_conf_t *tls_conf;
+
+ if (!cs)
+ return NULL;
+
+ rad_assert(attr != NULL);
+
+ parent = cf_item_parent(cf_section_to_item(cs));
+
+ cp = cf_pair_find(cs, attr);
+ if (cp) {
+ tls_conf_name = cf_pair_value(cp);
+
+ tls_cs = cf_section_sub_find_name2(parent, TLS_CONFIG_SECTION, tls_conf_name);
+
+ if (!tls_cs) {
+ ERROR("Cannot find tls config \"%s\"", tls_conf_name);
+ return NULL;
+ }
+ } else {
+ /*
+ * If we can't find the section given by the 'attr', we
+ * fall-back to looking for the "tls" section, as in
+ * previous versions.
+ *
+ * We don't fall back if the 'attr' is specified, but we can't
+ * find the section - that is just a config error.
+ */
+ INFO("TLS section \"%s\" missing, trying to use legacy configuration", attr);
+ tls_cs = cf_section_sub_find(parent, "tls");
+ }
+
+ if (!tls_cs)
+ return NULL;
+
+ tls_conf = tls_server_conf_parse(tls_cs);
+
+ if (!tls_conf)
+ return NULL;
+
+ /*
+ * The EAP RFC's say 1020, but we're less picky.
+ */
+ if (tls_conf->fragment_size < 100) {
+ ERROR("Configured fragment size is too small, must be >= 100");
+ return NULL;
+ }
+
+ /*
+ * The maximum size for a RADIUS packet is 4096,
+ * minus the header (20), Message-Authenticator (18),
+ * and State (18), etc. results in about 4000 bytes of data
+ * that can be devoted *solely* to EAP.
+ */
+ if (tls_conf->fragment_size > 4000) {
+ ERROR("Configured fragment size is too large, must be <= 4000");
+ return NULL;
+ }
+
+ /*
+ * Account for the EAP header (4), and the EAP-TLS header
+ * (6), as per Section 4.2 of RFC 2716. What's left is
+ * the maximum amount of data we read from a TLS buffer.
+ */
+ tls_conf->fragment_size -= 10;
+
+ return tls_conf;
+}
+
diff --git a/src/modules/rlm_eap/libeap/eap_tls.h b/src/modules/rlm_eap/libeap/eap_tls.h
new file mode 100644
index 0000000..8e5fc77
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eap_tls.h
@@ -0,0 +1,109 @@
+/*
+ * eap_tls.h
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _EAP_TLS_H
+#define _EAP_TLS_H
+
+RCSIDH(eap_tls_h, "$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <ctype.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/tls.h>
+
+#include "eap.h"
+
+/*
+ * Externally exported TLS functions.
+ */
+fr_tls_status_t eaptls_process(eap_handler_t *handler);
+
+int eaptls_success(eap_handler_t *handler, int peap_flag) CC_HINT(nonnull);
+int eaptls_fail(eap_handler_t *handler, int peap_flag) CC_HINT(nonnull);
+int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) CC_HINT(nonnull);
+
+
+void T_PRF(unsigned char const *secret, unsigned int secret_len, char const *prf_label, unsigned char const *seed, unsigned int seed_len, unsigned char *out, unsigned int out_len) CC_HINT(nonnull(1,3,6));
+void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, size_t context_size);
+void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size);
+void eaptls_gen_eap_key(eap_handler_t *handler);
+void eap_fast_tls_gen_challenge(SSL *ssl, int version, uint8_t *buffer, size_t size, char const *prf_label) CC_HINT(nonnull);
+
+#define BUFFER_SIZE 1024
+
+typedef enum tls_op {
+ EAP_TLS_START = 1,
+ EAP_TLS_ACK = 2,
+ EAP_TLS_SUCCESS = 3,
+ EAP_TLS_FAIL = 4,
+ EAP_TLS_ALERT = 9
+} tls_op_t;
+
+#define TLS_HEADER_LEN 4
+
+typedef struct tls_packet_t {
+ uint8_t flags;
+ uint8_t data[1];
+} eaptls_packet_t;
+
+typedef struct tls_packet {
+ uint8_t code;
+ uint8_t id;
+ uint32_t length;
+ uint8_t flags;
+ uint8_t *data;
+ uint32_t dlen;
+
+ //uint8_t *packet; /* Wired EAP-TLS packet as found in typdedata of eap_packet_t */
+} EAPTLS_PACKET;
+
+
+/* EAP-TLS framework */
+EAPTLS_PACKET *eaptls_alloc(void);
+void eaptls_free(EAPTLS_PACKET **eaptls_packet_ptr);
+tls_session_t *eaptls_session(eap_handler_t *handler, fr_tls_server_conf_t *tls_conf, bool client_cert, bool allow_tls13);
+int eaptls_start(EAP_DS *eap_ds, int peap);
+int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply);
+
+fr_tls_server_conf_t *eaptls_conf_parse(CONF_SECTION *cs, char const *key);
+
+#endif /*_EAP_TLS_H*/
diff --git a/src/modules/rlm_eap/libeap/eap_types.h b/src/modules/rlm_eap/libeap/eap_types.h
new file mode 100644
index 0000000..c6568ff
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eap_types.h
@@ -0,0 +1,162 @@
+/*
+ * eap_types.h Header file containing the interfaces for all EAP types.
+ *
+ * most contents moved from modules/rlm_eap/eap.h
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _EAP_TYPES_H
+#define _EAP_TYPES_H
+
+RCSIDH(eap_methods_h, "$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+/* Code (1) + Identifier (1) + Length (2) */
+#define EAP_HEADER_LEN 4
+
+typedef enum eap_code {
+ PW_EAP_REQUEST = 1,
+ PW_EAP_RESPONSE,
+ PW_EAP_SUCCESS,
+ PW_EAP_FAILURE,
+ PW_EAP_MAX_CODES
+} eap_code_t;
+
+typedef enum eap_method {
+ PW_EAP_INVALID = 0, /* 0 */
+ PW_EAP_IDENTITY, /* 1 */
+ PW_EAP_NOTIFICATION, /* 2 */
+ PW_EAP_NAK, /* 3 */
+ PW_EAP_MD5, /* 4 */
+ PW_EAP_OTP, /* 5 */
+ PW_EAP_GTC, /* 6 */
+ PW_EAP_7, /* 7 - unused */
+ PW_EAP_8, /* 8 - unused */
+ PW_EAP_RSA_PUBLIC_KEY, /* 9 */
+ PW_EAP_DSS_UNILATERAL, /* 10 */
+ PW_EAP_KEA, /* 11 */
+ PW_EAP_KEA_VALIDATE, /* 12 */
+ PW_EAP_TLS, /* 13 */
+ PW_EAP_DEFENDER_TOKEN, /* 14 */
+ PW_EAP_RSA_SECURID, /* 15 */
+ PW_EAP_ARCOT_SYSTEMS, /* 16 */
+ PW_EAP_LEAP, /* 17 */
+ PW_EAP_SIM, /* 18 */
+ PW_EAP_SRP_SHA1, /* 19 */
+ PW_EAP_20, /* 20 - unassigned */
+ PW_EAP_TTLS, /* 21 */
+ PW_EAP_REMOTE_ACCESS_SERVICE, /* 22 */
+ PW_EAP_AKA, /* 23 */
+ PW_EAP_3COM, /* 24 - should this be EAP-HP now? */
+ PW_EAP_PEAP, /* 25 */
+ PW_EAP_MSCHAPV2, /* 26 */
+ PW_EAP_MAKE, /* 27 */
+ PW_EAP_CRYPTOCARD, /* 28 */
+ PW_EAP_CISCO_MSCHAPV2, /* 29 */
+ PW_EAP_DYNAMID, /* 30 */
+ PW_EAP_ROB, /* 31 */
+ PW_EAP_POTP, /* 32 */
+ PW_EAP_MS_ATLV, /* 33 */
+ PW_EAP_SENTRINET, /* 34 */
+ PW_EAP_ACTIONTEC, /* 35 */
+ PW_EAP_COGENT_BIOMETRIC, /* 36 */
+ PW_EAP_AIRFORTRESS, /* 37 */
+ PW_EAP_TNC, /* 38 - fixme conflicts with HTTP DIGEST */
+// PW_EAP_HTTP_DIGEST, /* 38 */
+ PW_EAP_SECURISUITE, /* 39 */
+ PW_EAP_DEVICECONNECT, /* 40 */
+ PW_EAP_SPEKE, /* 41 */
+ PW_EAP_MOBAC, /* 42 */
+ PW_EAP_FAST, /* 43 */
+ PW_EAP_ZONELABS, /* 44 */
+ PW_EAP_LINK, /* 45 */
+ PW_EAP_PAX, /* 46 */
+ PW_EAP_PSK, /* 47 */
+ PW_EAP_SAKE, /* 48 */
+ PW_EAP_IKEV2, /* 49 */
+ PW_EAP_AKA2, /* 50 */
+ PW_EAP_GPSK, /* 51 */
+ PW_EAP_PWD, /* 52 */
+ PW_EAP_EKE, /* 53 */
+ PW_EAP_MAX_TYPES /* 54 - for validation */
+} eap_type_t;
+
+#define PW_EAP_EXPANDED_TYPE (254)
+
+typedef enum eap_rcode {
+ EAP_NOTFOUND, //!< EAP handler data not found.
+ EAP_FOUND, //!< EAP handler data found, continue.
+ EAP_OK, //!< Ok, continue.
+ EAP_FAIL, //!< Failed, don't reply.
+ EAP_NOOP, //!< Succeeded without doing anything.
+ EAP_INVALID, //!< Invalid, don't reply.
+ EAP_VALID, //!< Valid, continue.
+ EAP_MAX_RCODES
+} eap_rcode_t;
+
+extern const FR_NAME_NUMBER eap_rcode_table[];
+
+/** EAP-Type specific data
+ */
+typedef struct eap_type_data {
+ eap_type_t num;
+ size_t length;
+ uint8_t *data;
+} eap_type_data_t;
+
+/** Structure to hold EAP data
+ *
+ * length = code + id + length + type + type.data
+ * = 1 + 1 + 2 + 1 + X
+ */
+typedef struct eap_packet {
+ eap_code_t code;
+ uint8_t id;
+ size_t length;
+ eap_type_data_t type;
+
+ uint8_t *packet;
+} eap_packet_t;
+
+/** Structure to represent packet format of eap *on wire*
+ */
+typedef struct eap_packet_raw {
+ uint8_t code;
+ uint8_t id;
+ uint8_t length[2];
+ uint8_t data[1];
+} eap_packet_raw_t;
+
+
+/*
+ * interfaces in eapcommon.c
+ */
+eap_type_t eap_name2type(char const *name);
+char const *eap_type2name(eap_type_t method);
+int eap_wireformat(eap_packet_t *reply);
+int eap_basic_compose(RADIUS_PACKET *packet, eap_packet_t *reply);
+VALUE_PAIR *eap_packet2vp(RADIUS_PACKET *packet, eap_packet_raw_t const *reply);
+eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps);
+void eap_add_reply(REQUEST *request, char const *name, uint8_t const *value, int len);
+
+#endif /* _EAP_TYPES_H */
diff --git a/src/modules/rlm_eap/libeap/eapclient.h b/src/modules/rlm_eap/libeap/eapclient.h
new file mode 100644
index 0000000..594007f
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eapclient.h
@@ -0,0 +1,8 @@
+/*
+ * some of this seems like a repeat of rlm_eap, and needs to be better
+ * integrated, but as a client library, it deals with Request/Replies
+ * rather than with Replies -> new requests.
+ *
+ * Bare with me for a bit.
+ *
+ */
diff --git a/src/modules/rlm_eap/libeap/eapcommon.c b/src/modules/rlm_eap/libeap/eapcommon.c
new file mode 100644
index 0000000..96db30b
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eapcommon.c
@@ -0,0 +1,401 @@
+/*
+ * eapcommon.c rfc2284 & rfc2869 implementation
+ *
+ * code common to clients and to servers.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000-2003,2006 The FreeRADIUS server project
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ */
+/*
+ * EAP PACKET FORMAT
+ * --- ------ ------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Data ...
+ * +-+-+-+-+
+ *
+ *
+ * EAP Request and Response Packet Format
+ * --- ------- --- -------- ------ ------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Type-Data ...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+ *
+ *
+ * EAP Success and Failure Packet Format
+ * --- ------- --- ------- ------ ------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+RCSID("$Id$")
+
+#include <freeradius-devel/libradius.h>
+#include <freeradius-devel/rad_assert.h>
+#include "eap_types.h"
+
+const FR_NAME_NUMBER eap_rcode_table[] = {
+ { "notfound", EAP_NOTFOUND },
+ { "found", EAP_OK },
+ { "ok", EAP_FAIL },
+ { "fail", EAP_NOOP },
+ { "noop", EAP_INVALID },
+ { "invalid", EAP_VALID },
+ { "valid", EAP_MAX_RCODES },
+
+ { NULL , -1 }
+};
+
+/** Return an EAP-Type for a particular name
+ *
+ * Converts a name into an IANA EAP type.
+ *
+ * @param name to convert.
+ * @return The IANA EAP type or PW_EAP_INVALID if the name doesn't match any
+ * known types.
+ */
+eap_type_t eap_name2type(char const *name)
+{
+ DICT_VALUE *dv;
+
+ dv = dict_valbyname(PW_EAP_TYPE, 0, name);
+ if (!dv) return PW_EAP_INVALID;
+
+ if (dv->value >= PW_EAP_MAX_TYPES) return PW_EAP_INVALID;
+
+ return dv->value;
+}
+
+/** Return an EAP-name for a particular type
+ *
+ * Resolve
+ */
+char const *eap_type2name(eap_type_t method)
+{
+ DICT_VALUE *dv;
+
+ dv = dict_valbyattr(PW_EAP_TYPE, 0, method);
+ if (dv) {
+ return dv->name;
+ }
+
+ return "unknown";
+}
+
+/*
+ * EAP packet format to be sent over the wire
+ *
+ * i.e. code+id+length+data where data = null/type+typedata
+ * based on code.
+ *
+ * INPUT to function is reply->code
+ * reply->id
+ * reply->type - setup with data
+ *
+ * OUTPUT reply->packet is setup with wire format, and will
+ * be allocated to the right size.
+ *
+ */
+int eap_wireformat(eap_packet_t *reply)
+{
+ eap_packet_raw_t *header;
+ uint16_t total_length = 0;
+
+ if (!reply) return EAP_INVALID;
+
+ /*
+ * If reply->packet is set, then the wire format
+ * has already been calculated, just succeed.
+ */
+ if(reply->packet != NULL) return EAP_VALID;
+
+ total_length = EAP_HEADER_LEN;
+ if (reply->code < 3) {
+ total_length += 1/* EAP Method */;
+ if (reply->type.data && reply->type.length > 0) {
+ total_length += reply->type.length;
+ }
+ }
+
+ reply->packet = talloc_array(reply, uint8_t, total_length);
+ header = (eap_packet_raw_t *)reply->packet;
+ if (!header) {
+ return EAP_INVALID;
+ }
+
+ header->code = (reply->code & 0xFF);
+ header->id = (reply->id & 0xFF);
+
+ total_length = htons(total_length);
+ memcpy(header->length, &total_length, sizeof(total_length));
+
+ /*
+ * Request and Response packets are special.
+ */
+ if ((reply->code == PW_EAP_REQUEST) ||
+ (reply->code == PW_EAP_RESPONSE)) {
+ header->data[0] = (reply->type.num & 0xFF);
+
+ /*
+ * Here since we cannot know the typedata format and length
+ *
+ * Type_data is expected to be wired by each EAP-Type
+ *
+ * Zero length/No typedata is supported as long as
+ * type is defined
+ */
+ if (reply->type.data && reply->type.length > 0) {
+ memcpy(&header->data[1], reply->type.data, reply->type.length);
+ talloc_free(reply->type.data);
+ reply->type.data = reply->packet + EAP_HEADER_LEN + 1/*EAPtype*/;
+ }
+ }
+
+ return EAP_VALID;
+}
+
+
+/*
+ * compose EAP reply packet in EAP-Message attr of RADIUS. If
+ * EAP exceeds 253, frame it in multiple EAP-Message attrs.
+ */
+int eap_basic_compose(RADIUS_PACKET *packet, eap_packet_t *reply)
+{
+ VALUE_PAIR *vp;
+ eap_packet_raw_t *eap_packet;
+ int rcode;
+
+ if (eap_wireformat(reply) == EAP_INVALID) {
+ return RLM_MODULE_INVALID;
+ }
+ eap_packet = (eap_packet_raw_t *)reply->packet;
+
+ fr_pair_delete_by_num(&(packet->vps), PW_EAP_MESSAGE, 0, TAG_ANY);
+
+ vp = eap_packet2vp(packet, eap_packet);
+ if (!vp) return RLM_MODULE_INVALID;
+ fr_pair_add(&(packet->vps), vp);
+
+ /*
+ * EAP-Message is always associated with
+ * Message-Authenticator but not vice-versa.
+ *
+ * Don't add a Message-Authenticator if it's already
+ * there.
+ */
+ vp = fr_pair_find_by_num(packet->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+ if (!vp) {
+ vp = fr_pair_afrom_num(packet, PW_MESSAGE_AUTHENTICATOR, 0);
+ vp->vp_length = AUTH_VECTOR_LEN;
+ vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length);
+
+ fr_pair_add(&(packet->vps), vp);
+ }
+
+ /* Set request reply code, but only if it's not already set. */
+ rcode = RLM_MODULE_OK;
+ if (!packet->code) switch (reply->code) {
+ case PW_EAP_RESPONSE:
+ case PW_EAP_SUCCESS:
+ packet->code = PW_CODE_ACCESS_ACCEPT;
+ rcode = RLM_MODULE_HANDLED;
+ break;
+ case PW_EAP_FAILURE:
+ packet->code = PW_CODE_ACCESS_REJECT;
+ rcode = RLM_MODULE_REJECT;
+ break;
+ case PW_EAP_REQUEST:
+ packet->code = PW_CODE_ACCESS_CHALLENGE;
+ rcode = RLM_MODULE_HANDLED;
+ break;
+ default:
+ /* Should never enter here */
+ ERROR("rlm_eap: reply code %d is unknown, Rejecting the request.", reply->code);
+ packet->code = PW_CODE_ACCESS_REJECT;
+ break;
+ }
+
+ return rcode;
+}
+
+
+VALUE_PAIR *eap_packet2vp(RADIUS_PACKET *packet, eap_packet_raw_t const *eap)
+{
+ int total, size;
+ uint8_t const *ptr;
+ VALUE_PAIR *head = NULL;
+ VALUE_PAIR *vp;
+ vp_cursor_t out;
+
+ total = eap->length[0] * 256 + eap->length[1];
+
+ if (total == 0) {
+ DEBUG("Asked to encode empty EAP-Message!");
+ return NULL;
+ }
+
+ ptr = (uint8_t const *) eap;
+
+ fr_cursor_init(&out, &head);
+ do {
+ size = total;
+ if (size > 253) size = 253;
+
+ vp = fr_pair_afrom_num(packet, PW_EAP_MESSAGE, 0);
+ if (!vp) {
+ fr_pair_list_free(&head);
+ return NULL;
+ }
+ fr_pair_value_memcpy(vp, ptr, size);
+
+ fr_cursor_insert(&out, vp);
+
+ ptr += size;
+ total -= size;
+ } while (total > 0);
+
+ return head;
+}
+
+
+/*
+ * Handles multiple EAP-Message attrs
+ * ie concatenates all to get the complete EAP packet.
+ *
+ * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message,
+ * refer fragmentation in rfc2869.
+ */
+eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps)
+{
+ VALUE_PAIR *first, *i;
+ eap_packet_raw_t *eap_packet;
+ unsigned char *ptr;
+ uint16_t len;
+ int total_len;
+ vp_cursor_t cursor;
+
+ /*
+ * Get only EAP-Message attribute list
+ */
+ first = fr_pair_find_by_num(vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ if (!first) {
+ fr_strerror_printf("EAP-Message not found");
+ return NULL;
+ }
+
+ /*
+ * Sanity check the length before doing anything.
+ */
+ if (first->vp_length < 4) {
+ fr_strerror_printf("EAP packet is too short");
+ return NULL;
+ }
+
+ /*
+ * Get the Actual length from the EAP packet
+ * First EAP-Message contains the EAP packet header
+ */
+ memcpy(&len, first->vp_strvalue + 2, sizeof(len));
+ len = ntohs(len);
+
+ /*
+ * Take out even more weird things.
+ */
+ if (len < 4) {
+ fr_strerror_printf("EAP packet has invalid length (less than 4 bytes)");
+ return NULL;
+ }
+
+ /*
+ * Sanity check the length, BEFORE allocating memory.
+ */
+ total_len = 0;
+ fr_cursor_init(&cursor, &first);
+ while ((i = fr_cursor_next_by_num(&cursor, PW_EAP_MESSAGE, 0, TAG_ANY))) {
+ total_len += i->vp_length;
+
+ if (total_len > len) {
+ fr_strerror_printf("Malformed EAP packet. Length in packet header %i, "
+ "does not match actual length %i", len, total_len);
+ return NULL;
+ }
+ }
+
+ /*
+ * If the length is SMALLER, die, too.
+ */
+ if (total_len < len) {
+ fr_strerror_printf("Malformed EAP packet. Length in packet header does not "
+ "match actual length");
+ return NULL;
+ }
+
+ /*
+ * Now that we know the lengths are OK, allocate memory.
+ */
+ eap_packet = (eap_packet_raw_t *) talloc_zero_array(ctx, uint8_t, len);
+ if (!eap_packet) {
+ return NULL;
+ }
+
+ /*
+ * Copy the data from EAP-Message's over to our EAP packet.
+ */
+ ptr = (unsigned char *)eap_packet;
+
+ /* RADIUS ensures order of attrs, so just concatenate all */
+ fr_cursor_first(&cursor);
+ while ((i = fr_cursor_next_by_num(&cursor, PW_EAP_MESSAGE, 0, TAG_ANY))) {
+ memcpy(ptr, i->vp_strvalue, i->vp_length);
+ ptr += i->vp_length;
+ }
+
+ return eap_packet;
+}
+
+/*
+ * Add raw hex data to the reply.
+ */
+void eap_add_reply(REQUEST *request,
+ char const *name, uint8_t const *value, int len)
+{
+ VALUE_PAIR *vp;
+
+ vp = pair_make_reply(name, NULL, T_OP_EQ);
+ if (!vp) {
+ REDEBUG("Did not create attribute %s: %s\n",
+ name, fr_strerror());
+ return;
+ }
+
+ fr_pair_value_memcpy(vp, value, len);
+}
diff --git a/src/modules/rlm_eap/libeap/eapcrypto.c b/src/modules/rlm_eap/libeap/eapcrypto.c
new file mode 100644
index 0000000..f57714b
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eapcrypto.c
@@ -0,0 +1,301 @@
+/*
+ * eapcrypto.c Common key derivation routines for EAP/SIM.
+ *
+ * The development of the EAP/SIM support was funded by Internet Foundation
+ * Austria (http://www.nic.at/ipa).
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ * Copyright 2003,2006 The FreeRADIUS server project
+ *
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eap_types.h"
+#include "eap_sim.h"
+#include <freeradius-devel/sha1.h>
+
+void eapsim_calculate_keys(struct eapsim_keys *ek)
+{
+ fr_sha1_ctx context;
+ uint8_t fk[160];
+ unsigned char buf[256];
+ unsigned char *p;
+ unsigned int blen;
+
+ p = buf;
+ memcpy(p, ek->identity, ek->identitylen); p = p+ek->identitylen;
+ memcpy(p, ek->Kc[0], EAPSIM_KC_SIZE); p = p+EAPSIM_KC_SIZE;
+ memcpy(p, ek->Kc[1], EAPSIM_KC_SIZE); p = p+EAPSIM_KC_SIZE;
+ memcpy(p, ek->Kc[2], EAPSIM_KC_SIZE); p = p+EAPSIM_KC_SIZE;
+ memcpy(p, ek->nonce_mt, sizeof(ek->nonce_mt)); p=p+sizeof(ek->nonce_mt);
+ memcpy(p, ek->versionlist, ek->versionlistlen);p=p+ek->versionlistlen;
+ memcpy(p, ek->versionselect, sizeof(ek->versionselect)); p=p+sizeof(ek->versionselect);
+ /* *p++ = ek->versionselect[1]; */
+
+ blen = p - buf;
+
+#if defined(TEST_CASE) || defined(DUMP_EAPSIM_KEYS)
+ {
+ unsigned int i, j, k;
+
+ j=0; k=0;
+
+ printf("SHA1buffer was: ");
+ for (i = 0; i < blen; i++) {
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ if(k==20) {
+ printf("\n ");
+ k=0;
+ j=0;
+ }
+ j++;
+ k++;
+
+ printf("%02x", buf[i]);
+ }
+ printf("\n");
+ }
+#endif
+
+
+ /* do the master key first */
+ fr_sha1_init(&context);
+ fr_sha1_update(&context, buf, blen);
+ fr_sha1_final(ek->master_key, &context);
+
+ /*
+ * now use the PRF to expand it, generated K_aut, K_encr,
+ * MSK and EMSK.
+ */
+ fips186_2prf(ek->master_key, fk);
+
+ /* split up the result */
+ memcpy(ek->K_encr, fk + 0, 16); /* 128 bits for encryption */
+ memcpy(ek->K_aut, fk + 16, EAPSIM_AUTH_SIZE); /*128 bits for auth */
+ memcpy(ek->msk, fk + 32, 64); /* 64 bytes for Master Session Key */
+ memcpy(ek->emsk, fk + 96, 64); /* 64- extended Master Session Key */
+}
+
+
+void eapsim_dump_mk(struct eapsim_keys *ek)
+{
+ unsigned int i, j, k;
+
+ printf("Input was: \n");
+ printf(" identity: (len=%u)", ek->identitylen);
+ for (i = 0; i < ek->identitylen; i++) {
+ printf("%02x", ek->identity[i]);
+ }
+
+ printf("\n nonce_mt: ");
+ for (i = 0; i < EAPSIM_NONCEMT_SIZE; i++) {
+ printf("%02x", ek->nonce_mt[i]);
+ }
+
+ for (k = 0; k<3; k++) {
+ printf("\n rand%u: ", k);
+ for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+ printf("%02x", ek->rand[k][i]);
+ }
+ }
+
+ for (k = 0; k<3; k++) {
+ printf("\n sres%u: ", k);
+ for (i = 0; i < EAPSIM_SRES_SIZE; i++) {
+ printf("%02x", ek->sres[k][i]);
+ }
+ }
+
+ for (k = 0; k<3; k++) {
+ printf("\n Kc%u: ", k);
+ for (i = 0; i < EAPSIM_KC_SIZE; i++) {
+ printf("%02x", ek->Kc[k][i]);
+ }
+ }
+
+ printf("\n versionlist[%d]: ",ek->versionlistlen);
+ for (i = 0; i < ek->versionlistlen; i++) {
+ printf("%02x", ek->versionlist[i]);
+ }
+
+ printf("\n select %02x %02x\n",
+ ek->versionselect[0],
+ ek->versionselect[1]);
+
+ printf("\n\nOutput\n");
+
+ printf("mk: ");
+ j=0;
+ for (i = 0; i < sizeof(ek->master_key); i++) {
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ j++;
+
+ printf("%02x", ek->master_key[i]);
+ }
+
+ printf("\nK_aut: ");
+ j=0;
+ for (i = 0; i < sizeof(ek->K_aut); i++) {
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ j++;
+
+ printf("%02x", ek->K_aut[i]);
+ }
+
+ printf("\nK_encr: ");
+ j=0;
+ for (i = 0; i < sizeof(ek->K_encr); i++) {
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ j++;
+
+ printf("%02x", ek->K_encr[i]);
+ }
+
+ printf("\nmsk: ");
+ j=0; k=0;
+ for (i = 0; i < sizeof(ek->msk); i++) {
+ if(k==20) {
+ printf("\n ");
+ k=0;
+ j=0;
+ }
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ k++;
+ j++;
+
+ printf("%02x", ek->msk[i]);
+ }
+ printf("\nemsk: ");
+ j=0; k=0;
+ for (i = 0; i < sizeof(ek->emsk); i++) {
+ if(k==20) {
+ printf("\n ");
+ k=0;
+ j=0;
+ }
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ k++;
+ j++;
+
+ printf("%02x", ek->emsk[i]);
+ }
+ printf("\n");
+}
+
+#ifdef TEST_CASE
+
+#include <assert.h>
+
+struct eapsim_keys inputkey1 = {
+ {'e', 'a', 'p', 's','i','m' },
+ 6,
+ 0x4d, 0x6c, 0x40, 0xde, 0x48, 0x3a, 0xdd, 0x99, /* nonce_mt */
+ 0x50, 0x90, 0x2c, 0x40, 0x24, 0xce, 0x76, 0x5e,
+ 0x89, 0xab, 0xcd, 0xef, 0x89, 0xab, 0xcd, 0xef, /* chalX */
+ 0x89, 0xab, 0xcd, 0xef, 0x89, 0xab, 0xcd, 0xef,
+ 0x9a, 0xbc, 0xde, 0xf8, 0x9a, 0xbc, 0xde, 0xf8,
+ 0x9a, 0xbc, 0xde, 0xf8, 0x9a, 0xbc, 0xde, 0xf8,
+ 0xab, 0xcd, 0xef, 0x89, 0xab, 0xcd, 0xef, 0x89,
+ 0xab, 0xcd, 0xef, 0x89, 0xab, 0xcd, 0xef, 0x89,
+ 0x12, 0x34, 0xab, 0xcd, /* sresX */
+ 0x12, 0x34, 0xab, 0xcd,
+ 0x23, 0x4a, 0xbc, 0xd1,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, /* Kc */
+ 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+ 0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
+ {0x00, 0x02, 0x00, 0x01},
+ 4,
+ 0x00, 0x01 ,
+};
+
+struct eapsim_keys inputkey2 = {
+ {'1','2','4','4','0','7','0','1','0','0','0','0','0','0','0','1','@','e','a','p','s','i','m','.','f','o','o'},
+ 27,
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, /* nonce_mt */
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* chalX */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+
+ 0xd1, 0xd2, 0xd3, 0xd4, /* SRES 1 */
+ 0xe1, 0xe2, 0xe3, 0xe4,
+ 0xf1, 0xf2, 0xf3, 0xf4,
+
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* Kc */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ /* {0x00, 0x02, 0x00, 0x01}, */
+ {0x00, 0x01},
+ 2,
+ 0x00, 0x01 ,
+};
+
+
+
+main(int argc, char *argv[])
+{
+ struct eapsim_keys *ek;
+
+ ek = &inputkey1;
+
+ eapsim_calculate_keys(ek);
+ eapsim_dump_mk(ek);
+
+ ek = &inputkey2;
+
+ eapsim_calculate_keys(ek);
+ eapsim_dump_mk(ek);
+}
+#endif
+
+
+
+
+
+
+/*
+ * Local Variables:
+ * c-style: bsd
+ * End:
+ */
diff --git a/src/modules/rlm_eap/libeap/eapsimlib.c b/src/modules/rlm_eap/libeap/eapsimlib.c
new file mode 100644
index 0000000..67e21b2
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/eapsimlib.c
@@ -0,0 +1,508 @@
+/*
+ * eapsimlib.c based upon draft-haverinen-pppext-eap-sim-11.txt.
+ *
+ * The development of the EAP/SIM support was funded by Internet Foundation
+ * Austria (http://www.nic.at/ipa).
+ *
+ * code common to EAP-SIM clients and to servers.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000-2003,2006 The FreeRADIUS server project
+ * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ */
+
+/*
+ * EAP-SIM PACKET FORMAT
+ * ------- ------ ------
+ *
+ * EAP Request and Response Packet Format
+ * --- ------- --- -------- ------ ------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | SIM-Type | SIM-Length | value ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * with SIM-Type/SIM-Length/Value... repeating. SIM-Length is in units
+ * of 32 bits, and includes the Sim-Type/Sim-Length fields.
+ *
+ * The SIM-Type's are mapped to PW_EAP_SIM_BASE+Sim-type and
+ * unmapped by these functions.
+ *
+ */
+
+RCSID("$Id$")
+
+#include <freeradius-devel/libradius.h>
+#include "eap_types.h"
+#include "eap_sim.h"
+#include <freeradius-devel/sha1.h>
+
+/*
+ * given a radius request with many attributes in the EAP-SIM range, build
+ * them all into a single EAP-SIM body.
+ *
+ */
+int map_eapsim_basictypes(RADIUS_PACKET *r, eap_packet_t *ep)
+{
+ VALUE_PAIR *vp;
+ int encoded_size;
+ uint8_t *encodedmsg, *attr;
+ unsigned int id, eapcode;
+ uint8_t *macspace;
+ uint8_t const *append;
+ int appendlen;
+ unsigned char subtype;
+ vp_cursor_t cursor;
+
+ macspace = NULL;
+ append = NULL;
+ appendlen = 0;
+
+ /*
+ * encodedmsg is now an EAP-SIM message.
+ * it might be too big for putting into an EAP-Type-SIM
+ *
+ */
+ subtype = (vp = fr_pair_find_by_num(r->vps, PW_EAP_SIM_SUBTYPE, 0, TAG_ANY)) ?
+ vp->vp_integer : EAPSIM_START;
+
+ id = (vp = fr_pair_find_by_num(r->vps, PW_EAP_ID, 0, TAG_ANY)) ?
+ vp->vp_integer : ((int)getpid() & 0xff);
+
+ eapcode = (vp = fr_pair_find_by_num(r->vps, PW_EAP_CODE, 0, TAG_ANY)) ?
+ vp->vp_integer : PW_EAP_REQUEST;
+
+ /*
+ * take a walk through the attribute list to see how much space
+ * that we need to encode all of this.
+ */
+ encoded_size = 0;
+ for (vp = fr_cursor_init(&cursor, &r->vps);
+ vp;
+ vp = fr_cursor_next(&cursor)) {
+ int roundedlen;
+ int vplen;
+
+ if ((vp->da->attr < PW_EAP_SIM_BASE) || (vp->da->attr >= (PW_EAP_SIM_BASE + 256))) {
+ continue;
+ }
+
+ vplen = vp->vp_length;
+
+ /*
+ * the AT_MAC attribute is a bit different, when we get to this
+ * attribute, we pull the contents out, save it for later
+ * processing, set the size to 16 bytes (plus 2 bytes padding).
+ *
+ * At this point, we only care about the size.
+ */
+ if(vp->da->attr == PW_EAP_SIM_MAC) {
+ vplen = 18;
+ }
+
+ /* round up to next multiple of 4, after taking in
+ * account the type and length bytes
+ */
+ roundedlen = (vplen + 2 + 3) & ~3;
+ encoded_size += roundedlen;
+ }
+
+ if (ep->code != PW_EAP_SUCCESS) {
+ ep->code = eapcode;
+ }
+
+ ep->id = (id & 0xff);
+ ep->type.num = PW_EAP_SIM;
+
+ /*
+ * if no attributes were found, do very little.
+ *
+ */
+ if (encoded_size == 0) {
+ encodedmsg = talloc_array(ep, uint8_t, 3);
+ /* FIX: could be NULL */
+
+ encodedmsg[0] = subtype;
+ encodedmsg[1] = 0;
+ encodedmsg[2] = 0;
+
+ ep->type.length = 3;
+ ep->type.data = encodedmsg;
+
+ return 1;
+ }
+
+
+ /*
+ * figured out the length, so allocate some space for the results.
+ *
+ * Note that we do not bother going through an "EAP" stage, which
+ * is a bit strange compared to the unmap, which expects to see
+ * an EAP-SIM virtual attributes.
+ *
+ * EAP is 1-code, 1-identifier, 2-length, 1-type = 5 overhead.
+ *
+ * SIM code adds a subtype, and 2 bytes of reserved = 3.
+ *
+ */
+ encoded_size += 3;
+ encodedmsg = talloc_array(ep, uint8_t, encoded_size);
+ if (!encodedmsg) {
+ return 0;
+ }
+ memset(encodedmsg, 0, encoded_size);
+
+ /*
+ * now walk the attributes again, sticking them in.
+ *
+ * we go three bytes into the encoded message, because there are two
+ * bytes of reserved, and we will fill the "subtype" in later.
+ *
+ */
+ attr = encodedmsg+3;
+
+ for (vp = fr_cursor_first(&cursor); vp; vp = fr_cursor_next(&cursor)) {
+ int roundedlen;
+
+ if(vp->da->attr < PW_EAP_SIM_BASE ||
+ vp->da->attr >= PW_EAP_SIM_BASE + 256) {
+ continue;
+ }
+
+ /*
+ * the AT_MAC attribute is a bit different, when we get to this
+ * attribute, we pull the contents out, save it for later
+ * processing, set the size to 16 bytes (plus 2 bytes padding).
+ *
+ * At this point, we put in zeros, and remember where the
+ * sixteen bytes go.
+ */
+ if(vp->da->attr == PW_EAP_SIM_MAC) {
+ roundedlen = 20;
+ memset(&attr[2], 0, 18);
+ macspace = &attr[4];
+ append = vp->vp_octets;
+ appendlen = vp->vp_length;
+ } else {
+ roundedlen = (vp->vp_length + 2 + 3) & ~3;
+ memset(attr, 0, roundedlen);
+ memcpy(&attr[2], vp->vp_strvalue, vp->vp_length);
+ }
+ attr[0] = vp->da->attr - PW_EAP_SIM_BASE;
+ attr[1] = roundedlen >> 2;
+
+ attr += roundedlen;
+ }
+
+ encodedmsg[0] = subtype;
+
+ ep->type.length = encoded_size;
+ ep->type.data = encodedmsg;
+
+ /*
+ * if macspace was set and we have a key,
+ * then we should calculate the HMAC-SHA1 of the resulting EAP-SIM
+ * packet, appended with the value of append.
+ */
+ vp = fr_pair_find_by_num(r->vps, PW_EAP_SIM_KEY, 0, TAG_ANY);
+ if(macspace != NULL && vp != NULL) {
+ unsigned char *buffer;
+ eap_packet_raw_t *hdr;
+ uint16_t hmaclen, total_length = 0;
+ unsigned char sha1digest[20];
+
+ total_length = EAP_HEADER_LEN + 1 + encoded_size;
+ hmaclen = total_length + appendlen;
+ buffer = talloc_array(r, uint8_t, hmaclen);
+ hdr = (eap_packet_raw_t *) buffer;
+ if (!hdr) {
+ talloc_free(encodedmsg);
+ return 0;
+ }
+
+ hdr->code = eapcode & 0xFF;
+ hdr->id = (id & 0xFF);
+ total_length = htons(total_length);
+ memcpy(hdr->length, &total_length, sizeof(total_length));
+
+ hdr->data[0] = PW_EAP_SIM;
+
+ /* copy the data */
+ memcpy(&hdr->data[1], encodedmsg, encoded_size);
+
+ /* copy the nonce */
+ memcpy(&hdr->data[encoded_size+1], append, appendlen);
+
+ /* HMAC it! */
+ fr_hmac_sha1(sha1digest, buffer, hmaclen, vp->vp_octets, vp->vp_length);
+
+ /* done with the buffer, free it */
+ talloc_free(buffer);
+
+ /* now copy the digest to where it belongs in the AT_MAC */
+ /* note that it is truncated to 128-bits */
+ memcpy(macspace, sha1digest, 16);
+ }
+
+ /* if we had an AT_MAC and no key, then fail */
+ if ((macspace != NULL) && !vp) {
+ if (encodedmsg != NULL) {
+ talloc_free(encodedmsg);
+ }
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * given a radius request with an EAP-SIM body, decode it into TLV pairs
+ *
+ * return value is true if it succeeded, false if there was something
+ * wrong and the packet should be discarded.
+ *
+ */
+int unmap_eapsim_basictypes(RADIUS_PACKET *r,
+ uint8_t *attr, unsigned int attrlen)
+{
+ VALUE_PAIR *newvp;
+ int eapsim_attribute;
+ unsigned int eapsim_len;
+ int es_attribute_count;
+
+ es_attribute_count = 0;
+
+ /* big enough to have even a single attribute */
+ if (attrlen < 5) {
+ fr_strerror_printf("EAP-Sim attribute too short: %d < 5", attrlen);
+ return 0;
+ }
+
+ newvp = fr_pair_afrom_num(r, PW_EAP_SIM_SUBTYPE, 0);
+ if (!newvp) {
+ fr_strerror_printf("Failed creating EAP-SIM-Subtype");
+ return 0;
+ }
+
+ newvp->vp_integer = attr[0];
+ newvp->vp_length = 1;
+ fr_pair_add(&(r->vps), newvp);
+
+ /*
+ * EAP-SIM has a 1 octet of subtype, and 2 octets
+ * reserved.
+ */
+ attr += 3;
+ attrlen -= 3;
+
+ /*
+ * Loop over each attribute. The format is:
+ *
+ * 1 octet of type
+ * 1 octet of length (value 1..255)
+ * ((4 * length) - 2) octets of data.
+ */
+ while (attrlen > 0) {
+ uint8_t *p;
+
+ if (attrlen < 2) {
+ fr_strerror_printf("EAP-Sim attribute %d too short: %d < 2", es_attribute_count, attrlen);
+ return 0;
+ }
+
+ if (!attr[1]) {
+ fr_strerror_printf("EAP-Sim attribute %d (no.%d) has no data", attr[0],
+ es_attribute_count);
+ return 0;
+ }
+
+ eapsim_attribute = attr[0];
+ eapsim_len = attr[1] * 4;
+
+ /*
+ * The length includes the 2-byte header.
+ */
+ if (eapsim_len > attrlen) {
+ fr_strerror_printf("EAP-Sim attribute %d (no.%d) has length longer than data (%d > %d)",
+ eapsim_attribute, es_attribute_count, eapsim_len, attrlen);
+ return 0;
+ }
+
+ newvp = fr_pair_afrom_num(r, eapsim_attribute + PW_EAP_SIM_BASE, 0);
+ if (!newvp) {
+ /*
+ * RFC 4186 Section 8.1 says 0..127 are
+ * "non-skippable". If one such
+ * attribute is found and we don't
+ * understand it, the server has to send:
+ *
+ * EAP-Request/SIM/Notification packet with an
+ * (AT_NOTIFICATION code, which implies general failure ("General
+ * failure after authentication" (0), or "General failure" (16384),
+ * depending on the phase of the exchange), which terminates the
+ * authentication exchange.
+ */
+ if (eapsim_attribute <= 127) {
+ fr_strerror_printf("Unknown mandatory attribute %d, failing",
+ eapsim_attribute);
+ return 0;
+ }
+
+ } else {
+ /*
+ * It's known, ccount for header, and
+ * copy the value over.
+ */
+ newvp->vp_length = eapsim_len - 2;
+
+ newvp->vp_octets = p = talloc_array(newvp, uint8_t, newvp->vp_length);
+ memcpy(p, &attr[2], newvp->vp_length);
+ fr_pair_add(&(r->vps), newvp);
+ }
+
+ /* advance pointers, decrement length */
+ attr += eapsim_len;
+ attrlen -= eapsim_len;
+ es_attribute_count++;
+ }
+
+ return 1;
+}
+
+/*
+ * calculate the MAC for the EAP message, given the key.
+ * The "extra" will be appended to the EAP message and included in the
+ * HMAC.
+ *
+ */
+int eapsim_checkmac(TALLOC_CTX *ctx, VALUE_PAIR *rvps, uint8_t key[EAPSIM_AUTH_SIZE], uint8_t *extra, int extralen,
+ uint8_t calcmac[20])
+{
+ int ret;
+ eap_packet_raw_t *e;
+ uint8_t *buffer;
+ int elen,len;
+ VALUE_PAIR *mac;
+
+ mac = fr_pair_find_by_num(rvps, PW_EAP_SIM_MAC, 0, TAG_ANY);
+
+ if(!mac || mac->vp_length != 18) {
+ /* can't check a packet with no AT_MAC attribute */
+ return 0;
+ }
+
+ /* get original copy of EAP message, note that it was sanitized
+ * to have a valid length, which we depend upon.
+ */
+ e = eap_vp2packet(ctx, rvps);
+ if (!e) return 0;
+
+ /* make copy big enough for everything */
+ elen = (e->length[0] * 256) + e->length[1];
+ len = elen + extralen;
+
+ buffer = talloc_array(ctx, uint8_t, len);
+ if (!buffer) {
+ talloc_free(e);
+ return 0;
+ }
+
+ memcpy(buffer, e, elen);
+ memcpy(buffer + elen, extra, extralen);
+
+ /*
+ * now look for the AT_MAC attribute in the copy of the buffer
+ * and make sure that the checksum is zero.
+ *
+ */
+ {
+ uint8_t *attr;
+
+ /* first attribute is 8 bytes into the EAP packet.
+ * 4 bytes for EAP, 1 for type, 1 for subtype, 2 reserved.
+ */
+ attr = buffer+8;
+ while(attr < (buffer+elen)) {
+ if (attr[0] == (PW_EAP_SIM_MAC - PW_EAP_SIM_BASE)) {
+ /* zero the data portion, after making sure
+ * the size is >=5. Maybe future versions.
+ * will use more bytes, so be liberal.
+ */
+ if(attr[1] < 5) {
+ ret = 0;
+ goto done;
+ }
+ memset(&attr[4], 0, (attr[1]-1)*4);
+ }
+ /* advance the pointer */
+ attr += attr[1]*4;
+ }
+ }
+
+ /* now, HMAC-SHA1 it with the key. */
+ fr_hmac_sha1(calcmac, buffer, len, key, 16);
+
+ ret = memcmp(&mac->vp_strvalue[2], calcmac, 16) == 0 ? 1 : 0;
+ done:
+ talloc_free(e);
+ talloc_free(buffer);
+ return(ret);
+}
+
+/*
+ * definitions changed to take a buffer for unknowns
+ * as this is more thread safe.
+ */
+static char const *simstates[] = { "init", "start", NULL };
+
+char const *sim_state2name(enum eapsim_clientstates state,
+ char *statenamebuf,
+ int statenamebuflen)
+{
+ if(state >= EAPSIM_CLIENT_MAXSTATES) {
+ snprintf(statenamebuf, statenamebuflen, "eapstate:%d", state);
+ return statenamebuf;
+ }
+
+ return simstates[state];
+}
+
+static char const *subtypes[] = { "subtype0", "subtype1", "subtype2", "subtype3",
+ "subtype4", "subtype5", "subtype6", "subtype7",
+ "subtype8", "subtype9",
+ "start",
+ "challenge",
+ "notification",
+ "reauth",
+ "client-error",
+ NULL };
+
+char const *sim_subtype2name(enum eapsim_subtype subtype, char *subtypenamebuf, int subtypenamebuflen)
+{
+ if (subtype >= EAPSIM_MAX_SUBTYPE) {
+ snprintf(subtypenamebuf, subtypenamebuflen, "illegal-subtype:%d", subtype);
+
+ return subtypenamebuf;
+ }
+
+ return subtypes[subtype];
+}
diff --git a/src/modules/rlm_eap/libeap/fips186prf.c b/src/modules/rlm_eap/libeap/fips186prf.c
new file mode 100644
index 0000000..2002c62
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/fips186prf.c
@@ -0,0 +1,270 @@
+/*
+ * fips186prf.c An implementation of the FIPS-186-2 SHA1-based PRF.
+ *
+ * The development of the EAP/SIM support was funded by Internet Foundation
+ * Austria (http://www.nic.at/ipa).
+ *
+ * This code was written from scratch by Michael Richardson, and it is
+ * dual licensed under both GPL and BSD.
+ *
+ * Version: $Id$
+ *
+ * GPL notice:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * BSD notice:
+ *
+ * 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 The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ * Copyright 2006 The FreeRADIUS server project
+ *
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include <freeradius-devel/sha1.h>
+
+/*
+ * we do it in 8-bit chunks, because we have to keep the numbers
+ * in network byte order (i.e. MSB)
+ *
+ * make it a structure so that we can do structure assignments.
+ */
+typedef struct onesixty {
+ uint8_t p[20];
+} onesixty;
+
+static void onesixty_add_mod(onesixty *sum, onesixty *a, onesixty *b)
+{
+ uint32_t s;
+ int i, carry;
+
+ carry = 0;
+ for(i=19; i>=0; i--) {
+/* for(i=0; i<20; i++) { */
+ s = a->p[i] + b->p[i] + carry;
+ sum->p[i] = s & 0xff;
+ carry = s >> 8;
+ }
+}
+
+/*
+ * run the FIPS-186-2 PRF on the given Master Key (160 bits)
+ * in order to derive 1280 bits (160 bytes) of keying data from
+ * it.
+ *
+ * Given that in EAP-SIM, this is coming from a 64-bit Kc it seems
+ * like an awful lot of "randomness" to pull out.. (MCR)
+ *
+ */
+void fips186_2prf(uint8_t mk[20], uint8_t finalkey[160])
+{
+ fr_sha1_ctx context;
+ int j;
+ onesixty xval, xkey, w_0, w_1, sum, one;
+ uint8_t *f;
+ uint8_t zeros[64];
+
+ /*
+ * let XKEY := MK,
+ *
+ * Step 3: For j = 0 to 3 do
+ * a. XVAL = XKEY
+ * b. w_0 = SHA1(XVAL)
+ * c. XKEY = (1 + XKEY + w_0) mod 2^160
+ * d. XVAL = XKEY
+ * e. w_1 = SHA1(XVAL)
+ * f. XKEY = (1 + XKEY + w_1) mod 2^160
+ * 3.3 x_j = w_0|w_1
+ *
+ */
+ memcpy(&xkey, mk, sizeof(xkey));
+
+ /* make the value 1 */
+ memset(&one, 0, sizeof(one));
+ one.p[19]=1;
+
+ f=finalkey;
+
+ for(j=0; j<4; j++) {
+ /* a. XVAL = XKEY */
+ xval = xkey;
+
+ /* b. w_0 = SHA1(XVAL) */
+ fr_sha1_init(&context);
+
+ memset(zeros + 20, 0, sizeof(zeros) - 20);
+ memcpy(zeros, xval.p, 20);
+#ifndef WITH_OPENSSL_SHA1
+ fr_sha1_transform(context.state, zeros);
+#else
+ fr_sha1_transform(&context, zeros);
+#endif
+ fr_sha1_final_no_len(w_0.p, &context);
+
+ /* c. XKEY = (1 + XKEY + w_0) mod 2^160 */
+ onesixty_add_mod(&sum, &xkey, &w_0);
+ onesixty_add_mod(&xkey, &sum, &one);
+
+ /* d. XVAL = XKEY */
+ xval = xkey;
+
+ /* e. w_1 = SHA1(XVAL) */
+ fr_sha1_init(&context);
+
+ memset(zeros + 20, 0, sizeof(zeros) - 20);
+ memcpy(zeros, xval.p, 20);
+#ifndef WITH_OPENSSL_SHA1
+ fr_sha1_transform(context.state, zeros);
+#else
+ fr_sha1_transform(&context, zeros);
+#endif
+ fr_sha1_final_no_len(w_1.p, &context);
+
+ /* f. XKEY = (1 + XKEY + w_1) mod 2^160 */
+ onesixty_add_mod(&sum, &xkey, &w_1);
+ onesixty_add_mod(&xkey, &sum, &one);
+
+ /* now store it away */
+ memcpy(f, &w_0, 20);
+ f += 20;
+
+ memcpy(f, &w_1, 20);
+ f += 20;
+ }
+}
+
+/*
+ * test vectors
+ * from http://csrc.nist.gov/CryptoToolkit/dss/Examples-1024bit.pdf
+ *
+ * page 5
+ *
+ * XKEY= bd029bbe 7f51960b cf9edb2b 61f06f0f eb5a38b6
+ * XSEED= 00000000 00000000 00000000 00000000 00000000
+ *
+ *
+ * The first loop through step 3.2 provides:
+ *
+ * XVAL= bd029bbe 7f51960b cf9edb2b 61f06f0f eb5a38b6
+ *
+ * Using the routine in Appendix 3.3, Constructing The Function G From SHA-1,
+ * in step 3.2.b of the Change Notice algorithm for computing values of x
+ * provides:
+ *
+ * w[0]= 2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614
+ *
+ *
+ * The following value is the updated XKEY value from step 3.2.c:
+ *
+ * XKEY= dd734ee0 bd0bcd3b adbaeb27 dd1eaa59 76803ecb
+ *
+ * The second loop through step 3.2 provides:
+ *
+ * XVAL= dd734ee0 bd0bcd3b adbaeb27 dd1eaa59 76803ecb
+ *
+ * Using the routine in Appendix 3.3, Constructing The Function G From SHA-1,
+ * in step 3.2.b of the Change Notice algorithm for computing values of x
+ * provides:
+ *
+ * w[1]= 3c6c18ba cb0f6c55 babb1378 8e20d737 a3275116
+ *
+ * The following value is the updated XKEY value from step 3.2.c:
+ *
+ *
+ * XKEY= 19df679b 881b3991 6875fea0 6b3f8191 19a78fe2
+ *
+ * Step 3.3 provides the following values:
+ *
+ * w[0] || w[1]= 2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614
+ * 3c6c18ba cb0f6c55 babb1378 8e20d737 a3275116
+ *
+ */
+
+#ifdef TEST_CASE
+
+#include <assert.h>
+
+uint8_t mk[20]={ 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
+ 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
+ 0xeb, 0x5a, 0x38, 0xb6 };
+
+main(int argc, char *argv[])
+{
+ uint8_t finalkey[160];
+ int i, j, k;
+
+ fips186_2prf(mk, finalkey);
+
+ printf("Input was: |");
+ j=0;
+ for (i = 0; i < 20; i++) {
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ j++;
+
+ printf("%02x", mk[i]);
+ }
+
+ printf("|\nOutput was: ");
+ j=0; k=0;
+ for (i = 0; i < 160; i++) {
+ if(k==20) {
+ printf("\n ");
+ k=0;
+ j=0;
+ }
+ if(j==4) {
+ printf("_");
+ j=0;
+ }
+ k++;
+ j++;
+
+ printf("%02x", finalkey[i]);
+ }
+ printf("\n");
+}
+#endif
diff --git a/src/modules/rlm_eap/libeap/mppe_keys.c b/src/modules/rlm_eap/libeap/mppe_keys.c
new file mode 100644
index 0000000..385441c
--- /dev/null
+++ b/src/modules/rlm_eap/libeap/mppe_keys.c
@@ -0,0 +1,384 @@
+/*
+ * mppe_keys.c
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2002 Axis Communications AB
+ * Copyright 2006 The FreeRADIUS server project
+ * Authors: Henrik Eriksson <henriken@axis.com> & Lars Viklund <larsv@axis.com>
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include "eap_tls.h"
+#include <openssl/ssl.h>
+#include <openssl/hmac.h>
+#include <freeradius-devel/openssl3.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+#endif
+
+/*
+ * TLS P_hash from RFC 2246/5246 section 5
+ */
+static void P_hash(EVP_MD const *evp_md,
+ unsigned char const *secret, unsigned int secret_len,
+ unsigned char const *seed, unsigned int seed_len,
+ unsigned char *out, unsigned int out_len)
+{
+ HMAC_CTX *ctx_a, *ctx_out;
+ unsigned char a[EVP_MAX_MD_SIZE];
+ unsigned int size = EVP_MAX_MD_SIZE;
+ unsigned int digest_len;
+
+ ctx_a = HMAC_CTX_new();
+ ctx_out = HMAC_CTX_new();
+ HMAC_Init_ex(ctx_a, secret, secret_len, evp_md, NULL);
+ HMAC_Init_ex(ctx_out, secret, secret_len, evp_md, NULL);
+
+ /* Calculate A(1) */
+ HMAC_Update(ctx_a, seed, seed_len);
+ HMAC_Final(ctx_a, a, &size);
+
+ while (1) {
+ /* Calculate next part of output */
+ HMAC_Update(ctx_out, a, size);
+ HMAC_Update(ctx_out, seed, seed_len);
+
+ /* Check if last part */
+ if (out_len < size) {
+ digest_len = EVP_MAX_MD_SIZE;
+ HMAC_Final(ctx_out, a, &digest_len);
+ memcpy(out, a, out_len);
+ break;
+ }
+
+ /* Place digest in output buffer */
+ digest_len = EVP_MAX_MD_SIZE;
+ HMAC_Final(ctx_out, out, &digest_len);
+ HMAC_Init_ex(ctx_out, NULL, 0, NULL, NULL);
+ out += size;
+ out_len -= size;
+
+ /* Calculate next A(i) */
+ HMAC_Init_ex(ctx_a, NULL, 0, NULL, NULL);
+ HMAC_Update(ctx_a, a, size);
+ digest_len = EVP_MAX_MD_SIZE;
+ HMAC_Final(ctx_a, a, &digest_len);
+ }
+
+ HMAC_CTX_free(ctx_a);
+ HMAC_CTX_free(ctx_out);
+ memset(a, 0, sizeof(a));
+}
+
+/*
+ * TLS PRF from RFC 2246 section 5
+ */
+static void PRF(unsigned char const *secret, unsigned int secret_len,
+ unsigned char const *seed, unsigned int seed_len,
+ unsigned char *out, unsigned int out_len)
+{
+ uint8_t buf[out_len + (out_len % SHA_DIGEST_LENGTH)];
+ unsigned int i;
+
+ unsigned int len = (secret_len + 1) / 2;
+ uint8_t const *s1 = secret;
+ uint8_t const *s2 = secret + (secret_len - len);
+
+ EVP_MD const *md5 = NULL;
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MD *md5_to_free = NULL;
+
+ /*
+ * If we are using OpenSSL >= 3.0 and FIPS mode is
+ * enabled, we need to load the default provider in a
+ * standalone context in order to access MD5.
+ */
+ OSSL_LIB_CTX *libctx = NULL;
+ OSSL_PROVIDER *default_provider = NULL;
+
+ if (EVP_default_properties_is_fips_enabled(NULL)) {
+ libctx = OSSL_LIB_CTX_new();
+ default_provider = OSSL_PROVIDER_load(libctx, "default");
+
+ if (!default_provider) {
+ ERROR("Failed loading OpenSSL default provider.");
+ return;
+ }
+
+ md5_to_free = EVP_MD_fetch(libctx, "MD5", NULL);
+ if (!md5_to_free) {
+ ERROR("Failed loading OpenSSL MD5 function.");
+ return;
+ }
+
+ md5 = md5_to_free;
+ } else {
+ md5 = EVP_md5();
+ }
+#else
+ md5 = EVP_md5();
+#endif
+
+ P_hash(md5, s1, len, seed, seed_len, out, out_len);
+ P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len);
+
+ for (i = 0; i < out_len; i++) {
+ out[i] ^= buf[i];
+ }
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ if (libctx) {
+ OSSL_PROVIDER_unload(default_provider);
+ OSSL_LIB_CTX_free(libctx);
+ EVP_MD_free(md5_to_free);
+ }
+#endif
+}
+
+/*
+ * TLS 1.2 PRF from RFC 5246 section 5
+ */
+static void PRFv12(unsigned char const *secret, unsigned int secret_len,
+ unsigned char const *seed, unsigned int seed_len,
+ unsigned char *out, unsigned int out_len)
+{
+ P_hash(EVP_sha256(), secret, secret_len, seed, seed_len, out, out_len);
+}
+
+/* EAP-FAST Pseudo-Random Function (T-PRF): RFC 4851, Section 5.5 */
+void T_PRF(unsigned char const *secret, unsigned int secret_len,
+ char const *prf_label,
+ unsigned char const *seed, unsigned int seed_len,
+ unsigned char *out, unsigned int out_len)
+{
+ size_t prf_size = strlen(prf_label);
+ size_t pos;
+ uint8_t *buf;
+
+ if (prf_size > 128) prf_size = 128;
+ prf_size++; /* include trailing zero */
+
+ buf = talloc_size(NULL, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1);
+
+ memcpy(buf + SHA1_DIGEST_LENGTH, prf_label, prf_size);
+ if (seed) memcpy(buf + SHA1_DIGEST_LENGTH + prf_size, seed, seed_len);
+ *(uint16_t *)&buf[SHA1_DIGEST_LENGTH + prf_size + seed_len] = htons(out_len);
+ buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2] = 1;
+
+ // T1 is just the seed
+ fr_hmac_sha1(buf, buf + SHA1_DIGEST_LENGTH, prf_size + seed_len + 2 + 1, secret, secret_len);
+
+#define MIN(a,b) (((a)>(b)) ? (b) : (a))
+ memcpy(out, buf, MIN(out_len, SHA1_DIGEST_LENGTH));
+
+ pos = SHA1_DIGEST_LENGTH;
+ while (pos < out_len) {
+ buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2]++;
+
+ fr_hmac_sha1(buf, buf, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1, secret, secret_len);
+ memcpy(&out[pos], buf, MIN(out_len - pos, SHA1_DIGEST_LENGTH));
+
+ if (out_len - pos <= SHA1_DIGEST_LENGTH)
+ break;
+
+ pos += SHA1_DIGEST_LENGTH;
+ }
+
+ memset(buf, 0, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1);
+ talloc_free(buf);
+}
+
+#define EAPTLS_MPPE_KEY_LEN 32
+
+/*
+ * Generate keys according to RFC 2716 and add to reply
+ */
+void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size)
+{
+ uint8_t out[4 * EAPTLS_MPPE_KEY_LEN];
+ uint8_t *p;
+ size_t len;
+
+ len = strlen(label);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ if (SSL_export_keying_material(s, out, sizeof(out), label, len, context, context_size, context != NULL) != 1) {
+ ERROR("Failed generating keying material");
+ return;
+ }
+#else
+ {
+ uint8_t seed[64 + (2 * SSL3_RANDOM_SIZE) + (context ? 2 + context_size : 0)];
+ uint8_t buf[4 * EAPTLS_MPPE_KEY_LEN];
+
+ p = seed;
+
+ memcpy(p, label, len);
+ p += len;
+
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+ len += SSL3_RANDOM_SIZE;
+
+ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+ len += SSL3_RANDOM_SIZE;
+
+ if (context) {
+ /* cloned and reversed FR_PUT_LE16 */
+ p[0] = ((uint16_t) (context_size)) >> 8;
+ p[1] = ((uint16_t) (context_size)) & 0xff;
+ p += 2;
+ len += 2;
+ memcpy(p, context, context_size);
+ p += context_size;
+ len += context_size;
+ }
+
+ PRF(s->session->master_key, s->session->master_key_length,
+ seed, len, out, buf, sizeof(out));
+ }
+#endif
+
+ p = out;
+ eap_add_reply(request, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN);
+ p += EAPTLS_MPPE_KEY_LEN;
+ eap_add_reply(request, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN);
+
+ eap_add_reply(request, "EAP-MSK", out, 64);
+ eap_add_reply(request, "EAP-EMSK", out + 64, 64);
+}
+
+
+#define FR_TLS_PRF_CHALLENGE "ttls challenge"
+
+/*
+ * Generate the TTLS challenge
+ *
+ * It's in the TLS module simply because it's only a few lines
+ * of code, and it needs access to the TLS PRF functions.
+ */
+void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ if (SSL_export_keying_material(s, buffer, size, FR_TLS_PRF_CHALLENGE,
+ sizeof(FR_TLS_PRF_CHALLENGE)-1, NULL, 0, 0) != 1) {
+ ERROR("Failed generating keying material");
+ }
+#else
+ uint8_t out[32], buf[32];
+ uint8_t seed[sizeof(FR_TLS_PRF_CHALLENGE)-1 + 2*SSL3_RANDOM_SIZE];
+ uint8_t *p = seed;
+
+ memcpy(p, FR_TLS_PRF_CHALLENGE, sizeof(FR_TLS_PRF_CHALLENGE)-1);
+ p += sizeof(FR_TLS_PRF_CHALLENGE)-1;
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
+
+ PRF(s->session->master_key, s->session->master_key_length,
+ seed, sizeof(seed), out, buf, sizeof(out));
+ memcpy(buffer, out, size);
+#endif
+}
+
+#define FR_TLS_EXPORTER_METHOD_ID "EXPORTER_EAP_TLS_Method-Id"
+
+/*
+ * Actually generates EAP-Session-Id, which is an internal server
+ * attribute. Not all systems want to send EAP-Key-Name.
+ */
+void eaptls_gen_eap_key(eap_handler_t *handler)
+{
+ RADIUS_PACKET *packet = handler->request->reply;
+ tls_session_t *tls_session = handler->opaque;
+ SSL *s = tls_session->ssl;
+ VALUE_PAIR *vp;
+ uint8_t *buff, *p;
+ uint8_t type = handler->type & 0xff;
+
+ vp = fr_pair_afrom_num(packet, PW_EAP_SESSION_ID, 0);
+ if (!vp) return;
+
+ vp->vp_length = 1 + 2 * SSL3_RANDOM_SIZE;
+ buff = p = talloc_array(vp, uint8_t, vp->vp_length);
+
+ *p++ = type;
+
+ switch (SSL_version(tls_session->ssl)) {
+ case TLS1_VERSION:
+ case TLS1_1_VERSION:
+ case TLS1_2_VERSION:
+ SSL_get_client_random(s, p, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+ SSL_get_server_random(s, p, SSL3_RANDOM_SIZE);
+ break;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#ifdef TLS1_3_VERSION
+ case TLS1_3_VERSION:
+#endif
+ default:
+ {
+ uint8_t const context[] = { type };
+
+ if (SSL_export_keying_material(s, p, 2 * SSL3_RANDOM_SIZE,
+ FR_TLS_EXPORTER_METHOD_ID, sizeof(FR_TLS_EXPORTER_METHOD_ID)-1,
+ context, sizeof(context), 1) != 1) {
+ ERROR("Failed generating keying material");
+ return;
+ }
+ }
+#endif
+ }
+
+ vp->vp_octets = buff;
+ fr_pair_add(&packet->vps, vp);
+}
+
+/*
+ * Same as before, but for EAP-FAST the order of {server,client}_random is flipped
+ */
+void eap_fast_tls_gen_challenge(SSL *s, int version, uint8_t *buffer, size_t size, char const *prf_label)
+{
+ uint8_t *p;
+ size_t len, master_key_len;
+ uint8_t seed[128 + 2*SSL3_RANDOM_SIZE];
+ uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH];
+
+ len = strlen(prf_label);
+ if (len > 128) len = 128;
+
+ p = seed;
+ memcpy(p, prf_label, len);
+ p += len;
+ SSL_get_server_random(s, p, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+ SSL_get_client_random(s, p, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+
+ master_key_len = SSL_SESSION_get_master_key(SSL_get_session(s), master_key, sizeof(master_key));
+
+ if (version == TLS1_2_VERSION)
+ PRFv12(master_key, master_key_len, seed, p - seed, buffer, size);
+ else
+ PRF(master_key, master_key_len, seed, p - seed, buffer, size);
+}
diff --git a/src/modules/rlm_eap/mem.c b/src/modules/rlm_eap/mem.c
new file mode 100644
index 0000000..6be8ca4
--- /dev/null
+++ b/src/modules/rlm_eap/mem.c
@@ -0,0 +1,503 @@
+/*
+ * mem.c Memory allocation, deallocation stuff.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000,2001,2006 The FreeRADIUS server project
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include "rlm_eap.h"
+
+#ifdef WITH_TLS
+#include <freeradius-devel/tls.h>
+#endif
+
+#ifdef HAVE_PTHREAD_H
+#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
+#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
+#else
+#define PTHREAD_MUTEX_LOCK(_x)
+#define PTHREAD_MUTEX_UNLOCK(_x)
+#endif
+
+/*
+ * Allocate a new eap_packet_t
+ */
+EAP_DS *eap_ds_alloc(eap_handler_t *handler)
+{
+ EAP_DS *eap_ds;
+
+ eap_ds = talloc_zero(handler, EAP_DS);
+ eap_ds->response = talloc_zero(eap_ds, eap_packet_t);
+ if (!eap_ds->response) {
+ eap_ds_free(&eap_ds);
+ return NULL;
+ }
+ eap_ds->request = talloc_zero(eap_ds, eap_packet_t);
+ if (!eap_ds->response) {
+ eap_ds_free(&eap_ds);
+ return NULL;
+ }
+
+ return eap_ds;
+}
+
+void eap_ds_free(EAP_DS **eap_ds_p)
+{
+ EAP_DS *eap_ds;
+
+ if (!eap_ds_p) return;
+
+ eap_ds = *eap_ds_p;
+ if (!eap_ds) return;
+
+ if (eap_ds->response) talloc_free(eap_ds->response);
+ if (eap_ds->request) talloc_free(eap_ds->request);
+
+ talloc_free(eap_ds);
+ *eap_ds_p = NULL;
+}
+
+static int _eap_handler_free(eap_handler_t *handler)
+{
+ if (handler->identity) {
+ talloc_free(handler->identity);
+ handler->identity = NULL;
+ }
+
+ if (handler->prev_eapds) eap_ds_free(&(handler->prev_eapds));
+ if (handler->eap_ds) eap_ds_free(&(handler->eap_ds));
+
+ if ((handler->opaque) && (handler->free_opaque)) {
+ handler->free_opaque(handler->opaque);
+ handler->opaque = NULL;
+ }
+
+ handler->opaque = NULL;
+ handler->free_opaque = NULL;
+
+ /*
+ * Give helpful debug messages if:
+ *
+ * we're debugging TLS sessions, which don't finish,
+ * and which aren't deleted early due to a likely RADIUS
+ * retransmit which nukes our ID, and therefore our stare.
+ */
+ if (fr_debug_lvl && handler->tls && !handler->finished &&
+ (time(NULL) > (handler->timestamp + 3))) {
+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ WARN("!! EAP session with state 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x did not finish! !!",
+ handler->state[0], handler->state[1],
+ handler->state[2], handler->state[3],
+ handler->state[4], handler->state[5],
+ handler->state[6], handler->state[7],
+ handler->state[8], handler->state[9],
+ handler->state[10], handler->state[11],
+ handler->state[12], handler->state[13],
+ handler->state[14], handler->state[15]);
+
+ WARN("!! Please read http://wiki.freeradius.org/guide/Certificate_Compatibility !!");
+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ }
+
+ return 0;
+}
+
+/*
+ * Allocate a new eap_handler_t
+ */
+eap_handler_t *eap_handler_alloc(rlm_eap_t *inst)
+{
+ eap_handler_t *handler;
+
+ handler = talloc_zero(NULL, eap_handler_t);
+ if (!handler) {
+ ERROR("Failed allocating handler");
+ return NULL;
+ }
+ handler->inst_holder = inst;
+
+ /* Doesn't need to be inside the critical region */
+ talloc_set_destructor(handler, _eap_handler_free);
+
+ return handler;
+}
+
+
+void eaplist_free(rlm_eap_t *inst)
+{
+ eap_handler_t *node, *next;
+
+ for (node = inst->session_head; node != NULL; node = next) {
+ next = node->next;
+ talloc_free(node);
+ }
+
+ inst->session_head = inst->session_tail = NULL;
+}
+
+/*
+ * Return a 32-bit random number.
+ */
+static uint32_t eap_rand(fr_randctx *ctx)
+{
+ uint32_t num;
+
+ num = ctx->randrsl[ctx->randcnt++];
+ if (ctx->randcnt >= 256) {
+ ctx->randcnt = 0;
+ fr_isaac(ctx);
+ }
+
+ return num;
+}
+
+
+static eap_handler_t *eaplist_delete(rlm_eap_t *inst, REQUEST *request,
+ eap_handler_t *handler)
+{
+ rbnode_t *node;
+
+ node = rbtree_find(inst->session_tree, handler);
+ if (!node) return NULL;
+
+ handler = rbtree_node2data(inst->session_tree, node);
+
+ RDEBUG("Finished EAP session with state "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ handler->state[0], handler->state[1],
+ handler->state[2], handler->state[3],
+ handler->state[4], handler->state[5],
+ handler->state[6], handler->state[7]);
+ /*
+ * Delete old handler from the tree.
+ */
+ rbtree_delete(inst->session_tree, node);
+
+ /*
+ * And unsplice it from the linked list.
+ */
+ if (handler->prev) {
+ handler->prev->next = handler->next;
+ } else {
+ inst->session_head = handler->next;
+ }
+ if (handler->next) {
+ handler->next->prev = handler->prev;
+ } else {
+ inst->session_tail = handler->prev;
+ }
+ handler->prev = handler->next = NULL;
+
+ return handler;
+}
+
+
+static void eaplist_expire(rlm_eap_t *inst, REQUEST *request, time_t timestamp)
+{
+ int i;
+ eap_handler_t *handler;
+
+ /*
+ * Check the first few handlers in the list, and delete
+ * them if they're too old. We don't need to check them
+ * all, as incoming requests will quickly cause older
+ * handlers to be deleted.
+ *
+ */
+ for (i = 0; i < 3; i++) {
+ handler = inst->session_head;
+ if (!handler) break;
+
+ RDEBUG("Expiring EAP session with state "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ handler->state[0], handler->state[1],
+ handler->state[2], handler->state[3],
+ handler->state[4], handler->state[5],
+ handler->state[6], handler->state[7]);
+
+ /*
+ * Expire entries from the start of the list.
+ * They should be the oldest ones.
+ */
+ if ((timestamp - handler->timestamp) > (int)inst->timer_limit) {
+ rbnode_t *node;
+ node = rbtree_find(inst->session_tree, handler);
+ rad_assert(node != NULL);
+ rbtree_delete(inst->session_tree, node);
+
+ /*
+ * handler == inst->session_head
+ */
+ inst->session_head = handler->next;
+ if (handler->next) {
+ handler->next->prev = NULL;
+ } else {
+ inst->session_head = NULL;
+ inst->session_tail = NULL;
+ }
+
+#ifdef WITH_TLS
+ /*
+ * Remove expired TLS sessions.
+ */
+ switch (handler->type) {
+ case PW_EAP_TLS:
+ case PW_EAP_TTLS:
+ case PW_EAP_PEAP:
+ case PW_EAP_FAST:
+ tls_fail(handler->opaque); /* MUST be a tls_session! */
+ break;
+
+ default:
+ break;
+ }
+#endif
+
+ talloc_free(handler);
+ } else {
+ break;
+ }
+ }
+}
+
+/*
+ * Add a handler to the set of active sessions.
+ *
+ * Since we're adding it to the list, we guess that this means
+ * the packet needs a State attribute. So add one.
+ */
+int eaplist_add(rlm_eap_t *inst, eap_handler_t *handler)
+{
+ int status = 0;
+ VALUE_PAIR *state;
+ REQUEST *request = handler->request;
+
+ /*
+ * Generate State, since we've been asked to add it to
+ * the list.
+ */
+ state = pair_make_reply("State", NULL, T_OP_EQ);
+ if (!state) return 0;
+
+ /*
+ * The time at which this request was made was the time
+ * at which it was received by the RADIUS server.
+ */
+ handler->timestamp = request->timestamp;
+ handler->status = 1;
+
+ handler->src_ipaddr = request->packet->src_ipaddr;
+ handler->eap_id = handler->eap_ds->request->id;
+
+ /*
+ * Playing with a data structure shared among threads
+ * means that we need a lock, to avoid conflict.
+ */
+ PTHREAD_MUTEX_LOCK(&(inst->session_mutex));
+
+ /*
+ * If we have a DoS attack, discard new sessions.
+ */
+ if (rbtree_num_elements(inst->session_tree) >= inst->max_sessions) {
+ status = -1;
+ eaplist_expire(inst, request, handler->timestamp);
+ goto done;
+ }
+
+ /*
+ * Create a unique content for the State variable.
+ * It will be modified slightly per round trip, but less so
+ * than in 1.x.
+ */
+ if (handler->trips == 0) {
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ uint32_t lvalue;
+
+ lvalue = eap_rand(&inst->rand_pool);
+
+ memcpy(handler->state + i * 4, &lvalue,
+ sizeof(lvalue));
+ }
+ }
+
+ /*
+ * Add some more data to distinguish the sessions.
+ */
+ handler->state[4] = handler->trips ^ handler->state[0];
+ handler->state[5] = handler->eap_id ^ handler->state[1];
+ handler->state[6] = handler->type ^ handler->state[2];
+ handler->state[12] = handler->state[2] ^ (RADIUSD_VERSION & 0xff);
+
+ fr_pair_value_memcpy(state, handler->state, sizeof(handler->state));
+
+ /*
+ * Big-time failure.
+ */
+ status = rbtree_insert(inst->session_tree, handler);
+
+ if (status) {
+ eap_handler_t *prev;
+
+ prev = inst->session_tail;
+ if (prev) {
+ prev->next = handler;
+ handler->prev = prev;
+ handler->next = NULL;
+ inst->session_tail = handler;
+ } else {
+ inst->session_head = inst->session_tail = handler;
+ handler->next = handler->prev = NULL;
+ }
+ }
+
+ /*
+ * Now that we've finished mucking with the list,
+ * unlock it.
+ */
+ done:
+
+ /*
+ * We don't need this any more.
+ */
+ if (status > 0) handler->request = NULL;
+
+ PTHREAD_MUTEX_UNLOCK(&(inst->session_mutex));
+
+ if (status <= 0) {
+ fr_pair_delete_by_num(&request->reply->vps, PW_STATE, 0, TAG_ANY);
+
+ if (status < 0) {
+ static time_t last_logged = 0;
+
+ if (last_logged < handler->timestamp) {
+ last_logged = handler->timestamp;
+ ERROR("rlm_eap (%s): Too many open sessions. Try increasing \"max_sessions\" "
+ "in the EAP module configuration", inst->xlat_name);
+ }
+ } else {
+ ERROR("rlm_eap (%s): Failed to store handler", inst->xlat_name);
+ }
+ return 0;
+ }
+
+ RDEBUG("EAP session adding &reply:State = 0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ state->vp_octets[0], state->vp_octets[1], state->vp_octets[2], state->vp_octets[3],
+ state->vp_octets[4], state->vp_octets[5], state->vp_octets[6], state->vp_octets[7]);
+
+ return 1;
+}
+
+/*
+ * Find a a previous EAP-Request sent by us, which matches
+ * the current EAP-Response.
+ *
+ * Then, release the handle from the list, and return it to
+ * the caller.
+ *
+ * Also since we fill the eap_ds with the present EAP-Response we
+ * got to free the prev_eapds & move the eap_ds to prev_eapds
+ */
+eap_handler_t *eaplist_find(rlm_eap_t *inst, REQUEST *request,
+ eap_packet_raw_t *eap_packet)
+{
+ VALUE_PAIR *state;
+ eap_handler_t *handler, myHandler;
+
+ /*
+ * We key the sessions off of the 'state' attribute, so it
+ * must exist.
+ */
+ state = fr_pair_find_by_num(request->packet->vps, PW_STATE, 0, TAG_ANY);
+ if (!state) {
+ REDEBUG("EAP requires the State attribute to work, but no State exists in the Access-Request packet.");
+ REDEBUG("The RADIUS client is broken. No amount of changing FreeRADIUS will fix the RADIUS client.");
+ return NULL;
+ }
+
+ if (state->vp_length != EAP_STATE_LEN) {
+ REDEBUG("The RADIUS client has mangled the State attribute, OR you are forcing EAP in the wrong situation");
+ return NULL;
+ }
+
+ myHandler.src_ipaddr = request->packet->src_ipaddr;
+ myHandler.eap_id = eap_packet->id;
+ memcpy(myHandler.state, state->vp_strvalue, sizeof(myHandler.state));
+
+ /*
+ * Playing with a data structure shared among threads
+ * means that we need a lock, to avoid conflict.
+ */
+ PTHREAD_MUTEX_LOCK(&(inst->session_mutex));
+
+ eaplist_expire(inst, request, request->timestamp);
+
+ handler = eaplist_delete(inst, request, &myHandler);
+ PTHREAD_MUTEX_UNLOCK(&(inst->session_mutex));
+
+ /*
+ * Might not have been there.
+ */
+ if (!handler) {
+ RERROR("rlm_eap (%s): No EAP session matching state "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ inst->xlat_name,
+ state->vp_octets[0], state->vp_octets[1],
+ state->vp_octets[2], state->vp_octets[3],
+ state->vp_octets[4], state->vp_octets[5],
+ state->vp_octets[6], state->vp_octets[7]);
+ return NULL;
+ }
+
+ if (handler->trips >= 50) {
+ RERROR("rlm_eap (%s): Aborting! More than 50 roundtrips "
+ "made in session with state "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ inst->xlat_name,
+ state->vp_octets[0], state->vp_octets[1],
+ state->vp_octets[2], state->vp_octets[3],
+ state->vp_octets[4], state->vp_octets[5],
+ state->vp_octets[6], state->vp_octets[7]);
+
+
+ talloc_free(handler);
+ return NULL;
+ }
+ handler->trips++;
+
+ RDEBUG("Previous EAP request found for state "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x, released from the list",
+ state->vp_octets[0], state->vp_octets[1],
+ state->vp_octets[2], state->vp_octets[3],
+ state->vp_octets[4], state->vp_octets[5],
+ state->vp_octets[6], state->vp_octets[7]);
+
+ /*
+ * Remember what the previous request was.
+ */
+ eap_ds_free(&(handler->prev_eapds));
+ handler->prev_eapds = handler->eap_ds;
+ handler->eap_ds = NULL;
+
+ return handler;
+}
diff --git a/src/modules/rlm_eap/radeapclient.c b/src/modules/rlm_eap/radeapclient.c
new file mode 100644
index 0000000..ae24f06
--- /dev/null
+++ b/src/modules/rlm_eap/radeapclient.c
@@ -0,0 +1,2315 @@
+/*
+ * radeapclient.c EAP specific radius packet debug tool.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000,2006 The FreeRADIUS server project
+ * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
+ * Copyright 2000 Alan DeKok <aland@ox.org>
+ */
+
+RCSID("$Id$")
+
+#include <freeradius-devel/libradius.h>
+
+#include <ctype.h>
+#include <assert.h>
+
+#if HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+
+#include <freeradius-devel/conf.h>
+#include <freeradius-devel/radpaths.h>
+#include <freeradius-devel/md5.h>
+
+#include "eap_types.h"
+#include "eap_sim.h"
+#include "comp128.h"
+
+extern int sha1_data_problems;
+
+#undef DEBUG
+#undef DEBUG2
+#undef ERROR
+
+#define DEBUG if (fr_debug_lvl && fr_log_fp) fr_printf_log
+#define DEBUG2 if ((fr_debug_lvl >= 2) && fr_log_fp) fr_printf_log
+#define ERROR if (fr_debug_lvl && fr_log_fp) fr_printf_log
+
+#define USEC 1000000
+
+static uint32_t parallel = 1;
+static unsigned int retries = 3;
+static float timeout = 5;
+static struct timeval tv_timeout;
+static char const *secret = NULL;
+static int do_output = 1;
+static int do_summary = 0;
+static int totalapp = 0;
+static int totaldeny = 0;
+static char filesecret[256];
+static char const *radius_dir = NULL;
+static char const *progname = "radeapclient";
+/* fr_randctx randctx; */
+
+main_config_t main_config;
+char const *radiusd_version = "";
+
+#ifdef WITH_TLS
+#include <freeradius-devel/tls.h>
+#endif
+
+log_lvl_t rad_debug_lvl = 0;
+
+//TODO: move structures to a header file.
+
+typedef struct rc_input_vps_list rc_input_vps_list_t;
+typedef struct rc_input_vps rc_input_vps_t;
+typedef struct rc_transaction rc_transaction_t;
+
+/** Structure which contains EAP context, necessary to perform the full EAP transaction.
+ */
+typedef struct rc_eap_sim_context {
+ struct eapsim_keys keys;
+} rc_eap_sim_context_t;
+
+typedef struct rc_eap_md5_context {
+ int tried;
+} rc_eap_md5_context_t;
+
+typedef struct rc_eap_context {
+ int eap_type; //!< contains the EAP-Type
+ char password[256]; //!< copy of User-Password (or CHAP-Password).
+ VALUE_PAIR *ki;
+ union {
+ rc_eap_sim_context_t sim;
+ rc_eap_md5_context_t md5;
+ } eap;
+} rc_eap_context_t;
+
+
+/** Structure which holds a list of available input vps.
+ */
+struct rc_input_vps_list {
+ rc_input_vps_t *head;
+ rc_input_vps_t *tail;
+ uint32_t size;
+};
+
+/** Structure which holds an input vps entry (read from file or stdin),
+ * and linkage to previous / next entries.
+ */
+struct rc_input_vps {
+ uint32_t num; //!< The number (within the file) of the input we're reading.
+
+ VALUE_PAIR *vps_in; //!< the list of attribute/value pairs.
+
+ rc_input_vps_list_t *list; //!< the list to which this entry belongs (NULL for an unchained entry).
+
+ rc_input_vps_t *prev;
+ rc_input_vps_t *next;
+};
+
+
+/** Structure which holds a transaction: sent packet, reply received...
+ */
+struct rc_transaction {
+ uint32_t id; //!< id of transaction (0 for the first one).
+
+ uint32_t num_packet; //!< number of packets sent for this transaction.
+
+ RADIUS_PACKET *packet;
+ RADIUS_PACKET *reply;
+
+ rc_input_vps_t *input_vps;
+
+ rc_eap_context_t *eap_context;
+
+ uint32_t tries;
+
+ fr_event_t *event; //!< armed event (if any).
+
+ char password[256];
+ char const *name; //!< Test name (as specified in the request).
+};
+
+typedef struct eap_sim_server_state {
+ enum eapsim_serverstates state;
+ struct eapsim_keys keys;
+ int sim_id;
+} eap_sim_state_t;
+
+
+static TALLOC_CTX *autofree;
+static uint32_t num_trans = 0; //!< number of transactions initialized.
+static uint32_t num_started = 0; //!< number of transactions started.
+static uint32_t num_ongoing = 0; //!< number of ongoing transactions.
+static uint32_t num_finished = 0; //!< number of finished transactions.
+
+static rc_input_vps_list_t rc_vps_list_in; //!< list of available input vps entries.
+static fr_packet_list_t *pl = NULL; //!< list of outgoing packets.
+static unsigned int num_sockets = 0; //!< number of allocated sockets.
+static fr_event_list_t *ev_list = NULL; //!< list of armed events.
+
+static int force_af = AF_UNSPEC;
+static int ipproto = IPPROTO_UDP;
+static fr_ipaddr_t server_ipaddr;
+static bool server_addr_init = false;
+static uint16_t server_port = 0;
+static int packet_code = PW_CODE_UNDEFINED;
+
+static int rc_map_eap_methods(RADIUS_PACKET *req);
+static void rc_unmap_eap_methods(RADIUS_PACKET *rep);
+static int rc_map_eapsim_types(RADIUS_PACKET *r);
+static int rc_unmap_eapsim_types(RADIUS_PACKET *r);
+
+static void rc_get_port(PW_CODE type, uint16_t *port);
+static void rc_evprep_packet_timeout(rc_transaction_t *trans);
+static void rc_deallocate_id(rc_transaction_t *trans);
+
+/*
+ * For cbtls_cache_*()
+ */
+rlm_rcode_t process_post_auth(UNUSED int postauth_type, UNUSED REQUEST *request)
+{
+ return RLM_MODULE_FAIL;
+}
+
+
+fr_event_list_t *radius_event_list_corral(UNUSED event_corral_t hint)
+{
+ return NULL;
+}
+
+static void NEVER_RETURNS usage(void)
+{
+ fprintf(stdout, "Usage: radeapclient [options] server[:port] <command> [<secret>]\n");
+
+ fprintf(stdout, " <command> One of auth, acct, status, coa, disconnect or auto.\n");
+ fprintf(stdout, " -4 Use IPv4 address of server\n");
+ fprintf(stdout, " -6 Use IPv6 address of server.\n");
+ fprintf(stdout, " -d <raddb> Set user dictionary directory (defaults to " RADDBDIR ").\n");
+ fprintf(stdout, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
+ fprintf(stdout, " -f <file> Read packets from file, not stdin.\n");
+ fprintf(stdout, " -h Print usage help information.\n");
+ fprintf(stdout, " -p <num> Send 'num' packets in parallel.\n");
+ fprintf(stdout, " -q Do not print anything out.\n");
+ fprintf(stdout, " -r <retries> If timeout, retry sending the packet 'retries' times.\n");
+ fprintf(stdout, " -s Print out summary information of auth results.\n");
+ fprintf(stdout, " -S <file> read secret from file, not command line.\n");
+ fprintf(stdout, " -t <timeout> Wait 'timeout' seconds before retrying (may be a floating point number).\n");
+ fprintf(stdout, " -v Show program version information.\n");
+ fprintf(stdout, " -x Debugging mode.\n");
+
+ exit(1);
+}
+
+static const FR_NAME_NUMBER rc_request_types[] = {
+ { "auth", PW_CODE_ACCESS_REQUEST },
+ { "challenge", PW_CODE_ACCESS_CHALLENGE },
+ { "acct", PW_CODE_ACCOUNTING_REQUEST },
+ { "status", PW_CODE_STATUS_SERVER },
+ { "disconnect", PW_CODE_DISCONNECT_REQUEST },
+ { "coa", PW_CODE_COA_REQUEST },
+ { "auto", PW_CODE_UNDEFINED },
+
+ { NULL, 0}
+};
+
+int rad_virtual_server(REQUEST UNUSED *request)
+{
+ /*We're not the server so we cannot do this*/
+ abort();
+}
+
+/** Convert a float to struct timeval.
+ */
+static void rc_float_to_timeval(struct timeval *tv, float f_val)
+{
+ tv->tv_sec = (time_t)f_val;
+ uint64_t usec = (uint64_t)(f_val * USEC) - (tv->tv_sec * USEC);
+ tv->tv_usec = usec;
+}
+
+/** Add an allocated rc_input_vps_t entry to the tail of the list.
+ */
+ static void rc_add_vps_entry(rc_input_vps_list_t *list, rc_input_vps_t *entry)
+{
+ if (!list || !entry) return;
+
+ if (!list->head) {
+ assert(list->tail == NULL);
+ list->head = entry;
+ entry->prev = NULL;
+ } else {
+ assert(list->tail != NULL);
+ assert(list->tail->next == NULL);
+ list->tail->next = entry;
+ entry->prev = list->tail;
+ }
+ list->tail = entry;
+ entry->next = NULL;
+ entry->list = list;
+ list->size ++;
+}
+
+/** Remove a selected rc_input_vps_t entry from its current list.
+ */
+static rc_input_vps_t *rc_yank_vps_entry(rc_input_vps_t *entry)
+{
+ if (!entry) return NULL;
+
+ if (!entry->list) return entry; /* not in a list, nothing to do. Just return the entry. */
+
+ rc_input_vps_t *prev, *next;
+
+ prev = entry->prev;
+ next = entry->next;
+
+ rc_input_vps_list_t *list = entry->list;
+
+ assert(list->head != NULL); /* entry belongs to a list, so the list can't be empty. */
+ assert(list->tail != NULL); /* same. */
+
+ if (prev) {
+ assert(list->head != entry); /* if entry has a prev, then entry can't be head. */
+ prev->next = next;
+ }
+ else {
+ assert(list->head == entry); /* if entry has no prev, then entry must be head. */
+ list->head = next;
+ }
+
+ if (next) {
+ assert(list->tail != entry); /* if entry has a next, then entry can't be tail. */
+ next->prev = prev;
+ }
+ else {
+ assert(list->tail == entry); /* if entry has no next, then entry must be tail. */
+ list->tail = prev;
+ }
+
+ entry->list = NULL;
+ entry->prev = NULL;
+ entry->next = NULL;
+ list->size --;
+ return entry;
+}
+
+/** Load input entries (list of vps) from a file or stdin, and add them to the list.
+ * They will be used to initiate transactions.
+ */
+static int rc_load_input(TALLOC_CTX *ctx, char const *filename, rc_input_vps_list_t *list, uint32_t max_entries)
+{
+ FILE *file_in = NULL;
+ bool file_done = false;
+ rc_input_vps_t *request;
+ char const *input;
+ uint32_t input_num = 0;
+
+ /* Determine where to read the VP's from. */
+ if (filename && strcmp(filename, "-") != 0) {
+ DEBUG2("Opening input file: %s\n", filename);
+ file_in = fopen(filename, "r");
+ if (!file_in) {
+ ERROR("Error opening %s: %s\n", filename, strerror(errno));
+ return 0;
+ }
+ input = filename;
+ } else {
+ DEBUG2("Reading input vps from stdin\n");
+ file_in = stdin;
+ input = "stdin";
+ }
+
+ /* Loop over the file (or stdin). */
+ do {
+ input_num ++;
+ MEM(request = talloc_zero(ctx, rc_input_vps_t));
+
+ if (fr_pair_list_afrom_file(request, &request->vps_in, file_in, &file_done) < 0) {
+ ERROR("Error parsing entry %u from input: %s\n", input_num, input);
+ talloc_free(request);
+ break;
+ }
+ if (NULL == request->vps_in) {
+ /* Last line might be empty, in this case fr_pair_list_afrom_file will return a NULL vps pointer. Silently ignore this. */
+ talloc_free(request);
+ break;
+ }
+
+ /* Add that to the list */
+ rc_add_vps_entry(list, request);
+
+ request->num = list->size;
+
+ if (max_entries && list->size >= max_entries) {
+ /* Only load what we need. */
+ break;
+ }
+ } while (!file_done);
+
+ if (file_in != stdin) fclose(file_in);
+
+ /* And we're done. */
+ DEBUG("Read %d element(s) from input: %s\n", list->size, input);
+ return 1;
+}
+
+/** Perform packet initialization for a transaction.
+ */
+static int rc_init_packet(rc_transaction_t *trans)
+{
+ if (!trans || !trans->packet) return 0;
+
+ RADIUS_PACKET *packet = trans->packet;
+ vp_cursor_t cursor;
+ VALUE_PAIR *vp;
+
+ /*
+ * Process special attributes
+ */
+ for (vp = fr_cursor_init(&cursor, &packet->vps);
+ vp;
+ vp = fr_cursor_next(&cursor)) {
+ /*
+ * Double quoted strings get marked up as xlat expansions,
+ * but we don't support that in request.
+ */
+ if (vp->type == VT_XLAT) {
+ vp->type = VT_DATA;
+ vp->vp_strvalue = vp->value.xlat;
+ vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
+ }
+
+ if (!vp->da->vendor) switch (vp->da->attr) {
+ default:
+ break;
+
+ /*
+ * Allow it to set the packet type in
+ * the attributes read from the file.
+ */
+ case PW_PACKET_TYPE:
+ packet->code = vp->vp_integer;
+ break;
+
+ case PW_PACKET_DST_PORT:
+ packet->dst_port = (vp->vp_integer & 0xffff);
+ break;
+
+ case PW_PACKET_DST_IP_ADDRESS:
+ packet->dst_ipaddr.af = AF_INET;
+ packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+ packet->dst_ipaddr.prefix = 32;
+ break;
+
+ case PW_PACKET_DST_IPV6_ADDRESS:
+ packet->dst_ipaddr.af = AF_INET6;
+ packet->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
+ packet->dst_ipaddr.prefix = 128;
+ break;
+
+ case PW_PACKET_SRC_PORT:
+ if ((vp->vp_integer < 1024) ||
+ (vp->vp_integer > 65535)) {
+ DEBUG("Invalid value '%u' for Packet-Src-Port\n", vp->vp_integer);
+ } else {
+ packet->src_port = (vp->vp_integer & 0xffff);
+ }
+ break;
+
+ case PW_PACKET_SRC_IP_ADDRESS:
+ packet->src_ipaddr.af = AF_INET;
+ packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+ packet->src_ipaddr.prefix = 32;
+ break;
+
+ case PW_PACKET_SRC_IPV6_ADDRESS:
+ packet->src_ipaddr.af = AF_INET6;
+ packet->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
+ packet->src_ipaddr.prefix = 128;
+ break;
+
+ case PW_DIGEST_REALM:
+ case PW_DIGEST_NONCE:
+ case PW_DIGEST_METHOD:
+ case PW_DIGEST_URI:
+ case PW_DIGEST_QOP:
+ case PW_DIGEST_ALGORITHM:
+ case PW_DIGEST_BODY_DIGEST:
+ case PW_DIGEST_CNONCE:
+ case PW_DIGEST_NONCE_COUNT:
+ case PW_DIGEST_USER_NAME:
+ /* overlapping! */
+ {
+ DICT_ATTR const *da;
+ uint8_t *p, *q;
+
+ p = talloc_array(vp, uint8_t, vp->vp_length + 2);
+
+ memcpy(p + 2, vp->vp_octets, vp->vp_length);
+ p[0] = vp->da->attr - PW_DIGEST_REALM + 1;
+ vp->vp_length += 2;
+ p[1] = vp->vp_length;
+
+ da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0);
+ if (!da) {
+ ERROR("Attribute 'Digest-Attributes' not found by value\n");
+ exit(1);
+ }
+ vp->da = da;
+
+ /*
+ * Re-do fr_pair_value_memsteal ourselves,
+ * because we play games with
+ * vp->da, and fr_pair_value_memsteal goes
+ * to GREAT lengths to sanitize
+ * and fix and change and
+ * double-check the various
+ * fields.
+ */
+ memcpy(&q, &vp->vp_octets, sizeof(q));
+ talloc_free(q);
+
+ vp->vp_octets = talloc_steal(vp, p);
+ vp->type = VT_DATA;
+
+ VERIFY_VP(vp);
+ }
+ break;
+
+ /*
+ * Keep a copy of the the password attribute.
+ */
+ case PW_CLEARTEXT_PASSWORD:
+ case PW_USER_PASSWORD:
+ case PW_CHAP_PASSWORD:
+ case PW_MS_CHAP_PASSWORD:
+ strlcpy(trans->password, vp->vp_strvalue, sizeof(trans->password));
+ break;
+
+ case PW_RADCLIENT_TEST_NAME:
+ trans->name = vp->vp_strvalue;
+ break;
+ }
+ } /* loop over the VP's we read in */
+
+ if (packet->dst_port == 0) packet->dst_port = server_port;
+
+ if (packet->dst_ipaddr.af == AF_UNSPEC) {
+ if (!server_addr_init) {
+ DEBUG("No server was given, and input entry %u did not contain Packet-Dst-IP-Address, ignored.\n", trans->input_vps->num);
+ return 0;
+ }
+ packet->dst_ipaddr = server_ipaddr;
+ }
+
+ /* Use the default set on the command line. */
+ if (packet->code == PW_CODE_UNDEFINED) {
+ if (packet_code == PW_CODE_UNDEFINED) {
+ DEBUG("No packet type was given, and input entry %u did not contain Packet-Type, ignored.\n", trans->input_vps->num);
+ return 0;
+ }
+ packet->code = packet_code;
+ }
+
+ /* Automatically set the dst port (if one wasn't already set). */
+ if (packet->dst_port == 0) {
+ rc_get_port(packet->code, &packet->dst_port);
+ if (packet->dst_port == 0) {
+ DEBUG("Can't determine destination port for input entry %u, ignored.\n", trans->input_vps->num);
+ return 0;
+ }
+ }
+
+ packet->sockfd = -1;
+
+ /* Done. */
+ return 1;
+}
+
+/** Map EAP methods and build EAP-Message (if EAP is involved).
+ * Also allocate the EAP context.
+ */
+static void rc_build_eap_context(rc_transaction_t *trans)
+{
+ if (!trans || !trans->packet) return;
+
+ RADIUS_PACKET *packet = trans->packet;
+
+ /* Build EAP-Message (if EAP is involved. Otherwise, do nothing). */
+ int eap_type = rc_map_eap_methods(packet);
+
+ if (eap_type) {
+ if (!trans->eap_context) {
+ MEM(trans->eap_context = talloc_zero(trans, rc_eap_context_t));
+ }
+ trans->eap_context->eap_type = eap_type;
+
+ /*
+ * Keep a copy of the the User-Password or CHAP-Password.
+ * Note: this is not useful for EAP-SIM, but we cannot know what kind
+ * of challenge the server will issue.
+ */
+ VALUE_PAIR *vp;
+ vp = fr_pair_find_by_num(packet->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
+ if (!vp) vp = fr_pair_find_by_num(packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
+ if (!vp) vp = fr_pair_find_by_num(packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY);
+ if (vp) {
+ strlcpy(trans->eap_context->password, vp->vp_strvalue, sizeof(trans->eap_context->password));
+ }
+
+ vp = fr_pair_find_by_num(packet->vps, PW_EAP_SIM_KI, 0, TAG_ANY);
+ if (vp) trans->eap_context->ki = fr_pair_copy(autofree, vp);
+ }
+}
+
+
+/** Grab an element from the input list. Initialize a new transaction context, using this element.
+ */
+static rc_transaction_t *rc_init_transaction(TALLOC_CTX *ctx)
+{
+ if (!rc_vps_list_in.head || rc_vps_list_in.size == 0) {
+ /* Empty list, can't create a new transaction. */
+ return NULL;
+ }
+
+ rc_input_vps_t *vps_entry = rc_vps_list_in.head;
+
+ rc_yank_vps_entry(vps_entry); /* This cannot fail (we checked the list beforehand.) */
+
+ /* We grabbed an vps entry, now we can initialize a new transaction. */
+ rc_transaction_t *trans;
+ MEM(trans = talloc_zero(ctx, rc_transaction_t));
+
+ trans->input_vps = vps_entry;
+ trans->id = num_trans ++;
+
+ talloc_steal(trans, vps_entry); /* It's ours now. */
+
+ RADIUS_PACKET *packet;
+ MEM(packet = rad_alloc(trans, 1));
+ trans->packet = packet;
+
+ /* Fill in the packet value pairs. */
+ packet->vps = fr_pair_list_copy(packet, vps_entry->vps_in);
+
+ /* Initialize the transaction packet. */
+ if (!rc_init_packet(trans)) {
+ /* Failed... */
+ talloc_free(trans);
+ return NULL;
+ }
+
+ /* Update transactions counters. */
+ num_started ++;
+ num_ongoing ++;
+
+ return trans;
+}
+
+/** Terminate a transaction.
+ */
+static void rc_finish_transaction(rc_transaction_t *trans)
+{
+ if (!trans) return;
+
+ if (trans->event) fr_event_delete(ev_list, &trans->event);
+ rc_deallocate_id(trans);
+ talloc_free(trans);
+
+ /* Update transactions counters. */
+ num_ongoing --;
+ num_finished ++;
+
+ DEBUG4("pl: %d, ev: %d, in: %d\n", fr_packet_list_num_outgoing(pl), fr_event_list_num_elements(ev_list), rc_vps_list_in.size);
+}
+
+
+static uint16_t getport(char const *name)
+{
+ struct servent *svp;
+
+ svp = getservbyname(name, "udp");
+ if (!svp) return 0;
+
+ return ntohs(svp->s_port);
+}
+
+
+static void rc_cleanresp(RADIUS_PACKET *resp)
+{
+ VALUE_PAIR *vpnext, *vp, **last;
+
+ /*
+ * maybe should just copy things we care about, or keep
+ * a copy of the original input and start from there again?
+ */
+ fr_pair_delete_by_num(&resp->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ fr_pair_delete_by_num(&resp->vps, PW_EAP_TYPE_BASE+PW_EAP_IDENTITY, 0, TAG_ANY);
+
+ last = &resp->vps;
+ for (vp = *last; vp != NULL; vp = vpnext)
+ {
+ vpnext = vp->next;
+
+ if ((vp->da->attr > PW_EAP_TYPE_BASE &&
+ vp->da->attr <= PW_EAP_TYPE_BASE+256) ||
+ (vp->da->attr > PW_EAP_SIM_BASE &&
+ vp->da->attr <= PW_EAP_SIM_BASE+256))
+ {
+ *last = vpnext;
+ talloc_free(vp);
+ } else {
+ last = &vp->next;
+ }
+ }
+}
+
+
+static void generate_triplets(RADIUS_PACKET *packet, VALUE_PAIR *ki, uint8_t const *ch)
+{
+ int i, idx;
+ eap_sim_state_t ess;
+
+ for (idx = 0; idx < 3; idx++) {
+ VALUE_PAIR *vp;
+ char *p;
+ char buffer[33]; /* 32 hexits (16 bytes) + 1 */
+
+ for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+ ess.keys.rand[idx][i] = ch[(idx * EAPSIM_RAND_SIZE) + i];
+ }
+
+ /*
+ * <sigh>, we always do version 1.
+ */
+ switch (EAP_SIM_VERSION) {
+ case 1:
+ comp128v1(ess.keys.sres[idx], ess.keys.Kc[idx], ki->vp_octets, ess.keys.rand[idx]);
+ break;
+
+ case 2:
+ comp128v23(ess.keys.sres[idx], ess.keys.Kc[idx], ki->vp_octets, ess.keys.rand[idx],
+ true);
+ break;
+
+ case 3:
+ comp128v23(ess.keys.sres[idx], ess.keys.Kc[idx], ki->vp_octets, ess.keys.rand[idx],
+ false);
+ break;
+
+ case 4:
+ DEBUG("Comp128-4 algorithm is not supported as details have not yet been published. "
+ "If you have details of this algorithm please contact the FreeRADIUS "
+ "maintainers\n");
+ break;
+
+ default:
+ DEBUG("Unknown/unsupported algorithm Comp128-4\n");
+ }
+
+
+ DEBUG2("Generated following triplets for round %i:\n", idx);
+
+ p = buffer;
+ for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+ p += sprintf(p, "%02x", ess.keys.rand[idx][i]);
+ }
+ DEBUG2("RAND%d : 0x%s\n", idx, buffer);
+ vp = fr_pair_afrom_num(packet, PW_EAP_SIM_RAND1 + idx, 0);
+ fr_pair_value_memcpy(vp, ess.keys.rand[idx], EAPSIM_RAND_SIZE);
+ fr_pair_add(&packet->vps, vp);
+
+ p = buffer;
+ for (i = 0; i < EAPSIM_SRES_SIZE; i++) {
+ p += sprintf(p, "%02x", ess.keys.sres[idx][i]);
+ }
+ DEBUG2("SRES%d : 0x%s\n", idx, buffer);
+ vp = fr_pair_afrom_num(packet, PW_EAP_SIM_SRES1 + idx, 0);
+ fr_pair_value_memcpy(vp, ess.keys.sres[idx], EAPSIM_SRES_SIZE);
+ fr_pair_add(&packet->vps, vp);
+
+ p = buffer;
+ for (i = 0; i < EAPSIM_KC_SIZE; i++) {
+ p += sprintf(p, "%02x", ess.keys.Kc[idx][i]);
+ }
+ DEBUG2("Kc%d : 0x%s\n", idx, buffer);
+ vp = fr_pair_afrom_num(packet, PW_EAP_SIM_KC1 + idx, 0);
+ fr_pair_value_memcpy(vp, ess.keys.Kc[idx], EAPSIM_KC_SIZE);
+ fr_pair_add(&packet->vps, vp);
+ }
+}
+
+
+/*
+ * we got an EAP-Request/Sim/Start message in a legal state.
+ *
+ * pick a supported version, put it into the reply, and insert a nonce.
+ */
+static int rc_process_eap_start(rc_eap_context_t *eap_context,
+ RADIUS_PACKET *req, RADIUS_PACKET *rep)
+{
+ VALUE_PAIR *vp, *newvp;
+ VALUE_PAIR *anyidreq_vp, *fullauthidreq_vp, *permanentidreq_vp;
+ uint16_t const *versions;
+ uint16_t selectedversion;
+ unsigned int i,versioncount;
+ VALUE_PAIR *ki;
+
+ /* form new response clear of any EAP stuff */
+ rc_cleanresp(rep);
+
+ if ((vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_VERSION_LIST, 0, TAG_ANY)) == NULL) {
+ ERROR("illegal start message has no VERSION_LIST\n");
+ return 0;
+ }
+
+ versions = (uint16_t const *) vp->vp_strvalue;
+
+ /* verify that the attribute length is big enough for a length field */
+ if (vp->vp_length < 4)
+ {
+ ERROR("start message has illegal VERSION_LIST. Too short: %u\n", (unsigned int) vp->vp_length);
+ return 0;
+ }
+
+ versioncount = ntohs(versions[0])/2;
+ /* verify that the attribute length is big enough for the given number
+ * of versions present.
+ */
+ if ((unsigned)vp->vp_length <= (versioncount*2 + 2))
+ {
+ ERROR("start message is too short. Claimed %d versions does not fit in %u bytes\n", versioncount, (unsigned int) vp->vp_length);
+ return 0;
+ }
+
+ /*
+ * record the versionlist for the MK calculation.
+ */
+ eap_context->eap.sim.keys.versionlistlen = versioncount*2;
+ memcpy(eap_context->eap.sim.keys.versionlist, (unsigned char const *)(versions+1),
+ eap_context->eap.sim.keys.versionlistlen);
+
+ /* walk the version list, and pick the one we support, which
+ * at present, is 1, EAP_SIM_VERSION.
+ */
+ selectedversion=0;
+ for (i=0; i < versioncount; i++)
+ {
+ if (ntohs(versions[i+1]) == EAP_SIM_VERSION)
+ {
+ selectedversion=EAP_SIM_VERSION;
+ break;
+ }
+ }
+ if (selectedversion == 0)
+ {
+ ERROR("eap-sim start message. No compatible version found. We need %d\n", EAP_SIM_VERSION);
+ for (i=0; i < versioncount; i++)
+ {
+ ERROR("\tfound version %d\n",
+ ntohs(versions[i+1]));
+ }
+ }
+
+ /*
+ * now make sure that we have only FULLAUTH_ID_REQ.
+ * I think that it actually might not matter - we can answer in
+ * anyway we like, but it is illegal to have more than one
+ * present.
+ */
+ anyidreq_vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_ANY_ID_REQ, 0, TAG_ANY);
+ fullauthidreq_vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_FULLAUTH_ID_REQ, 0, TAG_ANY);
+ permanentidreq_vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_PERMANENT_ID_REQ, 0, TAG_ANY);
+
+ if (!fullauthidreq_vp ||
+ anyidreq_vp != NULL ||
+ permanentidreq_vp != NULL) {
+ ERROR("start message has %sanyidreq, %sfullauthid and %spermanentid. Illegal combination.\n",
+ (anyidreq_vp != NULL ? "a ": "no "),
+ (fullauthidreq_vp != NULL ? "a ": "no "),
+ (permanentidreq_vp != NULL ? "a ": "no "));
+ return 0;
+ }
+
+ /* okay, we have just any_id_req there, so fill in response */
+
+ /* mark the subtype as being EAP-SIM/Response/Start */
+ newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_SUBTYPE, 0);
+ newvp->vp_integer = EAPSIM_START;
+ fr_pair_replace(&(rep->vps), newvp);
+
+ /* insert selected version into response. */
+ {
+ uint16_t no_versions;
+
+ no_versions = htons(selectedversion);
+
+ newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_SELECTED_VERSION, 0);
+ fr_pair_value_memcpy(newvp, (uint8_t *) &no_versions, 2);
+ fr_pair_replace(&(rep->vps), newvp);
+
+ /* record the selected version */
+ memcpy(eap_context->eap.sim.keys.versionselect, &no_versions, 2);
+ }
+
+ vp = newvp = NULL;
+
+ {
+ uint32_t nonce[4];
+ uint8_t *p;
+ /*
+ * insert a nonce_mt that we make up.
+ */
+ nonce[0]=fr_rand();
+ nonce[1]=fr_rand();
+ nonce[2]=fr_rand();
+ nonce[3]=fr_rand();
+
+ newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_NONCE_MT, 0);
+
+ p = talloc_zero_array(newvp, uint8_t, 18); /* 18 = 16 bytes of nonce + padding */
+ memcpy(&p[2], nonce, 16);
+ fr_pair_value_memsteal(newvp, p);
+
+ fr_pair_replace(&(rep->vps), newvp);
+
+ /* also keep a copy of the nonce! */
+ memcpy(eap_context->eap.sim.keys.nonce_mt, nonce, 16);
+ }
+
+ {
+ uint16_t idlen;
+ uint8_t *p;
+ uint16_t no_idlen;
+
+ /*
+ * insert the identity here.
+ */
+ vp = fr_pair_find_by_num(rep->vps, PW_USER_NAME, 0, TAG_ANY);
+ if (!vp)
+ {
+ ERROR("eap-sim: We need to have a User-Name attribute!\n");
+ return 0;
+ }
+ newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_IDENTITY, 0);
+
+ idlen = strlen(vp->vp_strvalue);
+ p = talloc_zero_array(newvp, uint8_t, idlen + 2);
+ no_idlen = htons(idlen);
+ memcpy(p, &no_idlen, 2);
+ memcpy(p + 2, vp->vp_strvalue, idlen);
+ fr_pair_value_memsteal(newvp, p);
+
+ fr_pair_replace(&(rep->vps), newvp);
+
+ /* record it */
+ memcpy(eap_context->eap.sim.keys.identity, vp->vp_strvalue, idlen);
+ eap_context->eap.sim.keys.identitylen = idlen;
+ }
+
+ ki = fr_pair_find_by_num(req->vps, PW_EAP_SIM_KI, 0, TAG_ANY);
+ if (ki && !fr_pair_find_by_num(req->vps, PW_EAP_SIM_RAND1, 0, TAG_ANY)) {
+ generate_triplets(req, ki, NULL);
+ }
+
+ return 1;
+}
+
+
+/*
+ * we got an EAP-Request/Sim/Challenge message in a legal state.
+ *
+ * use the RAND challenge to produce the SRES result, and then
+ * use that to generate a new MAC.
+ *
+ * for the moment, we ignore the RANDs, then just plug in the SRES
+ * values.
+ *
+ */
+static int rc_process_eap_challenge(rc_eap_context_t *eap_context,
+ RADIUS_PACKET *req, RADIUS_PACKET *rep)
+{
+ VALUE_PAIR *newvp;
+ VALUE_PAIR *mac, *randvp;
+ VALUE_PAIR *sres1,*sres2,*sres3;
+ VALUE_PAIR *Kc1, *Kc2, *Kc3;
+ uint8_t calcmac[20];
+
+ /* look for the AT_MAC and the challenge data */
+ mac = fr_pair_find_by_num(req->vps, PW_EAP_SIM_MAC, 0, TAG_ANY);
+ randvp= fr_pair_find_by_num(req->vps, PW_EAP_SIM_RAND, 0, TAG_ANY);
+ if (!mac || !randvp) {
+ ERROR("challenge message needs to contain RAND and MAC\n");
+ return 0;
+ }
+
+ /*
+ * compare RAND with randX, to verify this is the right response
+ * to this challenge.
+ */
+ {
+ VALUE_PAIR *randcfgvp[3];
+ uint8_t const *randcfg[3];
+
+ randcfg[0] = &randvp->vp_octets[2];
+ randcfg[1] = &randvp->vp_octets[2+EAPSIM_RAND_SIZE];
+ randcfg[2] = &randvp->vp_octets[2+EAPSIM_RAND_SIZE*2];
+
+ randcfgvp[0] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND1, 0, TAG_ANY);
+ randcfgvp[1] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND2, 0, TAG_ANY);
+ randcfgvp[2] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND3, 0, TAG_ANY);
+
+ if (!randcfgvp[0] ||
+ !randcfgvp[1] ||
+ !randcfgvp[2]) {
+ int i;
+ VALUE_PAIR *ki;
+
+ /*
+ * Generate a new RAND value, and derive Kc and SRES from
+ * Ki, but only if we don't already have the random
+ * numbers.
+ */
+ ki = eap_context->ki;
+ if (!ki) {
+ ERROR("Need EAP-SIM-Rand1, EAP-SIM-Rand2, and EAP-SIM-Rand3\n");
+ return 0;
+ }
+
+ for (i = 0; i < 3; i++) {
+ fr_pair_delete_by_num(&req->vps, PW_EAP_SIM_RAND1 + i, 0, TAG_ANY);
+ fr_pair_delete_by_num(&req->vps, PW_EAP_SIM_SRES1 + i, 0, TAG_ANY);
+ fr_pair_delete_by_num(&req->vps, PW_EAP_SIM_KC1 + i, 0, TAG_ANY);
+ }
+
+ generate_triplets(rep, ki, randvp->vp_octets + 2);
+
+ randcfgvp[0] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND1, 0, TAG_ANY);
+ randcfgvp[1] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND2, 0, TAG_ANY);
+ randcfgvp[2] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND3, 0, TAG_ANY);
+
+ if (!randcfgvp[0] ||
+ !randcfgvp[1] ||
+ !randcfgvp[2]) {
+ ERROR("Failed to create triplets\n");
+ return 0;
+ }
+ }
+
+ if (memcmp(randcfg[0], randcfgvp[0]->vp_octets, EAPSIM_RAND_SIZE)!=0 ||
+ memcmp(randcfg[1], randcfgvp[1]->vp_octets, EAPSIM_RAND_SIZE)!=0 ||
+ memcmp(randcfg[2], randcfgvp[2]->vp_octets, EAPSIM_RAND_SIZE)!=0) {
+ int rnum, i;
+
+ ERROR("one of rand 1,2,3 didn't match\n");
+ for (rnum = 0; rnum < 3; rnum++) {
+ ERROR("rand %d\trecv\tconfig\n", rnum);
+ for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+ fprintf(fr_log_fp, "\t%02x\t%02x\n",
+ randcfg[rnum][i], randcfgvp[rnum]->vp_octets[i]);
+ }
+ }
+ return 0;
+ }
+ }
+
+ /*
+ * now dig up the sres values from the response packet,
+ * which were put there when we read things in.
+ *
+ * Really, they should be calculated from the RAND!
+ *
+ */
+ sres1 = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_SRES1, 0, TAG_ANY);
+ sres2 = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_SRES2, 0, TAG_ANY);
+ sres3 = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_SRES3, 0, TAG_ANY);
+
+ if (!sres1 ||
+ !sres2 ||
+ !sres3) {
+ ERROR("needs to have sres1, 2 and 3 set.\n");
+ return 0;
+ }
+ memcpy(eap_context->eap.sim.keys.sres[0], sres1->vp_strvalue, sizeof(eap_context->eap.sim.keys.sres[0]));
+ memcpy(eap_context->eap.sim.keys.sres[1], sres2->vp_strvalue, sizeof(eap_context->eap.sim.keys.sres[1]));
+ memcpy(eap_context->eap.sim.keys.sres[2], sres3->vp_strvalue, sizeof(eap_context->eap.sim.keys.sres[2]));
+
+ Kc1 = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_KC1, 0, TAG_ANY);
+ Kc2 = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_KC2, 0, TAG_ANY);
+ Kc3 = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_KC3, 0, TAG_ANY);
+
+ if (!Kc1 ||
+ !Kc2 ||
+ !Kc3) {
+ ERROR("needs to have Kc1, 2 and 3 set.\n");
+ return 0;
+ }
+ memcpy(eap_context->eap.sim.keys.Kc[0], Kc1->vp_strvalue, sizeof(eap_context->eap.sim.keys.Kc[0]));
+ memcpy(eap_context->eap.sim.keys.Kc[1], Kc2->vp_strvalue, sizeof(eap_context->eap.sim.keys.Kc[1]));
+ memcpy(eap_context->eap.sim.keys.Kc[2], Kc3->vp_strvalue, sizeof(eap_context->eap.sim.keys.Kc[2]));
+
+ /* all set, calculate keys */
+ eapsim_calculate_keys(&eap_context->eap.sim.keys);
+
+ if (rad_debug_lvl > 2) {
+ eapsim_dump_mk(&eap_context->eap.sim.keys);
+ }
+
+ /* verify the MAC, now that we have all the keys. */
+ if (eapsim_checkmac(NULL, req->vps, eap_context->eap.sim.keys.K_aut,
+ eap_context->eap.sim.keys.nonce_mt, sizeof(eap_context->eap.sim.keys.nonce_mt),
+ calcmac)) {
+ DEBUG2("MAC check succeed\n");
+ } else {
+ int i, j;
+ j=0;
+ DEBUG("calculated MAC (\n");
+ for (i = 0; i < 20; i++) {
+ if (j==4) {
+ printf("_");
+ j=0;
+ }
+ j++;
+
+ DEBUG("%02x\n", calcmac[i]);
+ }
+ DEBUG("did not match\n");
+ return 0;
+ }
+
+ /* form new response clear of any EAP stuff */
+ rc_cleanresp(rep);
+
+ /* mark the subtype as being EAP-SIM/Response/Start */
+ newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_SUBTYPE, 0);
+ newvp->vp_integer = EAPSIM_CHALLENGE;
+ fr_pair_replace(&(rep->vps), newvp);
+
+ {
+ uint8_t *p;
+ /*
+ * fill the SIM_MAC with a field that will in fact get appended
+ * to the packet before the MAC is calculated
+ */
+ newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_MAC, 0);
+
+ p = talloc_zero_array(newvp, uint8_t, EAPSIM_SRES_SIZE*3);
+ memcpy(p+EAPSIM_SRES_SIZE * 0, sres1->vp_strvalue, EAPSIM_SRES_SIZE);
+ memcpy(p+EAPSIM_SRES_SIZE * 1, sres2->vp_strvalue, EAPSIM_SRES_SIZE);
+ memcpy(p+EAPSIM_SRES_SIZE * 2, sres3->vp_strvalue, EAPSIM_SRES_SIZE);
+ fr_pair_value_memsteal(newvp, p);
+
+ fr_pair_replace(&(rep->vps), newvp);
+ }
+
+ newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_KEY, 0);
+ fr_pair_value_memcpy(newvp, eap_context->eap.sim.keys.K_aut, EAPSIM_AUTH_SIZE);
+
+ fr_pair_replace(&(rep->vps), newvp);
+
+ return 1;
+}
+
+/*
+ * this code runs the EAP-SIM client state machine.
+ * the *request* is from the server.
+ * the *reponse* is to the server.
+ *
+ */
+static int rc_respond_eap_sim(rc_eap_context_t *eap_context,
+ RADIUS_PACKET *req, RADIUS_PACKET *resp)
+{
+ enum eapsim_clientstates state, newstate;
+ enum eapsim_subtype subtype, newsubtype;
+ VALUE_PAIR *vp, *statevp, *radstate, *eapid;
+ char statenamebuf[32], subtypenamebuf[32];
+
+ if ((radstate = fr_pair_list_copy_by_num(NULL, req->vps, PW_STATE, 0, TAG_ANY)) == NULL)
+ {
+ return 0;
+ }
+
+ if ((eapid = fr_pair_list_copy_by_num(NULL, req->vps, PW_EAP_ID, 0, TAG_ANY)) == NULL)
+ {
+ return 0;
+ }
+
+ /* first, dig up the state from the request packet, setting
+ * ourselves to be in EAP-SIM-Start state if there is none.
+ */
+
+ if ((statevp = fr_pair_find_by_num(resp->vps, PW_EAP_SIM_STATE, 0, TAG_ANY)) == NULL)
+ {
+ /* must be initial request */
+ statevp = fr_pair_afrom_num(resp, PW_EAP_SIM_STATE, 0);
+ statevp->vp_integer = EAPSIM_CLIENT_INIT;
+ fr_pair_replace(&(resp->vps), statevp);
+ }
+ state = statevp->vp_integer;
+
+ /*
+ * map the attributes, and authenticate them.
+ */
+ rc_unmap_eapsim_types(req);
+
+ if ((vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_SUBTYPE, 0, TAG_ANY)) == NULL)
+ {
+ return 0;
+ }
+ subtype = vp->vp_integer;
+
+ DEBUG2("IN state %s subtype %s\n",
+ sim_state2name(state, statenamebuf, sizeof(statenamebuf)),
+ sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf)));
+
+ /*
+ * look for the appropriate state, and process incoming message
+ */
+ switch (state) {
+ case EAPSIM_CLIENT_INIT:
+ switch (subtype) {
+ case EAPSIM_START:
+ newstate = rc_process_eap_start(eap_context, req, resp);
+ break;
+
+ case EAPSIM_CHALLENGE:
+ case EAPSIM_NOTIFICATION:
+ case EAPSIM_REAUTH:
+ default:
+ ERROR("sim in state %s message %s is illegal. Reply dropped.\n",
+ sim_state2name(state, statenamebuf, sizeof(statenamebuf)),
+ sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf)));
+ /* invalid state, drop message */
+ return 0;
+ }
+ break;
+
+ case EAPSIM_CLIENT_START:
+ switch (subtype) {
+ case EAPSIM_START:
+ /* NOT SURE ABOUT THIS ONE, retransmit, I guess */
+ newstate = rc_process_eap_start(eap_context, req, resp);
+ break;
+
+ case EAPSIM_CHALLENGE:
+ newstate = rc_process_eap_challenge(eap_context, req, resp);
+ break;
+
+ default:
+ ERROR("sim in state %s message %s is illegal. Reply dropped.\n",
+ sim_state2name(state, statenamebuf, sizeof(statenamebuf)),
+ sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf)));
+ /* invalid state, drop message */
+ return 0;
+ }
+ break;
+
+
+ default:
+ ERROR("sim in illegal state %s\n",
+ sim_state2name(state, statenamebuf, sizeof(statenamebuf)));
+ return 0;
+ }
+
+ /* copy the eap state object in */
+ fr_pair_replace(&(resp->vps), eapid);
+
+ /* update stete info, and send new packet */
+ rc_map_eapsim_types(resp);
+
+ /* copy the radius state object in */
+ fr_pair_replace(&(resp->vps), radstate);
+
+ vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_SUBTYPE, 0, TAG_ANY);
+ newsubtype = vp->vp_integer;
+
+
+ DEBUG2("MOVE from state %s subtype %s\n",
+ sim_state2name(state, statenamebuf, sizeof(statenamebuf)),
+ sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf)));
+
+ DEBUG2(" to state %s subtype %s\n",
+ sim_state2name(newstate, statenamebuf, sizeof(statenamebuf)),
+ sim_subtype2name(newsubtype, subtypenamebuf, sizeof(subtypenamebuf)));
+
+ statevp->vp_integer = newstate;
+ return 1;
+}
+
+static int rc_respond_eap_md5(rc_eap_context_t *eap_context,
+ RADIUS_PACKET *req, RADIUS_PACKET *rep)
+{
+ VALUE_PAIR *vp, *id, *state;
+ size_t valuesize;
+ uint8_t identifier;
+ uint8_t const *value;
+ FR_MD5_CTX context;
+ uint8_t response[16];
+
+ rc_cleanresp(rep);
+
+ if ((state = fr_pair_list_copy_by_num(NULL, req->vps, PW_STATE, 0, TAG_ANY)) == NULL)
+ {
+ ERROR("no state attribute found\n");
+ return 0;
+ }
+
+ if ((id = fr_pair_list_copy_by_num(NULL, req->vps, PW_EAP_ID, 0, TAG_ANY)) == NULL)
+ {
+ ERROR("no EAP-ID attribute found\n");
+ return 0;
+ }
+ identifier = id->vp_integer;
+
+ if ((vp = fr_pair_find_by_num(req->vps, PW_EAP_TYPE_BASE+PW_EAP_MD5, 0, TAG_ANY)) == NULL)
+ {
+ ERROR("no EAP-MD5 attribute found\n");
+ return 0;
+ }
+
+ /* got the details of the MD5 challenge */
+ valuesize = vp->vp_octets[0];
+ value = &vp->vp_octets[1];
+
+ /* sanitize items */
+ if (valuesize > vp->vp_length)
+ {
+ ERROR("md5 valuesize if too big (%u > %u)\n",
+ (unsigned int) valuesize, (unsigned int) vp->vp_length);
+ return 0;
+ }
+
+ /* now do the CHAP operation ourself, rather than build the
+ * buffer. We could also call rad_chap_encode, but it wants
+ * a CHAP-Challenge, which we don't want to bother with.
+ */
+ fr_md5_init(&context);
+ fr_md5_update(&context, &identifier, 1);
+ fr_md5_update(&context, (uint8_t *) eap_context->password, strlen(eap_context->password));
+ fr_md5_update(&context, value, valuesize);
+ fr_md5_final(response, &context);
+
+ {
+ uint8_t *p;
+ uint8_t lg_response;
+
+ vp = fr_pair_afrom_num(rep, PW_EAP_TYPE_BASE+PW_EAP_MD5, 0);
+ vp->vp_length = 17;
+
+ p = talloc_zero_array(vp, uint8_t, 17);
+ lg_response = 16;
+ memcpy(p, &lg_response, 1);
+ memcpy(p + 1, response, 16);
+ fr_pair_value_memsteal(vp, p);
+ }
+ fr_pair_replace(&(rep->vps), vp);
+
+ fr_pair_replace(&(rep->vps), id);
+
+ /* copy the state object in */
+ fr_pair_replace(&(rep->vps), state);
+
+ return 1;
+}
+
+
+/** Allocate a new socket, and add it to the packet list.
+ */
+static void rc_add_socket(fr_ipaddr_t *src_ipaddr, uint16_t src_port, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port)
+{
+ int mysockfd;
+
+ /* Trace what we're doing. */
+ char src_addr[15+1] = "";
+ char dst_addr[15+1] = "";
+ inet_ntop(AF_INET, &(src_ipaddr->ipaddr.ip4addr.s_addr), src_addr, sizeof(src_addr));
+ inet_ntop(AF_INET, &(dst_ipaddr->ipaddr.ip4addr.s_addr), dst_addr, sizeof(dst_addr));
+
+ INFO("Adding new socket: src: %s:%d, dst: %s:%d", src_addr, src_port, dst_addr, dst_port);
+
+ mysockfd = fr_socket(src_ipaddr, src_port);
+ if (mysockfd < 0) {
+ ERROR("Failed to create new socket: %s\n", fr_strerror());
+ exit(1);
+ }
+
+ if (!fr_packet_list_socket_add(pl, mysockfd, ipproto,
+#ifdef WITH_RADIUSV11
+ false,
+#endif
+ dst_ipaddr, dst_port, NULL)) {
+ ERROR("Failed to add new socket: %s\n", fr_strerror());
+ exit(1);
+ }
+
+ num_sockets ++;
+ DEBUG("Added new socket: %d (num sockets: %d)\n", mysockfd, num_sockets);
+}
+
+/** Send one packet for a transaction.
+ */
+static int rc_send_one_packet(rc_transaction_t *trans, RADIUS_PACKET **packet_p)
+{
+ if (!trans || !packet_p || !*packet_p) return -1;
+
+ assert(pl != NULL);
+
+ RADIUS_PACKET *packet = *packet_p;
+
+ if (packet->id == -1) {
+ /* Haven't sent the packet yet. Initialize it. */
+ bool rcode;
+ int i;
+
+ rc_build_eap_context(trans); /* In case of EAP, build EAP-Message and initialize EAP context. */
+
+ assert(trans->reply == NULL);
+
+ trans->tries = 0;
+ packet->src_ipaddr.af = server_ipaddr.af;
+ int nb_sock_add = 0;
+ while (1) {
+ /* Allocate a RADIUS packet ID from a suitable socket of the packet list. */
+ rcode = fr_packet_list_id_alloc(pl, ipproto, packet_p, NULL);
+
+ if (rcode) { /* Got an ID. */
+ break;
+ }
+ if (nb_sock_add >= 1) {
+ ERROR("Added %d new socket(s), but still could not get an ID (currently: %d outgoing requests).\n",
+ nb_sock_add, fr_packet_list_num_outgoing(pl));
+ exit(1);
+ }
+
+ /* Could not find a free packet ID. Allocate a new socket, then try again. */
+ rc_add_socket(&packet->src_ipaddr, packet->src_port, &packet->dst_ipaddr, packet->dst_port);
+
+ nb_sock_add ++;
+ }
+
+ assert(packet->id != -1);
+ assert(packet->data == NULL);
+
+ for (i = 0; i < 4; i++) {
+ ((uint32_t *) packet->vector)[i] = fr_rand();
+ }
+ }
+
+ /*
+ * Send the packet.
+ */
+ DEBUG2("Transaction: %u, sending packet: %u (id: %u)...\n", trans->id, trans->num_packet, packet->id);
+
+ gettimeofday(&packet->timestamp, NULL); /* set outgoing packet timestamp. */
+
+ if (rad_send(packet, NULL, secret) < 0) {
+ ERROR("Failed to send packet (sockfd: %d, id: %d): %s\n",
+ packet->sockfd, packet->id, fr_strerror());
+ }
+
+ trans->num_packet ++;
+ trans->tries ++;
+
+ if (fr_debug_lvl > 0) fr_packet_header_print(fr_log_fp, packet, false);
+ if (fr_debug_lvl > 0) vp_printlist(fr_log_fp, packet->vps);
+
+ return 1;
+}
+
+/** Send current packet of a transaction. Arm timeout event.
+ */
+static int rc_send_transaction_packet(rc_transaction_t *trans, RADIUS_PACKET **packet_p)
+// note: we need a 'RADIUS_PACKET **' for fr_packet_list_id_alloc.
+{
+ if (!trans || !packet_p || !*packet_p) return -1;
+
+ int ret = rc_send_one_packet(trans, packet_p);
+ if (ret == 1) {
+ /* Send successful: arm the timeout callback. */
+ rc_evprep_packet_timeout(trans);
+ }
+ return ret;
+}
+
+/** Deallocate RADIUS packet ID.
+ */
+static void rc_deallocate_id(rc_transaction_t *trans)
+{
+ if (!trans || !trans->packet ||
+ (trans->packet->id < 0)) {
+ return;
+ }
+
+ RADIUS_PACKET *packet = trans->packet;
+
+ DEBUG2("Deallocating (sockfd: %d, id: %d)\n", packet->sockfd, packet->id);
+
+ /*
+ * One more unused RADIUS ID.
+ */
+ fr_packet_list_id_free(pl, packet, true);
+ /* note: "true" means automatically yank, so we must *not* yank ourselves before calling (otherwise, it does nothing)
+ * so, *don't*: fr_packet_list_yank(pl, request->packet); */
+
+ /* free more stuff to ensure next allocate won't be stuck on a "full" socket. */
+ packet->id = -1;
+ packet->sockfd = -1;
+ packet->src_ipaddr.af = AF_UNSPEC;
+ packet->src_port = 0;
+
+ /*
+ * If we've already sent a packet, free up the old one,
+ * and ensure that the next packet has a unique
+ * authentication vector.
+ */
+ if (packet->data) {
+ talloc_free(packet->data);
+ packet->data = NULL;
+ }
+
+ if (trans->reply) rad_free(&trans->reply);
+}
+
+/** Receive one packet, maybe.
+ */
+static int rc_recv_one_packet(struct timeval *tv_wait_time)
+{
+ fd_set set;
+ struct timeval tv;
+ rc_transaction_t *trans;
+ RADIUS_PACKET *reply, **packet_p;
+ volatile int max_fd;
+ bool ongoing_trans = false;
+ char buffer[128];
+
+ /* Wait for reply, timing out as necessary */
+ FD_ZERO(&set);
+
+ max_fd = fr_packet_list_fd_set(pl, &set);
+ if (max_fd < 0) {
+ /* no sockets to listen on! */
+ return 0;
+ }
+
+ if (NULL == tv_wait_time) {
+ timerclear(&tv);
+ } else {
+ tv.tv_sec = tv_wait_time->tv_sec;
+ tv.tv_usec = tv_wait_time->tv_usec;
+ }
+
+ if (select(max_fd, &set, NULL, NULL, &tv) <= 0) {
+ /* No packet was received. */
+ return 0;
+ }
+
+ /*
+ * Receive the reply.
+ */
+ reply = fr_packet_list_recv(pl, &set);
+ if (!reply) {
+ ERROR("Received bad packet: %s\n", fr_strerror());
+ return -1; /* bad packet */
+ }
+
+ /*
+ * Look for the packet which matches the reply.
+ */
+ reply->src_ipaddr = server_ipaddr;
+ reply->src_port = server_port;
+
+ /*
+ * Note: this only works if all packets have the same destination (IP, port).
+ * We should handle a list of destinations. But we don't. radclient doesn't do it either).
+ */
+
+ packet_p = fr_packet_list_find_byreply(pl, reply);
+
+ if (!packet_p) {
+ /* got reply to packet we didn't send.
+ * (or maybe we sent it, got no response, freed the ID. Then server responds to first request.)
+ */
+ DEBUG("No outstanding request was found for reply from %s, port %d (sockfd: %d, id: %d)\n",
+ inet_ntop(reply->src_ipaddr.af, &reply->src_ipaddr.ipaddr, buffer, sizeof(buffer)),
+ reply->src_port, reply->sockfd, reply->id);
+ rad_free(&reply);
+ return -1;
+ }
+
+ trans = fr_packet2myptr(rc_transaction_t, packet, packet_p);
+
+ if (trans->event) fr_event_delete(ev_list, &trans->event);
+
+ /*
+ * Fails the signature validation: not a valid reply.
+ */
+ if (rad_verify(reply, trans->packet, secret) < 0) {
+ /* shared secret is incorrect.
+ * (or maybe this is a response to another packet we sent, for which we got no response,
+ * freed the ID, then reused it. Then server responds to first packet.)
+ */
+ DEBUG("Conflicting response authenticator for reply from %s (sockfd: %d, id: %d)\n",
+ inet_ntop(reply->src_ipaddr.af, &reply->src_ipaddr.ipaddr, buffer, sizeof(buffer)),
+ reply->sockfd, reply->id);
+
+ goto packet_done;
+ }
+
+ /* Set reply destination = packet source. */
+ reply->dst_ipaddr = trans->packet->src_ipaddr;
+ reply->dst_port = trans->packet->src_port;
+
+ trans->reply = reply;
+ reply = NULL;
+
+ if (rad_decode(trans->reply, trans->packet, secret) != 0) {
+ /* This can fail if packet contains too many attributes. */
+ DEBUG("Failed decoding reply\n");
+ goto packet_done;
+ }
+
+ gettimeofday(&trans->reply->timestamp, NULL); /* set received packet timestamp. */
+
+ if (trans->eap_context) {
+ /* Call unmap before packet print (so we can see the decoded EAP stuff). */
+ rc_unmap_eap_methods(trans->reply);
+ }
+
+ DEBUG2("Transaction: %u, received packet (id: %u).\n", trans->id, trans->reply->id);
+
+ if (fr_debug_lvl > 0) fr_packet_header_print(fr_log_fp, trans->reply, true);
+ if (fr_debug_lvl > 0) vp_printlist(fr_log_fp, trans->reply->vps);
+
+ if (!trans->eap_context) {
+ goto packet_done;
+ }
+
+ /* now look for the code type. */
+ VALUE_PAIR *vp, *vpnext;
+ for (vp = trans->reply->vps; vp != NULL; vp = vpnext) {
+ vpnext = vp->next;
+
+ switch (vp->da->attr) {
+ default:
+ break;
+
+ case PW_EAP_TYPE_BASE + PW_EAP_MD5:
+ if (rc_respond_eap_md5(trans->eap_context, trans->reply, trans->packet) && trans->eap_context->eap.md5.tried < 3)
+ {
+ /* answer the challenge from server. */
+ trans->eap_context->eap.md5.tried ++;
+ rc_deallocate_id(trans);
+ rc_send_transaction_packet(trans, &trans->packet);
+ ongoing_trans = true; // don't free the transaction yet.
+ }
+ goto packet_done;
+
+ case PW_EAP_TYPE_BASE + PW_EAP_SIM:
+ if (rc_respond_eap_sim(trans->eap_context, trans->reply, trans->packet)) {
+ /* answer the challenge from server. */
+ rc_deallocate_id(trans);
+ rc_send_transaction_packet(trans, &trans->packet);
+ ongoing_trans = true; // don't free the transaction yet.
+ }
+ goto packet_done;
+ }
+ }
+
+ /* EAP transaction ends here (no more requests from EAP server). */
+
+ /*
+ * success: if we have EAP-Code = Success, and reply is an Access-Accept.
+ */
+ if (trans->reply->code != PW_CODE_ACCESS_ACCEPT) {
+ DEBUG("EAP transaction finished, but reply is not an Access-Accept");
+ goto packet_done;
+ }
+ vp = fr_pair_find_by_num(trans->reply->vps, PW_EAP_CODE, 0, TAG_ANY);
+ if ( (!vp) || (vp->vp_integer != 3) ) {
+ DEBUG("EAP transaction finished, but reply does not contain EAP-Code = Success");
+ goto packet_done;
+ }
+
+ goto packet_done;
+
+packet_done:
+
+ /* Basic statistics (salvaged from old code). TODO: something better. */
+ if (trans->reply) {
+ if (trans->reply->code == PW_CODE_ACCESS_ACCEPT) {
+ totalapp ++;
+ } else if (trans->reply->code == PW_CODE_ACCESS_REJECT) {
+ totaldeny ++;
+ }
+ }
+
+ rad_free(&trans->reply);
+ rad_free(&reply); /* may be NULL */
+
+ if (!ongoing_trans) {
+ rc_deallocate_id(trans);
+ rc_finish_transaction(trans);
+ }
+
+ return 1;
+}
+
+/** Event callback: packet timeout.
+ */
+static void rc_evcb_packet_timeout(void *ctx)
+{
+ rc_transaction_t *trans = ctx;
+ if (!trans || !trans->packet) return;
+
+ DEBUG("Timeout for transaction: %d, tries (so far): %d (max: %d)", trans->id, trans->tries, retries);
+
+ if (trans->event) fr_event_delete(ev_list, &trans->event);
+
+ if (trans->tries < retries) {
+ /* Try again. */
+ rc_send_transaction_packet(trans, &trans->packet);
+ } else {
+ DEBUG("No response for transaction: %d, giving up", trans->id);
+ rc_finish_transaction(trans);
+ }
+}
+
+/** Prepare event: packet timeout.
+ */
+static void rc_evprep_packet_timeout(rc_transaction_t *trans)
+{
+ struct timeval tv_event;
+ gettimeofday(&tv_event, NULL);
+ timeradd(&tv_event, &tv_timeout, &tv_event);
+
+ if (!fr_event_insert(ev_list, rc_evcb_packet_timeout, (void *)trans, &tv_event, &trans->event)) {
+ ERROR("Failed to insert event\n");
+ exit(1);
+ }
+}
+
+/** Trigger all armed events for which time is reached.
+ */
+static int rc_loop_events(void)
+{
+ struct timeval when;
+ uint32_t nb_processed = 0;
+
+ if (!fr_event_list_num_elements(ev_list)) return 0;
+
+ while (1) {
+ gettimeofday(&when, NULL);
+ if (!fr_event_run(ev_list, &when)) {
+ /* no more. */
+ break;
+ }
+ nb_processed ++;
+ }
+ return nb_processed;
+}
+
+/** Receive loop.
+ * Handle incoming packets, until nothing more is received.
+ */
+static int dhb_loop_recv(void)
+{
+ uint32_t nb_received = 0;
+ while (rc_recv_one_packet(NULL) > 0) {
+ nb_received ++;
+ }
+ return nb_received;
+}
+
+/** Loop starting new transactions, until a limit is reached
+ * (max parallelism, or no more input available.)
+ */
+static int rc_loop_start_transactions(void)
+{
+ int nb_started = 0;
+
+ while (1) {
+ if (num_ongoing >= parallel) break;
+
+ /* Try to initialize a new transaction. */
+ rc_transaction_t *trans = rc_init_transaction(autofree);
+ if (!trans) break;
+
+ nb_started ++;
+ rc_send_transaction_packet(trans, &trans->packet);
+ }
+ return nb_started;
+}
+
+/** Main loop: Handle events. Receive and process responses. Start new transactions.
+ * Until we're done.
+ */
+static void rc_main_loop(void)
+{
+ while (1) {
+ /* Handle events. */
+ rc_loop_events();
+
+ /* Receive and process response until no more are received (don't wait). */
+ dhb_loop_recv();
+
+ /* Start new transactions and send the associated packet. */
+ rc_loop_start_transactions();
+
+ /* Check if we're done. */
+ if ( (rc_vps_list_in.size == 0)
+ && (fr_packet_list_num_outgoing(pl) == 0) ) {
+ break;
+ }
+ }
+ INFO("Main loop: done.");
+}
+
+
+void set_radius_dir(TALLOC_CTX *ctx, char const *path)
+{
+ if (radius_dir) {
+ char *p;
+
+ memcpy(&p, &radius_dir, sizeof(p));
+ talloc_free(p);
+ radius_dir = NULL;
+ }
+ if (path) radius_dir = talloc_strdup(ctx, path);
+}
+
+
+/** Set a port from the request type if we don't already have one.
+ */
+static void rc_get_port(PW_CODE type, uint16_t *port)
+{
+ switch (type) {
+ default:
+ case PW_CODE_ACCESS_REQUEST:
+ case PW_CODE_ACCESS_CHALLENGE:
+ case PW_CODE_STATUS_SERVER:
+ if (*port == 0) *port = getport("radius");
+ if (*port == 0) *port = PW_AUTH_UDP_PORT;
+ return;
+
+ case PW_CODE_ACCOUNTING_REQUEST:
+ if (*port == 0) *port = getport("radacct");
+ if (*port == 0) *port = PW_ACCT_UDP_PORT;
+ return;
+
+ case PW_CODE_DISCONNECT_REQUEST:
+ if (*port == 0) *port = PW_POD_UDP_PORT;
+ return;
+
+ case PW_CODE_COA_REQUEST:
+ if (*port == 0) *port = PW_COA_UDP_PORT;
+ return;
+
+ case PW_CODE_UNDEFINED:
+ if (*port == 0) *port = 0;
+ return;
+ }
+}
+
+/** Resolve a port to a request type.
+ */
+static PW_CODE rc_get_code(uint16_t port)
+{
+ /*
+ * getport returns 0 if the service doesn't exist
+ * so we need to return early, to avoid incorrect
+ * codes.
+ */
+ if (port == 0) return PW_CODE_UNDEFINED;
+
+ if ((port == getport("radius")) || (port == PW_AUTH_UDP_PORT) || (port == PW_AUTH_UDP_PORT_ALT)) {
+ return PW_CODE_ACCESS_REQUEST;
+ }
+ if ((port == getport("radacct")) || (port == PW_ACCT_UDP_PORT) || (port == PW_ACCT_UDP_PORT_ALT)) {
+ return PW_CODE_ACCOUNTING_REQUEST;
+ }
+ if (port == PW_COA_UDP_PORT) return PW_CODE_COA_REQUEST;
+ if (port == PW_POD_UDP_PORT) return PW_CODE_DISCONNECT_REQUEST;
+
+ return PW_CODE_UNDEFINED;
+}
+
+/** Resolve server hostname.
+ */
+static void rc_resolve_hostname(char *server_arg)
+{
+ if (force_af == AF_UNSPEC) force_af = AF_INET;
+ server_ipaddr.af = force_af;
+ if (strcmp(server_arg, "-") != 0) {
+ char *p;
+ char const *hostname = server_arg;
+ char const *portname = server_arg;
+ char buffer[256];
+
+ if (*server_arg == '[') { /* IPv6 URL encoded */
+ p = strchr(server_arg, ']');
+ if ((size_t) (p - server_arg) >= sizeof(buffer)) {
+ usage();
+ }
+
+ memcpy(buffer, server_arg + 1, p - server_arg - 1);
+ buffer[p - server_arg - 1] = '\0';
+
+ hostname = buffer;
+ portname = p + 1;
+
+ }
+ p = strchr(portname, ':');
+ if (p && (strchr(p + 1, ':') == NULL)) {
+ *p = '\0';
+ portname = p + 1;
+ } else {
+ portname = NULL;
+ }
+
+ if (ip_hton(&server_ipaddr, force_af, hostname, false) < 0) {
+ ERROR("%s: Failed to find IP address for host %s: %s\n", progname, hostname, strerror(errno));
+ exit(1);
+ }
+ server_addr_init = true;
+
+ /* Strip port from hostname if needed. */
+ if (portname) server_port = atoi(portname);
+
+ /*
+ * Work backwards from the port to determine the packet type
+ */
+ if (packet_code == PW_CODE_UNDEFINED) packet_code = rc_get_code(server_port);
+ }
+ rc_get_port(packet_code, &server_port);
+}
+
+int main(int argc, char **argv)
+{
+ char *p;
+ int c;
+ char *filename = NULL;
+ FILE *fp;
+
+ static fr_log_t radclient_log = {
+ .colourise = true,
+ .fd = STDOUT_FILENO,
+ .dst = L_DST_STDOUT,
+ .file = NULL,
+ .debug_file = NULL,
+ };
+
+ radlog_init(&radclient_log, false);
+
+ /*
+ * We probably don't want to free the talloc autofree context
+ * directly, so we'll allocate a new context beneath it, and
+ * free that before any leak reports.
+ */
+ autofree = talloc_init("main");
+
+ fr_debug_lvl = 0;
+ fr_log_fp = stdout;
+
+ set_radius_dir(autofree, RADIUS_DIR);
+
+ while ((c = getopt(argc, argv, "46c:d:D:f:hp:qst:r:S:xXv")) != EOF)
+ {
+ switch (c) {
+ case '4':
+ force_af = AF_INET;
+ break;
+ case '6':
+ force_af = AF_INET6;
+ break;
+ case 'd':
+ set_radius_dir(autofree, optarg);
+ break;
+ case 'D':
+ main_config.dictionary_dir = talloc_typed_strdup(NULL, optarg);
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case 'p':
+ parallel = atoi(optarg);
+ if (parallel == 0) parallel = 1;
+ if (parallel > 65536) parallel = 65536;
+ break;
+ case 'q':
+ do_output = 0;
+ break;
+ case 'x':
+ rad_debug_lvl++;
+ fr_debug_lvl++;
+ break;
+
+ case 'X':
+#if 0
+ sha1_data_problems = 1; /* for debugging only */
+#endif
+ break;
+
+ case 'r':
+ if (!isdigit((uint8_t) *optarg))
+ usage();
+ retries = atoi(optarg);
+ break;
+ case 's':
+ do_summary = 1;
+ break;
+ case 't':
+ if (!isdigit((uint8_t) *optarg))
+ usage();
+ timeout = atof(optarg);
+ break;
+ case 'v':
+ printf("$Id$"
+#ifndef ENABLE_REPRODUCIBLE_BUILDS
+ ", built on " __DATE__ " at " __TIME__
+#endif
+ "\n"
+ );
+ exit(0);
+
+ case 'S':
+ fp = fopen(optarg, "r");
+ if (!fp) {
+ ERROR("Error opening %s: %s\n",
+ optarg, fr_syserror(errno));
+ exit(1);
+ }
+ if (fgets(filesecret, sizeof(filesecret), fp) == NULL) {
+ ERROR("Error reading %s: %s\n",
+ optarg, fr_syserror(errno));
+ exit(1);
+ }
+ fclose(fp);
+
+ /* truncate newline */
+ p = filesecret + strlen(filesecret) - 1;
+ while ((p >= filesecret) &&
+ (*p < ' ')) {
+ *p = '\0';
+ --p;
+ }
+
+ if (strlen(filesecret) < 2) {
+ ERROR("Secret in %s is too short\n", optarg);
+ exit(1);
+ }
+ secret = filesecret;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
+ argc -= (optind - 1);
+ argv += (optind - 1);
+
+ if ((argc < 3) ||
+ ((!secret) && (argc < 4))) {
+ usage();
+ }
+
+ /* Prepare the timeout. */
+ rc_float_to_timeval(&tv_timeout, timeout);
+
+ if (!main_config.dictionary_dir) {
+ main_config.dictionary_dir = DICTDIR;
+ }
+
+ /*
+ * Read the distribution dictionaries first, then
+ * the ones in raddb.
+ */
+ DEBUG2("including dictionary file %s/%s", main_config.dictionary_dir, RADIUS_DICTIONARY);
+ if (dict_init(main_config.dictionary_dir, RADIUS_DICTIONARY) != 0) {
+ ERROR("Errors reading dictionary: %s\n", fr_strerror());
+ exit(1);
+ }
+
+ /*
+ * It's OK if this one doesn't exist.
+ */
+ int rcode = dict_read(radius_dir, RADIUS_DICTIONARY);
+ if (rcode == -1) {
+ ERROR("Errors reading %s/%s: %s\n", radius_dir, RADIUS_DICTIONARY, fr_strerror());
+ exit(1);
+ }
+
+ /*
+ * We print this after reading it. That way if
+ * it doesn't exist, it's OK, and we don't print
+ * anything.
+ */
+ if (rcode == 0) {
+ DEBUG2("Including dictionary file %s/%s", radius_dir, RADIUS_DICTIONARY);
+ }
+
+ /*
+ * Get the request type
+ */
+ if (!isdigit((uint8_t) argv[2][0])) {
+ packet_code = fr_str2int(rc_request_types, argv[2], -2);
+ if (packet_code == -2) {
+ ERROR("Unrecognised request type \"%s\"\n", argv[2]);
+ usage();
+ }
+ } else {
+ packet_code = atoi(argv[2]);
+ }
+
+ /*
+ * Resolve hostname.
+ */
+ rc_resolve_hostname(argv[1]);
+
+ /*
+ * Add the secret.
+ */
+ if (argv[3]) secret = argv[3];
+
+ /*
+ * Read input data vp(s) from the file (or stdin).
+ */
+ INFO("Loading input data...");
+ if (!rc_load_input(autofree, filename, &rc_vps_list_in, 0)
+ || rc_vps_list_in.size == 0) {
+ ERROR("No valid input. Nothing to send.\n");
+ exit(EXIT_FAILURE);
+ }
+ INFO("Loaded: %d input element(s).", rc_vps_list_in.size);
+
+ /* Initialize the packets list. */
+ MEM(pl = fr_packet_list_create(1));
+
+ /* Initialize the events list. */
+ ev_list = fr_event_list_create(autofree, NULL);
+ if (!ev_list) {
+ ERROR("Failed to create event list\n");
+ exit(1);
+ }
+
+ /*
+ * Start main loop.
+ */
+ rc_main_loop();
+
+ if (do_summary) {
+ INFO("\n\t Total approved auths: %d", totalapp);
+ INFO("\t Total denied auths: %d", totaldeny);
+ }
+
+ talloc_free(autofree);
+
+ return 0;
+}
+
+/** Given a radius request with some attributes in the EAP range, build
+ * them all into a single EAP-Message body.
+ *
+ * If there are multiple eligibles EAP-Type, the first one is picked.
+ * Function returns 0 if no EAP is involved, or the EAP-Type otherwise.
+ */
+static int rc_map_eap_methods(RADIUS_PACKET *req)
+{
+ VALUE_PAIR *vp, *vpnext;
+ int id, eapcode;
+ int eap_method = 0;
+
+ eap_packet_t *pt_ep = talloc_zero(req, eap_packet_t);
+
+ vp = fr_pair_find_by_num(req->vps, PW_EAP_ID, 0, TAG_ANY);
+ if (!vp) {
+ id = ((int)getpid() & 0xff);
+ } else {
+ id = vp->vp_integer;
+ }
+
+ vp = fr_pair_find_by_num(req->vps, PW_EAP_CODE, 0, TAG_ANY);
+ if (!vp) {
+ eapcode = PW_EAP_REQUEST;
+ } else {
+ eapcode = vp->vp_integer;
+ }
+
+ for (vp = req->vps; vp != NULL; vp = vpnext) {
+ /* save it in case it changes! */
+ vpnext = vp->next;
+
+ if (vp->da->attr >= PW_EAP_TYPE_BASE &&
+ vp->da->attr < PW_EAP_TYPE_BASE+256) {
+ break;
+ }
+ }
+
+ if (!vp) {
+ return 0;
+ }
+
+ eap_method = vp->da->attr - PW_EAP_TYPE_BASE;
+
+ switch (eap_method) {
+ case PW_EAP_IDENTITY:
+ case PW_EAP_NOTIFICATION:
+ case PW_EAP_NAK:
+ case PW_EAP_MD5:
+ case PW_EAP_OTP:
+ case PW_EAP_GTC:
+ case PW_EAP_TLS:
+ case PW_EAP_LEAP:
+ case PW_EAP_TTLS:
+ case PW_EAP_PEAP:
+ default:
+ /*
+ * no known special handling, it is just encoded as an
+ * EAP-message with the given type.
+ */
+
+ /* nuke any existing EAP-Messages */
+ fr_pair_delete_by_num(&req->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+
+ pt_ep->code = eapcode;
+ pt_ep->id = id;
+ pt_ep->type.num = eap_method;
+ pt_ep->type.length = vp->vp_length;
+
+ pt_ep->type.data = talloc_memdup(vp, vp->vp_octets, vp->vp_length);
+ talloc_set_type(pt_ep->type.data, uint8_t);
+
+ eap_basic_compose(req, pt_ep);
+ }
+
+ return eap_method;
+}
+
+/*
+ * given a radius request with an EAP-Message body, decode it specific
+ * attributes.
+ */
+static void rc_unmap_eap_methods(RADIUS_PACKET *rep)
+{
+ VALUE_PAIR *eap1;
+ eap_packet_raw_t *e;
+ int len;
+ int type;
+
+ if (!rep) return;
+
+ /* find eap message */
+ e = eap_vp2packet(NULL, rep->vps);
+ if (!e) {
+ ERROR("failed decoding EAP: %s\n", fr_strerror());
+ return;
+ }
+ /* create EAP-ID and EAP-CODE attributes to start */
+ eap1 = fr_pair_afrom_num(rep, PW_EAP_ID, 0);
+ eap1->vp_integer = e->id;
+ fr_pair_add(&(rep->vps), eap1);
+
+ eap1 = fr_pair_afrom_num(rep, PW_EAP_CODE, 0);
+ eap1->vp_integer = e->code;
+ fr_pair_add(&(rep->vps), eap1);
+
+ switch (e->code) {
+ default:
+ case PW_EAP_SUCCESS:
+ case PW_EAP_FAILURE:
+ /* no data */
+ break;
+
+ case PW_EAP_REQUEST:
+ case PW_EAP_RESPONSE:
+ /* there is a type field, which we use to create
+ * a new attribute */
+
+ /* the length was decode already into the attribute
+ * length, and was checked already. Network byte
+ * order, just pull it out using math.
+ */
+ len = e->length[0]*256 + e->length[1];
+
+ /* verify the length is big enough to hold type */
+ if (len < 5)
+ {
+ talloc_free(e);
+ return;
+ }
+
+ type = e->data[0];
+
+ type += PW_EAP_TYPE_BASE;
+ len -= 5;
+
+ if (len > MAX_STRING_LEN) {
+ len = MAX_STRING_LEN;
+ }
+
+ eap1 = fr_pair_afrom_num(rep, type, 0);
+ fr_pair_value_memcpy(eap1, e->data + 1, len);
+
+ fr_pair_add(&(rep->vps), eap1);
+ break;
+ }
+
+ talloc_free(e);
+ return;
+}
+
+static int rc_map_eapsim_types(RADIUS_PACKET *r)
+{
+ int ret;
+
+ eap_packet_t *pt_ep = talloc_zero(r, eap_packet_t);
+
+ ret = map_eapsim_basictypes(r, pt_ep);
+
+ if (ret != 1) {
+ return ret;
+ }
+
+ eap_basic_compose(r, pt_ep);
+
+ return 1;
+}
+
+static int rc_unmap_eapsim_types(RADIUS_PACKET *r)
+{
+ VALUE_PAIR *esvp;
+ uint8_t *eap_data;
+ int rcode_unmap;
+
+ esvp = fr_pair_find_by_num(r->vps, PW_EAP_TYPE_BASE+PW_EAP_SIM, 0, TAG_ANY);
+ if (!esvp) {
+ ERROR("eap: EAP-Sim attribute not found\n");
+ return 0;
+ }
+
+ eap_data = talloc_memdup(esvp, esvp->vp_octets, esvp->vp_length);
+ talloc_set_type(eap_data, uint8_t);
+
+ rcode_unmap = unmap_eapsim_basictypes(r, eap_data, esvp->vp_length);
+
+ talloc_free(eap_data);
+ return rcode_unmap;
+}
+
diff --git a/src/modules/rlm_eap/radeapclient.mk b/src/modules/rlm_eap/radeapclient.mk
new file mode 100644
index 0000000..6068f54
--- /dev/null
+++ b/src/modules/rlm_eap/radeapclient.mk
@@ -0,0 +1,29 @@
+TARGET := radeapclient
+SOURCES := radeapclient.c
+
+SOURCES += ${top_srcdir}/src/main/files.c \
+ ${top_srcdir}/src/main/threads.c \
+ ${top_srcdir}/src/main/version.c
+
+TGT_PREREQS := libfreeradius-radius.a libfreeradius-server.a
+TGT_LDLIBS := $(LIBS)
+
+#
+# For future work, if we want radeapclient to become radclient
+#
+ifneq "$(filter libfreeradius-eap%,${ALL_TGTS})" ""
+TGT_PREREQS += libfreeradius-eap.a
+
+ifneq ($(OPENSSL_LIBS),)
+SOURCES += ${top_srcdir}/src/main/cb.c ${top_srcdir}/src/main/tls.c
+TGT_LDLIBS += $(OPENSSL_LIBS)
+endif
+
+SRC_CFLAGS += -DWITH_EAPCLIENT
+SRC_INCDIRS := ${top_srcdir}/src/modules/rlm_eap/libeap
+
+ifneq ($(MAKECMDGOALS),scan)
+SRC_CFLAGS += -DBUILT_WITH_CPPFLAGS=\"$(CPPFLAGS)\" -DBUILT_WITH_CFLAGS=\"$(CFLAGS)\" -DBUILT_WITH_LDFLAGS=\"$(LDFLAGS)\" -DBUILT_WITH_LIBS=\"$(LIBS)\"
+endif
+
+endif
diff --git a/src/modules/rlm_eap/rlm_eap.c b/src/modules/rlm_eap/rlm_eap.c
new file mode 100644
index 0000000..efb9660
--- /dev/null
+++ b/src/modules/rlm_eap/rlm_eap.c
@@ -0,0 +1,859 @@
+/*
+ * This program is is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file rlm_eap.c
+ * @brief Implements the EAP framework.
+ *
+ * @copyright 2000-2003,2006 The FreeRADIUS server project
+ * @copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * @copyright 2003 Alan DeKok <aland@freeradius.org>
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+#include "rlm_eap.h"
+
+#include <sys/stat.h>
+
+static const CONF_PARSER module_config[] = {
+ { "default_eap_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_t, default_method_name), "md5" },
+ { "timer_expire", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_t, timer_limit), "60" },
+ { "max_eap_type", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_t, max_eap_type), "52" },
+ { "ignore_unknown_eap_types", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_t, ignore_unknown_types), "no" },
+ { "cisco_accounting_username_bug", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_t, mod_accounting_username_bug), "no" },
+ { "max_sessions", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_t, max_sessions), "2048" },
+ CONF_PARSER_TERMINATOR
+};
+
+/*
+ * delete all the allocated space by eap module
+ */
+static int mod_detach(void *instance)
+{
+ rlm_eap_t *inst;
+
+ inst = (rlm_eap_t *)instance;
+
+#ifdef HAVE_PTHREAD_H
+ pthread_mutex_destroy(&(inst->session_mutex));
+#endif
+
+ rbtree_free(inst->session_tree);
+ inst->session_tree = NULL;
+ eaplist_free(inst);
+
+ return 0;
+}
+
+
+/*
+ * Compare two handlers.
+ */
+static int eap_handler_cmp(void const *a, void const *b)
+{
+ int rcode;
+ eap_handler_t const *one = a;
+ eap_handler_t const *two = b;
+
+ if (one->eap_id < two->eap_id) return -1;
+ if (one->eap_id > two->eap_id) return +1;
+
+ rcode = memcmp(one->state, two->state, sizeof(one->state));
+ if (rcode != 0) return rcode;
+
+ /*
+ * As of 2.1.8, we don't key off of source IP. This
+ * a NAS to send packets load-balanced (or fail-over)
+ * across multiple intermediate proxies, and still have
+ * EAP work.
+ */
+ if (fr_ipaddr_cmp(&one->src_ipaddr, &two->src_ipaddr) != 0) {
+ char src1[64], src2[64];
+
+ fr_ntop(src1, sizeof(src1), &one->src_ipaddr);
+ fr_ntop(src2, sizeof(src2), &two->src_ipaddr);
+
+ RATE_LIMIT(WARN("EAP packets for one session are arriving from two different upstream"
+ "servers (%s and %s). Has there been a proxy fail-over?",
+ src1, src2));
+ }
+
+ return 0;
+}
+
+
+/*
+ * read the config section and load all the eap authentication types present.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void *instance)
+{
+ int i, ret;
+ eap_type_t method;
+ int num_methods;
+ CONF_SECTION *scs;
+ rlm_eap_t *inst = instance;
+
+ /*
+ * Create our own random pool.
+ */
+ for (i = 0; i < 256; i++) {
+ inst->rand_pool.randrsl[i] = fr_rand();
+ }
+ fr_randinit(&inst->rand_pool, 1);
+ inst->rand_pool.randcnt = 0;
+
+ inst->xlat_name = cf_section_name2(cs);
+ if (!inst->xlat_name) inst->xlat_name = "EAP";
+
+ if (!dict_valbyname(PW_AUTH_TYPE, 0, inst->xlat_name)) {
+ cf_log_err_cs(cs, "Failed to find 'Auth-Type %s' section. Cannot authenticate users.",
+ inst->xlat_name);
+ return -1;
+ }
+
+ /* Load all the configured EAP-Types */
+ num_methods = 0;
+ for(scs = cf_subsection_find_next(cs, NULL, NULL);
+ scs != NULL;
+ scs = cf_subsection_find_next(cs, scs, NULL)) {
+ char const *name;
+
+ name = cf_section_name1(scs);
+ if (!name) continue;
+
+ if (!strcmp(name, TLS_CONFIG_SECTION)) continue;
+
+ /*
+ * Don't break configurations for lazy people who still have LEAP enabled.
+ */
+ if (!strcmp(name, "leap")) {
+ WARN("rlm_eap (%s): Ignoring EAP method 'leap', because it is no longer supported",
+ inst->xlat_name);
+ continue;
+ }
+
+ /*
+ * Easier sometimes than commenting out blocks,
+ * or deleting blocks.
+ */
+ if (!strcmp(name, "disable")) continue;
+
+ method = eap_name2type(name);
+ if (method == PW_EAP_INVALID) {
+ cf_log_err_cs(cs, "No dictionary definition for EAP method %s", name);
+ return -1;
+ }
+
+ if ((method < PW_EAP_MD5) || (method >= PW_EAP_MAX_TYPES)) {
+ cf_log_err_cs(cs, "Invalid EAP method %s (unsupported)", name);
+ return -1;
+ }
+
+#if !defined(HAVE_OPENSSL_SSL_H) || !defined(HAVE_LIBSSL)
+ /*
+ * This allows the default configuration to be
+ * shipped with EAP-TLS, etc. enabled. If the
+ * system doesn't have OpenSSL, they will be
+ * ignored.
+ *
+ * If the system does have OpenSSL, then this
+ * code will not be used. The administrator will
+ * then have to delete the tls,
+ * etc. configurations from eap.conf in order to
+ * have EAP without the TLS types.
+ */
+ switch (method) {
+ case PW_EAP_FAST:
+ case PW_EAP_TLS:
+ case PW_EAP_TTLS:
+ case PW_EAP_PEAP:
+ case PW_EAP_PWD:
+ WARN("rlm_eap (%s): Ignoring EAP method %s because we don't have OpenSSL support",
+ inst->xlat_name, name);
+ continue;
+
+ default:
+ break;
+ }
+#endif
+
+ /*
+ * Load the type.
+ */
+ ret = eap_module_instantiate(inst, &inst->methods[method], method, scs);
+
+ (void) talloc_get_type_abort(inst->methods[method], eap_module_t);
+
+ if (ret < 0) {
+ (void) talloc_steal(inst, inst->methods[method]);
+ return -1;
+ }
+
+ (void) talloc_steal(inst, inst->methods[method]);
+ num_methods++; /* successfully loaded one more methods */
+ }
+
+ if (num_methods == 0) {
+ cf_log_err_cs(cs, "No EAP method configured, module cannot do anything");
+ return -1;
+ }
+
+ /*
+ * Ensure that the default EAP type is loaded.
+ */
+ method = eap_name2type(inst->default_method_name);
+ if (method == PW_EAP_INVALID) {
+ cf_log_err_cs(cs, "No dictionary definition for default EAP method '%s'",
+ inst->default_method_name);
+ return -1;
+ }
+
+ if (!inst->methods[method]) {
+ cf_log_err_cs(cs, "No such sub-type for default EAP method %s",
+ inst->default_method_name);
+ return -1;
+ }
+ inst->default_method = method; /* save the numerical method */
+
+ /*
+ * List of sessions are set to NULL by the memset
+ * of 'inst', above.
+ */
+
+ /*
+ * Lookup sessions in the tree. We don't free them in
+ * the tree, as that's taken care of elsewhere...
+ */
+ inst->session_tree = rbtree_create(NULL, eap_handler_cmp, NULL, 0);
+ if (!inst->session_tree) {
+ ERROR("rlm_eap (%s): Cannot initialize tree", inst->xlat_name);
+ return -1;
+ }
+ fr_link_talloc_ctx_free(inst, inst->session_tree);
+
+#ifdef HAVE_PTHREAD_H
+ if (pthread_mutex_init(&(inst->session_mutex), NULL) < 0) {
+ ERROR("rlm_eap (%s): Failed initializing mutex: %s", inst->xlat_name, fr_syserror(errno));
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+
+/*
+ * For backwards compatibility.
+ */
+static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, REQUEST *request)
+{
+ rlm_eap_t *inst;
+ eap_handler_t *handler;
+ eap_packet_raw_t *eap_packet;
+ eap_rcode_t status;
+ rlm_rcode_t rcode;
+
+ inst = (rlm_eap_t *) instance;
+
+ if (!fr_pair_find_by_num(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
+ REDEBUG("You set 'Auth-Type = %s' for a request that does "
+ "not contain an EAP-Message attribute!", inst->xlat_name);
+ return RLM_MODULE_INVALID;
+ }
+
+ /*
+ * Get the eap packet to start with
+ */
+ eap_packet = eap_vp2packet(request, request->packet->vps);
+ if (!eap_packet) {
+ RERROR("Malformed EAP Message: %s", fr_strerror());
+ return RLM_MODULE_FAIL;
+ }
+
+ /*
+ * Create the eap handler. The eap_packet will end up being
+ * "swallowed" into the handler, so we can't access it after
+ * this call.
+ */
+ handler = eap_handler(inst, &eap_packet, request);
+ if (!handler) {
+ RDEBUG2("Failed in handler");
+ return RLM_MODULE_INVALID;
+ }
+
+ /*
+ * Select the appropriate method or default to the
+ * configured one
+ */
+ status = eap_method_select(inst, handler);
+
+ /*
+ * If it failed, die.
+ */
+ if (status == EAP_INVALID) {
+ eap_fail(handler);
+ talloc_free(handler);
+ RDEBUG2("Failed in EAP select");
+ return RLM_MODULE_INVALID;
+ }
+
+#ifdef WITH_PROXY
+ /*
+ * If we're doing horrible tunneling work, remember it.
+ */
+ if ((request->options & RAD_REQUEST_OPTION_PROXY_EAP) != 0) {
+ RDEBUG2("No EAP proxy set. Not composing EAP");
+ /*
+ * Add the handle to the proxied list, so that we
+ * can retrieve it in the post-proxy stage, and
+ * send a response.
+ */
+ handler->inst_holder = inst;
+ status = request_data_add(request, inst, REQUEST_DATA_EAP_HANDLER, handler, true);
+
+ rad_assert(status == 0);
+ return RLM_MODULE_HANDLED;
+ }
+#endif
+
+#ifdef WITH_PROXY
+ /*
+ * Maybe the request was marked to be proxied. If so,
+ * proxy it.
+ */
+ if (request->proxy != NULL) {
+ VALUE_PAIR *vp = NULL;
+
+ rad_assert(!request->proxy_reply);
+
+ /*
+ * Add the handle to the proxied list, so that we
+ * can retrieve it in the post-proxy stage, and
+ * send a response.
+ */
+ handler->inst_holder = inst;
+
+ status = request_data_add(request, inst, REQUEST_DATA_EAP_HANDLER, handler, true);
+
+ rad_assert(status == 0);
+
+ /*
+ * Some simple sanity checks. These should really
+ * be handled by the radius library...
+ */
+ vp = fr_pair_find_by_num(request->proxy->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ if (vp) {
+ vp = fr_pair_find_by_num(request->proxy->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+ if (!vp) {
+ fr_pair_make(request->proxy,
+ &request->proxy->vps,
+ "Message-Authenticator",
+ NULL, T_OP_EQ);
+ }
+ }
+
+ /*
+ * Delete the "proxied to" attribute, as it's
+ * set to 127.0.0.1 for tunneled requests, and
+ * we don't want to tell the world that...
+ */
+ fr_pair_delete_by_num(&request->proxy->vps, PW_FREERADIUS_PROXIED_TO, VENDORPEC_FREERADIUS, TAG_ANY);
+
+ RWDEBUG2("Tunneled session will be proxied. Not doing EAP");
+ return RLM_MODULE_HANDLED;
+ }
+#endif
+
+ /*
+ * We are done, wrap the EAP-request in RADIUS to send
+ * with all other required radius attributes
+ */
+ rcode = eap_compose(handler);
+
+ /*
+ * Add to the list only if it is EAP-Request.
+ */
+ if ((handler->eap_ds->request->code == PW_EAP_REQUEST) &&
+ (handler->eap_ds->request->type.num >= PW_EAP_MD5)) {
+ /*
+ * Return FAIL if we can't remember the handler.
+ * This is actually disallowed by the
+ * specification, as unexpected FAILs could have
+ * been forged. However, we want to signal to
+ * everyone else involved that we are
+ * intentionally failing the session, as opposed
+ * to accidentally failing it.
+ */
+ if (!eaplist_add(inst, handler)) {
+ RDEBUG("Failed adding handler to the list");
+ eap_fail(handler);
+ talloc_free(handler);
+ return RLM_MODULE_FAIL;
+ }
+
+ } else {
+ /*
+ * Enable the cached entry on success.
+ */
+ if (handler->eap_ds->request->code == PW_EAP_SUCCESS) {
+ VALUE_PAIR *vp;
+
+ vp = fr_pair_find_by_num(request->state, PW_TLS_CACHE_FILENAME, 0, TAG_ANY);
+ if (vp) (void) chmod(vp->vp_strvalue, S_IRUSR | S_IWUSR);
+ }
+
+ /*
+ * Disable the cached entry on failure.
+ */
+ if (handler->eap_ds->request->code == PW_EAP_FAILURE) {
+ VALUE_PAIR *vp;
+
+ vp = fr_pair_find_by_num(request->state, PW_TLS_CACHE_FILENAME, 0, TAG_ANY);
+ if (vp) (void) unlink(vp->vp_strvalue);
+ }
+
+ RDEBUG2("Freeing handler");
+ /* handler is not required any more, free it now */
+ talloc_free(handler);
+ }
+
+ /*
+ * If it's an Access-Accept, RFC 2869, Section 2.3.1
+ * says that we MUST include a User-Name attribute in the
+ * Access-Accept.
+ */
+ if ((request->reply->code == PW_CODE_ACCESS_ACCEPT) &&
+ request->username) {
+ VALUE_PAIR *vp;
+
+ /*
+ * Doesn't exist, add it in.
+ */
+ vp = fr_pair_find_by_num(request->reply->vps, PW_USER_NAME, 0, TAG_ANY);
+ if (!vp) {
+ vp = request->username;
+ if (vp->da->attr != PW_USER_NAME) {
+ vp = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ }
+ if (vp) {
+ vp = fr_pair_copy(request->reply, vp);
+ fr_pair_add(&request->reply->vps, vp);
+ }
+ }
+
+ /*
+ * Cisco AP1230 has a bug and needs a zero
+ * terminated string in Access-Accept. This
+ * means it requires 2 trailing zeros. One to
+ * send in the RADIUS packet, and the other to
+ * convince the rest of the server that
+ * vp->vp_strvalue is still a NUL-terminated C
+ * string.
+ */
+ if (vp && inst->mod_accounting_username_bug) {
+ char const *old = vp->vp_strvalue;
+ char *new;
+
+ vp->vp_length++; /* account for an additional zero */
+
+ new = talloc_array(vp, char, vp->vp_length + 1);
+
+ memcpy(new, old, vp->vp_length);
+ new[vp->length] = '\0';
+ vp->vp_strvalue = new;
+
+ rad_const_free(old);
+ VERIFY_VP(vp);
+ }
+ }
+
+ return rcode;
+}
+
+/*
+ * EAP authorization DEPENDS on other rlm authorizations,
+ * to check for user existence & get their configured values.
+ * It Handles EAP-START Messages, User-Name initilization.
+ */
+static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, REQUEST *request)
+{
+ rlm_eap_t *inst;
+ int status;
+ VALUE_PAIR *vp;
+
+ inst = (rlm_eap_t *)instance;
+
+#ifdef WITH_PROXY
+ /*
+ * We don't do authorization again, once we've seen the
+ * proxy reply (or the proxied packet)
+ */
+ if (request->proxy != NULL)
+ return RLM_MODULE_NOOP;
+#endif
+
+ /*
+ * For EAP_START, send Access-Challenge with EAP Identity
+ * request. even when we have to proxy this request
+ *
+ * RFC 2869, Section 2.3.1 notes that the "domain" of the
+ * user, (i.e. where to proxy him) comes from the EAP-Identity,
+ * so we CANNOT proxy the user, until we know his identity.
+ *
+ * We therefore send an EAP Identity request.
+ */
+ status = eap_start(inst, request);
+ switch (status) {
+ case EAP_NOOP:
+ return RLM_MODULE_NOOP;
+ case EAP_FAIL:
+ return RLM_MODULE_FAIL;
+ case EAP_FOUND:
+ return RLM_MODULE_HANDLED;
+ case EAP_OK:
+ case EAP_NOTFOUND:
+ default:
+ break;
+ }
+
+ /*
+ * RFC 2869, Section 2.3.1. If a NAS sends an EAP-Identity,
+ * it MUST copy the identity into the User-Name attribute.
+ *
+ * But we don't worry about that too much. We depend on
+ * each EAP sub-module to look for handler->request->username,
+ * and to get excited if it doesn't appear.
+ */
+ vp = fr_pair_find_by_num(request->config, PW_AUTH_TYPE, 0, TAG_ANY);
+ if ((!vp) || (vp->vp_integer != PW_AUTH_TYPE_REJECT)) {
+ vp = pair_make_config("Auth-Type", inst->xlat_name, T_OP_EQ);
+ if (!vp) {
+ RDEBUG2("Failed to create Auth-Type %s: %s\n",
+ inst->xlat_name, fr_strerror());
+ return RLM_MODULE_FAIL;
+ }
+ } else {
+ RWDEBUG2("Auth-Type already set. Not setting to EAP");
+ }
+
+ if (status == EAP_OK) return RLM_MODULE_OK;
+
+ return RLM_MODULE_UPDATED;
+}
+
+
+#ifdef WITH_PROXY
+static rlm_rcode_t CC_HINT(nonnull) mod_pre_proxy(void *instance, REQUEST *request)
+{
+ VALUE_PAIR *vp;
+ size_t length;
+ rlm_eap_t *inst = instance;
+
+ vp = fr_pair_find_by_num(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ if (!vp) return RLM_MODULE_NOOP;
+
+ if (vp->vp_length < 4) return RLM_MODULE_NOOP;
+
+ if ((vp->vp_octets[0] == 0) ||( vp->vp_octets[0] > 6)) {
+ RDEBUG("EAP header byte zero has invalid value");
+
+ add_error_cause:
+ /*
+ * Invalid EAP packet (ignored)
+ */
+ pair_make_reply("Error-Cause", "202", T_OP_EQ);
+ return RLM_MODULE_REJECT;
+ }
+
+ length = (vp->vp_octets[2] << 8) | vp->vp_octets[3];
+ if (length != vp->vp_length) {
+ RDEBUG("EAP length does not match attribute length");
+ return RLM_MODULE_REJECT;
+ }
+
+ if (vp->vp_octets[0] != PW_EAP_REQUEST) return RLM_MODULE_NOOP;
+ if (!inst->max_eap_type) return RLM_MODULE_NOOP;
+
+ if (vp->vp_length < 5) return RLM_MODULE_NOOP;
+
+ if (vp->vp_octets[4] == 254) return RLM_MODULE_NOOP; /* allow extended types */
+
+ if (vp->vp_octets[4] > inst->max_eap_type) {
+ RDEBUG("EAP method %u is too large", vp->vp_octets[4]);
+ goto add_error_cause;
+ }
+
+ return RLM_MODULE_NOOP;
+}
+
+/*
+ * If we're proxying EAP, then there may be magic we need
+ * to do.
+ */
+static rlm_rcode_t CC_HINT(nonnull) mod_post_proxy(void *inst, REQUEST *request)
+{
+ size_t i;
+ size_t len;
+ ssize_t ret;
+ char *p;
+ VALUE_PAIR *vp;
+ eap_handler_t *handler;
+ vp_cursor_t cursor;
+
+ /*
+ * If there was a handler associated with this request,
+ * then it's a tunneled request which was proxied...
+ */
+ handler = request_data_get(request, inst, REQUEST_DATA_EAP_HANDLER);
+ if (handler != NULL) {
+ rlm_rcode_t rcode;
+ eap_tunnel_data_t *data;
+
+ /*
+ * Grab the tunnel callbacks from the request.
+ */
+ data = (eap_tunnel_data_t *) request_data_get(request,
+ request->proxy,
+ REQUEST_DATA_EAP_TUNNEL_CALLBACK);
+ if (!data) {
+ RERROR("Failed to retrieve callback for tunneled session!");
+ talloc_free(handler);
+ return RLM_MODULE_FAIL;
+ }
+
+ /*
+ * Do the callback...
+ */
+ RDEBUG2("Doing post-proxy callback");
+ rcode = data->callback(handler, data->tls_session);
+ talloc_free(data);
+ if (rcode == 0) {
+ RDEBUG2("Failed in post-proxy callback");
+ eap_fail(handler);
+ talloc_free(handler);
+ return RLM_MODULE_REJECT;
+ }
+
+ /*
+ * We are done, wrap the EAP-request in RADIUS to send
+ * with all other required radius attributes
+ */
+ eap_compose(handler);
+
+ /*
+ * Add to the list only if it is EAP-Request.
+ */
+ if ((handler->eap_ds->request->code == PW_EAP_REQUEST) &&
+ (handler->eap_ds->request->type.num >= PW_EAP_MD5)) {
+ if (!eaplist_add(inst, handler)) {
+ eap_fail(handler);
+ talloc_free(handler);
+ return RLM_MODULE_FAIL;
+ }
+
+ } else {
+ RDEBUG2("Freeing handler");
+ /* handler is not required any more, free it now */
+ talloc_free(handler);
+ }
+
+ /*
+ * If it's an Access-Accept, RFC 2869, Section 2.3.1
+ * says that we MUST include a User-Name attribute in the
+ * Access-Accept.
+ */
+ if ((request->reply->code == PW_CODE_ACCESS_ACCEPT) &&
+ request->username) {
+ /*
+ * Doesn't exist, add it in.
+ */
+ vp = fr_pair_find_by_num(request->reply->vps, PW_USER_NAME, 0, TAG_ANY);
+ if (!vp) {
+ pair_make_reply("User-Name",
+ request->username->vp_strvalue,
+ T_OP_EQ);
+ }
+ }
+
+ return RLM_MODULE_OK;
+ } else {
+ RDEBUG2("No pre-existing handler found");
+ }
+
+ /*
+ * This is allowed.
+ */
+ if (!request->proxy_reply) return RLM_MODULE_NOOP;
+
+ /*
+ * There may be more than one Cisco-AVPair.
+ * Ensure we find the one with the LEAP attribute.
+ */
+ fr_cursor_init(&cursor, &request->proxy_reply->vps);
+ for (;;) {
+ /*
+ * Hmm... there's got to be a better way to
+ * discover codes for vendor attributes.
+ *
+ * This is vendor Cisco (9), Cisco-AVPair
+ * attribute (1)
+ */
+ vp = fr_cursor_next_by_num(&cursor, 1, 9, TAG_ANY);
+ if (!vp) {
+ return RLM_MODULE_NOOP;
+ }
+
+ /*
+ * If it's "leap:session-key", then stop.
+ *
+ * The format is VERY specific!
+ */
+ if (strncasecmp(vp->vp_strvalue, "leap:session-key=", 17) == 0) {
+ break;
+ }
+ }
+
+ /*
+ * The format is very specific.
+ */
+ if (vp->vp_length != (17 + 34)) {
+ RDEBUG2("Cisco-AVPair with leap:session-key has incorrect length %zu: Expected %d",
+ vp->vp_length, 17 + 34);
+ return RLM_MODULE_NOOP;
+ }
+
+ /*
+ * Decrypt the session key, using the proxy data.
+ *
+ * Note that the session key is *binary*, and therefore
+ * may contain embedded zeros. So we have to use memdup.
+ * However, Cisco-AVPair is a "string", so the rest of the
+ * code assumes that it's terminated by a trailing '\0'.
+ *
+ * So... be sure to (a) use memdup, and (b) include the last
+ * zero byte.
+ */
+ i = 34;
+ p = talloc_memdup(vp, vp->vp_strvalue, vp->vp_length + 1);
+ talloc_set_type(p, uint8_t);
+ ret = rad_tunnel_pwdecode((uint8_t *)p + 17, &i, request->home_server->secret, request->proxy->vector);
+ if (ret < 0) {
+ REDEBUG("Decoding leap:session-key failed");
+ talloc_free(p);
+ return RLM_MODULE_FAIL;
+ }
+ len = i;
+
+ if (i != 16) {
+ REDEBUG("Decoded key length is incorrect, must be 16 bytes");
+ talloc_free(p);
+ return RLM_MODULE_FAIL;
+ }
+
+ /*
+ * Encrypt the session key again, using the request data.
+ */
+ ret = rad_tunnel_pwencode(p + 17, &len, request->client->secret, request->packet->vector);
+ if (ret < 0) {
+ REDEBUG("Decoding leap:session-key failed");
+ talloc_free(p);
+ return RLM_MODULE_FAIL;
+ }
+
+ fr_pair_value_strsteal(vp, p);
+
+ return RLM_MODULE_UPDATED;
+}
+#endif
+
+static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, REQUEST *request)
+{
+ rlm_eap_t *inst = instance;
+ VALUE_PAIR *vp;
+ eap_handler_t *handler;
+ eap_packet_raw_t *eap_packet;
+
+ /*
+ * Only build a failure message if something previously rejected the request
+ */
+ vp = fr_pair_find_by_num(request->config, PW_POST_AUTH_TYPE, 0, TAG_ANY);
+
+ if (!vp || (vp->vp_integer != PW_POST_AUTH_TYPE_REJECT)) return RLM_MODULE_NOOP;
+
+ if (!fr_pair_find_by_num(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
+ RDEBUG3("Request didn't contain an EAP-Message, not inserting EAP-Failure");
+ return RLM_MODULE_NOOP;
+ }
+
+ if (fr_pair_find_by_num(request->reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
+ RDEBUG3("Reply already contained an EAP-Message, not inserting EAP-Failure");
+ return RLM_MODULE_NOOP;
+ }
+
+ eap_packet = eap_vp2packet(request, request->packet->vps);
+ if (!eap_packet) {
+ RERROR("Malformed EAP Message: %s", fr_strerror());
+ return RLM_MODULE_FAIL;
+ }
+
+ handler = eap_handler(inst, &eap_packet, request);
+ if (!handler) {
+ RDEBUG2("Failed to get handler, probably already removed, not inserting EAP-Failure");
+ return RLM_MODULE_NOOP;
+ }
+
+ RDEBUG2("Request was previously rejected, inserting EAP-Failure");
+ eap_fail(handler);
+ talloc_free(handler);
+
+ /*
+ * Make sure there's a message authenticator attribute in the response
+ * RADIUS protocol code will calculate the correct value later...
+ */
+ vp = fr_pair_find_by_num(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+ if (!vp) {
+ pair_make_reply("Message-Authenticator", "0x00", T_OP_EQ);
+ }
+
+ return RLM_MODULE_UPDATED;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern module_t rlm_eap;
+module_t rlm_eap = {
+ .magic = RLM_MODULE_INIT,
+ .name = "eap",
+ .inst_size = sizeof(rlm_eap_t),
+ .config = module_config,
+ .instantiate = mod_instantiate,
+ .detach = mod_detach,
+ .methods = {
+ [MOD_AUTHENTICATE] = mod_authenticate,
+ [MOD_AUTHORIZE] = mod_authorize,
+#ifdef WITH_PROXY
+ [MOD_PRE_PROXY] = mod_pre_proxy,
+ [MOD_POST_PROXY] = mod_post_proxy,
+#endif
+ [MOD_POST_AUTH] = mod_post_auth
+ },
+};
diff --git a/src/modules/rlm_eap/rlm_eap.h b/src/modules/rlm_eap/rlm_eap.h
new file mode 100644
index 0000000..0b9311c
--- /dev/null
+++ b/src/modules/rlm_eap/rlm_eap.h
@@ -0,0 +1,116 @@
+/*
+ * rlm_eap.h Local Header file.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _RLM_EAP_H
+#define _RLM_EAP_H
+
+RCSIDH(rlm_eap_h, "$Id$")
+
+#include <freeradius-devel/modpriv.h>
+#include "eap.h"
+#include "eap_types.h"
+
+/*
+ * Keep track of which sub modules we've loaded.
+ */
+typedef struct eap_module {
+ char const *name;
+ rlm_eap_module_t *type;
+ fr_dlhandle handle;
+ CONF_SECTION *cs;
+ void *instance;
+} eap_module_t;
+
+/*
+ * This structure contains eap's persistent data.
+ * sessions = remembered sessions, in a tree for speed.
+ * types = All supported EAP-Types
+ * mutex = ensure only one thread is updating the sessions[] struct
+ */
+typedef struct rlm_eap {
+ rbtree_t *session_tree;
+ eap_handler_t *session_head, *session_tail;
+ eap_module_t *methods[PW_EAP_MAX_TYPES];
+
+ /*
+ * Configuration items.
+ */
+ uint32_t timer_limit;
+ uint32_t max_eap_type;
+
+ char const *default_method_name;
+ eap_type_t default_method;
+
+ bool ignore_unknown_types;
+ bool mod_accounting_username_bug;
+
+ uint32_t max_sessions;
+
+#ifdef HAVE_PTHREAD_H
+ pthread_mutex_t session_mutex;
+ pthread_mutex_t handler_mutex;
+#endif
+
+ char const *xlat_name; /* no xlat's yet */
+ fr_randctx rand_pool;
+} rlm_eap_t;
+
+/*
+ * For simplicity in the rest of the code.
+ */
+#ifndef HAVE_PTHREAD_H
+/*
+ * This is easier than ifdef's throughout the code.
+ */
+#define pthread_mutex_init(_x, _y)
+#define pthread_mutex_destroy(_x)
+#define pthread_mutex_lock(_x)
+#define pthread_mutex_unlock(_x)
+#endif
+
+/* function definitions */
+/* EAP-Type */
+int eap_module_instantiate(rlm_eap_t *inst, eap_module_t **method, eap_type_t num, CONF_SECTION *cs);
+eap_rcode_t eap_method_select(rlm_eap_t *inst, eap_handler_t *handler);
+
+/* EAP */
+int eap_start(rlm_eap_t *inst, REQUEST *request) CC_HINT(nonnull);
+void eap_fail(eap_handler_t *handler) CC_HINT(nonnull);
+void eap_success(eap_handler_t *handler) CC_HINT(nonnull);
+rlm_rcode_t eap_compose(eap_handler_t *handler) CC_HINT(nonnull);
+eap_handler_t *eap_handler(rlm_eap_t *inst, eap_packet_raw_t **eap_msg, REQUEST *request) CC_HINT(nonnull);
+
+/* Memory Management */
+EAP_DS *eap_ds_alloc(eap_handler_t *handler);
+eap_handler_t *eap_handler_alloc(rlm_eap_t *inst);
+void eap_ds_free(EAP_DS **eap_ds);
+int eaplist_add(rlm_eap_t *inst, eap_handler_t *handler) CC_HINT(nonnull);
+eap_handler_t *eaplist_find(rlm_eap_t *inst, REQUEST *request, eap_packet_raw_t *eap_packet);
+void eaplist_free(rlm_eap_t *inst);
+
+/* State */
+void generate_key(void);
+VALUE_PAIR *generate_state(time_t timestamp);
+int verify_state(VALUE_PAIR *state, time_t timestamp);
+
+#endif /*_RLM_EAP_H*/
diff --git a/src/modules/rlm_eap/rlm_eap.mk b/src/modules/rlm_eap/rlm_eap.mk
new file mode 100644
index 0000000..4459563
--- /dev/null
+++ b/src/modules/rlm_eap/rlm_eap.mk
@@ -0,0 +1,6 @@
+TARGET := rlm_eap.a
+SOURCES := rlm_eap.c eap.c mem.c
+
+SRC_INCDIRS := . libeap
+
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/all.mk b/src/modules/rlm_eap/types/all.mk
new file mode 100644
index 0000000..b85d501
--- /dev/null
+++ b/src/modules/rlm_eap/types/all.mk
@@ -0,0 +1 @@
+SUBMAKEFILES := $(wildcard ${top_srcdir}/src/modules/rlm_eap/types/rlm_eap_*/all.mk)
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/.gitignore b/src/modules/rlm_eap/types/rlm_eap_fast/.gitignore
new file mode 100644
index 0000000..01a5daa
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/.gitignore
@@ -0,0 +1 @@
+all.mk
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/README.md b/src/modules/rlm_eap/types/rlm_eap_fast/README.md
new file mode 100644
index 0000000..0112975
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/README.md
@@ -0,0 +1,10 @@
+# rlm_eap_fast
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements [RFC 4851](https://tools.ietf.org/html/rfc4851),
+Cisco's EAP-FAST (Flexible Authentication via Secure Tunnelling)
+protocol.
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/all.mk.in b/src/modules/rlm_eap/types/rlm_eap_fast/all.mk.in
new file mode 100644
index 0000000..41920f5
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/all.mk.in
@@ -0,0 +1,12 @@
+TARGETNAME := @targetname@
+
+ifneq "$(OPENSSL_LIBS)" ""
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+endif
+
+SOURCES := $(TARGETNAME).c eap_fast.c eap_fast_crypto.c
+
+SRC_INCDIRS := ${top_srcdir}/src/modules/rlm_eap/ ${top_srcdir}/src/modules/rlm_eap/libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/configure b/src/modules/rlm_eap/types/rlm_eap_fast/configure
new file mode 100755
index 0000000..5aeb696
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/configure
@@ -0,0 +1,4512 @@
+#! /bin/sh
+# From configure.ac Revision.
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="rlm_eap_fast.c"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+mod_cflags
+mod_ldflags
+targetname
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_rlm_eap_fast
+with_openssl_lib_dir
+with_openssl_include_dir
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-rlm_eap_fast build without rlm_eap_fast
+ --with-openssl-lib-dir=DIR
+ directory for LDAP library files
+ -with-openssl-include-dir=DIR
+ directory for LDAP include files
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+echo
+echo Running tests for rlm_eap_fast
+echo
+
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+# Check whether --with-rlm_eap_fast was given.
+if test "${with_rlm_eap_fast+set}" = set; then :
+ withval=$with_rlm_eap_fast;
+fi
+
+
+
+mod_ldflags=
+mod_cflags=
+
+
+fail=
+fr_status=
+fr_features=
+: > "config.report"
+: > "config.report.tmp"
+
+
+
+if test x"$with_rlm_eap_fast" != xno; then
+
+
+openssl_lib_dir=
+
+# Check whether --with-openssl-lib-dir was given.
+if test "${with_openssl_lib_dir+set}" = set; then :
+ withval=$with_openssl_lib_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need openssl-lib-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_lib_dir="$withval"
+ ;;
+ esac
+fi
+
+
+openssl_include_dir=
+
+# Check whether --with-openssl-include-dir was given.
+if test "${with_openssl_include_dir+set}" = set; then :
+ withval=$with_openssl_include_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need openssl-include-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_include_dir="$withval"
+ ;;
+ esac
+fi
+
+
+
+smart_try_dir=$openssl_include_dir
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_safe=`echo "openssl/ec.h" | sed 'y%./+-%__pm%'`
+old_CPPFLAGS="$CPPFLAGS"
+smart_include=
+smart_include_dir="/usr/local/include /opt/include"
+
+_smart_try_dir=
+_smart_include_dir=
+
+for _prefix in $smart_prefix ""; do
+ for _dir in $smart_try_dir; do
+ _smart_try_dir="${_smart_try_dir} ${_dir}/${_prefix}"
+ done
+
+ for _dir in $smart_include_dir; do
+ _smart_include_dir="${_smart_include_dir} ${_dir}/${_prefix}"
+ done
+done
+
+if test "x$_smart_try_dir" != "x"; then
+ for try in $_smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ec.h in $try" >&5
+$as_echo_n "checking for openssl/ec.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" = "x"; then
+ for _prefix in $smart_prefix; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${_prefix}/openssl/ec.h" >&5
+$as_echo_n "checking for ${_prefix}/openssl/ec.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem ${_prefix}/"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+fi
+
+if test "x$smart_include" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ec.h" >&5
+$as_echo_n "checking for openssl/ec.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include=" "
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "x$smart_include" = "x"; then
+
+ for try in $_smart_include_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ec.h in $try" >&5
+$as_echo_n "checking for openssl/ec.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" != "x"; then
+ eval "ac_cv_header_$ac_safe=yes"
+ CPPFLAGS="$smart_include $old_CPPFLAGS"
+ SMART_CPPFLAGS="$smart_include $SMART_CPPFLAGS"
+fi
+
+smart_prefix=
+
+if test "$ac_cv_header_openssl_ec_h" != "yes"; then
+
+fail="$fail openssl/ec.h"
+
+fi
+
+smart_try_dir=$openssl_lib_dir
+
+
+sm_lib_safe=`echo "crypto" | sed 'y%./+-%__p_%'`
+sm_func_safe=`echo "EVP_CIPHER_CTX_new" | sed 'y%./+-%__p_%'`
+
+old_LIBS="$LIBS"
+old_CPPFLAGS="$CPPFLAGS"
+smart_lib=
+smart_ldflags=
+smart_lib_dir=
+
+if test "x$smart_try_dir" != "x"; then
+ for try in $smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto in $try" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto in $try... " >&6; }
+ LIBS="-lcrypto $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char EVP_CIPHER_CTX_new();
+int
+main ()
+{
+EVP_CIPHER_CTX_new()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lcrypto"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto... " >&6; }
+ LIBS="-lcrypto $old_LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char EVP_CIPHER_CTX_new();
+int
+main ()
+{
+EVP_CIPHER_CTX_new()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lcrypto"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$old_LIBS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ for try in /usr/local/lib /opt/lib; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto in $try" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto in $try... " >&6; }
+ LIBS="-lcrypto $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char EVP_CIPHER_CTX_new();
+int
+main ()
+{
+EVP_CIPHER_CTX_new()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lcrypto"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" != "x"; then
+ eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes"
+ LIBS="$smart_ldflags $smart_lib $old_LIBS"
+ SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS"
+fi
+
+if test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" != "xyes"; then
+
+fail="$fail libssl"
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <openssl/crypto.h>
+ #if (OPENSSL_VERSION_NUMBER >= 0x01000100fL)
+ yes
+ #endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL version >= 1.0.1a" >&5
+$as_echo_n "checking for OpenSSL version >= 1.0.1a... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL version >= 1.0.1a" >&5
+$as_echo_n "checking for OpenSSL version >= 1.0.1a... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fail="$fail OpenSSL>1.0.1"
+
+
+
+fi
+rm -f conftest*
+
+
+
+ targetname=rlm_eap_fast
+else
+ targetname=
+ echo \*\*\* module rlm_eap_fast is disabled.
+
+
+fr_status="disabled"
+
+fi
+
+if test x"$fail" != x""; then
+ targetname=""
+
+
+ if test x"${enable_strict_dependencies}" = x"yes"; then
+ as_fn_error $? "set --without-rlm_eap_fast to disable it explicitly." "$LINENO" 5
+ else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: silently not building rlm_eap_fast." >&5
+$as_echo "$as_me: WARNING: silently not building rlm_eap_fast." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: FAILURE: rlm_eap_fast requires: $fail." >&5
+$as_echo "$as_me: WARNING: FAILURE: rlm_eap_fast requires: $fail." >&2;};
+ fail="$(echo $fail)"
+
+
+fr_status="skipping (requires $fail)"
+
+ fr_features=
+
+ fi
+
+else
+
+
+fr_status="OK"
+
+fi
+
+if test x"$fr_features" = x""; then
+ $as_echo "$fr_status" > "config.report"
+else
+ $as_echo_n "$fr_status ... " > "config.report"
+ cat "config.report.tmp" >> "config.report"
+fi
+
+rm "config.report.tmp"
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files all.mk"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "all.mk") CONFIG_FILES="$CONFIG_FILES all.mk" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/configure.ac b/src/modules/rlm_eap/types/rlm_eap_fast/configure.ac
new file mode 100644
index 0000000..b778c42
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/configure.ac
@@ -0,0 +1,86 @@
+AC_PREREQ([2.69])
+AC_INIT
+AC_CONFIG_SRCDIR([rlm_eap_fast.c])
+AC_REVISION($Revision$)
+FR_INIT_MODULE([rlm_eap_fast])
+
+mod_ldflags=
+mod_cflags=
+
+FR_MODULE_START_TESTS
+
+dnl ############################################################
+dnl # Check for command line options
+dnl ############################################################
+dnl extra argument: --with-openssl-lib-dir
+openssl_lib_dir=
+AC_ARG_WITH(openssl-lib-dir,
+ [AS_HELP_STRING([--with-openssl-lib-dir=DIR],
+ [directory for LDAP library files])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need openssl-lib-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_lib_dir="$withval"
+ ;;
+ esac])
+
+dnl extra argument: --with-openssl-include-dir
+openssl_include_dir=
+AC_ARG_WITH(openssl-include-dir,
+ [AS_HELP_STRING([-with-openssl-include-dir=DIR],
+ [directory for LDAP include files])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need openssl-include-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_include_dir="$withval"
+ ;;
+ esac])
+
+dnl ############################################################
+dnl # Check for header files
+dnl ############################################################
+
+smart_try_dir=$openssl_include_dir
+FR_SMART_CHECK_INCLUDE(openssl/ec.h)
+if test "$ac_cv_header_openssl_ec_h" != "yes"; then
+ FR_MODULE_FAIL([openssl/ec.h])
+fi
+
+smart_try_dir=$openssl_lib_dir
+FR_SMART_CHECK_LIB(crypto, EVP_CIPHER_CTX_new)
+if test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" != "xyes"; then
+ FR_MODULE_FAIL([libssl])
+fi
+
+AC_EGREP_CPP(yes,
+ [#include <openssl/crypto.h>
+ #if (OPENSSL_VERSION_NUMBER >= 0x01000100fL)
+ yes
+ #endif
+ ],
+ [
+ AC_MSG_CHECKING([for OpenSSL version >= 1.0.1a])
+ AC_MSG_RESULT(yes)
+ ],
+ [
+ AC_MSG_CHECKING([for OpenSSL version >= 1.0.1a])
+ AC_MSG_RESULT(no)
+ FR_MODULE_FAIL([OpenSSL>1.0.1])
+ ]
+)
+
+FR_MODULE_END_TESTS
+
+AC_SUBST(mod_ldflags)
+AC_SUBST(mod_cflags)
+
+AC_CONFIG_FILES([all.mk])
+AC_OUTPUT
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c
new file mode 100644
index 0000000..bbb5a03
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c
@@ -0,0 +1,1315 @@
+/*
+ * eap_fast.c contains the interfaces that are called from the main handler
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2016 Alan DeKok <aland@freeradius.org>
+ * Copyright 2016 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+
+#include "eap_fast.h"
+#include "eap_fast_crypto.h"
+#include <freeradius-devel/sha1.h>
+#include <openssl/ssl.h>
+#include <openssl/rand.h>
+
+#define RANDFILL(x) do { rad_assert(sizeof(x) % sizeof(uint32_t) == 0); for (size_t i = 0; i < sizeof(x); i += sizeof(uint32_t)) *((uint32_t *)&x[i]) = fr_rand(); } while(0)
+
+/*
+ * Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
+ * All Rights Reserved.
+ *
+ * These programs are licensed under the BSD license (the one with
+ * advertisement clause removed).
+ *
+ * this function shamelessly stolen from from hostap:src/crypto/tls_openssl.c
+ */
+static int openssl_get_keyblock_size(REQUEST *request, SSL *ssl)
+{
+ const EVP_CIPHER *c;
+ const EVP_MD *h;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ int md_size;
+
+ if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
+ ssl->read_hash == NULL)
+ return -1;
+
+ c = ssl->enc_read_ctx->cipher;
+ h = EVP_MD_CTX_md(ssl->read_hash);
+ if (h)
+ md_size = EVP_MD_size(h);
+ else if (ssl->s3)
+ md_size = ssl->s3->tmp.new_mac_secret_size;
+ else
+ return -1;
+
+ RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d "
+ "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
+ EVP_CIPHER_iv_length(c));
+ return 2 * (EVP_CIPHER_key_length(c) +
+ md_size +
+ EVP_CIPHER_iv_length(c));
+#else
+ const SSL_CIPHER *ssl_cipher;
+ int cipher, digest;
+ int mac_key_len, enc_key_len, fixed_iv_len;
+
+ ssl_cipher = SSL_get_current_cipher(ssl);
+ if (!ssl_cipher)
+ return -1;
+ cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
+ digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
+ RDEBUG3("OpenSSL: cipher nid %d digest nid %d",
+ cipher, digest);
+ if (cipher < 0 || digest < 0)
+ return -1;
+ if (cipher == NID_undef) {
+ RDEBUG3("OpenSSL: no cipher in use?!");
+ return -1;
+ }
+ c = EVP_get_cipherbynid(cipher);
+ if (!c)
+ return -1;
+ enc_key_len = EVP_CIPHER_key_length(c);
+ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE ||
+ EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE)
+ fixed_iv_len = 4; /* only part of IV from PRF */
+ else
+ fixed_iv_len = EVP_CIPHER_iv_length(c);
+ if (digest == NID_undef) {
+ RDEBUG3("OpenSSL: no digest in use (e.g., AEAD)");
+ mac_key_len = 0;
+ } else {
+ h = EVP_get_digestbynid(digest);
+ if (!h)
+ return -1;
+ mac_key_len = EVP_MD_size(h);
+ }
+
+ RDEBUG2("OpenSSL: keyblock size: mac_key_len=%d enc_key_len=%d fixed_iv_len=%d",
+ mac_key_len, enc_key_len, fixed_iv_len);
+ return 2 * (mac_key_len + enc_key_len + fixed_iv_len);
+#endif
+}
+
+/**
+ * RFC 4851 section 5.1 - EAP-FAST Authentication Phase 1: Key Derivations
+ */
+static void eap_fast_init_keys(REQUEST *request, tls_session_t *tls_session)
+{
+ eap_fast_tunnel_t *t = tls_session->opaque;
+ uint8_t *buf;
+ size_t ksize;
+
+ RDEBUG2("Deriving EAP-FAST keys");
+
+ rad_assert(t->simck == NULL);
+
+ ksize = openssl_get_keyblock_size(request, tls_session->ssl);
+ rad_assert(ksize > 0);
+ buf = talloc_size(request, ksize + sizeof(*t->keyblock));
+
+ t->keyblock = talloc(t, eap_fast_keyblock_t);
+
+ eap_fast_tls_gen_challenge(tls_session->ssl, SSL_version(tls_session->ssl), buf, ksize + sizeof(*t->keyblock), "key expansion");
+ memcpy(t->keyblock, &buf[ksize], sizeof(*t->keyblock));
+ memset(buf, 0, ksize + sizeof(*t->keyblock));
+
+ t->simck = talloc_size(t, EAP_FAST_SIMCK_LEN);
+ memcpy(t->simck, t->keyblock, EAP_FAST_SKS_LEN); /* S-IMCK[0] = session_key_seed */
+
+ t->cmk = talloc_size(t, EAP_FAST_CMK_LEN); /* note that CMK[0] is not defined */
+ t->imckc = 0;
+
+ talloc_free(buf);
+}
+
+/**
+ * RFC 4851 section 5.2 - Intermediate Compound Key Derivations
+ */
+static void eap_fast_update_icmk(REQUEST *request, tls_session_t *tls_session, uint8_t *msk)
+{
+ eap_fast_tunnel_t *t = tls_session->opaque;
+ uint8_t imck[EAP_FAST_SIMCK_LEN + EAP_FAST_CMK_LEN];
+
+ RDEBUG2("Updating ICMK");
+
+ T_PRF(t->simck, EAP_FAST_SIMCK_LEN, "Inner Methods Compound Keys", msk, 32, imck, sizeof(imck));
+
+ memcpy(t->simck, imck, EAP_FAST_SIMCK_LEN);
+ memcpy(t->cmk, &imck[EAP_FAST_SIMCK_LEN], EAP_FAST_CMK_LEN);
+ t->imckc++;
+
+ /*
+ * Calculate MSK/EMSK at the same time as they are coupled to ICMK
+ *
+ * RFC 4851 section 5.4 - EAP Master Session Key Generation
+ */
+ t->msk = talloc_size(t, EAP_FAST_KEY_LEN);
+ T_PRF(t->simck, EAP_FAST_SIMCK_LEN, "Session Key Generating Function", NULL, 0, t->msk, EAP_FAST_KEY_LEN);
+
+ t->emsk = talloc_size(t, EAP_EMSK_LEN);
+ T_PRF(t->simck, EAP_FAST_SIMCK_LEN, "Extended Session Key Generating Function", NULL, 0, t->emsk, EAP_EMSK_LEN);
+}
+
+void eap_fast_tlv_append(tls_session_t *tls_session, int tlv, bool mandatory, int length, const void *data)
+{
+ uint16_t hdr[2];
+
+ hdr[0] = (mandatory) ? htons(tlv | EAP_FAST_TLV_MANDATORY) : htons(tlv);
+ hdr[1] = htons(length);
+
+ tls_session->record_plus(&tls_session->clean_in, &hdr, 4);
+ tls_session->record_plus(&tls_session->clean_in, data, length);
+}
+
+static void eap_fast_send_error(tls_session_t *tls_session, int error)
+{
+ uint32_t value;
+ value = htonl(error);
+
+ eap_fast_tlv_append(tls_session, EAP_FAST_TLV_ERROR, true, sizeof(value), &value);
+}
+
+static void eap_fast_append_result(tls_session_t *tls_session, PW_CODE code)
+{
+ eap_fast_tunnel_t *t = (eap_fast_tunnel_t *) tls_session->opaque;
+
+ int type = (t->result_final)
+ ? EAP_FAST_TLV_RESULT
+ : EAP_FAST_TLV_INTERMED_RESULT;
+
+ uint16_t state = (code == PW_CODE_ACCESS_REJECT)
+ ? EAP_FAST_TLV_RESULT_FAILURE
+ : EAP_FAST_TLV_RESULT_SUCCESS;
+ state = htons(state);
+
+ eap_fast_tlv_append(tls_session, type, true, sizeof(state), &state);
+}
+
+static void eap_fast_send_identity_request(REQUEST *request, tls_session_t *tls_session, eap_handler_t *eap_session)
+{
+ eap_packet_raw_t eap_packet;
+
+ RDEBUG("Sending EAP-Identity");
+
+ eap_packet.code = PW_EAP_REQUEST;
+ eap_packet.id = eap_session->eap_ds->response->id + 1;
+ eap_packet.length[0] = 0;
+ eap_packet.length[1] = EAP_HEADER_LEN + 1;
+ eap_packet.data[0] = PW_EAP_IDENTITY;
+
+ eap_fast_tlv_append(tls_session, EAP_FAST_TLV_EAP_PAYLOAD, true, sizeof(eap_packet), &eap_packet);
+}
+
+static void eap_fast_send_pac_tunnel(REQUEST *request, tls_session_t *tls_session)
+{
+ eap_fast_tunnel_t *t = tls_session->opaque;
+ eap_fast_pac_t pac;
+ eap_fast_attr_pac_opaque_plaintext_t opaque_plaintext;
+ int alen, dlen;
+
+ memset(&pac, 0, sizeof(pac));
+ memset(&opaque_plaintext, 0, sizeof(opaque_plaintext));
+
+ RDEBUG("Sending Tunnel PAC");
+
+ pac.key.hdr.type = htons(EAP_FAST_TLV_MANDATORY | PAC_INFO_PAC_KEY);
+ pac.key.hdr.length = htons(sizeof(pac.key.data));
+ rad_assert(sizeof(pac.key.data) % sizeof(uint32_t) == 0);
+ RANDFILL(pac.key.data);
+
+ pac.info.lifetime.hdr.type = htons(PAC_INFO_PAC_LIFETIME);
+ pac.info.lifetime.hdr.length = htons(sizeof(pac.info.lifetime.data));
+ pac.info.lifetime.data = htonl(time(NULL) + t->pac_lifetime);
+
+ pac.info.a_id.hdr.type = htons(EAP_FAST_TLV_MANDATORY | PAC_INFO_A_ID);
+ pac.info.a_id.hdr.length = htons(sizeof(pac.info.a_id.data));
+ memcpy(pac.info.a_id.data, t->a_id, sizeof(pac.info.a_id.data));
+
+ pac.info.a_id_info.hdr.type = htons(PAC_INFO_A_ID_INFO);
+ pac.info.a_id_info.hdr.length = htons(sizeof(pac.info.a_id_info.data));
+ #define MIN(a,b) (((a)>(b)) ? (b) : (a))
+ alen = MIN(talloc_array_length(t->authority_identity) - 1, sizeof(pac.info.a_id_info.data));
+ memcpy(pac.info.a_id_info.data, t->authority_identity, alen);
+
+ pac.info.type.hdr.type = htons(EAP_FAST_TLV_MANDATORY | PAC_INFO_PAC_TYPE);
+ pac.info.type.hdr.length = htons(sizeof(pac.info.type.data));
+ pac.info.type.data = htons(PAC_TYPE_TUNNEL);
+
+ pac.info.hdr.type = htons(EAP_FAST_TLV_MANDATORY | PAC_INFO_PAC_INFO);
+ pac.info.hdr.length = htons(sizeof(pac.info.lifetime)
+ + sizeof(pac.info.a_id)
+ + sizeof(pac.info.a_id_info)
+ + sizeof(pac.info.type));
+
+ memcpy(&opaque_plaintext.type, &pac.info.type, sizeof(opaque_plaintext.type));
+ memcpy(&opaque_plaintext.lifetime, &pac.info.lifetime, sizeof(opaque_plaintext.lifetime));
+ memcpy(&opaque_plaintext.key, &pac.key, sizeof(opaque_plaintext.key));
+
+
+ rad_assert(PAC_A_ID_LENGTH <= EVP_GCM_TLS_TAG_LEN);
+ memcpy(pac.opaque.aad, t->a_id, PAC_A_ID_LENGTH);
+ rad_assert(RAND_bytes(pac.opaque.iv, sizeof(pac.opaque.iv)) != 0);
+ dlen = eap_fast_encrypt((unsigned const char *)&opaque_plaintext, sizeof(opaque_plaintext),
+ t->a_id, PAC_A_ID_LENGTH, t->pac_opaque_key, pac.opaque.iv,
+ pac.opaque.data, pac.opaque.tag);
+ if (dlen < 0) return;
+
+ pac.opaque.hdr.type = htons(EAP_FAST_TLV_MANDATORY | PAC_INFO_PAC_OPAQUE);
+ pac.opaque.hdr.length = htons(sizeof(pac.opaque) - sizeof(pac.opaque.hdr) - sizeof(pac.opaque.data) + dlen);
+
+ eap_fast_tlv_append(tls_session, EAP_FAST_TLV_MANDATORY | EAP_FAST_TLV_PAC, true,
+ sizeof(pac) - sizeof(pac.opaque.data) + dlen, &pac);
+}
+
+static void eap_fast_append_crypto_binding(REQUEST *request, tls_session_t *tls_session)
+{
+ eap_fast_tunnel_t *t = tls_session->opaque;
+ eap_tlv_crypto_binding_tlv_t binding;
+ const int len = sizeof(binding) - (&binding.reserved - (uint8_t *)&binding);
+
+ RDEBUG("Sending Cryptobinding");
+
+ memset(&binding, 0, sizeof(eap_tlv_crypto_binding_tlv_t));
+ binding.tlv_type = htons(EAP_FAST_TLV_MANDATORY | EAP_FAST_TLV_CRYPTO_BINDING);
+ binding.length = htons(len);
+ binding.version = EAP_FAST_VERSION;
+ binding.received_version = EAP_FAST_VERSION; /* FIXME use the clients value */
+ binding.subtype = EAP_FAST_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST;
+
+ rad_assert(sizeof(binding.nonce) % sizeof(uint32_t) == 0);
+ RANDFILL(binding.nonce);
+ binding.nonce[sizeof(binding.nonce) - 1] &= ~0x01; /* RFC 4851 section 4.2.8 */
+
+ fr_hmac_sha1(binding.compound_mac, (uint8_t *)&binding, sizeof(binding), t->cmk, EAP_FAST_CMK_LEN);
+
+ eap_fast_tlv_append(tls_session, EAP_FAST_TLV_CRYPTO_BINDING, true, len, &binding.reserved);
+}
+
+static int eap_fast_verify(REQUEST *request, tls_session_t *tls_session, uint8_t const *data, unsigned int data_len)
+{
+ uint16_t attr;
+ uint16_t length;
+ unsigned int remaining = data_len;
+ int total = 0;
+ int num[EAP_FAST_TLV_MAX] = {0};
+ eap_fast_tunnel_t *t = (eap_fast_tunnel_t *) tls_session->opaque;
+ uint32_t present = 0;
+
+ rad_assert(sizeof(present) * 8 > EAP_FAST_TLV_MAX);
+
+ while (remaining > 0) {
+ if (remaining < 4) {
+ RDEBUG2("EAP-FAST TLV is too small (%u) to contain a EAP-FAST TLV header", remaining);
+ return 0;
+ }
+
+ memcpy(&attr, data, sizeof(attr));
+ attr = ntohs(attr) & EAP_FAST_TLV_TYPE;
+
+ switch (attr) {
+ case EAP_FAST_TLV_RESULT:
+ case EAP_FAST_TLV_NAK:
+ case EAP_FAST_TLV_ERROR:
+ case EAP_FAST_TLV_VENDOR_SPECIFIC:
+ case EAP_FAST_TLV_EAP_PAYLOAD:
+ case EAP_FAST_TLV_INTERMED_RESULT:
+ case EAP_FAST_TLV_PAC:
+ case EAP_FAST_TLV_CRYPTO_BINDING:
+ num[attr]++;
+ present |= 1 << attr;
+
+ if (num[EAP_FAST_TLV_EAP_PAYLOAD] > 1) {
+ RDEBUG("Too many EAP-Payload TLVs");
+unexpected:
+ for (int i = 0; i < EAP_FAST_TLV_MAX; i++)
+ if (present & (1 << i))
+ RDEBUG(" - attribute %d is present", i);
+ eap_fast_send_error(tls_session, EAP_FAST_ERR_UNEXPECTED_TLV);
+ return 0;
+ }
+
+ if (num[EAP_FAST_TLV_INTERMED_RESULT] > 1) {
+ RDEBUG("Too many Intermediate-Result TLVs");
+ goto unexpected;
+ }
+ break;
+ default:
+ if ((data[0] & 0x80) != 0) {
+ RDEBUG("Unknown mandatory TLV %02x", attr);
+ goto unexpected;
+ }
+
+ num[0]++;
+ }
+
+ total++;
+
+ memcpy(&length, data + 2, sizeof(length));
+ length = ntohs(length);
+
+ data += 4;
+ remaining -= 4;
+
+ if (length > remaining) {
+ RDEBUG2("EAP-FAST TLV %u is longer than room remaining in the packet (%u > %u).", attr,
+ length, remaining);
+ return 0;
+ }
+
+ /*
+ * If the rest of the TLVs are larger than
+ * this attribute, continue.
+ *
+ * Otherwise, if the attribute over-flows the end
+ * of the TLCs, die.
+ */
+ if (remaining < length) {
+ RDEBUG2("EAP-FAST TLV overflows packet!");
+ return 0;
+ }
+
+ /*
+ * If there's an error, we bail out of the
+ * authentication process before allocating
+ * memory.
+ */
+ if ((attr == EAP_FAST_TLV_INTERMED_RESULT) || (attr == EAP_FAST_TLV_RESULT)) {
+ uint16_t status;
+
+ if (length < 2) {
+ RDEBUG("EAP-FAST TLV %u is too short. Expected 2, got %d.", attr, length);
+ return 0;
+ }
+
+ memcpy(&status, data, 2);
+ status = ntohs(status);
+
+ if (status == EAP_FAST_TLV_RESULT_FAILURE) {
+ RDEBUG("EAP-FAST TLV %u indicates failure. Rejecting request.", attr);
+ return 0;
+ }
+
+ if (status != EAP_FAST_TLV_RESULT_SUCCESS) {
+ RDEBUG("EAP-FAST TLV %u contains unknown value. Rejecting request.", attr);
+ goto unexpected;
+ }
+ }
+
+ /*
+ * remaining > length, continue.
+ */
+ remaining -= length;
+ data += length;
+ }
+
+ /*
+ * Check if the peer mixed & matched TLVs.
+ */
+ if ((num[EAP_FAST_TLV_NAK] > 0) && (num[EAP_FAST_TLV_NAK] != total)) {
+ RDEBUG("NAK TLV sent with non-NAK TLVs. Rejecting request.");
+ goto unexpected;
+ }
+
+ if (num[EAP_FAST_TLV_INTERMED_RESULT] > 0 && num[EAP_FAST_TLV_RESULT]) {
+ RDEBUG("NAK TLV sent with non-NAK TLVs. Rejecting request.");
+ goto unexpected;
+ }
+
+ /*
+ * Check mandatory or not mandatory TLVs.
+ */
+ switch (t->stage) {
+ case TLS_SESSION_HANDSHAKE:
+ if (present) {
+ RDEBUG("Unexpected TLVs in TLS Session Handshake stage");
+ goto unexpected;
+ }
+ break;
+ case AUTHENTICATION:
+ if (present != 1 << EAP_FAST_TLV_EAP_PAYLOAD) {
+ RDEBUG("Unexpected TLVs in authentication stage");
+ goto unexpected;
+ }
+ break;
+ case CRYPTOBIND_CHECK:
+ {
+ uint32_t bits = (t->result_final)
+ ? 1 << EAP_FAST_TLV_RESULT
+ : 1 << EAP_FAST_TLV_INTERMED_RESULT;
+ if (present & ~(bits | (1 << EAP_FAST_TLV_CRYPTO_BINDING) | (1 << EAP_FAST_TLV_PAC))) {
+ RDEBUG("Unexpected TLVs in cryptobind checking stage");
+ goto unexpected;
+ }
+ break;
+ }
+ case PROVISIONING:
+ if (present & ~((1 << EAP_FAST_TLV_PAC) | (1 << EAP_FAST_TLV_RESULT))) {
+ RDEBUG("Unexpected TLVs in provisioning stage");
+ goto unexpected;
+ }
+ break;
+ case COMPLETE:
+ if (present) {
+ RDEBUG("Unexpected TLVs in complete stage");
+ goto unexpected;
+ }
+ break;
+ default:
+ RDEBUG("Unexpected stage %d", t->stage);
+ return 0;
+ }
+
+ /*
+ * We got this far. It looks OK.
+ */
+ return 1;
+}
+
+static ssize_t eap_fast_decode_vp(TALLOC_CTX *request, DICT_ATTR const *parent,
+ uint8_t const *data, size_t const attr_len, VALUE_PAIR **out)
+{
+ int8_t tag = TAG_NONE;
+ VALUE_PAIR *vp;
+ uint8_t const *p = data;
+
+ /*
+ * FIXME: Attrlen can be larger than 253 for extended attrs!
+ */
+ if (!parent || !out ) {
+ RERROR("eap_fast_decode_vp: Invalid arguments");
+ return -1;
+ }
+
+ /*
+ * Silently ignore zero-length attributes.
+ */
+ if (attr_len == 0) return 0;
+
+ /*
+ * And now that we've verified the basic type
+ * information, decode the actual p.
+ */
+ vp = fr_pair_afrom_da(request, parent);
+ if (!vp) return -1;
+
+ vp->vp_length = attr_len;
+ vp->tag = tag;
+
+ switch (parent->type) {
+ case PW_TYPE_STRING:
+ fr_pair_value_bstrncpy(vp, p, attr_len);
+ break;
+
+ case PW_TYPE_OCTETS:
+ fr_pair_value_memcpy(vp, p, attr_len);
+ break;
+
+ case PW_TYPE_ABINARY:
+ if (vp->vp_length > sizeof(vp->vp_filter)) {
+ vp->vp_length = sizeof(vp->vp_filter);
+ }
+ memcpy(vp->vp_filter, p, vp->vp_length);
+ break;
+
+ case PW_TYPE_BYTE:
+ vp->vp_byte = p[0];
+ break;
+
+ case PW_TYPE_SHORT:
+ vp->vp_short = (p[0] << 8) | p[1];
+ break;
+
+ case PW_TYPE_INTEGER:
+ memcpy(&vp->vp_integer, p, 4);
+ vp->vp_integer = ntohl(vp->vp_integer);
+ break;
+
+ case PW_TYPE_INTEGER64:
+ memcpy(&vp->vp_integer64, p, 8);
+ vp->vp_integer64 = ntohll(vp->vp_integer64);
+ break;
+
+ case PW_TYPE_DATE:
+ memcpy(&vp->vp_date, p, 4);
+ vp->vp_date = ntohl(vp->vp_date);
+ break;
+
+ case PW_TYPE_ETHERNET:
+ memcpy(vp->vp_ether, p, 6);
+ break;
+
+ case PW_TYPE_IPV4_ADDR:
+ memcpy(&vp->vp_ipaddr, p, 4);
+ break;
+
+ case PW_TYPE_IFID:
+ memcpy(vp->vp_ifid, p, 8);
+ break;
+
+ case PW_TYPE_IPV6_ADDR:
+ memcpy(&vp->vp_ipv6addr, p, 16);
+ break;
+
+ case PW_TYPE_IPV6_PREFIX:
+ /*
+ * FIXME: double-check that
+ * (vp->vp_octets[1] >> 3) matches vp->vp_length + 2
+ */
+ memcpy(vp->vp_ipv6prefix, p, vp->vp_length);
+ if (vp->vp_length < 18) {
+ memset(((uint8_t *)vp->vp_ipv6prefix) + vp->vp_length, 0,
+ 18 - vp->vp_length);
+ }
+ break;
+
+ case PW_TYPE_IPV4_PREFIX:
+ /* FIXME: do the same double-check as for IPv6Prefix */
+ memcpy(vp->vp_ipv4prefix, p, vp->vp_length);
+
+ /*
+ * /32 means "keep all bits". Otherwise, mask
+ * them out.
+ */
+ if ((p[1] & 0x3f) > 32) {
+ uint32_t addr, mask;
+
+ memcpy(&addr, vp->vp_octets + 2, sizeof(addr));
+ mask = 1;
+ mask <<= (32 - (p[1] & 0x3f));
+ mask--;
+ mask = ~mask;
+ mask = htonl(mask);
+ addr &= mask;
+ memcpy(vp->vp_ipv4prefix + 2, &addr, sizeof(addr));
+ }
+ break;
+
+ case PW_TYPE_SIGNED: /* overloaded with vp_integer */
+ memcpy(&vp->vp_integer, p, 4);
+ vp->vp_integer = ntohl(vp->vp_integer);
+ break;
+
+ default:
+ RERROR("eap_fast_decode_vp: type %d Internal sanity check %d ", parent->type, __LINE__);
+ fr_pair_list_free(&vp);
+ return -1;
+ }
+ vp->type = VT_DATA;
+ *out = vp;
+ return attr_len;
+}
+
+
+VALUE_PAIR *eap_fast_fast2vp(REQUEST *request, SSL *ssl, uint8_t const *data, size_t data_len,
+ DICT_ATTR const *fast_da, vp_cursor_t *out)
+{
+ uint16_t attr;
+ uint16_t length;
+ size_t data_left = data_len;
+ VALUE_PAIR *first = NULL;
+ VALUE_PAIR *vp = NULL;
+ DICT_ATTR const *da;
+
+ if (!fast_da)
+ fast_da = dict_attrbyvalue(PW_FREERADIUS_EAP_FAST_TLV, VENDORPEC_FREERADIUS);
+ rad_assert(fast_da != NULL);
+
+ if (!out) {
+ out = talloc(request, vp_cursor_t);
+ rad_assert(out != NULL);
+ fr_cursor_init(out, &first);
+ }
+
+ /*
+ * Decode the TLVs
+ */
+ while (data_left > 0) {
+ ssize_t decoded;
+
+ /* FIXME do something with mandatory */
+
+ memcpy(&attr, data, sizeof(attr));
+ attr = ntohs(attr) & EAP_FAST_TLV_TYPE;
+
+ memcpy(&length, data + 2, sizeof(length));
+ length = ntohs(length);
+
+ data += 4;
+ data_left -= 4;
+
+ /*
+ * Look up the TLV.
+ *
+ * For now, if it doesn't exist, ignore it.
+ */
+ da = dict_attrbyparent(fast_da, attr, fast_da->vendor);
+ if (!da) {
+ RDEBUG("eap_fast_fast2vp: no sub attribute found %s attr: %u vendor: %u",
+ fast_da->name, attr, fast_da->vendor);
+ goto next_attr;
+ }
+ if (da->type == PW_TYPE_TLV) {
+ eap_fast_fast2vp(request, ssl, data, length, da, out);
+ goto next_attr;
+ }
+ decoded = eap_fast_decode_vp(request, da, data, length, &vp);
+ if (decoded < 0) {
+ RERROR("Failed decoding %s: %s", da->name, fr_strerror());
+ goto next_attr;
+ }
+
+ fr_cursor_merge(out, vp);
+
+ next_attr:
+ while (fr_cursor_next(out)) {
+ /* nothing */
+ }
+
+ data += length;
+ data_left -= length;
+ }
+
+ /*
+ * We got this far. It looks OK.
+ */
+ return first;
+}
+
+
+static void eapfast_copy_request_to_tunnel(REQUEST *request, REQUEST *fake) {
+ VALUE_PAIR *copy, *vp;
+ vp_cursor_t cursor;
+
+ for (vp = fr_cursor_init(&cursor, &request->packet->vps);
+ vp;
+ vp = fr_cursor_next(&cursor)) {
+ /*
+ * The attribute is a server-side thingy,
+ * don't copy it.
+ */
+ if ((vp->da->attr > 255) && (((vp->da->attr >> 16) & 0xffff) == 0)) {
+ continue;
+ }
+
+ /*
+ * The outside attribute is already in the
+ * tunnel, don't copy it.
+ *
+ * This works for BOTH attributes which
+ * are originally in the tunneled request,
+ * AND attributes which are copied there
+ * from below.
+ */
+ if (fr_pair_find_by_da(fake->packet->vps, vp->da, TAG_ANY)) continue;
+
+ /*
+ * Some attributes are handled specially.
+ */
+ if (!vp->da->vendor) switch (vp->da->attr) {
+ /*
+ * NEVER copy Message-Authenticator,
+ * EAP-Message, or State. They're
+ * only for outside of the tunnel.
+ */
+ case PW_USER_NAME:
+ case PW_USER_PASSWORD:
+ case PW_CHAP_PASSWORD:
+ case PW_CHAP_CHALLENGE:
+ case PW_PROXY_STATE:
+ case PW_MESSAGE_AUTHENTICATOR:
+ case PW_EAP_MESSAGE:
+ case PW_STATE:
+ continue;
+
+ /*
+ * By default, copy it over.
+ */
+ default:
+ break;
+ }
+
+ /*
+ * Don't copy from the head, we've already
+ * checked it.
+ */
+ copy = fr_pair_list_copy_by_num(fake->packet, vp, vp->da->attr, vp->da->vendor, TAG_ANY);
+ fr_pair_add(&fake->packet->vps, copy);
+ }
+}
+
+/*
+ * Use a reply packet to determine what to do.
+ */
+static rlm_rcode_t CC_HINT(nonnull) process_reply( eap_handler_t *eap_session,
+ tls_session_t *tls_session,
+ REQUEST *request, RADIUS_PACKET *reply)
+{
+ rlm_rcode_t rcode = RLM_MODULE_REJECT;
+ VALUE_PAIR *vp;
+ vp_cursor_t cursor;
+
+ eap_fast_tunnel_t *t = tls_session->opaque;
+
+ rad_assert(eap_session->request == request);
+
+ /*
+ * If the response packet was Access-Accept, then
+ * we're OK. If not, die horribly.
+ *
+ * FIXME: EAP-Messages can only start with 'identity',
+ * NOT 'eap start', so we should check for that....
+ */
+ switch (reply->code) {
+ case PW_CODE_ACCESS_ACCEPT:
+ RDEBUG("Got tunneled Access-Accept");
+ tls_session->authentication_success = true;
+ rcode = RLM_MODULE_OK;
+
+ for (vp = fr_cursor_init(&cursor, &reply->vps); vp; vp = fr_cursor_next(&cursor)) {
+ if (vp->da->vendor != VENDORPEC_MICROSOFT) continue;
+
+ /* FIXME must be a better way to capture/re-derive this later for ISK */
+ switch (vp->da->attr) {
+ case PW_MSCHAP_MPPE_SEND_KEY:
+ if (vp->vp_length != CHAP_VALUE_LENGTH) {
+ wrong_length:
+ REDEBUG("Found %s with incorrect length. Expected %u, got %zu",
+ vp->da->name, 16, vp->vp_length);
+ rcode = RLM_MODULE_INVALID;
+ break;
+ }
+
+
+ memcpy(t->isk.mppe_send, vp->vp_octets, CHAP_VALUE_LENGTH);
+ break;
+
+ case PW_MSCHAP_MPPE_RECV_KEY:
+ if (vp->length != CHAP_VALUE_LENGTH) goto wrong_length;
+
+ memcpy(t->isk.mppe_recv, vp->vp_octets, CHAP_VALUE_LENGTH);
+ break;
+
+ case PW_MSCHAP2_SUCCESS:
+ RDEBUG("Got %s, tunneling it to the client in a challenge", vp->da->name);
+ rcode = RLM_MODULE_HANDLED;
+ if (t->use_tunneled_reply) {
+ t->authenticated = true;
+ /*
+ * Clean up the tunneled reply.
+ */
+ fr_pair_delete_by_num(&reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+
+ /*
+ * Delete MPPE keys & encryption policy. We don't
+ * want these here.
+ */
+ fr_pair_delete_by_num(&reply->vps, 7, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 8, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 16, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 17, VENDORPEC_MICROSOFT, TAG_ANY);
+
+ fr_pair_list_free(&t->accept_vps); /* for proxying MS-CHAP2 */
+ fr_pair_list_mcopy_by_num(t, &t->accept_vps, &reply->vps, 0, 0, TAG_ANY);
+ rad_assert(!reply->vps);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case PW_CODE_ACCESS_REJECT:
+ RDEBUG("Got tunneled Access-Reject");
+ rcode = RLM_MODULE_REJECT;
+ break;
+
+ /*
+ * Handle Access-Challenge, but only if we
+ * send tunneled reply data. This is because
+ * an Access-Challenge means that we MUST tunnel
+ * a Reply-Message to the client.
+ */
+ case PW_CODE_ACCESS_CHALLENGE:
+ RDEBUG("Got tunneled Access-Challenge");
+
+ /*
+ * Keep the State attribute, if necessary.
+ *
+ * Get rid of the old State, too.
+ */
+ fr_pair_list_free(&t->state);
+ fr_pair_list_mcopy_by_num(t, &t->state, &reply->vps, PW_STATE, 0, TAG_ANY);
+
+ /*
+ * Copy the EAP-Message back to the tunnel.
+ */
+ (void) fr_cursor_init(&cursor, &reply->vps);
+
+ while ((vp = fr_cursor_next_by_num(&cursor, PW_EAP_MESSAGE, 0, TAG_ANY)) != NULL) {
+ eap_fast_tlv_append(tls_session, EAP_FAST_TLV_EAP_PAYLOAD, true, vp->vp_length, vp->vp_octets);
+ }
+
+ rcode = RLM_MODULE_HANDLED;
+ break;
+
+ default:
+ RDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
+ rcode = RLM_MODULE_INVALID;
+ break;
+ }
+
+
+ return rcode;
+}
+
+static PW_CODE eap_fast_eap_payload(REQUEST *request, eap_handler_t *eap_session,
+ tls_session_t *tls_session, VALUE_PAIR *tlv_eap_payload)
+{
+ PW_CODE code = PW_CODE_ACCESS_REJECT;
+ rlm_rcode_t rcode;
+ VALUE_PAIR *vp;
+ eap_fast_tunnel_t *t;
+ REQUEST *fake;
+
+ RDEBUG("Processing received EAP Payload");
+
+ /*
+ * Allocate a fake REQUEST structure.
+ */
+ fake = request_alloc_fake(request);
+ rad_assert(!fake->packet->vps);
+
+ t = (eap_fast_tunnel_t *) tls_session->opaque;
+
+ /*
+ * Add the tunneled attributes to the fake request.
+ */
+
+ fake->packet->vps = fr_pair_afrom_num(fake->packet, PW_EAP_MESSAGE, 0);
+ fr_pair_value_memcpy(fake->packet->vps, tlv_eap_payload->vp_octets, tlv_eap_payload->vp_length);
+
+ RDEBUG("Got tunneled request");
+ rdebug_pair_list(L_DBG_LVL_1, request, fake->packet->vps, NULL);
+
+ /*
+ * Tell the request that it's a fake one.
+ */
+ fr_pair_make(fake->packet, &fake->packet->vps, "Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
+
+ /*
+ * Update other items in the REQUEST data structure.
+ */
+ fake->username = fr_pair_find_by_num(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ fake->password = fr_pair_find_by_num(fake->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
+
+ /*
+ * No User-Name, try to create one from stored data.
+ */
+ if (!fake->username) {
+ /*
+ * No User-Name in the stored data, look for
+ * an EAP-Identity, and pull it out of there.
+ */
+ if (!t->username) {
+ vp = fr_pair_find_by_num(fake->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ if (vp &&
+ (vp->vp_length >= EAP_HEADER_LEN + 2) &&
+ (vp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
+ (vp->vp_strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY) &&
+ (vp->vp_strvalue[EAP_HEADER_LEN + 1] != 0)) {
+ /*
+ * Create & remember a User-Name
+ */
+ t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
+ rad_assert(t->username != NULL);
+
+ fr_pair_value_bstrncpy(t->username, vp->vp_octets + 5, vp->vp_length - 5);
+
+ RDEBUG("Got tunneled identity of %s", t->username->vp_strvalue);
+ } else {
+ /*
+ * Don't reject the request outright,
+ * as it's permitted to do EAP without
+ * user-name.
+ */
+ RWDEBUG2("No EAP-Identity found to start EAP conversation");
+ }
+ } /* else there WAS a t->username */
+
+ if (t->username) {
+ vp = fr_pair_list_copy(fake->packet, t->username);
+ fr_pair_add(&fake->packet->vps, vp);
+ fake->username = vp;
+ }
+ } /* else the request ALREADY had a User-Name */
+
+ /*
+ * Add the State attribute, too, if it exists.
+ */
+ if (t->state) {
+ vp = fr_pair_list_copy(fake->packet, t->state);
+ if (vp) fr_pair_add(&fake->packet->vps, vp);
+ }
+
+
+ if (t->stage == AUTHENTICATION) { /* FIXME do this only for MSCHAPv2 */
+ VALUE_PAIR *tvp;
+
+ RDEBUG2("AUTHENTICATION");
+ vp = fr_pair_make(fake, &fake->config, "EAP-Type", "0", T_OP_EQ);
+ vp->vp_integer = t->default_method;
+
+ /*
+ * RFC 5422 section 3.2.3 - Authenticating Using EAP-FAST-MSCHAPv2
+ */
+ if (t->mode == EAP_FAST_PROVISIONING_ANON) {
+ tvp = fr_pair_afrom_num(fake, PW_MSCHAP_CHALLENGE, VENDORPEC_MICROSOFT);
+ fr_pair_value_memcpy(tvp, t->keyblock->server_challenge, CHAP_VALUE_LENGTH);
+ fr_pair_add(&fake->config, tvp);
+
+ tvp = fr_pair_afrom_num(fake, PW_MS_CHAP_PEER_CHALLENGE, 0);
+ fr_pair_value_memcpy(tvp, t->keyblock->client_challenge, CHAP_VALUE_LENGTH);
+ fr_pair_add(&fake->config, tvp);
+ }
+ }
+
+ if (t->copy_request_to_tunnel) {
+ eapfast_copy_request_to_tunnel(request, fake);
+ }
+
+ if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
+ fake->server = vp->vp_strvalue;
+
+ } else if (t->virtual_server) {
+ fake->server = t->virtual_server;
+
+ } /* else fake->server == request->server */
+
+ /*
+ * Call authentication recursively, which will
+ * do PAP, CHAP, MS-CHAP, etc.
+ */
+ rad_virtual_server(fake);
+
+ /*
+ * Decide what to do with the reply.
+ */
+ switch (fake->reply->code) {
+ case 0:
+ RDEBUG("No tunneled reply was found, rejecting the user.");
+ code = PW_CODE_ACCESS_REJECT;
+ break;
+
+ default:
+ /*
+ * Returns RLM_MODULE_FOO, and we want to return PW_FOO
+ */
+ rcode = process_reply(eap_session, tls_session, request, fake->reply);
+ switch (rcode) {
+ case RLM_MODULE_REJECT:
+ code = PW_CODE_ACCESS_REJECT;
+ break;
+
+ case RLM_MODULE_HANDLED:
+ code = PW_CODE_ACCESS_CHALLENGE;
+ break;
+
+ case RLM_MODULE_OK:
+ code = PW_CODE_ACCESS_ACCEPT;
+ break;
+
+ default:
+ code = PW_CODE_ACCESS_REJECT;
+ break;
+ }
+ break;
+ }
+
+ talloc_free(fake);
+
+ return code;
+}
+
+static PW_CODE eap_fast_crypto_binding(REQUEST *request, UNUSED eap_handler_t *eap_session,
+ tls_session_t *tls_session, eap_tlv_crypto_binding_tlv_t *binding)
+{
+ uint8_t cmac[sizeof(binding->compound_mac)];
+ eap_fast_tunnel_t *t = tls_session->opaque;
+
+ memcpy(cmac, binding->compound_mac, sizeof(cmac));
+ memset(binding->compound_mac, 0, sizeof(binding->compound_mac));
+
+
+ fr_hmac_sha1(binding->compound_mac, (uint8_t *)binding, sizeof(*binding), t->cmk, EAP_FAST_CMK_LEN);
+ if (memcmp(binding->compound_mac, cmac, sizeof(cmac))) {
+ RDEBUG2("Crypto-Binding TLV mis-match");
+ return PW_CODE_ACCESS_REJECT;
+ }
+
+ return PW_CODE_ACCESS_ACCEPT;
+}
+
+
+#define PW_EAP_FAST_TLV_PAC (PW_FREERADIUS_EAP_FAST_TLV | (EAP_FAST_TLV_PAC << 8))
+
+
+
+static PW_CODE eap_fast_process_tlvs(REQUEST *request, eap_handler_t *eap_session,
+ tls_session_t *tls_session, VALUE_PAIR *fast_vps)
+{
+ eap_fast_tunnel_t *t = (eap_fast_tunnel_t *) tls_session->opaque;
+ VALUE_PAIR *vp;
+ vp_cursor_t cursor;
+ eap_tlv_crypto_binding_tlv_t *binding = NULL;
+ eap_tlv_crypto_binding_tlv_t my_binding;
+
+ for (vp = fr_cursor_init(&cursor, &fast_vps); vp; vp = fr_cursor_next(&cursor)) {
+ PW_CODE code = PW_CODE_ACCESS_REJECT;
+ char *value;
+ DICT_ATTR const *parent_da = NULL;
+ parent_da = dict_parent(vp->da->attr, vp->da->vendor);
+ if (parent_da == NULL || vp->da->vendor != VENDORPEC_FREERADIUS ||
+ ((vp->da->attr & 0xff) != PW_FREERADIUS_EAP_FAST_TLV)) {
+ value = vp_aprints(request->packet, vp, '"');
+ RDEBUG2("ignoring non-EAP-FAST TLV %s", value);
+ talloc_free(value);
+ continue;
+ }
+
+ switch (parent_da->attr) {
+ case PW_FREERADIUS_EAP_FAST_TLV:
+ switch (vp->da->attr >> 8) {
+ case EAP_FAST_TLV_EAP_PAYLOAD:
+ code = eap_fast_eap_payload(request, eap_session, tls_session, vp);
+ if (code == PW_CODE_ACCESS_ACCEPT)
+ t->stage = CRYPTOBIND_CHECK;
+ break;
+ case EAP_FAST_TLV_RESULT:
+ case EAP_FAST_TLV_INTERMED_RESULT:
+ code = PW_CODE_ACCESS_ACCEPT;
+ t->stage = PROVISIONING;
+ break;
+ case EAP_FAST_TLV_CRYPTO_BINDING:
+ if (!binding && (vp->vp_length >= sizeof(eap_tlv_crypto_binding_tlv_t))) {
+ binding = &my_binding;
+ binding->tlv_type = htons(EAP_FAST_TLV_MANDATORY | EAP_FAST_TLV_CRYPTO_BINDING);
+ binding->length = htons(sizeof(*binding) - 2 * sizeof(uint16_t));
+ memcpy(&my_binding.reserved, vp->vp_octets, sizeof(my_binding) - 4);
+ }
+ continue;
+ default:
+ value = vp_aprints_value(request->packet, vp, '"');
+ RDEBUG2("ignoring unknown %s", value);
+ talloc_free(value);
+ continue;
+ }
+ break;
+ case PW_EAP_FAST_TLV_PAC:
+ switch ( ( vp->da->attr >> 16 )) {
+ case PAC_INFO_PAC_ACK:
+ if (vp->vp_integer == EAP_FAST_TLV_RESULT_SUCCESS) {
+ code = PW_CODE_ACCESS_ACCEPT;
+ t->pac.expires = UINT32_MAX;
+ t->pac.expired = false;
+ t->stage = COMPLETE;
+ }
+ break;
+ case PAC_INFO_PAC_TYPE:
+ if (vp->vp_integer != PAC_TYPE_TUNNEL) {
+ RDEBUG("only able to serve Tunnel PAC's, ignoring request");
+ continue;
+ }
+ t->pac.send = true;
+ continue;
+ default:
+ value = vp_aprints(request->packet, vp, '"');
+ RDEBUG2("ignoring unknown EAP-FAST-PAC-TLV %s", value);
+ talloc_free(value);
+ continue;
+ }
+ break;
+ default:
+ value = vp_aprints(request->packet, vp, '"');
+ RDEBUG2("ignoring EAP-FAST TLV %s", value);
+ talloc_free(value);
+ continue;
+ }
+
+ if (code == PW_CODE_ACCESS_REJECT)
+ return PW_CODE_ACCESS_REJECT;
+ }
+
+ if (binding) {
+ PW_CODE code = eap_fast_crypto_binding(request, eap_session, tls_session, binding);
+ if (code == PW_CODE_ACCESS_ACCEPT) {
+ t->stage = PROVISIONING;
+ }
+ return code;
+ }
+
+ return PW_CODE_ACCESS_ACCEPT;
+}
+
+
+/*
+ * Process the inner tunnel data
+ */
+PW_CODE eap_fast_process(eap_handler_t *eap_session, tls_session_t *tls_session)
+{
+ PW_CODE code;
+ VALUE_PAIR *fast_vps;
+ uint8_t const *data;
+ size_t data_len;
+ eap_fast_tunnel_t *t;
+ REQUEST *request = eap_session->request;
+
+ /*
+ * Just look at the buffer directly, without doing
+ * record_to_buff.
+ */
+ data_len = tls_session->clean_out.used;
+ tls_session->clean_out.used = 0;
+ data = tls_session->clean_out.data;
+
+ t = (eap_fast_tunnel_t *) tls_session->opaque;
+
+ /*
+ * See if the tunneled data is well formed.
+ */
+ if (!eap_fast_verify(request, tls_session, data, data_len)) return PW_CODE_ACCESS_REJECT;
+
+ if (t->stage == TLS_SESSION_HANDSHAKE) {
+ rad_assert(t->mode == EAP_FAST_UNKNOWN);
+
+ char buf[256];
+ if (strstr(SSL_CIPHER_description(SSL_get_current_cipher(tls_session->ssl),
+ buf, sizeof(buf)), "Au=None")) {
+ /* FIXME enforce MSCHAPv2 - RFC 5422 section 3.2.2 */
+ RDEBUG2("Using anonymous provisioning");
+ t->mode = EAP_FAST_PROVISIONING_ANON;
+ t->pac.send = true;
+ } else {
+ if (SSL_session_reused(tls_session->ssl)) {
+ RDEBUG("Session Resumed from PAC");
+ t->mode = EAP_FAST_NORMAL_AUTH;
+ } else {
+ RDEBUG2("Using authenticated provisioning");
+ t->mode = EAP_FAST_PROVISIONING_AUTH;
+ }
+
+ /*
+ * Send a new pac at ~0.6 times the lifetime.
+ */
+ if (!t->pac.expires || t->pac.expired || t->pac.expires < (time(NULL) + (t->pac_lifetime >> 1) + (t->pac_lifetime >> 3))) {
+ t->pac.send = true;
+ }
+ }
+
+ eap_fast_init_keys(request, tls_session);
+
+ eap_fast_send_identity_request(request, tls_session, eap_session);
+
+ t->stage = AUTHENTICATION;
+ return PW_CODE_ACCESS_CHALLENGE;
+ }
+
+ fast_vps = eap_fast_fast2vp(request, tls_session->ssl, data, data_len, NULL, NULL);
+
+ RDEBUG("Got Tunneled FAST TLVs");
+ rdebug_pair_list(L_DBG_LVL_1, request, fast_vps, NULL);
+
+ code = eap_fast_process_tlvs(request, eap_session, tls_session, fast_vps);
+
+ fr_pair_list_free(&fast_vps);
+
+ if (code == PW_CODE_ACCESS_REJECT) return PW_CODE_ACCESS_REJECT;
+
+ switch (t->stage) {
+ case AUTHENTICATION:
+ code = PW_CODE_ACCESS_CHALLENGE;
+ break;
+ case CRYPTOBIND_CHECK:
+ {
+ if (t->mode != EAP_FAST_PROVISIONING_ANON && !t->pac.send)
+ t->result_final = true;
+
+ eap_fast_append_result(tls_session, code);
+
+ eap_fast_update_icmk(request, tls_session, (uint8_t *)&t->isk);
+ eap_fast_append_crypto_binding(request, tls_session);
+
+ code = PW_CODE_ACCESS_CHALLENGE;
+ break;
+ }
+ case PROVISIONING:
+ t->result_final = true;
+
+ eap_fast_append_result(tls_session, code);
+
+ if (t->pac.send) {
+ RDEBUG("Peer requires new PAC");
+ eap_fast_send_pac_tunnel(request, tls_session);
+ code = PW_CODE_ACCESS_CHALLENGE;
+ break;
+ }
+
+ t->stage = COMPLETE;
+ /* fallthrough */
+ case COMPLETE:
+ /*
+ * RFC 5422 section 3.5 - Network Access after EAP-FAST Provisioning
+ */
+ if (t->pac.type && t->pac.expired) {
+ REDEBUG("Rejecting expired PAC.");
+ code = PW_CODE_ACCESS_REJECT;
+ break;
+ }
+
+ if (t->mode == EAP_FAST_PROVISIONING_ANON) {
+ REDEBUG("Rejecting unauthenticated provisioning");
+ code = PW_CODE_ACCESS_REJECT;
+ break;
+ }
+
+ /*
+ * eap_tls_gen_mppe_keys() is unsuitable for EAP-FAST as Cisco decided
+ * it would be a great idea to flip the recv/send keys around
+ */
+ #define EAPTLS_MPPE_KEY_LEN 32
+ eap_add_reply(request, "MS-MPPE-Recv-Key", t->msk, EAPTLS_MPPE_KEY_LEN);
+ eap_add_reply(request, "MS-MPPE-Send-Key", &t->msk[EAPTLS_MPPE_KEY_LEN], EAPTLS_MPPE_KEY_LEN);
+ eap_add_reply(request, "EAP-MSK", t->msk, EAP_FAST_KEY_LEN);
+ eap_add_reply(request, "EAP-EMSK", t->emsk, EAP_EMSK_LEN);
+
+ break;
+
+ default:
+ RERROR("Internal sanity check failed in EAP-FAST at %d", t->stage);
+ code = PW_CODE_ACCESS_REJECT;
+ }
+
+ return code;
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.h b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.h
new file mode 100644
index 0000000..8a88bd6
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.h
@@ -0,0 +1,260 @@
+/*
+ * eap_fast.h
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _EAP_FAST_H
+#define _EAP_FAST_H
+
+RCSIDH(eap_fast_h, "$Id$")
+
+#include "eap_tls.h"
+
+#define EAP_FAST_VERSION 1
+
+#define EAP_FAST_KEY_LEN 64
+#define EAP_EMSK_LEN 64
+#define EAP_FAST_SKS_LEN 40
+#define EAP_FAST_SIMCK_LEN 40
+#define EAP_FAST_CMK_LEN 20
+
+#define EAP_FAST_TLV_MANDATORY 0x8000
+#define EAP_FAST_TLV_TYPE 0x3fff
+
+#define EAP_FAST_FATAL_ERROR 2000
+#define EAP_FAST_ERR_TUNNEL_COMPROMISED 2001
+#define EAP_FAST_ERR_UNEXPECTED_TLV 2002
+
+#define EAP_FAST_TLV_RESULT_SUCCESS 1
+#define EAP_FAST_TLV_RESULT_FAILURE 2
+
+typedef enum eap_fast_stage_t {
+ TLS_SESSION_HANDSHAKE = 0,
+ AUTHENTICATION,
+ CRYPTOBIND_CHECK,
+ PROVISIONING,
+ COMPLETE
+} eap_fast_stage_t;
+
+typedef enum eap_fast_auth_type {
+ EAP_FAST_UNKNOWN = 0,
+ EAP_FAST_PROVISIONING_ANON,
+ EAP_FAST_PROVISIONING_AUTH,
+ EAP_FAST_NORMAL_AUTH
+} eap_fast_auth_type_t;
+
+typedef enum eap_fast_pac_info_attr_type_t {
+ PAC_INFO_PAC_KEY = 1, // 1
+ PAC_INFO_PAC_OPAQUE, // 2
+ PAC_INFO_PAC_LIFETIME, // 3
+ PAC_INFO_A_ID, // 4
+ PAC_INFO_I_ID, // 5
+ PAC_INFO_PAC_RESERVED6, // 6
+ PAC_INFO_A_ID_INFO, // 7
+ PAC_INFO_PAC_ACK, // 8
+ PAC_INFO_PAC_INFO, // 9
+ PAC_INFO_PAC_TYPE, // 10
+ PAC_INFO_MAX
+} eap_fast_pac_info_attr_type_t;
+
+typedef enum eap_fast_pac_type_t {
+ PAC_TYPE_TUNNEL = 1, // 1
+ PAC_TYPE_MACHINE_AUTH, // 2
+ PAC_TYPE_USER_AUTHZ, // 3
+ PAC_TYPE_MAX
+} eap_fast_pac_type_t;
+
+#define PAC_KEY_LENGTH 32
+#define PAC_A_ID_LENGTH 16
+#define PAC_I_ID_LENGTH 16
+#define PAC_A_ID_INFO_LENGTH 32
+
+typedef struct eap_fast_pac_attr_hdr_t {
+ uint16_t type;
+ uint16_t length;
+} CC_HINT(__packed__) eap_fast_pac_attr_hdr_t;
+
+typedef struct eap_fast_pac_attr_lifetime_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ uint32_t data; // secs since epoch
+} CC_HINT(__packed__) eap_fast_pac_attr_lifetime_t;
+
+typedef struct eap_fast_pac_attr_a_id_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ uint8_t data[PAC_A_ID_LENGTH];
+} CC_HINT(__packed__) eap_fast_pac_attr_a_id_t;
+
+typedef struct eap_fast_pac_attr_i_id_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ uint8_t data[PAC_I_ID_LENGTH];
+} CC_HINT(__packed__) eap_fast_pac_attr_i_id_t;
+
+typedef struct eap_fast_pac_attr_a_id_info_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ uint8_t data[PAC_A_ID_INFO_LENGTH];
+} CC_HINT(__packed__) eap_fast_pac_attr_a_id_info_t;
+
+typedef struct eap_fast_pac_attr_pac_type_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ uint16_t data;
+} CC_HINT(__packed__) eap_fast_pac_attr_pac_type_t;
+
+typedef struct eap_fast_pac_attr_pac_key_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ uint8_t data[PAC_KEY_LENGTH];
+} CC_HINT(__packed__) eap_fast_pac_attr_pac_key_t;
+
+typedef struct eap_fast_attr_pac_opaque_plaintext_t {
+ eap_fast_pac_attr_pac_type_t type;
+ eap_fast_pac_attr_lifetime_t lifetime;
+ eap_fast_pac_attr_pac_key_t key;
+} CC_HINT(__packed__) eap_fast_attr_pac_opaque_plaintext_t;
+
+typedef struct eap_fast_attr_pac_opaque_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ unsigned char aad[PAC_A_ID_LENGTH];
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char tag[EVP_GCM_TLS_TAG_LEN];
+ uint8_t data[sizeof(eap_fast_attr_pac_opaque_plaintext_t) * 2]; // space for EVP
+} CC_HINT(__packed__) eap_fast_attr_pac_opaque_t;
+
+typedef struct eap_fast_attr_pac_info_t {
+ eap_fast_pac_attr_hdr_t hdr;
+ eap_fast_pac_attr_lifetime_t lifetime;
+ eap_fast_pac_attr_a_id_t a_id;
+ eap_fast_pac_attr_a_id_info_t a_id_info;
+ eap_fast_pac_attr_pac_type_t type;
+} CC_HINT(__packed__) eap_fast_attr_pac_info_t;
+
+typedef struct eap_fast_pac_t {
+ eap_fast_pac_attr_pac_key_t key;
+ eap_fast_attr_pac_info_t info;
+ eap_fast_attr_pac_opaque_t opaque; // has to be last!
+} CC_HINT(__packed__) eap_fast_pac_t;
+
+/* RFC 4851, Section 4.2.8 - Crypto-Binding TLV */
+typedef struct eap_tlv_crypto_binding_tlv_t {
+ uint16_t tlv_type;
+ uint16_t length;
+ uint8_t reserved;
+ uint8_t version;
+ uint8_t received_version;
+ uint8_t subtype;
+ uint8_t nonce[32];
+ uint8_t compound_mac[20];
+} CC_HINT(__packed__) eap_tlv_crypto_binding_tlv_t;
+
+typedef enum eap_fast_tlv_type_t {
+ EAP_FAST_TLV_RESERVED_0 = 0, // 0
+ EAP_FAST_TLV_RESERVED_1, // 1
+ EAP_FAST_TLV_RESERVED_2, // 2
+ EAP_FAST_TLV_RESULT, // 3
+ EAP_FAST_TLV_NAK, // 4
+ EAP_FAST_TLV_ERROR, // 5
+ EAP_FAST_TLV_RESERVED6, // 6
+ EAP_FAST_TLV_VENDOR_SPECIFIC, // 7
+ EAP_FAST_TLV_RESERVED8, // 8
+ EAP_FAST_TLV_EAP_PAYLOAD, // 9
+ EAP_FAST_TLV_INTERMED_RESULT, // 10
+ EAP_FAST_TLV_PAC, // 11
+ EAP_FAST_TLV_CRYPTO_BINDING, // 12
+ EAP_FAST_TLV_RESERVED_13, // 13
+ EAP_FAST_TLV_RESERVED_14, // 14
+ EAP_FAST_TLV_RESERVED_15, // 15
+ EAP_FAST_TLV_RESERVED_16, // 16
+ EAP_FAST_TLV_RESERVED_17, // 17
+ EAP_FAST_TLV_TRUSTED_ROOT, // 18
+ EAP_FAST_TLV_REQ_ACTION, // 19
+ EAP_FAST_TLV_PKCS, // 20
+ EAP_FAST_TLV_MAX
+} eap_fast_tlv_type_t;
+
+typedef enum eap_fast_tlv_crypto_binding_tlv_subtype_t {
+ EAP_FAST_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST = 0, // 0
+ EAP_FAST_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE // 1
+} eap_fast_tlv_crypto_binding_tlv_subtype_t;
+
+/* RFC 5422: Section 3.3 - Key Derivations Used in the EAP-FAST Provisioning Exchange */
+typedef struct eap_fast_keyblock_t {
+ uint8_t session_key_seed[EAP_FAST_SKS_LEN];
+ uint8_t server_challenge[CHAP_VALUE_LENGTH];
+ uint8_t client_challenge[CHAP_VALUE_LENGTH];
+} CC_HINT(__packed__) eap_fast_keyblock_t;
+
+typedef struct eap_fast_tunnel_t {
+ VALUE_PAIR *username;
+ VALUE_PAIR *state;
+ VALUE_PAIR *accept_vps;
+ bool copy_request_to_tunnel;
+ bool use_tunneled_reply;
+
+ bool authenticated;
+
+ int mode;
+ eap_fast_stage_t stage;
+ eap_fast_keyblock_t *keyblock;
+ uint8_t *simck;
+ uint8_t *cmk;
+ int imckc;
+ struct {
+ uint8_t mppe_send[CHAP_VALUE_LENGTH];
+ uint8_t mppe_recv[CHAP_VALUE_LENGTH];
+ } CC_HINT(__packed__) isk;
+ uint8_t *msk;
+ uint8_t *emsk;
+
+ int default_method;
+
+ uint32_t pac_lifetime;
+ char const *authority_identity;
+ uint8_t const *a_id;
+ uint8_t const *pac_opaque_key;
+
+ struct {
+ uint8_t *key;
+ eap_fast_pac_type_t type;
+ uint32_t expires;
+ bool expired;
+ bool send;
+ } pac;
+
+ bool result_final;
+
+#ifdef WITH_PROXY
+ bool proxy_tunneled_request_as_eap; //!< Proxy tunneled session as EAP, or as de-capsulated
+ //!< protocol.
+#endif
+ char const *virtual_server;
+} eap_fast_tunnel_t;
+
+/*
+ * Process the FAST portion of an EAP-FAST request.
+ */
+void eap_fast_tlv_append(tls_session_t *tls_session, int tlv, bool mandatory,
+ int length, const void *data) CC_HINT(nonnull);
+PW_CODE eap_fast_process(eap_handler_t *eap_session, tls_session_t *tls_session) CC_HINT(nonnull);
+
+/*
+ * A bunch of EAP-FAST helper functions.
+ */
+VALUE_PAIR *eap_fast_fast2vp(REQUEST *request, UNUSED SSL *ssl, uint8_t const *data,
+ size_t data_len, DICT_ATTR const *fast_da, vp_cursor_t *out);
+
+#endif /* _EAP_FAST_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c
new file mode 100644
index 0000000..e386e70
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c
@@ -0,0 +1,198 @@
+/*
+ * fast-crypto.c Cryptographic functions for EAP-FAST.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2016 Alan DeKok <aland@freeradius.org>
+ * Copyright 2016 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include <stdio.h>
+#include <freeradius-devel/libradius.h>
+
+#include <openssl/evp.h>
+#include <openssl/aes.h>
+#include <openssl/err.h>
+
+#include "eap_fast_crypto.h"
+
+# define DEBUG if (fr_debug_lvl && fr_log_fp) fr_printf_log
+
+static void debug_errors(void)
+{
+ unsigned long errCode;
+
+ while((errCode = ERR_get_error())) {
+ char *err = ERR_error_string(errCode, NULL);
+ DEBUG("EAP-FAST error in OpenSSL - %s", err);
+ }
+}
+
+// https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_GCM_mode
+int eap_fast_encrypt(uint8_t const *plaintext, size_t plaintext_len,
+ uint8_t const *aad, size_t aad_len,
+ uint8_t const *key, uint8_t *iv, unsigned char *ciphertext,
+ uint8_t *tag)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ int len;
+
+ int ciphertext_len;
+
+
+ /* Create and initialise the context */
+ if (!(ctx = EVP_CIPHER_CTX_new())) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Initialise the encryption operation. */
+ if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Set IV length if default 12 bytes (96 bits) is not appropriate */
+ if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Initialise key and IV */
+ if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Provide any AAD data. This can be called zero or more times as
+ * required
+ */
+ if (1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Provide the message to be encrypted, and obtain the encrypted output.
+ * EVP_EncryptUpdate can be called multiple times if necessary
+ */
+ if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
+ debug_errors();
+ return -1;
+ };
+ ciphertext_len = len;
+
+ /* Finalise the encryption. Normally ciphertext bytes may be written at
+ * this stage, but this does not occur in GCM mode
+ */
+ if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
+ debug_errors();
+ return -1;
+ };
+ ciphertext_len += len;
+
+ /* Get the tag */
+ if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Clean up */
+ EVP_CIPHER_CTX_free(ctx);
+
+ return ciphertext_len;
+}
+
+int eap_fast_decrypt(uint8_t const *ciphertext, size_t ciphertext_len,
+ uint8_t const *aad, size_t aad_len,
+ uint8_t const *tag, uint8_t const *key, uint8_t const *iv, uint8_t *plaintext)
+{
+ EVP_CIPHER_CTX *ctx;
+ int len;
+ int plaintext_len;
+ int ret;
+
+ /* Create and initialise the context */
+ if (!(ctx = EVP_CIPHER_CTX_new())) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Initialise the decryption operation. */
+ if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Initialise key and IV */
+ if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Provide any AAD data. This can be called zero or more times as
+ * required
+ */
+ if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) {
+ debug_errors();
+ return -1;
+ };
+
+ /* Provide the message to be decrypted, and obtain the plaintext output.
+ * EVP_DecryptUpdate can be called multiple times if necessary
+ */
+ if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
+ debug_errors();
+ return -1;
+ };
+ plaintext_len = len;
+
+ {
+ unsigned char *tmp;
+
+ memcpy(&tmp, &tag, sizeof(tmp));
+
+ /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tmp)) {
+ debug_errors();
+ return -1;
+ };
+ }
+
+ /* Finalise the decryption. A positive return value indicates success,
+ * anything else is a failure - the plaintext is not trustworthy.
+ */
+ ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
+
+ /* Clean up */
+ EVP_CIPHER_CTX_free(ctx);
+
+ if (ret < 0) return -1;
+
+ /* Success */
+ plaintext_len += len;
+ return plaintext_len;
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.h b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.h
new file mode 100644
index 0000000..d00e9a2
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.h
@@ -0,0 +1,39 @@
+/*
+ * eap_fast_crypto.h
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+#ifndef _EAP_FAST_CRYPTO_H
+#define _EAP_FAST_CRYPTO_H
+
+RCSIDH(eap_fast_crypto_h, "$Id$")
+
+
+int eap_fast_encrypt(uint8_t const *plaintext, size_t plaintext_len,
+ uint8_t const *aad, size_t aad_len,
+ uint8_t const *key, uint8_t *iv, unsigned char *ciphertext,
+ uint8_t *tag);
+
+int eap_fast_decrypt(uint8_t const *ciphertext, size_t ciphertext_len,
+ uint8_t const *aad, size_t aad_len,
+ uint8_t const *tag, uint8_t const *key, uint8_t const *iv, uint8_t *plaintext);
+
+#endif /* _EAP_FAST_CRYPTO_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c
new file mode 100644
index 0000000..093dc86
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c
@@ -0,0 +1,659 @@
+/*
+ * rlm_eap_fast.c contains the interfaces that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2016 Alan DeKok <aland@freeradius.org>
+ * Copyright 2016 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+
+#include "eap_fast.h"
+#include "eap_fast_crypto.h"
+
+
+#include <freeradius-devel/md5.h>
+
+/*
+ * An instance of EAP-FAST
+ */
+typedef struct rlm_eap_fast_t {
+ char const *tls_conf_name; //!< Name of shared TLS config.
+ fr_tls_server_conf_t *tls_conf;
+
+ char const *default_method_name;
+ int default_method;
+
+ char const *virtual_server; //!< Virtual server to use for processing
+ //!< inner EAP method.
+ char const *cipher_list; //!< cipher list specific to EAP-FAST
+ bool req_client_cert; //!< Whether we require a client cert
+ //!< in the outer tunnel.
+
+ int stage; //!< Processing stage.
+
+ uint32_t pac_lifetime; //!< seconds to add to current time to describe PAC lifetime
+ char const *authority_identity; //!< The identity we present in the EAP-TLS
+ uint8_t a_id[PAC_A_ID_LENGTH]; //!< The identity we present in the EAP-TLS
+ char const *pac_opaque_key; //!< The key used to encrypt PAC-Opaque
+ bool use_tunneled_reply; //!< Use the reply attributes from the tunneled session in
+ //!< the non-tunneled reply to the client.
+
+ bool copy_request_to_tunnel; //!< Use SOME of the request attributes from outside of the
+} rlm_eap_fast_t;
+
+
+static CONF_PARSER module_config[] = {
+ { "tls", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, tls_conf_name), NULL },
+
+ { "default_eap_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, default_method_name), "mschapv2" },
+
+ { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED | PW_TYPE_NOT_EMPTY, rlm_eap_fast_t, virtual_server) , NULL},
+ { "cipher_list", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, cipher_list) , NULL},
+
+ { "require_client_cert", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_fast_t, req_client_cert), "no" },
+
+ { "pac_lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_fast_t, pac_lifetime), "604800" },
+ { "authority_identity", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_eap_fast_t, authority_identity), NULL },
+ { "pac_opaque_key", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_eap_fast_t, pac_opaque_key), NULL },
+ { "copy_request_to_tunnel", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_fast_t, copy_request_to_tunnel), "no" },
+
+ { "use_tunneled_reply", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_fast_t, use_tunneled_reply), "no" },
+
+ CONF_PARSER_TERMINATOR
+};
+
+/*
+ * Attach the module.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_fast_t *inst;
+
+ *instance = inst = talloc_zero(cs, rlm_eap_fast_t);
+ if (!inst) return -1;
+
+ /*
+ * Parse the configuration attributes.
+ */
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ if (!cf_section_sub_find_name2(main_config.config, "server", inst->virtual_server)) {
+ ERROR("rlm_eap_fast.virtual_server: Unknown virtual server '%s'", inst->virtual_server);
+ return -1;
+ }
+
+ inst->default_method = eap_name2type(inst->default_method_name);
+ if (!inst->default_method) {
+ ERROR("rlm_eap_fast.default_provisioning_eap_type: "
+ "Unknown EAP type %s",
+ inst->default_method_name);
+ return -1;
+ }
+
+ /*
+ * Read tls configuration, either from group given by 'tls'
+ * option, or from the eap-tls configuration.
+ */
+ inst->tls_conf = eaptls_conf_parse(cs, "tls");
+
+ if (!inst->tls_conf) {
+ ERROR("rlm_eap_fast.tls: Failed initializing SSL context");
+ return -1;
+ }
+
+ if (talloc_array_length(inst->pac_opaque_key) - 1 != 32) {
+ ERROR("rlm_eap_fast.pac_opaque_key: Must be 32 bytes long");
+ return -1;
+ }
+
+ if (!inst->pac_lifetime) {
+ ERROR("rlm_eap_fast.pac_lifetime: must be non-zero");
+ return -1;
+ }
+
+#ifdef TLS1_3_VERSION
+ if (inst->tls_conf->min_version == TLS1_3_VERSION) {
+ ERROR("There are no standards for using TLS 1.3 with EAP-FAST.");
+ ERROR("You MUST enable TLS 1.2 for EAP-FAST to work.");
+ return -1;
+ }
+
+ if ((inst->tls_conf->max_version == TLS1_3_VERSION) ||
+ (inst->tls_conf->min_version == TLS1_3_VERSION)) {
+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ WARN("!! There is no standard for using EAP-FAST with TLS 1.3");
+ WARN("!! Please set tls_max_version = \"1.2\"");
+ WARN("!! FreeRADIUS only supports TLS 1.3 for special builds of wpa_supplicant and Windows");
+ WARN("!! This limitation is likely to change in late 2021.");
+ WARN("!! If you are using this version of FreeRADIUS after 2021, you will probably need to upgrade");
+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ }
+#endif
+
+ rad_assert(PAC_A_ID_LENGTH == MD5_DIGEST_LENGTH);
+ FR_MD5_CTX ctx;
+ fr_md5_init(&ctx);
+ fr_md5_update(&ctx, inst->authority_identity, talloc_array_length(inst->authority_identity) - 1);
+ fr_md5_final(inst->a_id, &ctx);
+
+ return 0;
+}
+
+/** Allocate the FAST per-session data
+ *
+ */
+static eap_fast_tunnel_t *eap_fast_alloc(TALLOC_CTX *ctx, rlm_eap_fast_t *inst)
+{
+ eap_fast_tunnel_t *t = talloc_zero(ctx, eap_fast_tunnel_t);
+
+ t->mode = EAP_FAST_UNKNOWN;
+ t->stage = TLS_SESSION_HANDSHAKE;
+
+ t->default_method = inst->default_method;
+ t->copy_request_to_tunnel = inst->copy_request_to_tunnel;
+ t->use_tunneled_reply = inst->use_tunneled_reply;
+
+ t->pac_lifetime = inst->pac_lifetime;
+ t->authority_identity = inst->authority_identity;
+ t->a_id = inst->a_id;
+ t->pac_opaque_key = (const uint8_t *)inst->pac_opaque_key;
+
+ t->virtual_server = inst->virtual_server;
+
+ return t;
+}
+
+static void eap_fast_session_ticket(tls_session_t *tls_session, uint8_t *client_random,
+ uint8_t *server_random, uint8_t *secret, int *secret_len)
+{
+ eap_fast_tunnel_t *t = (eap_fast_tunnel_t *) tls_session->opaque;
+ uint8_t seed[2 * SSL3_RANDOM_SIZE];
+
+ rad_assert(t->pac.key);
+
+ memcpy(seed, server_random, SSL3_RANDOM_SIZE);
+ memcpy(&seed[SSL3_RANDOM_SIZE], client_random, SSL3_RANDOM_SIZE);
+
+ T_PRF(t->pac.key, PAC_KEY_LENGTH, "PAC to master secret label hash",
+ seed, sizeof(seed), secret, SSL_MAX_MASTER_KEY_LENGTH);
+ *secret_len = SSL_MAX_MASTER_KEY_LENGTH;
+}
+
+// hostap:src/crypto/tls_openssl.c:tls_sess_sec_cb()
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+static int _session_secret(SSL *s, void *secret, int *secret_len,
+ UNUSED STACK_OF(SSL_CIPHER) *peer_ciphers,
+ UNUSED SSL_CIPHER **cipher, void *arg)
+#else
+static int _session_secret(SSL *s, void *secret, int *secret_len,
+ UNUSED STACK_OF(SSL_CIPHER) *peer_ciphers,
+ UNUSED const SSL_CIPHER **cipher, void *arg)
+#endif
+{
+ // FIXME enforce non-anon cipher
+
+ REQUEST *request = (REQUEST *)SSL_get_ex_data(s, FR_TLS_EX_INDEX_REQUEST);
+ tls_session_t *tls_session = arg;
+ eap_fast_tunnel_t *t;
+
+ if (!tls_session) return 0;
+
+ t = (eap_fast_tunnel_t *) tls_session->opaque;
+
+ if (!t->pac.key) return 0;
+
+ RDEBUG("processing PAC-Opaque");
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ eap_fast_session_ticket(tls_session, s->s3->client_random, s->s3->server_random, secret, secret_len);
+#else
+ uint8_t client_random[SSL3_RANDOM_SIZE];
+ uint8_t server_random[SSL3_RANDOM_SIZE];
+
+ SSL_get_client_random(s, client_random, sizeof(client_random));
+ SSL_get_server_random(s, server_random, sizeof(server_random));
+
+ eap_fast_session_ticket(tls_session, client_random, server_random, secret, secret_len);
+#endif
+
+ memset(t->pac.key, 0, PAC_KEY_LENGTH);
+ talloc_free(t->pac.key);
+ t->pac.key = NULL;
+
+ return 1;
+}
+
+/*
+ * hints from hostap:src/crypto/tls_openssl.c:tls_session_ticket_ext_cb()
+ *
+ * N.B. we actually always tell OpenSSL we have digested the ticket so that
+ * it does not cause a fail loop and enables us to update the PAC easily
+ *
+ */
+static int _session_ticket(SSL *s, uint8_t const *data, int len, void *arg)
+{
+ tls_session_t *tls_session = arg;
+ REQUEST *request = (REQUEST *)SSL_get_ex_data(s, FR_TLS_EX_INDEX_REQUEST);
+ eap_fast_tunnel_t *t;
+ VALUE_PAIR *fast_vps = NULL;
+ vp_cursor_t cursor;
+ DICT_ATTR const *fast_da;
+ char const *errmsg;
+ int dlen, plen;
+ int length;
+ eap_fast_attr_pac_opaque_t const *opaque = (eap_fast_attr_pac_opaque_t const *) data;
+ eap_fast_attr_pac_opaque_t opaque_plaintext;
+
+ if (!tls_session) return 0;
+
+ t = (eap_fast_tunnel_t *) tls_session->opaque;
+
+ RDEBUG("PAC provided via ClientHello SessionTicket extension");
+
+ if ((ntohs(opaque->hdr.type) & EAP_FAST_TLV_TYPE) != PAC_INFO_PAC_OPAQUE) {
+ errmsg = "PAC is not of type Opaque";
+error:
+ RERROR("%s, sending alert to client", errmsg);
+ /*
+ if (tls_session_handshake_alert(request, tls_session, SSL3_AL_FATAL, SSL_AD_BAD_CERTIFICATE)) {
+ RERROR("too many alerts");
+ return 0;
+ }
+ */
+ if (t->pac.key) talloc_free(t->pac.key);
+
+ memset(&t->pac, 0, sizeof(t->pac));
+ if (fast_vps) fr_pair_list_free(&fast_vps);
+ return 1;
+ }
+
+ /*
+ * we would like to use the length of the SessionTicket
+ * but Cisco hates everyone and sends a zero padding payload
+ * so we have to use the length in the PAC-Opaque header
+ */
+ length = ntohs(opaque->hdr.length);
+ if (len < (int) (length + sizeof(opaque->hdr))) {
+ errmsg = "PAC has bad length in header";
+ goto error;
+ }
+
+ if (length < PAC_A_ID_LENGTH + EVP_MAX_IV_LENGTH + EVP_GCM_TLS_TAG_LEN + 1) {
+ errmsg = "PAC file too short";
+ goto error;
+ }
+
+ if (memcmp(opaque->aad, t->a_id, PAC_A_ID_LENGTH)) {
+ errmsg = "PAC has incorrect A_ID";
+ goto error;
+ }
+
+ dlen = length - sizeof(opaque->aad) - sizeof(opaque->iv) - sizeof(opaque->tag);
+ plen = eap_fast_decrypt(opaque->data, dlen, opaque->aad, PAC_A_ID_LENGTH,
+ (uint8_t const *) opaque->tag, t->pac_opaque_key, opaque->iv,
+ (uint8_t *)&opaque_plaintext);
+ if (plen < 0) {
+ errmsg = "PAC failed to decrypt";
+ goto error;
+ }
+
+ fast_da = dict_attrbyname("FreeRADIUS-EAP-FAST-PAC-Opaque-TLV");
+ rad_assert(fast_da != NULL);
+
+ fast_vps = eap_fast_fast2vp((REQUEST *)tls_session, s, (uint8_t *)&opaque_plaintext, plen, fast_da, NULL);
+ if (!fast_vps) return 0;
+
+ for (VALUE_PAIR *vp = fr_cursor_init(&cursor, &fast_vps); vp; vp = fr_cursor_next(&cursor)) {
+ char *value;
+
+ switch ((vp->da->attr >> fr_attr_shift[3]) & fr_attr_mask[3]) {
+ case PAC_INFO_PAC_TYPE:
+ rad_assert(t->pac.type == 0);
+ t->pac.type = vp->vp_integer;
+ break;
+ case PAC_INFO_PAC_LIFETIME:
+ rad_assert(t->pac.expires == 0);
+ t->pac.expires = vp->vp_integer + time(NULL);
+ t->pac.expired = false;
+ break;
+ case PAC_INFO_PAC_KEY:
+ rad_assert(t->pac.key == NULL);
+ rad_assert(vp->vp_length == PAC_KEY_LENGTH);
+ t->pac.key = talloc_size(t, PAC_KEY_LENGTH);
+ rad_assert(t->pac.key != NULL);
+ memcpy(t->pac.key, vp->vp_octets, PAC_KEY_LENGTH);
+ break;
+ default:
+ value = vp_aprints(tls_session, vp, '"');
+ RERROR("unknown TLV: %s", value);
+ talloc_free(value);
+ errmsg = "unknown TLV";
+ goto error;
+ }
+ }
+
+ fr_pair_list_free(&fast_vps);
+
+ if (!t->pac.type) {
+ errmsg = "PAC missing type TLV";
+ goto error;
+ }
+
+ if (t->pac.type != PAC_TYPE_TUNNEL) {
+ errmsg = "PAC is of not of tunnel type";
+ goto error;
+ }
+
+ if (!t->pac.expires) {
+ errmsg = "PAC missing lifetime TLV";
+ goto error;
+ }
+
+ if (!t->pac.key) {
+ errmsg = "PAC missing key TLV";
+ goto error;
+ }
+
+ if (!SSL_set_session_secret_cb(tls_session->ssl, _session_secret, tls_session)) {
+ RERROR("Failed setting SSL session secret callback");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/*
+ * Do authentication, by letting EAP-TLS do most of the work.
+ */
+static int mod_process(void *arg, eap_handler_t *handler)
+{
+ int rcode;
+ int ret = 0;
+ fr_tls_status_t status;
+ rlm_eap_fast_t *inst = (rlm_eap_fast_t *) arg;
+ tls_session_t *tls_session = (tls_session_t *) handler->opaque;
+ eap_fast_tunnel_t *t = (eap_fast_tunnel_t *) tls_session->opaque;
+ REQUEST *request = handler->request;
+
+ RDEBUG2("Authenticate");
+
+ /*
+ * We need FAST data associated with the session, so
+ * allocate it here, if it wasn't already alloacted.
+ */
+ if (!t) t = tls_session->opaque = eap_fast_alloc(tls_session, inst);
+
+ /*
+ * Process TLS layer until done.
+ */
+ status = eaptls_process(handler);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+
+ /*
+ * Make request available to any SSL callbacks
+ */
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
+ switch (status) {
+ /*
+ * EAP-TLS handshake was successful, tell the
+ * client to keep talking.
+ *
+ * If this was EAP-TLS, we would just return
+ * an EAP-TLS-Success packet here.
+ */
+ case FR_TLS_SUCCESS:
+ tls_handshake_send(request, tls_session);
+ rad_assert(t != NULL);
+ break;
+
+ /*
+ * The TLS code is still working on the TLS
+ * exchange, and it's a valid TLS request.
+ * do nothing.
+ */
+ case FR_TLS_HANDLED:
+ ret = 1;
+ goto done;
+
+ /*
+ * Handshake is done, proceed with decoding tunneled
+ * data.
+ */
+ case FR_TLS_OK:
+ break;
+
+ /*
+ * Anything else: fail.
+ */
+ default:
+ ret = 0;
+ goto done;
+ }
+
+ /*
+ * Session is established, proceed with decoding
+ * tunneled data.
+ */
+ RDEBUG2("Session established. Proceeding to decode tunneled attributes");
+
+ /*
+ * Process the FAST portion of the request.
+ */
+ rcode = eap_fast_process(handler, tls_session);
+
+ switch (rcode) {
+ case PW_CODE_ACCESS_REJECT:
+ RDEBUG("Reject");
+ eaptls_fail(handler, EAP_FAST_VERSION);
+ ret = 0;
+ goto done;
+
+ /*
+ * Access-Challenge, continue tunneled conversation.
+ */
+ case PW_CODE_ACCESS_CHALLENGE:
+ RDEBUG("Challenge");
+ tls_handshake_send(request, tls_session);
+ eaptls_request(handler->eap_ds, tls_session);
+ ret = 1;
+ goto done;
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ case PW_CODE_ACCESS_ACCEPT:
+ if (t->accept_vps) {
+ RDEBUG2("Using saved attributes from the original Access-Accept");
+ rdebug_pair_list(L_DBG_LVL_2, request, t->accept_vps, NULL);
+ fr_pair_list_mcopy_by_num(handler->request->reply,
+ &handler->request->reply->vps,
+ &t->accept_vps, 0, 0, TAG_ANY);
+ } else if (t->use_tunneled_reply) {
+ RDEBUG2("No saved attributes in the original Access-Accept");
+ }
+ ret = eaptls_success(handler, EAP_FAST_VERSION);
+ goto done;
+
+ /*
+ * No response packet, MUST be proxying it.
+ * The main EAP module will take care of discovering
+ * that the request now has a "proxy" packet, and
+ * will proxy it, rather than returning an EAP packet.
+ */
+ case PW_CODE_STATUS_CLIENT:
+#ifdef WITH_PROXY
+ rad_assert(handler->request->proxy != NULL);
+#endif
+ ret = 1;
+ goto done;
+
+ default:
+ break;
+ }
+
+ /*
+ * Something we don't understand: Reject it.
+ */
+ eaptls_fail(handler, EAP_FAST_VERSION);
+
+done:
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
+
+ return ret;
+}
+
+static int eap_fast_tls_start(EAP_DS * eap_ds,tls_session_t *tls_session)
+{
+ EAPTLS_PACKET reply;
+
+ reply.code = FR_TLS_START;
+ reply.length = TLS_HEADER_LEN + 1 + tls_session->clean_in.used;/*flags*/
+
+ reply.flags = tls_session->peap_flag;
+ reply.flags = SET_START(reply.flags);
+
+ reply.data = tls_session->clean_in.data;
+ reply.dlen = tls_session->clean_in.used;
+
+ eaptls_compose(eap_ds, &reply);
+
+ return 1;
+}
+
+
+/*
+ * Send an initial eap-tls request to the peer, using the libeap functions.
+ */
+static int mod_session_init(void *type_arg, eap_handler_t *handler)
+{
+ int rcode;
+ tls_session_t *tls_session;
+ rlm_eap_fast_t *inst;
+ VALUE_PAIR *vp;
+ bool client_cert;
+ REQUEST *request = handler->request;
+
+ inst = type_arg;
+
+ handler->tls = true;
+
+ /*
+ * EAP-TLS-Require-Client-Cert attribute will override
+ * the require_client_cert configuration option.
+ */
+ vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0, TAG_ANY);
+ if (vp) {
+ client_cert = vp->vp_integer ? true : false;
+ } else {
+ client_cert = inst->req_client_cert;
+ }
+
+ /*
+ * Don't allow TLS 1.3 for us, even if it's allowed
+ * elsewhere. We haven't implemented the necessary
+ * changes, so we don't allow it.
+ */
+ handler->opaque = tls_session = eaptls_session(handler, inst->tls_conf, client_cert, false);
+
+ if (!tls_session) return 0;
+
+ if (inst->cipher_list) {
+ RDEBUG("Over-riding main cipher list with '%s'", inst->cipher_list);
+
+ if (!SSL_set_cipher_list(tls_session->ssl, inst->cipher_list)) {
+ REDEBUG("Failed over-riding cipher list to '%s'. EAP-FAST will likely not work",
+ inst->cipher_list);
+ }
+ }
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ {
+ int i;
+ for (i = 0; ; i++) {
+ const char *cipher = SSL_get_cipher_list(tls_session->ssl, i);
+ if (!cipher) break;
+ if (!strstr(cipher, "ADH-")) continue;
+ RDEBUG("Setting security level to 0 to allow anonymous cipher suites");
+ SSL_set_security_level(tls_session->ssl, 0);
+ break;
+ }
+ }
+#endif
+
+#ifdef SSL_OP_NO_TLSv1_3
+ /*
+ * Forcibly disable TLSv1.3
+ *
+ * TLSv1.3 does not support opaque session tickets, which
+ * are needed for EAP-FAST.
+ */
+ SSL_set_options(tls_session->ssl, SSL_OP_NO_TLSv1_3);
+#endif
+
+ /*
+ * Push TLV of authority_identity into tls_record
+ * call eap_tls_compose() with args
+ *
+ * RFC 4851 section 4.1.1
+ * N.B. mandatory/reserved flags are not applicable here
+ */
+ eap_fast_tlv_append(tls_session, PAC_INFO_A_ID, false, PAC_A_ID_LENGTH, inst->a_id);
+ tls_session->peap_flag = EAP_FAST_VERSION;
+ tls_session->length_flag = false;
+ rcode = eap_fast_tls_start(handler->eap_ds, tls_session);
+
+ if (rcode < 0) {
+ error:
+ talloc_free(tls_session);
+ return 0;
+ }
+
+ tls_session->record_init(&tls_session->clean_in);
+
+ if (!SSL_set_session_ticket_ext_cb(tls_session->ssl, _session_ticket, tls_session)) {
+ RERROR("Failed setting SSL session ticket callback");
+ goto error;
+ }
+
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_fast;
+rlm_eap_module_t rlm_eap_fast = {
+ .name = "eap_fast",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_gtc/README.md b/src/modules/rlm_eap/types/rlm_eap_gtc/README.md
new file mode 100644
index 0000000..d608462
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_gtc/README.md
@@ -0,0 +1,12 @@
+# rlm_eap_gtc
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements [RFC 3748](https://tools.ietf.org/html/rfc3748) EAP-GTC authentication. EAP-GTC allows EAP authentication
+using a plaintext password.
+
+Does not provide keying material for 802.11i, so cannot be used for WPA/2-Enterprise authentication unless wrapped
+in another method such as EAP-TTLS.
diff --git a/src/modules/rlm_eap/types/rlm_eap_gtc/all.mk b/src/modules/rlm_eap/types/rlm_eap_gtc/all.mk
new file mode 100644
index 0000000..26f2eb0
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_gtc/all.mk
@@ -0,0 +1,12 @@
+TARGETNAME := rlm_eap_gtc
+
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c
+
+SRC_CFLAGS :=
+TGT_LDLIBS :=
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c b/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c
new file mode 100644
index 0000000..031eba2
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c
@@ -0,0 +1,250 @@
+/*
+ * rlm_eap_gtc.c Handles that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003,2006 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eap.h"
+
+#include <freeradius-devel/rad_assert.h>
+
+/*
+ * EAP-GTC is just ASCII data carried inside of the EAP session.
+ * The length of the data is indicated by the encapsulating EAP
+ * protocol.
+ */
+typedef struct rlm_eap_gtc_t {
+ char const *challenge;
+ char const *auth_type_name;
+ int auth_type;
+} rlm_eap_gtc_t;
+
+static CONF_PARSER module_config[] = {
+ { "challenge", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_gtc_t, challenge), "Password: " },
+ { "auth_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_gtc_t, auth_type_name), "PAP" },
+ CONF_PARSER_TERMINATOR
+};
+
+
+
+/*
+ * Attach the module.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_gtc_t *inst;
+ DICT_VALUE *dval;
+
+ *instance = inst = talloc_zero(cs, rlm_eap_gtc_t);
+ if (!inst) return -1;
+
+ /*
+ * Parse the configuration attributes.
+ */
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ if (inst->auth_type_name && *inst->auth_type_name) {
+ dval = dict_valbyname(PW_AUTH_TYPE, 0, inst->auth_type_name);
+ if (!dval) {
+ ERROR("rlm_eap_gtc: Unknown Auth-Type %s",
+ inst->auth_type_name);
+ return -1;
+ }
+
+ inst->auth_type = dval->value;
+ } else {
+ inst->auth_type = PW_AUTH_TYPE_LOCAL;
+ }
+ return 0;
+}
+
+/*
+ * Initiate the EAP-GTC session by sending a challenge to the peer.
+ */
+static int mod_session_init(void *instance, eap_handler_t *handler)
+{
+ char challenge_str[1024];
+ int length;
+ EAP_DS *eap_ds = handler->eap_ds;
+ rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) instance;
+
+ if (radius_xlat(challenge_str, sizeof(challenge_str), handler->request, inst->challenge, NULL, NULL) < 0) {
+ return 0;
+ }
+
+ length = strlen(challenge_str);
+
+ /*
+ * We're sending a request...
+ */
+ eap_ds->request->code = PW_EAP_REQUEST;
+
+ eap_ds->request->type.data = talloc_array(eap_ds->request,
+ uint8_t, length);
+ if (!eap_ds->request->type.data) {
+ return 0;
+ }
+
+ memcpy(eap_ds->request->type.data, challenge_str, length);
+ eap_ds->request->type.length = length;
+
+ /*
+ * We don't need to authorize the user at this point.
+ *
+ * We also don't need to keep the challenge, as it's
+ * stored in 'handler->eap_ds', which will be given back
+ * to us...
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+
+/*
+ * Authenticate a previously sent challenge.
+ */
+static int CC_HINT(nonnull) mod_process(void *instance, eap_handler_t *handler)
+{
+ VALUE_PAIR *vp;
+ EAP_DS *eap_ds = handler->eap_ds;
+ rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) instance;
+ REQUEST *request = handler->request;
+
+ /*
+ * Get the Cleartext-Password for this user.
+ */
+ rad_assert(handler->stage == PROCESS);
+
+ /*
+ * Sanity check the response. We need at least one byte
+ * of data.
+ */
+ if (eap_ds->response->length <= 4) {
+ ERROR("rlm_eap_gtc: corrupted data");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+#if 0
+ if ((rad_debug_lvl > 2) && fr_log_fp) {
+ int i;
+
+ for (i = 0; i < eap_ds->response->length - 4; i++) {
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, "%d: ", i);
+
+ fprintf(fr_log_fp, "%02x ", eap_ds->response->type.data[i]);
+
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+ }
+ }
+#endif
+
+ /*
+ * Handle passwords here.
+ */
+ if (inst->auth_type == PW_AUTH_TYPE_LOCAL) {
+ /*
+ * For now, do cleartext password authentication.
+ */
+ vp = fr_pair_find_by_num(request->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
+ if (!vp) {
+ REDEBUG2("Cleartext-Password is required for authentication");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ if (eap_ds->response->type.length != vp->vp_length) {
+ REDEBUG2("Passwords are of different length. %u %u", (unsigned) eap_ds->response->type.length, (unsigned) vp->vp_length);
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ if (memcmp(eap_ds->response->type.data,
+ vp->vp_strvalue, vp->vp_length) != 0) {
+ REDEBUG2("Passwords are different");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ /*
+ * EAP packets can be ~64k long maximum, and
+ * we don't like that.
+ */
+ } else if (eap_ds->response->type.length <= 128) {
+ int rcode;
+
+ /*
+ * If there was a User-Password in the request,
+ * why the heck are they using EAP-GTC?
+ */
+ fr_pair_delete_by_num(&request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
+
+ vp = pair_make_request("User-Password", NULL, T_OP_EQ);
+ if (!vp) {
+ return 0;
+ }
+
+ fr_pair_value_bstrncpy(vp, eap_ds->response->type.data, eap_ds->response->type.length);
+
+ /*
+ * Add the password to the request, and allow
+ * another module to do the work of authenticating it.
+ */
+ request->password = vp;
+
+ /*
+ * This is a wild & crazy hack.
+ */
+ rcode = process_authenticate(inst->auth_type, request);
+ if (rcode != RLM_MODULE_OK) {
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ } else {
+ ERROR("rlm_eap_gtc: Response is too large to understand");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+
+ }
+
+ eap_ds->request->code = PW_EAP_SUCCESS;
+
+ return 1;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_gtc;
+rlm_eap_module_t rlm_eap_gtc = {
+ .name = "eap_gtc",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/.gitignore b/src/modules/rlm_eap/types/rlm_eap_ikev2/.gitignore
new file mode 100644
index 0000000..01a5daa
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/.gitignore
@@ -0,0 +1 @@
+all.mk
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/README.md b/src/modules/rlm_eap/types/rlm_eap_ikev2/README.md
new file mode 100644
index 0000000..9f80791
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/README.md
@@ -0,0 +1,11 @@
+# rlm_eap_ikev2
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements the EAP-IKEv2 authentication method based on the Internet
+Key Exchange Protocol version 2 (IKEv2), as specified in
+[draft-tschofenig-eap-ikev2-12](https://datatracker.ietf.org/doc/html/draft-tschofenig-eap-ikev2-12).
+Not compatible with RFC 5106 and should not be used.
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/all.mk.in b/src/modules/rlm_eap/types/rlm_eap_ikev2/all.mk.in
new file mode 100644
index 0000000..40ba9e7
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/all.mk.in
@@ -0,0 +1,13 @@
+TARGETNAME := @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c logging_impl.c ike_conf.c
+
+SRC_CFLAGS := @mod_cflags@
+TGT_LDLIBS := @mod_cflags@
+TGT_LDLIBS += $(LIBS)
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/configure b/src/modules/rlm_eap/types/rlm_eap_ikev2/configure
new file mode 100755
index 0000000..e125aa6
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/configure
@@ -0,0 +1,4206 @@
+#! /bin/sh
+# From configure.ac Revision.
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="rlm_eap_ikev2.c"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+mod_cflags
+mod_ldflags
+targetname
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_rlm_eap_ikev2
+with_eap_ikev2_include_dir
+with_eap_ikev2_lib_dir
+with_eap_ikev2_dir
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-rlm_eap_ikev2 build without rlm_eap_ikev2
+ --with-eap-ikev2-include-dir=DIR
+ Directory where the eap-ikev2 includes may be found
+ --with-eap-ikev2-lib-dir=DIR
+ Directory where the eap-ikev2 libraries may be found
+ --with-eap-ikev2-dir=DIR
+ Base directory where eap-ikev2 is installed
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+echo
+echo Running tests for rlm_eap_ikev2
+echo
+
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+# Check whether --with-rlm_eap_ikev2 was given.
+if test "${with_rlm_eap_ikev2+set}" = set; then :
+ withval=$with_rlm_eap_ikev2;
+fi
+
+
+
+
+fail=
+fr_status=
+fr_features=
+: > "config.report"
+: > "config.report.tmp"
+
+
+
+if test x"$with_rlm_eap_ikev2" != xno; then
+
+
+eap_ikev2_include_dir=
+
+# Check whether --with-eap-ikev2-include-dir was given.
+if test "${with_eap_ikev2_include_dir+set}" = set; then :
+ withval=$with_eap_ikev2_include_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need eap-ikev2-include-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ eap_ikev2_include_dir="$withval"
+ ;;
+ esac
+fi
+
+
+eap_ikev2_lib_dir=
+
+# Check whether --with-eap-ikev2-lib-dir was given.
+if test "${with_eap_ikev2_lib_dir+set}" = set; then :
+ withval=$with_eap_ikev2_lib_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need eap-ikev2-lib-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ eap_ikev2_lib_dir="$withval"
+ ;;
+ esac
+fi
+
+
+
+# Check whether --with-eap-ikev2-dir was given.
+if test "${with_eap_ikev2_dir+set}" = set; then :
+ withval=$with_eap_ikev2_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need eap-ikev2-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ eap_ikev2_lib_dir="$withval/lib"
+ eap_ikev2_include_dir="$withval/include"
+ ;;
+ esac
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL support" >&5
+$as_echo_n "checking for OpenSSL support... " >&6; }
+if test "x$OPENSSL_LIBS" != "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fail="$fail OpenSSL"
+
+fi
+
+
+smart_try_dir="$eap_ikev2_include_dir"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_safe=`echo "EAPIKEv2/connector.h" | sed 'y%./+-%__pm%'`
+old_CPPFLAGS="$CPPFLAGS"
+smart_include=
+smart_include_dir="/usr/local/include /opt/include"
+
+_smart_try_dir=
+_smart_include_dir=
+
+for _prefix in $smart_prefix ""; do
+ for _dir in $smart_try_dir; do
+ _smart_try_dir="${_smart_try_dir} ${_dir}/${_prefix}"
+ done
+
+ for _dir in $smart_include_dir; do
+ _smart_include_dir="${_smart_include_dir} ${_dir}/${_prefix}"
+ done
+done
+
+if test "x$_smart_try_dir" != "x"; then
+ for try in $_smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EAPIKEv2/connector.h in $try" >&5
+$as_echo_n "checking for EAPIKEv2/connector.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <EAPIKEv2/connector.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" = "x"; then
+ for _prefix in $smart_prefix; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${_prefix}/EAPIKEv2/connector.h" >&5
+$as_echo_n "checking for ${_prefix}/EAPIKEv2/connector.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <EAPIKEv2/connector.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem ${_prefix}/"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+fi
+
+if test "x$smart_include" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EAPIKEv2/connector.h" >&5
+$as_echo_n "checking for EAPIKEv2/connector.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <EAPIKEv2/connector.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include=" "
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "x$smart_include" = "x"; then
+
+ for try in $_smart_include_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EAPIKEv2/connector.h in $try" >&5
+$as_echo_n "checking for EAPIKEv2/connector.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <EAPIKEv2/connector.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" != "x"; then
+ eval "ac_cv_header_$ac_safe=yes"
+ CPPFLAGS="$smart_include $old_CPPFLAGS"
+ SMART_CPPFLAGS="$smart_include $SMART_CPPFLAGS"
+fi
+
+smart_prefix=
+
+if test "x$ac_cv_header_EAPIKEv2_connector_h" != "xyes"; then
+
+fail="$fail EAPIKEv2/connector.h"
+
+fi
+
+
+LIBS="${OPENSSL_LIBS}"
+smart_try_dir="$eap_ikev2_lib_dir"
+
+
+sm_lib_safe=`echo "eap-ikev2" | sed 'y%./+-%__p_%'`
+sm_func_safe=`echo "ikev2_set_log_callback" | sed 'y%./+-%__p_%'`
+
+old_LIBS="$LIBS"
+old_CPPFLAGS="$CPPFLAGS"
+smart_lib=
+smart_ldflags=
+smart_lib_dir=
+
+if test "x$smart_try_dir" != "x"; then
+ for try in $smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ikev2_set_log_callback in -leap-ikev2 in $try" >&5
+$as_echo_n "checking for ikev2_set_log_callback in -leap-ikev2 in $try... " >&6; }
+ LIBS="-leap-ikev2 $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char ikev2_set_log_callback();
+int
+main ()
+{
+ikev2_set_log_callback()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-leap-ikev2"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ikev2_set_log_callback in -leap-ikev2" >&5
+$as_echo_n "checking for ikev2_set_log_callback in -leap-ikev2... " >&6; }
+ LIBS="-leap-ikev2 $old_LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char ikev2_set_log_callback();
+int
+main ()
+{
+ikev2_set_log_callback()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-leap-ikev2"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$old_LIBS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ for try in /usr/local/lib /opt/lib; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ikev2_set_log_callback in -leap-ikev2 in $try" >&5
+$as_echo_n "checking for ikev2_set_log_callback in -leap-ikev2 in $try... " >&6; }
+ LIBS="-leap-ikev2 $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char ikev2_set_log_callback();
+int
+main ()
+{
+ikev2_set_log_callback()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-leap-ikev2"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" != "x"; then
+ eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes"
+ LIBS="$smart_ldflags $smart_lib $old_LIBS"
+ SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS"
+fi
+
+if test "x$ac_cv_lib_eap_ikev2_ikev2_set_log_callback" != "xyes"; then
+
+fail="$fail libeap-ikev2"
+
+fi
+
+
+ targetname=rlm_eap_ikev2
+else
+ targetname=
+ echo \*\*\* module rlm_eap_ikev2 is disabled.
+
+
+fr_status="disabled"
+
+fi
+
+if test x"$fail" != x""; then
+ targetname=""
+
+
+ if test x"${enable_strict_dependencies}" = x"yes"; then
+ as_fn_error $? "set --without-rlm_eap_ikev2 to disable it explicitly." "$LINENO" 5
+ else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: silently not building rlm_eap_ikev2." >&5
+$as_echo "$as_me: WARNING: silently not building rlm_eap_ikev2." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: FAILURE: rlm_eap_ikev2 requires: $fail." >&5
+$as_echo "$as_me: WARNING: FAILURE: rlm_eap_ikev2 requires: $fail." >&2;};
+ fail="$(echo $fail)"
+
+
+fr_status="skipping (requires $fail)"
+
+ fr_features=
+
+ fi
+
+else
+
+
+fr_status="OK"
+
+fi
+
+if test x"$fr_features" = x""; then
+ $as_echo "$fr_status" > "config.report"
+else
+ $as_echo_n "$fr_status ... " > "config.report"
+ cat "config.report.tmp" >> "config.report"
+fi
+
+rm "config.report.tmp"
+
+
+
+
+mod_ldfags="$SMART_LIBS"
+mod_cflags="$SMART_CPPFLAGS"
+
+
+
+
+ac_config_files="$ac_config_files all.mk"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "all.mk") CONFIG_FILES="$CONFIG_FILES all.mk" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/configure.ac b/src/modules/rlm_eap/types/rlm_eap_ikev2/configure.ac
new file mode 100644
index 0000000..6c01056
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/configure.ac
@@ -0,0 +1,99 @@
+AC_PREREQ([2.69])
+AC_INIT
+AC_CONFIG_SRCDIR([rlm_eap_ikev2.c])
+AC_REVISION($Revision$)
+FR_INIT_MODULE([rlm_eap_ikev2])
+
+FR_MODULE_START_TESTS
+
+dnl extra argument: --with-eap-ikev2-include-dir=DIR
+eap_ikev2_include_dir=
+AC_ARG_WITH(eap-ikev2-include-dir,
+ [AS_HELP_STRING([--with-eap-ikev2-include-dir=DIR],
+ [Directory where the eap-ikev2 includes may be found])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need eap-ikev2-include-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ eap_ikev2_include_dir="$withval"
+ ;;
+ esac])
+
+dnl extra argument: --with-eap-ikev2-lib-dir=DIR
+eap_ikev2_lib_dir=
+AC_ARG_WITH(eap-ikev2-lib-dir,
+ [AS_HELP_STRING([--with-eap-ikev2-lib-dir=DIR],
+ [Directory where the eap-ikev2 libraries may be found])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need eap-ikev2-lib-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ eap_ikev2_lib_dir="$withval"
+ ;;
+ esac])
+
+dnl extra argument: --with-eap-ikev2-dir=DIR
+AC_ARG_WITH(eap-ikev2-dir,
+ [AS_HELP_STRING([--with-eap-ikev2-dir=DIR],
+ [Base directory where eap-ikev2 is installed])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need eap-ikev2-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ eap_ikev2_lib_dir="$withval/lib"
+ eap_ikev2_include_dir="$withval/include"
+ ;;
+ esac])
+
+dnl ############################################################
+dnl # Check for OpenSSL support
+dnl ############################################################
+
+AC_MSG_CHECKING(for OpenSSL support)
+if test "x$OPENSSL_LIBS" != "x"; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+ FR_MODULE_FAIL([OpenSSL])
+fi
+
+dnl ############################################################
+dnl # Check for eap-ikev2 includes
+dnl ############################################################
+
+smart_try_dir="$eap_ikev2_include_dir"
+FR_SMART_CHECK_INCLUDE([EAPIKEv2/connector.h])
+if test "x$ac_cv_header_EAPIKEv2_connector_h" != "xyes"; then
+ FR_MODULE_FAIL([EAPIKEv2/connector.h])
+fi
+
+dnl ############################################################
+dnl # Check for eap-ikev2 library
+dnl ############################################################
+
+LIBS="${OPENSSL_LIBS}"
+smart_try_dir="$eap_ikev2_lib_dir"
+FR_SMART_CHECK_LIB([eap-ikev2],[ikev2_set_log_callback])
+if test "x$ac_cv_lib_eap_ikev2_ikev2_set_log_callback" != "xyes"; then
+ FR_MODULE_FAIL([libeap-ikev2])
+fi
+
+FR_MODULE_END_TESTS
+
+mod_ldfags="$SMART_LIBS"
+mod_cflags="$SMART_CPPFLAGS"
+
+AC_SUBST(mod_ldflags)
+AC_SUBST(mod_cflags)
+
+AC_CONFIG_FILES([all.mk])
+AC_OUTPUT
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.c b/src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.c
new file mode 100644
index 0000000..dda4f67
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.c
@@ -0,0 +1,420 @@
+/*
+ * ike_conf.c - module config loading functions
+ *
+ * This file is part of rlm_eap_ikev2 freeRADIUS module which implements
+ * EAP-IKEv2 protocol functionality.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) 2005-2006 Krzysztof Rzecki <krzysztof.rzecki@ccns.pl>
+ * Copyright (C) 2005-2006 Rafal Mijal <rafal.mijal@ccns.pl>
+ * Copyright (C) 2005-2006 Piotr Marnik <piotr.marnik@ccns.pl>
+ * Copyright (C) 2005-2006 Pawel Matejski <pawel.matejski@ccns.pl>
+ * Copyright 1999-2007 The FreeRADIUS server project
+ *
+ */
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+
+#include "ike_conf.h"
+#include "eap.h"
+#include "logging_impl.h"
+
+static int rad_load_transforms(struct Protocol *prot,CONF_SECTION *cf);
+
+struct config_transform
+{
+ char const *name;
+ u_int8_t type;
+ int exist_flag;
+};
+
+enum {
+ OPT_INTEGRITY = 0x01,
+ OPT_PRF = 0x02,
+ OPT_ENCRYPTION = 0x04,
+ OPT_DHGROUP = 0x08,
+ OPT_NEEDED = OPT_INTEGRITY | OPT_PRF | OPT_ENCRYPTION | OPT_DHGROUP
+
+};
+
+static struct config_transform config_transforms[] =
+{
+ {"integrity", IKEv2_TRT_INTEGRITY_ALGORITHM, OPT_INTEGRITY},
+ {"prf", IKEv2_TRT_PSEUDO_RANDOM_FUNCTION, OPT_PRF},
+ {"encryption", IKEv2_TRT_ENCRYPTION_ALGORITHM, OPT_ENCRYPTION},
+ {"dhgroup", IKEv2_TRT_DIFFIE_HELLMAN_GROUP, OPT_DHGROUP },
+ {NULL, 0, 0} /* end of list */
+
+};
+
+/*
+ * Copied from rlm_files, and NOT under the same copyright
+ * as the rest of the module!
+ *
+ * Also, it is UNNECESSARY to read the "users" file here!
+ * Doing this shows a misunderstanding of how the server works.
+ */
+int getusersfile(TALLOC_CTX *ctx, char const *filename, PAIR_LIST **pair_list, char const *compat_mode_str)
+{
+ int rcode;
+ PAIR_LIST *users = NULL;
+
+ rcode = pairlist_read(ctx, filename, &users, 1);
+ if (rcode < 0) {
+ return -1;
+ }
+
+ /*
+ * Walk through the 'users' file list, if we're debugging,
+ * or if we're in compat_mode.
+ */
+ if ((rad_debug_lvl) ||
+ (strcmp(compat_mode_str, "cistron") == 0)) {
+ PAIR_LIST *entry;
+ VALUE_PAIR *vp;
+ bool compat_mode = false;
+
+ if (strcmp(compat_mode_str, "cistron") == 0) {
+ compat_mode = true;
+ }
+
+ entry = users;
+ while (entry) {
+ if (compat_mode) {
+ DEBUG("[%s]:%d Cistron compatibility checks for entry %s ...",
+ filename, entry->lineno,
+ entry->name);
+ }
+
+ /*
+ * Look for improper use of '=' in the
+ * check items. They should be using
+ * '==' for on-the-wire RADIUS attributes,
+ * and probably ':=' for server
+ * configuration items.
+ */
+ for (vp = entry->check; vp != NULL; vp = vp->next) {
+ /*
+ * Ignore attributes which are set
+ * properly.
+ */
+ if (vp->op != T_OP_EQ) {
+ continue;
+ }
+
+ /*
+ * If it's a vendor attribute,
+ * or it's a wire protocol,
+ * ensure it has '=='.
+ */
+ if ((vp->da->vendor!= 0) ||
+ (vp->da->attr < 0x100)) {
+ if (!compat_mode) {
+ WARN("[%s]:%d Changing '%s =' to '%s =='\n\tfor comparing RADIUS attribute in check item list for user %s",
+ filename, entry->lineno,
+ vp->da->name, vp->da->name,
+ entry->name);
+ } else {
+ DEBUG("\tChanging '%s =' to '%s =='",
+ vp->da->name, vp->da->name);
+ }
+ vp->op = T_OP_CMP_EQ;
+ continue;
+ }
+
+ /*
+ * Cistron Compatibility mode.
+ *
+ * Re-write selected attributes
+ * to be '+=', instead of '='.
+ *
+ * All others get set to '=='
+ */
+ if (compat_mode) {
+ /*
+ * Non-wire attributes become +=
+ *
+ * On the write attributes
+ * become ==
+ */
+ if ((vp->da->attr >= 0x100) &&
+ (vp->da->attr <= 0xffff) &&
+ (vp->da->attr != PW_HINT) &&
+ (vp->da->attr != PW_HUNTGROUP_NAME)) {
+ DEBUG("\tChanging '%s =' to '%s +='",
+ vp->da->name, vp->da->name);
+ vp->op = T_OP_ADD;
+ } else {
+ DEBUG("\tChanging '%s =' to '%s =='",
+ vp->da->name, vp->da->name);
+ vp->op = T_OP_CMP_EQ;
+ }
+ }
+
+ } /* end of loop over check items */
+
+
+ /*
+ * Look for server configuration items
+ * in the reply list.
+ *
+ * It's a common enough mistake, that it's
+ * worth doing.
+ */
+ for (vp = entry->reply; vp != NULL; vp = vp->next) {
+ /*
+ * If it's NOT a vendor attribute,
+ * and it's NOT a wire protocol
+ * and we ignore Fall-Through,
+ * then bitch about it, giving a
+ * good warning message.
+ */
+ if ((vp->da->vendor == 0) &&
+ (vp->da->attr > 1000)) {
+ WARN("[%s]:%d Check item \"%s\"\n"
+ "\tfound in reply item list for user \"%s\".\n"
+ "\tThis attribute MUST go on the first line"
+ " with the other check items",
+ filename, entry->lineno, vp->da->name, entry->name);
+ }
+ }
+
+ entry = entry->next;
+ }
+ }
+
+ *pair_list = users;
+ return 0;
+}
+
+/**
+ * Load all proposals from 'propsals' subsection
+ */
+
+int rad_load_proposals(ikev2_ctx *i2,CONF_SECTION *cf)
+{
+ rad_assert(i2!=NULL && cf!=NULL);
+
+ CONF_SECTION *cf_prop=NULL;
+ cf=cf_subsection_find_next(cf,NULL,"proposals");
+ if(!cf) {
+ ERROR(IKEv2_LOG_PREFIX "Can't find proposals section");
+ return -1;
+ }
+ int nprop=0;
+ for(
+ cf_prop=cf_subsection_find_next(cf,NULL,"proposal");
+ cf_prop;
+ cf_prop=cf_subsection_find_next(cf,cf_prop,"proposal")
+ ) {
+ nprop++;
+ struct Proposal *prop;
+ struct Protocol *prot;
+ prop=AddProposal(&i2->suppProp);
+ prot=AddProtocol(prop,IKEv2_PID_IKE_SA,0,0);
+ if(rad_load_transforms(prot,cf_prop)) {
+ ERROR(IKEv2_LOG_PREFIX "Failed to load proposal (%d)",
+ nprop);
+ return -1;
+ }
+ }
+ if(!nprop) {
+ ERROR(IKEv2_LOG_PREFIX "Can't find any proposal");
+ return -1;
+ }
+ return 0;
+
+}
+
+
+
+/**
+ * Load transforms from protocol subsection
+ */
+
+static int rad_load_transforms(struct Protocol *prot, CONF_SECTION *cf)
+{
+ CONF_PAIR *cp;
+ int option_exists = 0;
+ int i = 0;
+
+ rad_assert(prot);
+ rad_assert(cf);
+
+ DEBUG(IKEv2_LOG_PREFIX "Begin load transforms");
+
+ while(config_transforms[i].name)
+ {
+ uint8_t id;
+ uint16_t keylen;
+
+ for(cp = cf_pair_find(cf,config_transforms[i].name);
+ cp;
+ cp = cf_pair_find_next(cf,cp,config_transforms[i].name)) {
+ if (TransformFromName(cf_pair_value(cp),config_transforms[i].type,&id,&keylen)) {
+ ERROR(IKEv2_LOG_PREFIX "Unsupported %s transform: %s ",
+ config_transforms[i].name,cf_pair_value(cp));
+ return -1;
+ }
+
+ if (!AddTransform(prot,config_transforms[i].type,id,keylen)) {
+ ERROR(IKEv2_LOG_PREFIX "Problem with transform %s:%s",
+ config_transforms[i].name,cf_pair_value(cp));
+ return -1;
+ }
+ option_exists |= config_transforms[i].exist_flag;
+ }
+ i++;
+ }
+
+ if ((option_exists & OPT_NEEDED) != OPT_NEEDED) {
+ ERROR(IKEv2_LOG_PREFIX "Not all mandatory transforms are set properly");
+ DEBUG(IKEv2_LOG_PREFIX "Option flags: 0x%02X",option_exists);
+
+ return -1;
+ }
+ return 0;
+}
+
+
+void rad_update_shared_seclist(struct sharedSecList **list, char const *id, VALUE_PAIR *items,
+ int default_client_authtype)
+{
+ rad_assert(list && id);
+
+ char *ike_id;
+ char *secret = NULL;
+ int id_type = 0;
+ int authtype = default_client_authtype;
+ VALUE_PAIR *vp;
+
+ memcpy(&ike_id, &id, sizeof(id));
+
+ if (!items) {
+ AddSharedSec(list, 0, ike_id, NULL, default_client_authtype);
+
+ return;
+ }
+
+ //idtype
+ vp = fr_pair_find_by_num(items, RAD_EAP_IKEV2_IDTYPE, 0, TAG_ANY);
+ if (!vp) {
+ DEBUG(IKEv2_LOG_PREFIX "[%s] -- Id type not set", id);
+ } else {
+ id_type = vp->vp_integer;
+ if (!id_type) {
+ DEBUG(IKEv2_LOG_PREFIX "[%s] -- Not valid id type", id);
+ }
+ }
+
+ //secret
+ vp = fr_pair_find_by_num(items, RAD_EAP_IKEV2_SECRET, 0, TAG_ANY);
+ if (!vp || !vp->vp_length) {
+ DEBUG(IKEv2_LOG_PREFIX "[%s] -- Secret not set", id);
+ } else {
+ memcpy(&secret, &vp->vp_strvalue, sizeof(secret));
+ }
+
+ //authtype
+ vp = fr_pair_find_by_num(items, RAD_EAP_IKEV2_AUTHTYPE, 0, TAG_ANY);
+ if (vp && vp->vp_length) {
+ authtype = AuthtypeFromName(vp->vp_strvalue);
+
+ if (authtype == -1) {
+ ERROR(IKEv2_LOG_PREFIX "Unsupported 'EAP-IKEv2-AuthType' value (%s),using 'both'",
+ vp->vp_strvalue);
+ authtype = IKEv2_AUTH_BOTH;
+ }
+
+ }
+
+ AddSharedSec(list, id_type, ike_id, secret, authtype);
+}
+
+/**
+ * load user credentials from raddb/users (read directly from users file)
+ */
+
+int rad_load_credentials(TALLOC_CTX *ctx, ikev2_ctx *i2,char *filename,char *authtype_name)
+{
+ rad_assert(i2 && filename && authtype_name);
+ int authtype;
+
+ authtype=AuthtypeFromName(authtype_name);
+ if(authtype==-1) {
+ ERROR(IKEv2_LOG_PREFIX "Unsupported 'default_auth_type' value (%s), using both",authtype_name);
+ authtype=IKEv2_AUTH_BOTH;
+ }
+
+ PAIR_LIST *users=NULL;
+ if(getusersfile(ctx, filename,&users,"no")!=0) {
+ ERROR(IKEv2_LOG_PREFIX "Error while loading %s userfile",filename);
+ return -1;
+ }
+ PAIR_LIST *tusers=users;
+ while(tusers) {
+ if(strcmp(tusers->name,"DEFAULT")) {
+ rad_update_shared_seclist(&i2->sslist,tusers->name,tusers->check,authtype);
+ }
+ tusers=tusers->next;
+ }
+ pairlist_free(&users);
+ //print sslist
+// struct sharedSecList *sslist=i2->sslist;
+// while(sslist) {
+// ERROR("sslist:id=%s",sslist->id);
+// ERROR("sslist:idlen=%d",sslist->idlen);
+// ERROR("sslist:pwd=%s",sslist->pwd);
+// ERROR("sslist:pwdlen=%d",sslist->pwdlen);
+// ERROR("sslist:idtype= %d",sslist->idtype);
+// ERROR("sslist:authtype=%d",sslist->authtype);
+// sslist=sslist->next;
+// }
+ return 0;
+
+
+}
+
+int rad_get_authtype(char* authtype_name)
+{
+ rad_assert(authtype_name);
+ if(!strcmp(authtype_name,"cert")) {
+ DEBUG(IKEv2_LOG_PREFIX "Using server auth type: cert");
+ return IKEv2_AUTH_CERT;
+ }
+ if(!strcmp(authtype_name,"secret")) {
+ DEBUG(IKEv2_LOG_PREFIX "Using server auth type: secret");
+ return IKEv2_AUTH_SK;
+ }
+ AUTH(IKEv2_LOG_PREFIX "Unsupported server auth type: %s",authtype_name);
+ AUTH(IKEv2_LOG_PREFIX "Using server auth type: secret (default)");
+ return IKEv2_AUTH_SK;
+}
+
+int file_exists(char *filename)
+{
+ int result=0;
+ FILE *fp=fopen(filename,"r");
+ if(fp) {
+ result=1;
+ fclose(fp);
+ }
+ return result;
+}
+
+
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.h b/src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.h
new file mode 100644
index 0000000..ee2561c
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/ike_conf.h
@@ -0,0 +1,48 @@
+/*
+ * ike_conf.h - module config loading functions
+ *
+ * This file is part of rlm_eap_ikev2 freeRADIUS module which implements
+ * EAP-IKEv2 protocol functionality.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) 2005-2006 Krzysztof Rzecki <krzysztof.rzecki@ccns.pl>
+ * Copyright (C) 2005-2006 Rafal Mijal <rafal.mijal@ccns.pl>
+ * Copyright (C) 2005-2006 Piotr Marnik <piotr.marnik@ccns.pl>
+ * Copyright (C) 2005-2006 Pawel Matejski <pawel.matejski@ccns.pl>
+ *
+ */
+
+#ifndef IKE_CONF_H
+#define IKE_CONF_H
+
+#include <EAPIKEv2/connector.h>
+#include "eap.h"
+
+#define RAD_EAP_IKEV2_IDTYPE 1103
+#define RAD_EAP_IKEV2_ID 1104
+#define RAD_EAP_IKEV2_SECRET 1105
+#define RAD_EAP_IKEV2_AUTHTYPE 1106
+
+
+int rad_load_proposals(ikev2_ctx *i2,CONF_SECTION *cf);
+int rad_load_credentials(TALLOC_CTX *ctx, ikev2_ctx *i2,char *filename,char *authtype_name);
+int getusersfile(TALLOC_CTX *ctx, char const *filename, PAIR_LIST **pair_list,char const *compat_mode_str);
+void rad_update_shared_seclist(struct sharedSecList **list, char const *id, VALUE_PAIR *items,
+ int default_client_authtype);
+int rad_get_authtype(char *authtype_name);
+int rad_get_client_authtype(char const *authtype);
+int file_exists(char *filename);
+#endif //IKE_CONF_H
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.c b/src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.c
new file mode 100644
index 0000000..d618b6f
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.c
@@ -0,0 +1,52 @@
+/*
+ * logging_impl.c - logging callback for lib-eapikev2
+ *
+ * This file is part of rlm_eap_ikev2 freeRADIUS module which implements
+ * EAP-IKEv2 protocol functionality.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) 2005-2006 Krzysztof Rzecki <krzysztof.rzecki@ccns.pl>
+ * Copyright (C) 2005-2006 Rafal Mijal <rafal.mijal@ccns.pl>
+ * Copyright (C) 2005-2006 Piotr Marnik <piotr.marnik@ccns.pl>
+ * Copyright (C) 2005-2006 Pawel Matejski <pawel.matejski@ccns.pl>
+ *
+ */
+
+#include <freeradius-devel/radiusd.h>
+#include "logging_impl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <EAPIKEv2/logging.h>
+
+void vxlogf(int iklevel, char const * fmt,va_list ap)
+{
+ int level;
+ switch (iklevel) {
+ case I2L_DBG:
+ level=L_DBG;
+ break;
+ case I2L_INFO:
+ level=L_INFO;
+ break;
+ case I2L_ERR:
+ level=L_ERR;
+ break;
+ default:
+ level=L_DBG;
+
+ }
+ vradlog(level, fmt, ap);
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.h b/src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.h
new file mode 100644
index 0000000..923cd04
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/logging_impl.h
@@ -0,0 +1,35 @@
+/*
+ * logging_impl.c - logging callback for lib-eapikev2
+ *
+ * This file is part of rlm_eap_ikev2 freeRADIUS module which implements
+ * EAP-IKEv2 protocol functionality.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) 2005-2006 Krzysztof Rzecki <krzysztof.rzecki@ccns.pl>
+ * Copyright (C) 2005-2006 Rafal Mijal <rafal.mijal@ccns.pl>
+ * Copyright (C) 2005-2006 Piotr Marnik <piotr.marnik@ccns.pl>
+ * Copyright (C) 2005-2006 Pawel Matejski <pawel.matejski@ccns.pl>
+ *
+ */
+
+#ifndef LOGGING_IMPL_H
+#define LOGGING_IMPL_H
+#include <stdarg.h>
+
+#define IKEv2_LOG_PREFIX " rlm_eap_ikev2: "
+
+void CC_HINT(format (printf, 2, 0)) vxlogf(int iklevel, char const * fmt, va_list ap);
+#endif //LOGGING_IMPL_H
diff --git a/src/modules/rlm_eap/types/rlm_eap_ikev2/rlm_eap_ikev2.c b/src/modules/rlm_eap/types/rlm_eap_ikev2/rlm_eap_ikev2.c
new file mode 100644
index 0000000..9733632
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ikev2/rlm_eap_ikev2.c
@@ -0,0 +1,526 @@
+/*
+ * rlm_eap_ikev2.c - Handles that are called from eap
+ *
+ * This file is part of rlm_eap_ikev2 freeRADIUS module which implements
+ * EAP-IKEv2 protocol functionality.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) 2005-2006 Krzysztof Rzecki <krzysztof.rzecki@ccns.pl>
+ * Copyright (C) 2005-2006 Rafal Mijal <rafal.mijal@ccns.pl>
+ * Copyright (C) 2005-2006 Piotr Marnik <piotr.marnik@ccns.pl>
+ * Copyright (C) 2005-2006 Pawel Matejski <pawel.matejski@ccns.pl>
+ * Copyright 1999-2007 The FreeRADIUS server project
+ *
+ */
+
+#include <freeradius-devel/radiusd.h>
+#include "eap.h"
+
+#include <assert.h>
+#include <freeradius-devel/rad_assert.h>
+
+#include "logging_impl.h"
+#include <EAPIKEv2/connector.h>
+#include "ike_conf.h"
+
+typedef enum {
+ PW_IKEV2_CHALLENGE = 1,
+ PW_IKEV2_RESPONSE,
+ PW_IKEV2_SUCCESS,
+ PW_IKEV2_FAILURE,
+ PW_IKEV2_MAX_CODES
+} pw_ikev2_code;
+
+#define IKEV2_HEADER_LEN 4
+#define IKEV2_MPPE_KEY_LEN 32
+
+typedef struct rlm_eap_ikev2 {
+ char const *tls_ca_file; //!< Sets the full path to a CA certificate (used to validate
+ //!< the certificate the server presents).
+
+ char const *tls_private_key_file; //!< Sets the path to the private key for our public
+ //!< certificate.
+ char const *tls_private_key_password; //!< Sets the path to the private key for our public
+ //!< certificate.
+
+ char const *tls_certificate_file; //!< Sets the path to the public certificate file we present
+ //!< to the servers.
+ char const *tls_crl;
+
+ char const *id;
+ uint32_t max_fragment_size;
+ uint32_t dh_counter_max;
+
+ char const *default_auth_type;
+ char const *users_file_name;
+ char const *server_auth_type;
+ char const *server_id_type;
+ bool send_cert_request;
+
+ uint32_t fast_expire;
+
+ bool enable_fast_dhex;
+ bool enable_fast_reconnect;
+} rlm_eap_ikev2_t;
+
+CONF_PARSER module_config[] = {
+ { "ca_file", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, tls_ca_file), NULL },
+ { "private_key_file", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, tls_private_key_file), NULL },
+ { "private_key_password", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, tls_private_key_password), NULL },
+ { "certificate_file", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, tls_certificate_file), NULL },
+ { "crl_file", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, tls_crl), NULL },
+
+ { "id", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, id), NULL },
+ { "fragment_size", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_ikev2_t, max_fragment_size), IKEv2_DEFAULT_MAX_FRAGMENT_SIZE_STR },
+ { "dh_counter_max", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_ikev2_t, dh_counter_max), IKEv2_DEFAULT_DH_COUNTER_MAX_STR },
+ { "default_authtype", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, default_auth_type), "both" },
+ { "usersfile", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT, rlm_eap_ikev2_t, users_file_name),"${confdir}/users" },
+ { "server_authtype", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, server_auth_type), "secret" },
+ { "idtype", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ikev2_t, server_id_type), IKEv2_DEFAULT_IDTYPE_STR },
+ { "certreq", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_ikev2_t, send_cert_request), "no" },
+ { "fast_timer_expire", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_ikev2_t, fast_expire), "900" },
+
+ { "fast_dh_exchange", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_ikev2_t, enable_fast_dhex), "no" },
+ { "enable_fast_reauth", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_ikev2_t, enable_fast_reconnect), "yes" },
+ CONF_PARSER_TERMINATOR
+};
+
+static int set_mppe_keys(eap_handler_t *handler)
+{
+ uint8_t const *p;
+ struct IKEv2Session *session;
+
+ session = ((struct IKEv2Data*)handler->opaque)->session;
+
+ if (session->eapKeyData==NULL){
+ INFO(IKEv2_LOG_PREFIX "Key session not available!!!");
+ return 1;
+ }
+
+ p = session->eapKeyData;
+ eap_add_reply(handler->request, "MS-MPPE-Recv-Key", p, IKEV2_MPPE_KEY_LEN);
+ p += IKEV2_MPPE_KEY_LEN;
+ eap_add_reply(handler->request, "MS-MPPE-Send-Key", p, IKEV2_MPPE_KEY_LEN);
+ return 0;
+}
+
+/** Compose Radius like message from table of output bytes
+ *
+ */
+static int compose_rad_message(uint8_t *out,u_int32_t olen, EAP_DS *eap_ds) {
+ int len;
+
+ eap_ds->request->type.num = PW_EAP_IKEV2;
+ eap_ds->request->code = ((struct EAPHeader *)out)->Code;
+
+ if (eap_ds->request->code > PW_EAP_REQUEST || (olen <= 4)) {
+ eap_ds->request->type.data = NULL;
+ eap_ds->request->type.length = 0;
+
+ return 0;
+ }
+
+ len = ntohs(((struct EAPHeader *)out)->Length);
+
+ eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, len);
+ if (!eap_ds->request->type.data) return 1;
+
+ memcpy(eap_ds->request->type.data, out + 5, len - 5);
+ eap_ds->request->type.length = len - 5;
+
+ return 0;
+}
+
+/** Free memory after EAP-IKEv2 module usage
+ *
+ */
+static int mod_detach(void *instance)
+{
+ struct ikev2_ctx *data = (struct ikev2_ctx *) instance;
+
+ if (data) {
+ Free_ikev2_ctx(data);
+ data = NULL;
+ }
+ return 0;
+}
+
+/** Free memory after finished IKEv2 session
+ *
+ */
+static void ikev2_free_opaque(void *opaque)
+{
+
+ int fast_deleted;
+ struct IKEv2Data *ikev2_data=(struct IKEv2Data*)opaque;
+
+ DEBUG(IKEv2_LOG_PREFIX "Free session data");
+
+ if (ikev2_data->session) {
+ if (ikev2_data->session->Status != IKEv2_SST_ESTABLISHED) {
+ DEBUG(IKEv2_LOG_PREFIX "Unfinished IKEv2 session - cleanup!!!");
+ IKEv2EndSession(ikev2_data->i2, ikev2_data->session);
+ ikev2_data->session = NULL;
+ } else {
+ DEBUG(IKEv2_LOG_PREFIX "Unfinished IKEv2 session - keep it!!!");
+ ikev2_data->session = NULL;
+ }
+ }
+
+ fast_deleted = FreeSessionIfExpired(ikev2_data->i2, time(NULL));
+ if (fast_deleted) {
+ DEBUG(IKEv2_LOG_PREFIX "Deleted %d expired IKEv2 sessions", fast_deleted);
+ }
+
+ free(ikev2_data);
+}
+
+/** Configure EAP-ikev2 handler
+ *
+ */
+static int mod_instantiate(CONF_SECTION *conf, void **instance)
+{
+ int ret;
+
+ struct ikev2_ctx *i2;
+ rlm_eap_ikev2_t *inst;
+
+ char *server_auth_type, *default_auth_type, *users_file_name;
+
+ ikev2_set_log_callback(vxlogf);
+
+ inst = talloc_zero(conf, rlm_eap_ikev2_t);
+ if (cf_section_parse(conf, &inst, module_config) < 0) return -1;
+
+ i2 = Create_ikev2_ctx();
+ if (!i2) return -1;
+ *instance = i2;
+
+ /*
+ * Map our config structure onto the IKEv2 context
+ */
+ memcpy(&i2->trusted, &inst->tls_ca_file, sizeof(i2->trusted));
+ memcpy(&i2->pkfile, &inst->tls_private_key_file, sizeof(i2->pkfile));
+ memcpy(&i2->pkfile_pwd, &inst->tls_private_key_password, sizeof(i2->pkfile_pwd));
+ memcpy(&i2->certfile, &inst->tls_certificate_file, sizeof(i2->certfile));
+ memcpy(&i2->id, &inst->id, sizeof(i2->id));
+ i2->max_fragment_size = inst->max_fragment_size;
+ i2->DHCounterMax = inst->dh_counter_max;
+ i2->sendCertReq = (uint8_t) inst->send_cert_request;
+ i2->fastExpire = inst->fast_expire;
+ i2->enableFastDHEx = inst->enable_fast_dhex;
+ i2->enableFastReconnect = inst->enable_fast_reconnect;
+
+ memcpy(&server_auth_type, &inst->server_auth_type, sizeof(server_auth_type));
+ memcpy(&default_auth_type, &inst->default_auth_type, sizeof(default_auth_type));
+ memcpy(&users_file_name, &inst->users_file_name, sizeof(users_file_name));
+ hexalize(&i2->id, &i2->idlen);
+
+ i2->authtype = rad_get_authtype(server_auth_type);
+ if (!i2->id) {
+ ERROR(IKEv2_LOG_PREFIX "'id' configuration option is required!!!");
+ return -1;
+ }
+
+ switch (i2->authtype) {
+ default:
+ case IKEv2_AUTH_SK:
+ break;
+
+ case IKEv2_AUTH_CERT:
+ if (!i2->certfile || !i2->pkfile) {
+ ERROR(IKEv2_LOG_PREFIX "'certificate_file' and 'private_key_file' items are required "
+ "for 'cert' auth type");
+ return -1;
+ }
+
+ if (!file_exists(i2->certfile)) {
+ ERROR(IKEv2_LOG_PREFIX "Can not open 'certificate_file' %s", i2->certfile);
+ return -1;
+ }
+
+ if (!file_exists(i2->pkfile)) {
+ ERROR(IKEv2_LOG_PREFIX "Can not open 'private_key_file' %s",i2->pkfile);
+ return -1;
+ }
+ break;
+ }
+
+ if (!i2->trusted) {
+ AUTH(IKEv2_LOG_PREFIX "'ca_file' item not set, client cert based authentication will fail");
+ } else {
+ if (!file_exists(i2->trusted)) {
+ ERROR(IKEv2_LOG_PREFIX "Can not open 'ca_file' %s", i2->trusted);
+ return -1;
+ }
+ }
+
+ if (i2->crl_file) {
+ if (!file_exists(i2->crl_file)) {
+ ERROR(IKEv2_LOG_PREFIX "Can not open 'crl_file' %s", i2->crl_file);
+ return -1;
+ }
+ }
+
+ i2->idtype = IdTypeFromName(inst->server_id_type);
+ if (i2->idtype <= 0) {
+ ERROR(IKEv2_LOG_PREFIX "Unsupported 'idtype': %s", inst->server_id_type);
+ return -1;
+ }
+
+ if (rad_load_proposals(i2, conf)) {
+ ERROR(IKEv2_LOG_PREFIX "Failed to load proposals");
+ return -1;
+ }
+
+ ret = rad_load_credentials(instance, i2, users_file_name, default_auth_type);
+ if (ret == -1) {
+ ERROR(IKEv2_LOG_PREFIX "Error while loading users credentials");
+ return -1;
+ }
+
+ i2->x509_store = NULL;
+ if(CertInit(i2)){
+ ERROR(IKEv2_LOG_PREFIX "Error while loading certs/crl");
+ return -1;
+ }
+
+ return 0;
+}
+
+/** Initiate the EAP-ikev2 session by sending a challenge to the peer.
+ *
+ */
+static int mod_session_init(void *instance, eap_handler_t *handler)
+{
+ INFO(IKEv2_LOG_PREFIX "Initiate connection!");
+
+ struct IKEv2Data *ikev2_data;
+ struct ikev2_ctx *i2=(struct ikev2_ctx*)instance;
+
+ uint8_t *sikemsg = NULL;
+ u_int32_t slen = 0;
+
+ uint8_t *out = NULL;
+ u_int32_t olen = 0;
+
+ struct IKEv2Session *session;
+ handler->free_opaque = ikev2_free_opaque;
+
+ /* try get respondent FASTID */
+ uint8_t const *eap_username;
+
+ eap_username = handler->request->username->vp_octets;
+ session = FindSessionByFastid(i2, (char const *)eap_username);
+ if (!session) {
+ if (IKEv2BeginSession( i2, &session, IKEv2_STY_INITIATOR ) != IKEv2_RET_OK) {
+ ERROR(IKEv2_LOG_PREFIX "Can't initialize IKEv2 session");
+ return 1;
+ }
+ } else {
+ DEBUG(IKEv2_LOG_PREFIX "Fast reconnect procedure start");
+ }
+ session->timestamp=time(NULL);
+
+ ikev2_data = IKEv2Data_new(i2,session);
+ handler->opaque = ikev2_data;
+
+ if (IKEv2ProcessMsg(i2, NULL , &sikemsg, &slen, session) != IKEv2_RET_OK) {
+ ERROR(IKEv2_LOG_PREFIX "Error while processing IKEv2 message");
+ return 1;
+ }
+
+ if (slen != 0) {
+ session->eapMsgID++;
+ olen = CreateIKEv2Message(i2, sikemsg, slen, false, 0, session, &out );
+ if (session->fragdata) {
+ session->sendfrag = true;
+ }
+ }
+
+ if ((olen > 0) && (out!=NULL)) {
+ if (compose_rad_message(out, olen, handler->eap_ds)) {
+ free(out);
+ return 0;
+ }
+ free(out);
+ }
+
+ /*
+ * We don't need to authorize the user at this point.
+ *
+ * We also don't need to keep the challenge, as it's
+ * stored in 'handler->eap_ds', which will be given back
+ * to us...
+ */
+ handler->stage = PROCESS;
+ return 1;
+}
+
+/** Authenticate a previously sent challenge
+ *
+ */
+static int mod_process(void *instance, eap_handler_t *handler)
+{
+ uint8_t *in;
+ uint8_t *out = NULL;
+
+ uint8_t *ikemsg;
+ u_int32_t len;
+
+ uint8_t *sikemsg = NULL; //out message
+ u_int32_t slen = 0;
+
+ u_int32_t olen = 0;
+ struct ikev2_ctx *i2 = (struct ikev2_ctx*)instance;
+ struct EAPHeader *hdr;
+
+ struct IKEv2Data *ikev2_data;
+ struct IKEv2Session *session;
+
+ INFO(IKEv2_LOG_PREFIX "authenticate" );
+
+ rad_assert(handler->request != NULL);
+ rad_assert(handler->stage == PROCESS);
+
+ EAP_DS *eap_ds=handler->eap_ds;
+ if (!eap_ds ||
+ !eap_ds->response ||
+ (eap_ds->response->code != PW_IKEV2_RESPONSE) ||
+ eap_ds->response->type.num != PW_EAP_IKEV2 ||
+ !eap_ds->response->type.data) {
+ ERROR(IKEv2_LOG_PREFIX "corrupted data");
+ return -1;
+ }
+
+ in = talloc_array(eap_ds, uint8_t, eap_ds->response->length);
+ if (in){
+ ERROR(IKEv2_LOG_PREFIX "alloc error");
+ return -1;
+ }
+
+ rad_assert(in != NULL);
+ hdr = (struct EAPHeader *)in;
+
+ hdr->Code = eap_ds->response->code;
+ hdr->Id = eap_ds->response->id;
+ hdr->Length = htons(eap_ds->response->length);
+ hdr->Type = eap_ds->response->type.num;
+ memcpy(in + 5, eap_ds->response->type.data, eap_ds->response->length - 5);
+
+ ikev2_data = (struct IKEv2Data*)handler->opaque;
+ session = ikev2_data->session;
+ session->timestamp = time(NULL);
+
+ if (!session->fragdata) session->sendfrag = false;
+
+ if (session->sendfrag && !ParseFragmentAck(in, session)){
+ session->eapMsgID = eap_ds->response->id + 1;
+
+ olen = CreateIKEv2Message(i2, NULL, 0, false, hdr->Id, session, (uint8_t **)&out);
+ talloc_free(in);
+
+ if (compose_rad_message(out,olen,handler->eap_ds)) {
+ free(out);
+ return 0;
+ }
+
+ free(out);
+ return 1;
+ }
+
+ session->eapMsgID = eap_ds->response->id + 1;
+
+ if (ParseIKEv2Message(in, &ikemsg, &len, session)){
+ if (ikemsg != NULL) free(ikemsg);
+
+ handler->eap_ds->request->code=PW_EAP_FAILURE;
+ INFO(IKEv2_LOG_PREFIX "Discarded packet");
+
+ return 1;
+ }
+
+ /* Send fragment ack */
+ if (!ikemsg || !len) {
+ if (session->SK_ready) session->include_integ = 1;
+
+ olen = CreateFragmentAck(in, &out, session); // confirm fragment
+ TALLOC_FREE(in);
+
+ if (compose_rad_message(out,olen,handler->eap_ds)) {
+ free(out);
+ return 0;
+ }
+
+ free(out);
+ return 1;
+ }
+ TALLOC_FREE(in);
+
+ if (IKEv2ProcessMsg(i2, ikemsg, &sikemsg, &slen, session) != IKEv2_RET_OK) {
+ INFO(IKEv2_LOG_PREFIX "EAP_STATE_DISCARD");
+ //session->State = EAP_STATE_DISCARD;
+ free(out);
+ return 1;
+ }
+
+ free(ikemsg);
+
+ /* If there is there is something to send */
+ if (slen != 0){
+ olen = CreateIKEv2Message(i2, sikemsg, slen, false, 0, session, &out);
+ if (session->fragdata) session->sendfrag = true;
+ } else {
+ if (session->Status == IKEv2_SST_FAILED ) {
+ INFO(IKEv2_LOG_PREFIX "FAILED");
+ olen = CreateResultMessage( false, session, &out );
+ }
+
+ if(session->Status == IKEv2_SST_ESTABLISHED) {
+ INFO(IKEv2_LOG_PREFIX "SUCCESS");
+ olen = CreateResultMessage(true, session, &out);
+ session->fFastReconnect = i2->enableFastReconnect;
+
+ GenEapKeys(session ,EAP_IKEv2_KEY_LEN);
+ set_mppe_keys(handler);
+ }
+
+ // keep sessions in memory, only reference cleared
+ ikev2_data->session = NULL;
+ }
+ if ((olen > 0) && (out != NULL)){
+ if (compose_rad_message(out, olen, handler->eap_ds)){
+ free(out);
+ return 0;
+ }
+ }
+
+ free(out);
+ return 1;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_ikev2;
+rlm_eap_module_t rlm_eap_ikev2 = {
+ .name = "eap_ikev2",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process, /* Process next round of EAP method */
+ .detach = mod_detach /* detach */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_md5/README.md b/src/modules/rlm_eap/types/rlm_eap_md5/README.md
new file mode 100644
index 0000000..dba25cc
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_md5/README.md
@@ -0,0 +1,12 @@
+# rlm_eap_md5
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements [RFC 3748](https://tools.ietf.org/html/rfc3748) EAP-MD5 authentication. EAP-MD5 allows EAP authentication
+using a plaintext password.
+
+Does not provide keying material for 802.11i, so cannot be used for WPA/2-Enterprise authentication unless wrapped
+in another method such as EAP-TTLS.
diff --git a/src/modules/rlm_eap/types/rlm_eap_md5/all.mk b/src/modules/rlm_eap/types/rlm_eap_md5/all.mk
new file mode 100644
index 0000000..528ee82
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_md5/all.mk
@@ -0,0 +1,12 @@
+TARGETNAME := rlm_eap_md5
+
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c eap_md5.c
+
+SRC_CFLAGS :=
+TGT_LDLIBS :=
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.c b/src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.c
new file mode 100644
index 0000000..e8acb5c
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.c
@@ -0,0 +1,229 @@
+/*
+ * eap_md5.c EAP MD5 functionality.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000,2001,2006 The FreeRADIUS server project
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ */
+
+/*
+ *
+ * MD5 Packet Format in EAP Type-Data
+ * --- ------ ------ -- --- ---------
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Value-Size | Value ...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Name ...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "eap.h"
+
+#include "eap_md5.h"
+#include <freeradius-devel/md5.h>
+
+/*
+ * We expect only RESPONSE for which SUCCESS or FAILURE is sent back
+ */
+MD5_PACKET *eapmd5_extract(EAP_DS *eap_ds)
+{
+ md5_packet_t *data;
+ MD5_PACKET *packet;
+ unsigned short name_len;
+
+ /*
+ * We need a response, of type EAP-MD5, with at least
+ * one byte of type data (EAP-MD5) following the 4-byte
+ * EAP-Packet header.
+ */
+ if (!eap_ds ||
+ !eap_ds->response ||
+ (eap_ds->response->code != PW_MD5_RESPONSE) ||
+ eap_ds->response->type.num != PW_EAP_MD5 ||
+ !eap_ds->response->type.data ||
+ (eap_ds->response->length <= MD5_HEADER_LEN) ||
+ (eap_ds->response->type.data[0] <= 0)) {
+ ERROR("rlm_eap_md5: corrupted data");
+ return NULL;
+ }
+
+ packet = talloc_zero(eap_ds, MD5_PACKET);
+ if (!packet) return NULL;
+
+ /*
+ * Code & id for MD5 & EAP are same
+ *
+ * but md5_length = length of the EAP-MD5 data, which
+ * doesn't include the EAP header, or the octet saying
+ * EAP-MD5.
+ */
+ packet->code = eap_ds->response->code;
+ packet->id = eap_ds->response->id;
+ packet->length = eap_ds->response->length - (MD5_HEADER_LEN + 1);
+
+ /*
+ * Sanity check the EAP-MD5 packet sent to us
+ * by the client.
+ */
+ data = (md5_packet_t *)eap_ds->response->type.data;
+
+ /*
+ * Already checked the size above.
+ */
+ packet->value_size = data->value_size;
+
+ /*
+ * Allocate room for the data, and copy over the data.
+ */
+ packet->value = talloc_array(packet, uint8_t, packet->value_size);
+ if (!packet->value) {
+ talloc_free(packet);
+ return NULL;
+ }
+ memcpy(packet->value, data->value_name, packet->value_size);
+
+ /*
+ * Name is optional and is present after Value, but we
+ * need to check for it, as eapmd5_compose()
+ */
+ name_len = packet->length - (packet->value_size + 1);
+ if (name_len) {
+ packet->name = talloc_array(packet, char, name_len + 1);
+ if (!packet->name) {
+ talloc_free(packet);
+ return NULL;
+ }
+ memcpy(packet->name, data->value_name + packet->value_size,
+ name_len);
+ packet->name[name_len] = 0;
+ }
+
+ return packet;
+}
+
+
+/*
+ * verify = MD5(id+password+challenge_sent)
+ */
+int eapmd5_verify(MD5_PACKET *packet, VALUE_PAIR* password,
+ uint8_t *challenge)
+{
+ char *ptr;
+ char string[1 + MAX_STRING_LEN*2];
+ uint8_t digest[16];
+ unsigned short len;
+
+ /*
+ * Sanity check it.
+ */
+ if (packet->value_size != 16) {
+ ERROR("rlm_eap_md5: Expected 16 bytes of response to challenge, got %d", packet->value_size);
+ return 0;
+ }
+
+ len = 0;
+ ptr = string;
+
+ /*
+ * This is really rad_chap_pwencode()...
+ */
+ *ptr++ = packet->id;
+ len++;
+ memcpy(ptr, password->vp_strvalue, password->vp_length);
+ ptr += password->vp_length;
+ len += password->vp_length;
+
+ /*
+ * The challenge size is hard-coded.
+ */
+ memcpy(ptr, challenge, MD5_CHALLENGE_LEN);
+ len += MD5_CHALLENGE_LEN;
+
+ fr_md5_calc(digest, (u_char *)string, len);
+
+ /*
+ * The length of the response is always 16 for MD5.
+ */
+ if (rad_digest_cmp(digest, packet->value, 16) != 0) {
+ DEBUG("EAP-MD5 digests do not match.");
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Compose the portions of the reply packet specific to the
+ * EAP-MD5 protocol, in the EAP reply typedata
+ */
+int eapmd5_compose(EAP_DS *eap_ds, MD5_PACKET *reply)
+{
+ uint8_t *ptr;
+ unsigned short name_len;
+
+ /*
+ * We really only send Challenge (EAP-Identity),
+ * and EAP-Success, and EAP-Failure.
+ */
+ if (reply->code < 3) {
+ eap_ds->request->type.num = PW_EAP_MD5;
+
+ rad_assert(reply->length > 0);
+
+ eap_ds->request->type.data = talloc_array(eap_ds->request,
+ uint8_t,
+ reply->length);
+ if (!eap_ds->request->type.data) {
+ talloc_free(reply);
+ return 0;
+ }
+ ptr = eap_ds->request->type.data;
+ *ptr++ = (uint8_t)(reply->value_size & 0xFF);
+ memcpy(ptr, reply->value, reply->value_size);
+
+ /* Just the Challenge length */
+ eap_ds->request->type.length = reply->value_size + 1;
+
+ /*
+ * Return the name, if necessary.
+ *
+ * Don't see why this is *ever* necessary...
+ */
+ name_len = reply->length - (reply->value_size + 1);
+ if (name_len && reply->name) {
+ ptr += reply->value_size;
+ memcpy(ptr, reply->name, name_len);
+ /* Challenge length + Name length */
+ eap_ds->request->type.length += name_len;
+ }
+ } else {
+ eap_ds->request->type.length = 0;
+ /* TODO: In future we might add message here wrt rfc1994 */
+ }
+ eap_ds->request->code = reply->code;
+ talloc_free(reply);
+
+ return 1;
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.h b/src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.h
new file mode 100644
index 0000000..aafa407
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.h
@@ -0,0 +1,52 @@
+#ifndef _EAP_MD5_H
+#define _EAP_MD5_H
+
+RCSIDH(eap_md5_h, "$Id$")
+
+#include "eap.h"
+
+#define PW_MD5_CHALLENGE 1
+#define PW_MD5_RESPONSE 2
+#define PW_MD5_SUCCESS 3
+#define PW_MD5_FAILURE 4
+#define PW_MD5_MAX_CODES 4
+
+#define MD5_HEADER_LEN 4
+#define MD5_CHALLENGE_LEN 16
+
+/*
+ ****
+ * EAP - MD5 does not specify code, id & length but chap specifies them,
+ * for generalization purpose, complete header should be sent
+ * and not just value_size, value and name.
+ * future implementation.
+ *
+ * Huh? What does that mean?
+ */
+
+/* eap packet structure */
+typedef struct md5_packet_t {
+/*
+ uint8_t code;
+ uint8_t id;
+ uint16_t length;
+*/
+ uint8_t value_size;
+ uint8_t value_name[1];
+} md5_packet_t;
+
+typedef struct md5_packet {
+ unsigned char code;
+ unsigned char id;
+ unsigned short length;
+ unsigned char value_size;
+ unsigned char *value;
+ char *name;
+} MD5_PACKET;
+
+/* function declarations here */
+
+int eapmd5_compose(EAP_DS *auth, MD5_PACKET *reply);
+MD5_PACKET *eapmd5_extract(EAP_DS *auth);
+int eapmd5_verify(MD5_PACKET *pkt, VALUE_PAIR* pwd, uint8_t *ch);
+#endif /*_EAP_MD5_H*/
diff --git a/src/modules/rlm_eap/types/rlm_eap_md5/rlm_eap_md5.c b/src/modules/rlm_eap/types/rlm_eap_md5/rlm_eap_md5.c
new file mode 100644
index 0000000..2fa0077
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_md5/rlm_eap_md5.c
@@ -0,0 +1,168 @@
+/*
+ * rlm_eap_md5.c Handles that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000,2001,2006 The FreeRADIUS server project
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eap_md5.h"
+
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/md5.h>
+
+/*
+ * Initiate the EAP-MD5 session by sending a challenge to the peer.
+ */
+static int mod_session_init(UNUSED void *instance, eap_handler_t *handler)
+{
+ int i;
+ MD5_PACKET *reply;
+ REQUEST *request = handler->request;
+
+ /*
+ * Allocate an EAP-MD5 packet.
+ */
+ reply = talloc(handler, MD5_PACKET);
+ if (!reply) {
+ return 0;
+ }
+
+ /*
+ * Fill it with data.
+ */
+ reply->code = PW_MD5_CHALLENGE;
+ reply->length = 1 + MD5_CHALLENGE_LEN; /* one byte of value size */
+ reply->value_size = MD5_CHALLENGE_LEN;
+
+ /*
+ * Allocate user data.
+ */
+ reply->value = talloc_array(reply, uint8_t, reply->value_size);
+ if (!reply->value) {
+ talloc_free(reply);
+ return 0;
+ }
+
+ /*
+ * Get a random challenge.
+ */
+ for (i = 0; i < reply->value_size; i++) {
+ reply->value[i] = fr_rand();
+ }
+ RDEBUG2("Issuing MD5 Challenge");
+
+ /*
+ * Keep track of the challenge.
+ */
+ handler->opaque = talloc_array(handler, uint8_t, reply->value_size);
+ rad_assert(handler->opaque != NULL);
+ memcpy(handler->opaque, reply->value, reply->value_size);
+ handler->free_opaque = NULL;
+
+ /*
+ * Compose the EAP-MD5 packet out of the data structure,
+ * and free it.
+ */
+ eapmd5_compose(handler->eap_ds, reply);
+
+ /*
+ * We don't need to authorize the user at this point.
+ *
+ * We also don't need to keep the challenge, as it's
+ * stored in 'handler->eap_ds', which will be given back
+ * to us...
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+/*
+ * Authenticate a previously sent challenge.
+ */
+static int mod_process(UNUSED void *arg, eap_handler_t *handler)
+{
+ MD5_PACKET *packet;
+ MD5_PACKET *reply;
+ VALUE_PAIR *password;
+ REQUEST *request = handler->request;
+
+ /*
+ * Get the Cleartext-Password for this user.
+ */
+ rad_assert(handler->request != NULL);
+ rad_assert(handler->stage == PROCESS);
+
+ password = fr_pair_find_by_num(handler->request->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
+ if (!password) {
+ REDEBUG2("Cleartext-Password is required for EAP-MD5 authentication");
+ return 0;
+ }
+
+ /*
+ * Extract the EAP-MD5 packet.
+ */
+ if (!(packet = eapmd5_extract(handler->eap_ds)))
+ return 0;
+
+ /*
+ * Create a reply, and initialize it.
+ */
+ reply = talloc(packet, MD5_PACKET);
+ if (!reply) {
+ talloc_free(packet);
+ return 0;
+ }
+ reply->id = handler->eap_ds->request->id;
+ reply->length = 0;
+
+ /*
+ * Verify the received packet against the previous packet
+ * (i.e. challenge) which we sent out.
+ */
+ if (eapmd5_verify(packet, password, handler->opaque)) {
+ reply->code = PW_MD5_SUCCESS;
+ } else {
+ reply->code = PW_MD5_FAILURE;
+ }
+
+ /*
+ * Compose the EAP-MD5 packet out of the data structure,
+ * and free it.
+ */
+ eapmd5_compose(handler->eap_ds, reply);
+ talloc_free(packet);
+ return 1;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_md5;
+rlm_eap_module_t rlm_eap_md5 = {
+ .name = "eap_md5",
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/README.md b/src/modules/rlm_eap/types/rlm_eap_mschapv2/README.md
new file mode 100644
index 0000000..4d87c49
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_mschapv2/README.md
@@ -0,0 +1,13 @@
+# rlm_eap_mschapv2
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements EAP-MSCHAPv2. Usually used as an inner method for PEAP.
+
+Allows NTLMv2 style authentication against Active-Directory, or where the NT-Password is known.
+
+Technically does provide its own keying material via MPPE key attributes which could be used for 802.11i
+(WPA/2-Enterprise) but in most instances, the keying material from an outer method is used instead.
diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/all.mk b/src/modules/rlm_eap/types/rlm_eap_mschapv2/all.mk
new file mode 100644
index 0000000..d57c636
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_mschapv2/all.mk
@@ -0,0 +1,12 @@
+TARGETNAME := rlm_eap_mschapv2
+
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c
+
+SRC_CFLAGS :=
+TGT_LDLIBS :=
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/eap_mschapv2.h b/src/modules/rlm_eap/types/rlm_eap_mschapv2/eap_mschapv2.h
new file mode 100644
index 0000000..1ce2470
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_mschapv2/eap_mschapv2.h
@@ -0,0 +1,51 @@
+#ifndef _EAP_MSCHAPV2_H
+#define _EAP_MSCHAPV2_H
+
+RCSIDH(eap_mschapv2_h, "$Id$")
+
+#include "eap.h"
+
+/*
+ * draft-kamath-pppext-eap-mschapv2-00.txt says:
+ *
+ * Supplicant FreeRADIUS
+ * <-- challenge
+ * response -->
+ * <-- success
+ * success -->
+ *
+ * But what we often see is:
+ *
+ * Supplicant FreeRADIUS
+ * <-- challenge
+ * response -->
+ * <-- success
+ * ack -->
+ */
+#define PW_EAP_MSCHAPV2_ACK 0
+#define PW_EAP_MSCHAPV2_CHALLENGE 1
+#define PW_EAP_MSCHAPV2_RESPONSE 2
+#define PW_EAP_MSCHAPV2_SUCCESS 3
+#define PW_EAP_MSCHAPV2_FAILURE 4
+#define PW_EAP_MSCHAPV2_CHGPASSWD 7
+#define PW_EAP_MSCHAPV2_MAX_CODES 7
+
+#define MSCHAPV2_HEADER_LEN 5
+#define MSCHAPV2_CHALLENGE_LEN 16
+#define MSCHAPV2_RESPONSE_LEN 50
+
+typedef struct mschapv2_header_t {
+ uint8_t opcode;
+ uint8_t mschapv2_id;
+ uint8_t ms_length[2];
+ uint8_t value_size;
+} mschapv2_header_t;
+
+typedef struct mschapv2_opaque_t {
+ int code;
+ uint8_t challenge[MSCHAPV2_CHALLENGE_LEN];
+ VALUE_PAIR *mppe_keys;
+ VALUE_PAIR *reply;
+} mschapv2_opaque_t;
+
+#endif /*_EAP_MSCHAPV2_H*/
diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c b/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c
new file mode 100644
index 0000000..c1a0045
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c
@@ -0,0 +1,757 @@
+/*
+ * rlm_eap_mschapv2.c Handles that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003,2006 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eap_mschapv2.h"
+
+#include <freeradius-devel/rad_assert.h>
+
+typedef struct rlm_eap_mschapv2_t {
+ bool with_ntdomain_hack;
+ bool send_error;
+ char const *identity;
+ int auth_type_mschap;
+} rlm_eap_mschapv2_t;
+
+static CONF_PARSER module_config[] = {
+ { "with_ntdomain_hack", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_mschapv2_t, with_ntdomain_hack), "no" },
+
+ { "send_error", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_mschapv2_t, send_error), "no" },
+ { "identity", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_mschapv2_t, identity), NULL },
+ CONF_PARSER_TERMINATOR
+};
+
+
+static void fix_mppe_keys(eap_handler_t *handler, mschapv2_opaque_t *data)
+{
+ fr_pair_list_mcopy_by_num(data, &data->mppe_keys, &handler->request->reply->vps, 7, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_list_mcopy_by_num(data, &data->mppe_keys, &handler->request->reply->vps, 8, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_list_mcopy_by_num(data, &data->mppe_keys, &handler->request->reply->vps, 16, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_list_mcopy_by_num(data, &data->mppe_keys, &handler->request->reply->vps, 17, VENDORPEC_MICROSOFT, TAG_ANY);
+}
+
+/*
+ * Attach the module.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_mschapv2_t *inst;
+ DICT_VALUE const *dv;
+
+ *instance = inst = talloc_zero(cs, rlm_eap_mschapv2_t);
+ if (!inst) return -1;
+
+ /*
+ * Parse the configuration attributes.
+ */
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ if (inst->identity && (strlen(inst->identity) > 255)) {
+ cf_log_err_cs(cs, "identity is too long");
+ return -1;
+ }
+
+ if (!inst->identity) {
+ inst->identity = talloc_asprintf(inst, "freeradius-%s", RADIUSD_VERSION_STRING);
+ }
+
+ dv = dict_valbyname(PW_AUTH_TYPE, 0, "MSCHAP");
+ if (!dv) dv = dict_valbyname(PW_AUTH_TYPE, 0, "MS-CHAP");
+ if (!dv) {
+ cf_log_err_cs(cs, "Failed to find 'Auth-Type MS-CHAP' section. Cannot authenticate users.");
+ return -1;
+ }
+ inst->auth_type_mschap = dv->value;
+
+ return 0;
+}
+
+
+/*
+ * Compose the response.
+ */
+static int eapmschapv2_compose(rlm_eap_mschapv2_t *inst, eap_handler_t *handler, VALUE_PAIR *reply)
+{
+ uint8_t *ptr;
+ int16_t length;
+ mschapv2_header_t *hdr;
+ EAP_DS *eap_ds = handler->eap_ds;
+ REQUEST *request = handler->request;
+
+ eap_ds->request->code = PW_EAP_REQUEST;
+ eap_ds->request->type.num = PW_EAP_MSCHAPV2;
+
+ /*
+ * Always called with vendor Microsoft
+ */
+ switch (reply->da->attr) {
+ case PW_MSCHAP_CHALLENGE:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | OpCode | MS-CHAPv2-ID | MS-Length...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | MS-Length | Value-Size | Challenge...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Challenge...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Server Name...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ length = MSCHAPV2_HEADER_LEN + MSCHAPV2_CHALLENGE_LEN + strlen(inst->identity);
+ eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, length);
+
+ /*
+ * Allocate room for the EAP-MS-CHAPv2 data.
+ */
+ if (!eap_ds->request->type.data) {
+ return 0;
+ }
+ eap_ds->request->type.length = length;
+
+ ptr = eap_ds->request->type.data;
+ hdr = (mschapv2_header_t *) ptr;
+
+ hdr->opcode = PW_EAP_MSCHAPV2_CHALLENGE;
+ hdr->mschapv2_id = eap_ds->response->id + 1;
+ length = htons(length);
+ memcpy(hdr->ms_length, &length, sizeof(uint16_t));
+ hdr->value_size = MSCHAPV2_CHALLENGE_LEN;
+
+ ptr += MSCHAPV2_HEADER_LEN;
+
+ /*
+ * Copy the Challenge, success, or error over.
+ */
+ memcpy(ptr, reply->vp_octets, reply->vp_length);
+
+ memcpy((ptr + reply->vp_length), inst->identity, strlen(inst->identity));
+ break;
+
+ case PW_MSCHAP2_SUCCESS:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | OpCode | MS-CHAPv2-ID | MS-Length...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | MS-Length | Message...
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ RDEBUG2("MSCHAP Success");
+ length = 46;
+ eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, length);
+ /*
+ * Allocate room for the EAP-MS-CHAPv2 data.
+ */
+ if (!eap_ds->request->type.data) {
+ return 0;
+ }
+ memset(eap_ds->request->type.data, 0, length);
+ eap_ds->request->type.length = length;
+
+ eap_ds->request->type.data[0] = PW_EAP_MSCHAPV2_SUCCESS;
+ eap_ds->request->type.data[1] = eap_ds->response->id;
+ length = htons(length);
+ memcpy((eap_ds->request->type.data + 2), &length, sizeof(uint16_t));
+ memcpy((eap_ds->request->type.data + 4), reply->vp_strvalue + 1, 42);
+ break;
+
+ case PW_MSCHAP_ERROR:
+ REDEBUG("MSCHAP Failure");
+ length = 4 + reply->vp_length - 1;
+ eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, length);
+
+ /*
+ * Allocate room for the EAP-MS-CHAPv2 data.
+ */
+ if (!eap_ds->request->type.data) return 0;
+ memset(eap_ds->request->type.data, 0, length);
+ eap_ds->request->type.length = length;
+
+ eap_ds->request->type.data[0] = PW_EAP_MSCHAPV2_FAILURE;
+ eap_ds->request->type.data[1] = eap_ds->response->id;
+ length = htons(length);
+ memcpy((eap_ds->request->type.data + 2), &length, sizeof(uint16_t));
+ /*
+ * Copy the entire failure message.
+ */
+ memcpy((eap_ds->request->type.data + 4),
+ reply->vp_strvalue + 1, reply->vp_length - 1);
+ break;
+
+ default:
+ RERROR("Internal sanity check failed");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/*
+ * Initiate the EAP-MSCHAPV2 session by sending a challenge to the peer.
+ */
+static int mod_session_init(void *instance, eap_handler_t *handler)
+{
+ int i;
+ VALUE_PAIR *challenge;
+ mschapv2_opaque_t *data;
+ REQUEST *request = handler->request;
+ uint8_t *p;
+ bool created_challenge = false;
+ rlm_eap_mschapv2_t *inst = instance;
+
+ challenge = fr_pair_find_by_num(request->config, PW_MSCHAP_CHALLENGE, VENDORPEC_MICROSOFT, TAG_ANY);
+ if (challenge && (challenge->vp_length != MSCHAPV2_CHALLENGE_LEN)) {
+ RWDEBUG("control:MS-CHAP-Challenge is incorrect length. Ignoring it.");
+ challenge = NULL;
+ }
+
+ if (!challenge) {
+ created_challenge = true;
+ challenge = fr_pair_make(handler, NULL, "MS-CHAP-Challenge", NULL, T_OP_EQ);
+
+ /*
+ * Get a random challenge.
+ */
+ challenge->vp_length = MSCHAPV2_CHALLENGE_LEN;
+ challenge->vp_octets = p = talloc_array(challenge, uint8_t, challenge->vp_length);
+ for (i = 0; i < MSCHAPV2_CHALLENGE_LEN; i++) {
+ p[i] = fr_rand();
+ }
+ }
+ RDEBUG2("Issuing Challenge");
+
+ /*
+ * Keep track of the challenge.
+ */
+ data = talloc_zero(handler, mschapv2_opaque_t);
+ rad_assert(data != NULL);
+
+ /*
+ * We're at the stage where we're challenging the user.
+ */
+ data->code = PW_EAP_MSCHAPV2_CHALLENGE;
+ memcpy(data->challenge, challenge->vp_octets, MSCHAPV2_CHALLENGE_LEN);
+ data->mppe_keys = NULL;
+ data->reply = NULL;
+
+ handler->opaque = data;
+
+ /*
+ * Compose the EAP-MSCHAPV2 packet out of the data structure,
+ * and free it.
+ */
+ eapmschapv2_compose(inst, handler, challenge);
+ if (created_challenge) fr_pair_list_free(&challenge);
+
+#ifdef WITH_PROXY
+ /*
+ * The EAP session doesn't have enough information to
+ * proxy the "inside EAP" protocol. Disable EAP proxying.
+ */
+ handler->request->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
+#endif
+
+ /*
+ * We don't need to authorize the user at this point.
+ *
+ * We also don't need to keep the challenge, as it's
+ * stored in 'handler->eap_ds', which will be given back
+ * to us...
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+#ifdef WITH_PROXY
+/*
+ * Do post-proxy processing,
+ * 0 = fail
+ * 1 = OK.
+ *
+ * Called from rlm_eap.c, eap_postproxy().
+ */
+static int CC_HINT(nonnull) mschap_postproxy(eap_handler_t *handler, UNUSED void *tunnel_data)
+{
+ VALUE_PAIR *response = NULL;
+ mschapv2_opaque_t *data;
+ REQUEST *request = handler->request;
+
+ data = (mschapv2_opaque_t *) handler->opaque;
+ rad_assert(request != NULL);
+
+ RDEBUG2("Passing reply from proxy back into the tunnel %d", request->reply->code);
+
+ /*
+ * There is only a limited number of possibilities.
+ */
+ switch (request->reply->code) {
+ case PW_CODE_ACCESS_ACCEPT:
+ RDEBUG2("Proxied authentication succeeded");
+
+ /*
+ * Move the attribute, so it doesn't go into
+ * the reply.
+ */
+ fr_pair_list_mcopy_by_num(data, &response, &request->reply->vps, PW_MSCHAP2_SUCCESS, VENDORPEC_MICROSOFT, TAG_ANY);
+ break;
+
+ default:
+ case PW_CODE_ACCESS_REJECT:
+ REDEBUG("Proxied authentication was rejected");
+ return 0;
+ }
+
+ /*
+ * No response, die.
+ */
+ if (!response) {
+ REDEBUG("Proxied reply contained no MS-CHAP2-Success or MS-CHAP-Error");
+ return 0;
+ }
+
+ /*
+ * Done doing EAP proxy stuff.
+ */
+ request->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
+ eapmschapv2_compose(NULL, handler, response);
+ data->code = PW_EAP_MSCHAPV2_SUCCESS;
+
+ /*
+ * Delete MPPE keys & encryption policy
+ *
+ * FIXME: Use intelligent names...
+ */
+ fix_mppe_keys(handler, data);
+
+ /*
+ * Save any other attributes for re-use in the final
+ * access-accept e.g. vlan, etc. This lets the PEAP
+ * use_tunneled_reply code work
+ */
+ data->reply = fr_pair_list_copy(data, request->reply->vps);
+
+ /*
+ * And we need to challenge the user, not ack/reject them,
+ * so we re-write the ACK to a challenge. Yuck.
+ */
+ request->reply->code = PW_CODE_ACCESS_CHALLENGE;
+ fr_pair_list_free(&response);
+
+ return 1;
+}
+#endif
+
+/*
+ * Authenticate a previously sent challenge.
+ */
+static int CC_HINT(nonnull) mod_process(void *arg, eap_handler_t *handler)
+{
+ int rcode, ccode;
+ uint8_t *p;
+ size_t length;
+ char *q;
+ mschapv2_opaque_t *data;
+ EAP_DS *eap_ds = handler->eap_ds;
+ VALUE_PAIR *challenge, *response, *name;
+ rlm_eap_mschapv2_t *inst = (rlm_eap_mschapv2_t *) arg;
+ REQUEST *request = handler->request;
+
+ rad_assert(handler->stage == PROCESS);
+
+ data = (mschapv2_opaque_t *) handler->opaque;
+
+ /*
+ * Sanity check the response.
+ */
+ if (eap_ds->response->length <= 5) {
+ REDEBUG("corrupted data");
+ return 0;
+ }
+
+ ccode = eap_ds->response->type.data[0];
+
+ switch (data->code) {
+ case PW_EAP_MSCHAPV2_FAILURE:
+ if (ccode == PW_EAP_MSCHAPV2_RESPONSE) {
+ RDEBUG2("Authentication re-try from client after we sent a failure");
+ break;
+ }
+
+ /*
+ * if we sent error 648 (password expired) to the client
+ * we might get an MSCHAP-CPW packet here; turn it into a
+ * regular MS-CHAP2-CPW packet and pass it to rlm_mschap
+ * (or proxy it, I guess)
+ */
+ if (ccode == PW_EAP_MSCHAPV2_CHGPASSWD) {
+ VALUE_PAIR *cpw;
+ int mschap_id = eap_ds->response->type.data[1];
+ int copied = 0 ,seq = 1;
+
+ RDEBUG2("Password change packet received");
+
+ challenge = pair_make_request("MS-CHAP-Challenge", NULL, T_OP_EQ);
+ if (!challenge) return 0;
+ fr_pair_value_memcpy(challenge, data->challenge, MSCHAPV2_CHALLENGE_LEN);
+
+ cpw = pair_make_request("MS-CHAP2-CPW", NULL, T_OP_EQ);
+ cpw->vp_length = 68;
+
+ cpw->vp_octets = p = talloc_array(cpw, uint8_t, cpw->vp_length);
+ p[0] = 7;
+ p[1] = mschap_id;
+ memcpy(p + 2, eap_ds->response->type.data + 520, 66);
+
+ /*
+ * break the encoded password into VPs (3 of them)
+ */
+ while (copied < 516) {
+ VALUE_PAIR *nt_enc;
+
+ int to_copy = 516 - copied;
+ if (to_copy > 243) to_copy = 243;
+
+ nt_enc = pair_make_request("MS-CHAP-NT-Enc-PW", NULL, T_OP_ADD);
+ nt_enc->vp_length = 4 + to_copy;
+
+ nt_enc->vp_octets = p = talloc_array(nt_enc, uint8_t, nt_enc->vp_length);
+
+ p[0] = 6;
+ p[1] = mschap_id;
+ p[2] = 0;
+ p[3] = seq++;
+
+ memcpy(p + 4, eap_ds->response->type.data + 4 + copied, to_copy);
+ copied += to_copy;
+ }
+
+ RDEBUG2("Built change password packet");
+ rdebug_pair_list(L_DBG_LVL_2, request, request->packet->vps, NULL);
+
+ /*
+ * jump to "authentication"
+ */
+ goto packet_ready;
+ }
+
+ /*
+ * we sent a failure and are expecting a failure back
+ */
+ if (ccode != PW_EAP_MSCHAPV2_FAILURE) {
+ REDEBUG("Sent FAILURE expecting FAILURE but got %d", ccode);
+ return 0;
+ }
+
+failure:
+ request->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 1;
+
+ case PW_EAP_MSCHAPV2_SUCCESS:
+ /*
+ * we sent a success to the client; some clients send a
+ * success back as-per the RFC, some send an ACK. Permit
+ * both, I guess...
+ */
+
+ switch (ccode) {
+ case PW_EAP_MSCHAPV2_SUCCESS:
+ eap_ds->request->code = PW_EAP_SUCCESS;
+
+ fr_pair_list_mcopy_by_num(request->reply, &request->reply->vps, &data->mppe_keys, 0, 0, TAG_ANY);
+ /* FALL-THROUGH */
+
+ case PW_EAP_MSCHAPV2_ACK:
+#ifdef WITH_PROXY
+ /*
+ * It's a success. Don't proxy it.
+ */
+ request->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
+#endif
+ fr_pair_list_mcopy_by_num(request->reply, &request->reply->vps, &data->reply, 0, 0, TAG_ANY);
+ return 1;
+ }
+ REDEBUG("Sent SUCCESS expecting SUCCESS (or ACK) but got %d", ccode);
+ return 0;
+
+ case PW_EAP_MSCHAPV2_CHALLENGE:
+ if (ccode == PW_EAP_MSCHAPV2_FAILURE) goto failure;
+
+ /*
+ * we sent a challenge, expecting a response
+ */
+ if (ccode != PW_EAP_MSCHAPV2_RESPONSE) {
+ REDEBUG("Sent CHALLENGE expecting RESPONSE but got %d", ccode);
+ return 0;
+ }
+ /* authentication happens below */
+ break;
+
+ default:
+ /* should never happen */
+ REDEBUG("Unknown state %d", data->code);
+ return 0;
+ }
+
+
+ /*
+ * Ensure that we have at least enough data
+ * to do the following checks.
+ *
+ * EAP header (4), EAP type, MS-CHAP opcode,
+ * MS-CHAP ident, MS-CHAP data length (2),
+ * MS-CHAP value length.
+ */
+ if (eap_ds->response->length < (4 + 1 + 1 + 1 + 2 + 1)) {
+ REDEBUG("Response is too short");
+ return 0;
+ }
+
+ /*
+ * The 'value_size' is the size of the response,
+ * which is supposed to be the response (48
+ * bytes) plus 1 byte of flags at the end.
+ *
+ * NOTE: When using Cisco NEAT with EAP-MSCHAPv2, the
+ * switch supplicant will send MSCHAPv2 data (EAP type = 26)
+ * but will always set a value_size of 16 and NULL out the
+ * peer challenge.
+ *
+ */
+ if ((eap_ds->response->type.data[4] != 49) &&
+ (eap_ds->response->type.data[4] != 16)) {
+ REDEBUG("Response is of incorrect length %d", eap_ds->response->type.data[4]);
+ return 0;
+ }
+
+ /*
+ * The MS-Length field is 5 + value_size + length
+ * of name, which is put after the response.
+ */
+ length = (eap_ds->response->type.data[2] << 8) | eap_ds->response->type.data[3];
+ if ((length < (5 + 49)) || (length > (256 + 5 + 49))) {
+ REDEBUG("Response contains contradictory length %zu %d", length, 5 + 49);
+ return 0;
+ }
+
+ /*
+ * We now know that the user has sent us a response
+ * to the challenge. Let's try to authenticate it.
+ *
+ * We do this by taking the challenge from 'data',
+ * the response from the EAP packet, and creating VALUE_PAIR's
+ * to pass to the 'mschap' module. This is a little wonky,
+ * but it works.
+ */
+ challenge = pair_make_request("MS-CHAP-Challenge", NULL, T_OP_EQ);
+ if (!challenge) return 0;
+ fr_pair_value_memcpy(challenge, data->challenge, MSCHAPV2_CHALLENGE_LEN);
+
+ response = pair_make_request("MS-CHAP2-Response", NULL, T_OP_EQ);
+ if (!response) return 0;
+ response->vp_length = MSCHAPV2_RESPONSE_LEN;
+ response->vp_octets = p = talloc_array(response, uint8_t, response->vp_length);
+
+ p[0] = eap_ds->response->type.data[1];
+ p[1] = eap_ds->response->type.data[5 + MSCHAPV2_RESPONSE_LEN];
+ memcpy(p + 2, &eap_ds->response->type.data[5], MSCHAPV2_RESPONSE_LEN - 2);
+
+ name = pair_make_request("MS-CHAP-User-Name", NULL, T_OP_EQ);
+ if (!name) return 0;
+
+ /*
+ * MS-Length - MS-Value - 5.
+ */
+ name->vp_length = length - 49 - 5;
+ name->vp_strvalue = q = talloc_array(name, char, name->vp_length + 1);
+ memcpy(q, &eap_ds->response->type.data[4 + MSCHAPV2_RESPONSE_LEN], name->vp_length);
+ q[name->vp_length] = '\0';
+
+packet_ready:
+
+#ifdef WITH_PROXY
+ /*
+ * If this options is set, then we do NOT authenticate the
+ * user here. Instead, now that we've added the MS-CHAP
+ * attributes to the request, we STOP, and let the outer
+ * tunnel code handle it.
+ *
+ * This means that the outer tunnel code will DELETE the
+ * EAP attributes, and proxy the MS-CHAP attributes to a
+ * home server.
+ */
+ if (request->options & RAD_REQUEST_OPTION_PROXY_EAP) {
+ char *username = NULL;
+ eap_tunnel_data_t *tunnel;
+
+ RDEBUG2("Cancelling authentication and letting it be proxied");
+
+ /*
+ * Set up the callbacks for the tunnel
+ */
+ tunnel = talloc_zero(request, eap_tunnel_data_t);
+
+ tunnel->tls_session = arg;
+ tunnel->callback = mschap_postproxy;
+
+ /*
+ * Associate the callback with the request.
+ */
+ rcode = request_data_add(request,
+ request->proxy,
+ REQUEST_DATA_EAP_TUNNEL_CALLBACK,
+ tunnel, false);
+ rad_assert(rcode == 0);
+
+ /*
+ * The State attribute is NOT supposed to
+ * go into the proxied packet, it will confuse
+ * other RADIUS servers, and they will discard
+ * the request.
+ *
+ * The PEAP module will take care of adding
+ * the State attribute back, before passing
+ * the handler & request back into the tunnel.
+ */
+ fr_pair_delete_by_num(&request->packet->vps, PW_STATE, 0, TAG_ANY);
+
+ /*
+ * Fix the User-Name when proxying, to strip off
+ * the NT Domain, if we're told to, and a User-Name
+ * exists, and there's a \\, meaning an NT-Domain
+ * in the user name, THEN discard the user name.
+ */
+ if (inst->with_ntdomain_hack &&
+ ((challenge = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY)) != NULL) &&
+ ((username = memchr(challenge->vp_octets, '\\', challenge->vp_length)) != NULL)) {
+ /*
+ * Wipe out the NT domain.
+ *
+ * FIXME: Put it into MS-CHAP-Domain?
+ */
+ username++; /* skip the \\ */
+ fr_pair_value_strcpy(challenge, username);
+ }
+
+ /*
+ * Remember that in the post-proxy stage, we've got
+ * to do the work below, AFTER the call to MS-CHAP
+ * authentication...
+ */
+ return 1;
+ }
+#endif
+
+ /*
+ * This is a wild & crazy hack.
+ */
+ rcode = process_authenticate(inst->auth_type_mschap, request);
+
+ /*
+ * Delete MPPE keys & encryption policy. We don't
+ * want these here.
+ */
+ fix_mppe_keys(handler, data);
+
+ /*
+ * Take the response from the mschap module, and
+ * return success or failure, depending on the result.
+ */
+ response = NULL;
+ if (rcode == RLM_MODULE_OK) {
+ fr_pair_list_mcopy_by_num(data, &response, &request->reply->vps, PW_MSCHAP2_SUCCESS, VENDORPEC_MICROSOFT, TAG_ANY);
+ data->code = PW_EAP_MSCHAPV2_SUCCESS;
+ } else if (inst->send_error) {
+ fr_pair_list_mcopy_by_num(data, &response, &request->reply->vps, PW_MSCHAP_ERROR, VENDORPEC_MICROSOFT, TAG_ANY);
+ if (response) {
+ int n,err,retry;
+ char buf[34];
+
+ VERIFY_VP(response);
+
+ RDEBUG2("MSCHAP-Error: %s", response->vp_strvalue);
+
+ /*
+ * Parse the new challenge out of the
+ * MS-CHAP-Error, so that if the client
+ * issues a re-try, we will know which
+ * challenge value that they used.
+ */
+ n = sscanf(response->vp_strvalue, "%*cE=%d R=%d C=%32s", &err, &retry, &buf[0]);
+ if (n == 3) {
+ RDEBUG2("Found new challenge from MS-CHAP-Error: err=%d retry=%d challenge=%s",
+ err, retry, buf);
+ fr_hex2bin(data->challenge, 16, buf, strlen(buf));
+ } else {
+ RDEBUG2("Could not parse new challenge from MS-CHAP-Error: %d", n);
+ }
+ }
+ data->code = PW_EAP_MSCHAPV2_FAILURE;
+ } else {
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 1;
+ }
+
+ /*
+ * No response, die.
+ */
+ if (!response) {
+ REDEBUG("No MS-CHAP2-Success or MS-CHAP-Error was found");
+ return 0;
+ }
+
+ /*
+ * Compose the response (whatever it is),
+ * and return it to the over-lying EAP module.
+ */
+ eapmschapv2_compose(inst, handler, response);
+ fr_pair_list_free(&response);
+
+ return 1;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_mschapv2;
+rlm_eap_module_t rlm_eap_mschapv2 = {
+ .name = "eap_mschapv2",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/README.md b/src/modules/rlm_eap/types/rlm_eap_peap/README.md
new file mode 100644
index 0000000..26e7d73
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_peap/README.md
@@ -0,0 +1,13 @@
+# rlm_eap_peap
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements PEAPv0, Microsoft's proprietary EAP method.
+
+Allows NTLMv2 style authentication against Active-Directory, or where the NT-Password is known.
+
+PEAP can also act as a transport for SoH (Statement of Health) messages, and as such, can be used as part of a NAC
+solution, providing firewall, patch level, and antivirus state of the client.
diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/all.mk b/src/modules/rlm_eap/types/rlm_eap_peap/all.mk
new file mode 100644
index 0000000..19f51d8
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_peap/all.mk
@@ -0,0 +1,10 @@
+TARGETNAME := rlm_eap_peap
+
+ifneq "$(OPENSSL_LIBS)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c peap.c
+
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/eap_peap.h b/src/modules/rlm_eap/types/rlm_eap_peap/eap_peap.h
new file mode 100644
index 0000000..7b803f8
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_peap/eap_peap.h
@@ -0,0 +1,76 @@
+/*
+ * eap_peap.h
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _EAP_PEAP_H
+#define _EAP_PEAP_H
+
+RCSIDH(eap_peap_h, "$Id$")
+
+#include "eap_tls.h"
+#include <freeradius-devel/soh.h>
+
+typedef enum {
+ PEAP_STATUS_INVALID,
+ PEAP_STATUS_SENT_TLV_SUCCESS,
+ PEAP_STATUS_SENT_TLV_FAILURE,
+ PEAP_STATUS_TUNNEL_ESTABLISHED,
+ PEAP_STATUS_INNER_IDENTITY_REQ_SENT,
+ PEAP_STATUS_PHASE2_INIT,
+ PEAP_STATUS_PHASE2,
+ PEAP_STATUS_WAIT_FOR_SOH_RESPONSE
+} peap_status;
+
+typedef enum {
+ PEAP_RESUMPTION_NO,
+ PEAP_RESUMPTION_YES,
+ PEAP_RESUMPTION_MAYBE
+} peap_resumption;
+
+typedef struct peap_tunnel_t {
+ VALUE_PAIR *username;
+ VALUE_PAIR *state;
+ VALUE_PAIR *accept_vps;
+ peap_status status;
+ bool home_access_accept;
+ int default_method;
+ bool copy_request_to_tunnel;
+ bool use_tunneled_reply;
+ bool proxy_tunneled_request_as_eap;
+ char const *virtual_server;
+ bool soh;
+ char const *soh_virtual_server;
+ VALUE_PAIR *soh_reply_vps;
+ peap_resumption session_resumption_state;
+} peap_tunnel_t;
+
+
+#define EAP_TLV_SUCCESS (1)
+#define EAP_TLV_FAILURE (2)
+#define EAP_TLV_ACK_RESULT (3)
+
+#define PW_EAP_TLV 33
+
+/*
+ * Process the PEAP portion of an EAP-PEAP request.
+ */
+rlm_rcode_t eappeap_process(eap_handler_t *handler, tls_session_t *tls_session, int auth_type_eap) CC_HINT(nonnull);
+#endif /* _EAP_PEAP_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/peap.c
new file mode 100644
index 0000000..a8589ae
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_peap/peap.c
@@ -0,0 +1,1316 @@
+/*
+ * peap.c contains the interfaces that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include "eap_peap.h"
+
+static int setup_fake_request(REQUEST *request, REQUEST *fake, peap_tunnel_t *t);
+
+/*
+ * Send protected EAP-Failure
+ *
+ * Result-TLV = Failure
+ */
+static int eappeap_failure(eap_handler_t *handler, tls_session_t *tls_session)
+{
+ uint8_t tlv_packet[11];
+ REQUEST *request = handler->request;
+
+ RDEBUG2("FAILURE");
+
+ tlv_packet[0] = PW_EAP_REQUEST;
+ tlv_packet[1] = handler->eap_ds->response->id +1;
+ tlv_packet[2] = 0;
+ tlv_packet[3] = 11; /* length of this packet */
+ tlv_packet[4] = PW_EAP_TLV;
+ tlv_packet[5] = 0x80;
+ tlv_packet[6] = EAP_TLV_ACK_RESULT;
+ tlv_packet[7] = 0;
+ tlv_packet[8] = 2; /* length of the data portion */
+ tlv_packet[9] = 0;
+ tlv_packet[10] = EAP_TLV_FAILURE;
+
+ (tls_session->record_plus)(&tls_session->clean_in, tlv_packet, 11);
+
+ /*
+ * FIXME: Check the return code.
+ */
+ tls_handshake_send(request, tls_session);
+
+ return 1;
+}
+
+
+/*
+ * Send protected EAP-Success
+ *
+ * Result-TLV = Success
+ */
+static int eappeap_success(eap_handler_t *handler, tls_session_t *tls_session)
+{
+ uint8_t tlv_packet[11];
+ REQUEST *request = handler->request;
+
+ RDEBUG2("SUCCESS");
+
+ tlv_packet[0] = PW_EAP_REQUEST;
+ tlv_packet[1] = handler->eap_ds->response->id +1;
+ tlv_packet[2] = 0;
+ tlv_packet[3] = 11; /* length of this packet */
+ tlv_packet[4] = PW_EAP_TLV;
+ tlv_packet[5] = 0x80; /* mandatory AVP */
+ tlv_packet[6] = EAP_TLV_ACK_RESULT;
+ tlv_packet[7] = 0;
+ tlv_packet[8] = 2; /* length of the data portion */
+ tlv_packet[9] = 0;
+ tlv_packet[10] = EAP_TLV_SUCCESS;
+
+ (tls_session->record_plus)(&tls_session->clean_in, tlv_packet, 11);
+
+ /*
+ * FIXME: Check the return code.
+ */
+ tls_handshake_send(request, tls_session);
+
+ return 1;
+}
+
+
+static int eappeap_identity(eap_handler_t *handler, tls_session_t *tls_session)
+{
+ eap_packet_raw_t eap_packet;
+
+ eap_packet.code = PW_EAP_REQUEST;
+ eap_packet.id = handler->eap_ds->response->id + 1;
+ eap_packet.length[0] = 0;
+ eap_packet.length[1] = EAP_HEADER_LEN + 1;
+ eap_packet.data[0] = PW_EAP_IDENTITY;
+
+ (tls_session->record_plus)(&tls_session->clean_in,
+ &eap_packet, sizeof(eap_packet));
+
+ tls_handshake_send(handler->request, tls_session);
+ (tls_session->record_init)(&tls_session->clean_in);
+
+ return 1;
+}
+
+/*
+ * Send an MS SoH request
+ */
+static int eappeap_soh(eap_handler_t *handler, tls_session_t *tls_session)
+{
+ uint8_t tlv_packet[20];
+
+ tlv_packet[0] = 254; /* extended type */
+
+ tlv_packet[1] = 0;
+ tlv_packet[2] = 0x01; /* ms vendor */
+ tlv_packet[3] = 0x37;
+
+ tlv_packet[4] = 0; /* ms soh eap */
+ tlv_packet[5] = 0;
+ tlv_packet[6] = 0;
+ tlv_packet[7] = 0x21;
+
+ tlv_packet[8] = 0; /* vendor-spec tlv */
+ tlv_packet[9] = 7;
+
+ tlv_packet[10] = 0;
+ tlv_packet[11] = 8; /* payload len */
+
+ tlv_packet[12] = 0; /* ms vendor */
+ tlv_packet[13] = 0;
+ tlv_packet[14] = 0x01;
+ tlv_packet[15] = 0x37;
+
+ tlv_packet[16] = 0;
+ tlv_packet[17] = 2;
+ tlv_packet[18] = 0;
+ tlv_packet[19] = 0;
+
+ (tls_session->record_plus)(&tls_session->clean_in, tlv_packet, 20);
+ tls_handshake_send(handler->request, tls_session);
+ return 1;
+}
+
+static void eapsoh_verify(REQUEST *request, RADIUS_PACKET *packet,
+ uint8_t const *data, unsigned int data_len) {
+
+ VALUE_PAIR *vp;
+ uint8_t eap_method_base;
+ uint32_t eap_vendor;
+ uint32_t eap_method;
+ int rv;
+
+ vp = fr_pair_make(packet, &packet->vps, "SoH-Supported", "no", T_OP_EQ);
+ if (data && data[0] == PW_EAP_NAK) {
+ RDEBUG("SoH - client NAKed");
+ return;
+ }
+
+ if (!data || data_len < 8) {
+ RDEBUG("SoH - eap payload too short");
+ return;
+ }
+
+ eap_method_base = *data++;
+ if (eap_method_base != 254) {
+ RDEBUG("SoH - response is not extended EAP: %i", eap_method_base);
+ return;
+ }
+
+ eap_vendor = soh_pull_be_24(data); data += 3;
+ if (eap_vendor != 0x137) {
+ RDEBUG("SoH - extended eap vendor %08x is not Microsoft", eap_vendor);
+ return;
+ }
+
+ eap_method = soh_pull_be_32(data); data += 4;
+ if (eap_method != 0x21) {
+ RDEBUG("SoH - response eap type %08x is not EAP-SoH", eap_method);
+ return;
+ }
+
+
+ rv = soh_verify(request, data, data_len - 8);
+ if (rv<0) {
+ RDEBUG("SoH - error decoding payload: %s", fr_strerror());
+ } else {
+ vp->vp_integer = 1;
+ }
+}
+
+/*
+ * Verify the tunneled EAP message.
+ */
+static int eapmessage_verify(REQUEST *request,
+ uint8_t const *data, unsigned int data_len, int peap_version)
+{
+ eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
+ eap_type_t eap_method;
+
+ /*
+ * Hack for now.
+ */
+ if (peap_version == 1) return 1;
+
+ /*
+ * No data, OR only 1 byte of EAP type.
+ */
+ if (!data || (data_len == 0) ||
+ ((data_len <= 1) && (data[0] != PW_EAP_IDENTITY))) {
+ return 0;
+ }
+
+ eap_method = *data;
+ switch (eap_method) {
+ case PW_EAP_IDENTITY:
+ if (data_len == 1) {
+ RDEBUG2("Identity - ");
+ return 1;
+ }
+ RDEBUG2("Identity - %*s",
+ data_len - 1, data + 1);
+ return 1;
+
+ /*
+ * If the first byte of the packet is
+ * EAP-Response, and the EAP data is a TLV,
+ * then it looks OK...
+ */
+ case PW_EAP_RESPONSE:
+ if (eap_packet->data[0] == PW_EAP_TLV) {
+ RDEBUG2("Received EAP-TLV response");
+ return 1;
+ }
+ RDEBUG2("Received unexpected EAP-Response, rejecting the session.");
+ break;
+
+
+ /*
+ * We normally do Microsoft MS-CHAPv2 (26), versus
+ * Cisco MS-CHAPv2 (29).
+ */
+ case PW_EAP_MSCHAPV2:
+ default:
+ RDEBUG2("EAP method %s (%d)", eap_type2name(eap_method),
+ eap_method);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Convert a pseudo-EAP packet to a list of VALUE_PAIR's.
+ */
+static VALUE_PAIR *eap2vp(UNUSED REQUEST *request, RADIUS_PACKET *packet,
+ EAP_DS *eap_ds,
+ uint8_t const *data, size_t data_len, int peap_version)
+{
+ size_t total;
+ uint8_t *p;
+ VALUE_PAIR *vp = NULL, *head = NULL;
+ vp_cursor_t cursor;
+
+ if (data_len > 65535) return NULL; /* paranoia */
+
+ vp = fr_pair_afrom_num(packet, PW_EAP_MESSAGE, 0);
+ if (!vp) {
+ return NULL;
+ }
+
+ total = data_len;
+ if (total > 249) total = 249;
+
+ if (peap_version == 0) {
+ /*
+ * Hand-build an EAP packet from the crap in PEAP version 0.
+ */
+ vp->vp_length = EAP_HEADER_LEN + total;
+ vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
+
+ p[0] = PW_EAP_RESPONSE;
+ p[1] = eap_ds->response->id;
+ p[2] = (data_len + EAP_HEADER_LEN) >> 8;
+ p[3] = (data_len + EAP_HEADER_LEN) & 0xff;
+
+ memcpy(p + EAP_HEADER_LEN, data, total);
+
+ } else { /* peapv1 */
+ vp->vp_length = total;
+ vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
+ memcpy(p, data, total);
+ }
+
+ fr_cursor_init(&cursor, &head);
+ fr_cursor_insert(&cursor, vp);
+ while (total < data_len) {
+ vp = fr_pair_afrom_num(packet, PW_EAP_MESSAGE, 0);
+ if (!vp) {
+ fr_pair_list_free(&head);
+ return NULL;
+ }
+
+ fr_pair_value_memcpy(vp, data + total, (data_len - total));
+
+ total += vp->vp_length;
+
+ fr_cursor_insert(&cursor, vp);
+ }
+
+ return head;
+}
+
+
+/*
+ * Convert a list of VALUE_PAIR's to an EAP packet, through the
+ * simple expedient of dumping the EAP message
+ */
+static int vp2eap(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *vp)
+{
+ rad_assert(vp != NULL);
+ VALUE_PAIR *this;
+ vp_cursor_t cursor;
+ size_t header = EAP_HEADER_LEN;
+
+ if (tls_session->peap_flag > 0) header = 0;
+
+ /*
+ * Skip the id, code, and length. Just write the EAP
+ * type & data to the client.
+ */
+#ifndef NDEBUG
+ if ((rad_debug_lvl > 2) && fr_log_fp) {
+ size_t i, total, start = header;
+ total = 0;
+
+ for (this = fr_cursor_init(&cursor, &vp); this; this = fr_cursor_next(&cursor)) {
+ for (i = start; i < vp->vp_length; i++) {
+ if ((total & 0x0f) == 0) {
+ fprintf(fr_log_fp, " PEAP tunnel data out %04x: ", (int) total);
+ }
+ fprintf(fr_log_fp, "%02x ", vp->vp_octets[i]);
+
+ if ((total & 0x0f) == 0x0f) {
+ fprintf(fr_log_fp, "\n");
+ }
+
+ total++;
+ }
+
+ start = 0;
+ }
+
+ if ((total & 0x0f) != 0) {
+ fprintf(fr_log_fp, "\n");
+ }
+ }
+#endif
+
+ /*
+ * Send the EAP data in the first attribute, WITHOUT the
+ * header.
+ */
+ (tls_session->record_plus)(&tls_session->clean_in, vp->vp_octets + header, vp->vp_length - header);
+
+ /*
+ * Send the rest of the EAP data, but skipping the first VP.
+ */
+ fr_cursor_init(&cursor, &vp);
+ for (this = fr_cursor_next(&cursor);
+ this;
+ this = fr_cursor_next(&cursor)) {
+ (tls_session->record_plus)(&tls_session->clean_in, this->vp_octets, this->vp_length);
+ }
+
+ tls_handshake_send(request, tls_session);
+
+ return 1;
+}
+
+
+/*
+ * See if there's a TLV in the response.
+ */
+static int eappeap_check_tlv(REQUEST *request, uint8_t const *data,
+ size_t data_len)
+{
+ eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
+
+ if (data_len < 11) return 0;
+
+ /*
+ * Look for success or failure.
+ */
+ if ((eap_packet->code == PW_EAP_RESPONSE) &&
+ (eap_packet->data[0] == PW_EAP_TLV)) {
+ if (data[10] == EAP_TLV_SUCCESS) {
+ return 1;
+ }
+
+ if (data[10] == EAP_TLV_FAILURE) {
+ RDEBUG2("Client rejected our response. The password is probably incorrect");
+ return 0;
+ }
+ }
+
+ RDEBUG("Unknown TLV %02x", data[10]);
+
+ return 0;
+}
+
+
+/*
+ * Use a reply packet to determine what to do.
+ */
+static rlm_rcode_t CC_HINT(nonnull) process_reply(eap_handler_t *handler, tls_session_t *tls_session,
+ REQUEST *request, RADIUS_PACKET *reply)
+{
+ rlm_rcode_t rcode = RLM_MODULE_REJECT;
+ VALUE_PAIR *vp;
+ peap_tunnel_t *t = tls_session->opaque;
+
+ if ((rad_debug_lvl > 0) && fr_log_fp) {
+ RDEBUG("Got tunneled reply RADIUS code %d", reply->code);
+ rdebug_pair_list(L_DBG_LVL_1, request, reply->vps, NULL);
+ }
+
+ switch (reply->code) {
+ case PW_CODE_ACCESS_ACCEPT:
+ RDEBUG2("Tunneled authentication was successful");
+ tls_session->authentication_success = true;
+ t->status = PEAP_STATUS_SENT_TLV_SUCCESS;
+ eappeap_success(handler, tls_session);
+ rcode = RLM_MODULE_HANDLED;
+
+ /*
+ * If we've been told to use the attributes from
+ * the reply, then do so.
+ *
+ * WARNING: This may leak information about the
+ * tunneled user!
+ */
+ if (t->use_tunneled_reply) {
+ RDEBUG2("Saving tunneled attributes for later");
+
+ /*
+ * Clean up the tunneled reply.
+ */
+ fr_pair_delete_by_num(&reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+
+ /*
+ * Delete MPPE keys & encryption policy. We don't
+ * want these here.
+ */
+ fr_pair_delete_by_num(&reply->vps, 7, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 8, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 16, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 17, VENDORPEC_MICROSOFT, TAG_ANY);
+
+ fr_pair_list_free(&t->accept_vps); /* for proxying MS-CHAP2 */
+ fr_pair_list_mcopy_by_num(t, &t->accept_vps, &reply->vps, 0, 0, TAG_ANY);
+ rad_assert(!reply->vps);
+ }
+ break;
+
+ case PW_CODE_ACCESS_REJECT:
+ RDEBUG2("Tunneled authentication was rejected");
+ t->status = PEAP_STATUS_SENT_TLV_FAILURE;
+ eappeap_failure(handler, tls_session);
+ rcode = RLM_MODULE_HANDLED;
+ break;
+
+ case PW_CODE_ACCESS_CHALLENGE:
+ RDEBUG2("Got tunneled Access-Challenge");
+
+ /*
+ * Keep the State attribute, if necessary.
+ *
+ * Get rid of the old State, too.
+ */
+ fr_pair_list_free(&t->state);
+ fr_pair_list_mcopy_by_num(t, &t->state, &reply->vps, PW_STATE, 0, TAG_ANY);
+
+ /*
+ * PEAP takes only EAP-Message attributes inside
+ * of the tunnel. Any Reply-Message in the
+ * Access-Challenge is ignored.
+ */
+ vp = NULL;
+ fr_pair_list_mcopy_by_num(t, &vp, &reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+
+ /*
+ * Handle EAP-MSCHAP-V2, where Access-Accept's
+ * from the home server may contain MS-CHAP2-Success,
+ * which the module turns into challenges, so that
+ * the client may respond to the challenge with
+ * an "ack" packet.
+ */
+ if (t->home_access_accept && t->use_tunneled_reply) {
+ RDEBUG2("Saving tunneled attributes for later");
+
+ /*
+ * Clean up the tunneled reply.
+ */
+ fr_pair_delete_by_num(&reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
+
+ rad_assert(!t->accept_vps);
+ fr_pair_list_mcopy_by_num(t, &t->accept_vps, &reply->vps, 0, 0, TAG_ANY);
+ rad_assert(!reply->vps);
+ }
+
+ /*
+ * Handle the ACK, by tunneling any necessary reply
+ * VP's back to the client.
+ */
+ if (vp) {
+ vp2eap(request, tls_session, vp);
+ fr_pair_list_free(&vp);
+ }
+
+ rcode = RLM_MODULE_HANDLED;
+ break;
+
+ default:
+ RDEBUG2("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
+ rcode = RLM_MODULE_REJECT;
+ break;
+ }
+
+ return rcode;
+}
+
+#ifdef WITH_PROXY
+/*
+ * Do post-proxy processing,
+ */
+static int CC_HINT(nonnull) eappeap_postproxy(eap_handler_t *handler, void *data)
+{
+ int rcode;
+ tls_session_t *tls_session = (tls_session_t *) data;
+ REQUEST *fake, *request = handler->request;
+
+ RDEBUG2("Passing reply from proxy back into the tunnel");
+
+ /*
+ * If there was a fake request associated with the proxied
+ * request, do more processing of it.
+ */
+ fake = (REQUEST *) request_data_get(handler->request,
+ handler->request->proxy,
+ REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);
+
+ /*
+ * Do the callback, if it exists, and if it was a success.
+ */
+ if (fake && (handler->request->proxy_reply->code == PW_CODE_ACCESS_ACCEPT)) {
+ peap_tunnel_t *t = tls_session->opaque;
+
+ t->home_access_accept = true;
+
+ /*
+ * Terrible hacks.
+ */
+ rad_assert(!fake->packet);
+ fake->packet = talloc_steal(fake, request->proxy);
+ fake->packet->src_ipaddr = request->packet->src_ipaddr;
+ request->proxy = NULL;
+
+ rad_assert(!fake->reply);
+ fake->reply = talloc_steal(fake, request->proxy_reply);
+ request->proxy_reply = NULL;
+
+ if ((rad_debug_lvl > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "server %s {\n", fake->server);
+ }
+
+ fake->reply->code = PW_CODE_ACCESS_ACCEPT;
+
+ /*
+ * Perform a post-auth stage, which will get the EAP
+ * handler, too...
+ */
+ fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
+ RDEBUG2("Passing reply back for EAP-MS-CHAP-V2");
+ process_post_proxy(0, fake);
+
+ /*
+ * FIXME: If rcode returns fail, do something
+ * intelligent...
+ */
+ rcode = rad_postauth(fake);
+
+ if ((rad_debug_lvl > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "} # server %s\n", fake->server);
+
+ RDEBUG("Final reply from tunneled session code %d", fake->reply->code);
+ rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);
+ }
+
+ /*
+ * Terrible hacks.
+ */
+ request->proxy = talloc_steal(request, fake->packet);
+ fake->packet = NULL;
+ request->proxy_reply = talloc_steal(request, fake->reply);
+ fake->reply = NULL;
+
+ /*
+ * And we're done with this request.
+ */
+
+ switch (rcode) {
+ case RLM_MODULE_FAIL:
+ talloc_free(fake);
+ eaptls_fail(handler, 0);
+ return 0;
+
+ default: /* Don't Do Anything */
+ RDEBUG2("Got reply %d", request->proxy_reply->code);
+ break;
+ }
+ }
+ talloc_free(fake); /* robust if !fake */
+
+ /*
+ * If there was no EAP-Message in the reply packet, then
+ * we know that we're supposed to re-run the "authenticate"
+ * stage, in order to get the right kind of handling...
+ */
+
+ /*
+ * Process the reply from the home server.
+ */
+
+ rcode = process_reply(handler, tls_session, handler->request,
+ handler->request->proxy_reply);
+
+ /*
+ * The proxy code uses the reply from the home server as
+ * the basis for the reply to the NAS. We don't want that,
+ * so we toss it, after we've had our way with it.
+ */
+ fr_pair_list_free(&handler->request->proxy_reply->vps);
+
+ switch (rcode) {
+ case RLM_MODULE_REJECT:
+ RDEBUG2("Reply was rejected");
+ eaptls_fail(handler, 0);
+ return 0;
+
+ case RLM_MODULE_HANDLED:
+ RDEBUG2("Reply was handled");
+ eaptls_request(handler->eap_ds, tls_session);
+ request->proxy_reply->code = PW_CODE_ACCESS_CHALLENGE;
+ return 1;
+
+ case RLM_MODULE_OK:
+ RDEBUG2("Reply was OK");
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ return eaptls_success(handler, 0);
+
+ default:
+ RDEBUG2("Reply was unknown");
+ break;
+ }
+
+ eaptls_fail(handler, 0);
+ return 0;
+}
+#endif
+
+
+static char const *peap_state(peap_tunnel_t *t)
+{
+ switch (t->status) {
+ case PEAP_STATUS_TUNNEL_ESTABLISHED:
+ return "TUNNEL ESTABLISHED";
+
+ case PEAP_STATUS_WAIT_FOR_SOH_RESPONSE:
+ return "WAITING FOR SOH RESPONSE";
+
+ case PEAP_STATUS_INNER_IDENTITY_REQ_SENT:
+ return "WAITING FOR INNER IDENTITY";
+
+ case PEAP_STATUS_SENT_TLV_SUCCESS:
+ return "send tlv success";
+
+ case PEAP_STATUS_SENT_TLV_FAILURE:
+ return "send tlv failure";
+
+ case PEAP_STATUS_PHASE2_INIT:
+ return "phase2_init";
+
+ case PEAP_STATUS_PHASE2:
+ return "phase2";
+
+ default:
+ break;
+ }
+ return "?";
+}
+
+static void print_tunneled_data(uint8_t const *data, size_t data_len)
+{
+ size_t i;
+
+ if ((rad_debug_lvl > 2) && fr_log_fp) {
+ for (i = 0; i < data_len; i++) {
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, " PEAP tunnel data in %02x: ", (int) i);
+
+ fprintf(fr_log_fp, "%02x ", data[i]);
+
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+ }
+ if ((data_len & 0x0f) != 0) fprintf(fr_log_fp, "\n");
+ }
+}
+
+
+/*
+ * Process the pseudo-EAP contents of the tunneled data.
+ */
+rlm_rcode_t eappeap_process(eap_handler_t *handler, tls_session_t *tls_session, int auth_type_eap)
+{
+ peap_tunnel_t *t = tls_session->opaque;
+ REQUEST *fake;
+ VALUE_PAIR *vp;
+ rlm_rcode_t rcode = RLM_MODULE_REJECT;
+ uint8_t const *data;
+ unsigned int data_len;
+ size_t header = 0;
+
+ REQUEST *request = handler->request;
+ EAP_DS *eap_ds = handler->eap_ds;
+
+ /*
+ * Just look at the buffer directly, without doing
+ * record_minus. This lets us avoid another data copy.
+ */
+ data_len = tls_session->clean_out.used;
+ tls_session->clean_out.used = 0;
+ data = tls_session->clean_out.data;
+
+ RDEBUG2("PEAP state %s", peap_state(t));
+
+ if ((t->status != PEAP_STATUS_TUNNEL_ESTABLISHED) &&
+ !eapmessage_verify(request, data, data_len, tls_session->peap_flag)) {
+ REDEBUG("Tunneled data is invalid");
+ if (rad_debug_lvl > 2) print_tunneled_data(data, data_len);
+ return RLM_MODULE_REJECT;
+ }
+
+ if (tls_session->peap_flag > 0) header = EAP_HEADER_LEN;
+
+ switch (t->status) {
+ case PEAP_STATUS_TUNNEL_ESTABLISHED:
+ /* FIXME: should be no data in the buffer here, check & assert? */
+
+ if (SSL_session_reused(tls_session->ssl)) {
+ RDEBUG2("Skipping Phase2 because of session resumption");
+ t->session_resumption_state = PEAP_RESUMPTION_YES;
+ if (t->soh) {
+ t->status = PEAP_STATUS_WAIT_FOR_SOH_RESPONSE;
+ RDEBUG2("Requesting SoH from client");
+ eappeap_soh(handler, tls_session);
+ return RLM_MODULE_HANDLED;
+ }
+ /* we're good, send success TLV */
+ t->status = PEAP_STATUS_SENT_TLV_SUCCESS;
+ eappeap_success(handler, tls_session);
+
+ } else {
+ /* send an identity request */
+ t->session_resumption_state = PEAP_RESUMPTION_NO;
+ t->status = PEAP_STATUS_INNER_IDENTITY_REQ_SENT;
+ tls_session->session_not_resumed = true;
+ eappeap_identity(handler, tls_session);
+ }
+ return RLM_MODULE_HANDLED;
+
+ case PEAP_STATUS_INNER_IDENTITY_REQ_SENT:
+ /* we're expecting an identity response */
+ if (data[header] != PW_EAP_IDENTITY) {
+ REDEBUG("Expected EAP-Identity, got something else");
+ return RLM_MODULE_REJECT;
+ }
+
+ /*
+ * Save it for later.
+ */
+ t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
+ rad_assert(t->username != NULL);
+
+ fr_pair_value_bstrncpy(t->username, data + header + 1, data_len - header - 1);
+
+ RDEBUG("Got inner identity '%s'", t->username->vp_strvalue);
+ if (t->soh) {
+ t->status = PEAP_STATUS_WAIT_FOR_SOH_RESPONSE;
+ RDEBUG2("Requesting SoH from client");
+ eappeap_soh(handler, tls_session);
+ return RLM_MODULE_HANDLED;
+ }
+ t->status = PEAP_STATUS_PHASE2_INIT;
+ break;
+
+ case PEAP_STATUS_WAIT_FOR_SOH_RESPONSE:
+ fake = request_alloc_fake(request);
+ rad_assert(!fake->packet->vps);
+ eapsoh_verify(fake, fake->packet, data + header, data_len - header);
+ setup_fake_request(request, fake, t);
+
+ if (t->soh_virtual_server) {
+ fake->server = t->soh_virtual_server;
+ }
+ RDEBUG("Sending SoH request to server %s", fake->server ? fake->server : "NULL");
+ rad_virtual_server(fake);
+
+ if (fake->reply->code != PW_CODE_ACCESS_ACCEPT) {
+ RDEBUG2("SoH was rejected");
+ talloc_free(fake);
+ t->status = PEAP_STATUS_SENT_TLV_FAILURE;
+ eappeap_failure(handler, tls_session);
+ return RLM_MODULE_HANDLED;
+ }
+
+ /* save the SoH VPs */
+ rad_assert(!t->soh_reply_vps);
+ fr_pair_list_mcopy_by_num(t, &t->soh_reply_vps, &fake->reply->vps, 0, 0, TAG_ANY);
+ rad_assert(!fake->reply->vps);
+ talloc_free(fake);
+
+ if (t->session_resumption_state == PEAP_RESUMPTION_YES) {
+ /* we're good, send success TLV */
+ t->status = PEAP_STATUS_SENT_TLV_SUCCESS;
+ eappeap_success(handler, tls_session);
+ return RLM_MODULE_HANDLED;
+ }
+
+ t->status = PEAP_STATUS_PHASE2_INIT;
+ break;
+
+
+ /*
+ * If we authenticated the user, then it's OK.
+ */
+ case PEAP_STATUS_SENT_TLV_SUCCESS:
+ if (eappeap_check_tlv(request, data + header, data_len - header)) {
+ RDEBUG2("Success");
+ return RLM_MODULE_OK;
+ }
+
+ /*
+ * Otherwise, the client rejected the session
+ * resumption. If the session is being re-used,
+ * we need to do a full authentication.
+ *
+ * We do this by sending an EAP-Identity request
+ * inside of the PEAP tunnel.
+ */
+ if (t->session_resumption_state == PEAP_RESUMPTION_YES) {
+ RDEBUG2("Client rejected session resumption. Re-starting full authentication");
+
+ /*
+ * Mark session resumption status.
+ */
+ t->status = PEAP_STATUS_INNER_IDENTITY_REQ_SENT;
+ t->session_resumption_state = PEAP_RESUMPTION_NO;
+
+ eappeap_identity(handler, tls_session);
+ return RLM_MODULE_HANDLED;
+ }
+
+ REDEBUG("We sent a success, but the client did not agree");
+ return RLM_MODULE_REJECT;
+
+ /*
+ * Supplicant ACKs our failure.
+ */
+ case PEAP_STATUS_SENT_TLV_FAILURE:
+ RINDENT();
+ REDEBUG("The users session was previously rejected: returning reject (again.)");
+ RDEBUG("This means you need to read the PREVIOUS messages in the debug output");
+ RDEBUG("to find out the reason why the user was rejected");
+ RDEBUG("Look for \"reject\" or \"fail\". Those earlier messages will tell you");
+ RDEBUG("what went wrong, and how to fix the problem");
+ REXDENT();
+
+ return RLM_MODULE_REJECT;
+
+ case PEAP_STATUS_PHASE2_INIT:
+ RDEBUG("In state machine in phase2 init?");
+
+ case PEAP_STATUS_PHASE2:
+ break;
+
+ default:
+ REDEBUG("Unhandled state in peap");
+ return RLM_MODULE_REJECT;
+ }
+
+ fake = request_alloc_fake(request);
+
+ rad_assert(!fake->packet->vps);
+
+ switch (t->status) {
+ /*
+ * If we're in PHASE2_INIT, the phase2 method hasn't been
+ * sent an Identity packet yet; do so from the stored
+ * username and this will kick off the phase2 eap method
+ */
+
+ case PEAP_STATUS_PHASE2_INIT: {
+ size_t len = t->username->vp_length + EAP_HEADER_LEN + 1;
+ uint8_t *q;
+
+ t->status = PEAP_STATUS_PHASE2;
+
+ vp = fr_pair_afrom_num(fake->packet, PW_EAP_MESSAGE, 0);
+ vp->vp_length = len;
+ vp->vp_octets = q = talloc_array(vp, uint8_t, vp->vp_length);
+
+ q[0] = PW_EAP_RESPONSE;
+ q[1] = eap_ds->response->id;
+ q[2] = (len >> 8) & 0xff;
+ q[3] = len & 0xff;
+ q[4] = PW_EAP_IDENTITY;
+
+ memcpy(q + EAP_HEADER_LEN + 1,
+ t->username->vp_strvalue, t->username->vp_length);
+
+ fr_pair_add(&fake->packet->vps, vp);
+
+ if (t->default_method != 0) {
+ RDEBUG2("Setting default EAP type for tunneled EAP session");
+ vp = fr_pair_make(fake, &fake->config, "EAP-Type", "0", T_OP_EQ);
+ vp->vp_integer = t->default_method;
+ }
+ break; }
+
+ case PEAP_STATUS_PHASE2:
+ fake->packet->vps = eap2vp(request, fake->packet,
+ eap_ds, data, data_len, tls_session->peap_flag);
+ if (!fake->packet->vps) {
+ talloc_free(fake);
+ RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
+ return RLM_MODULE_REJECT;
+ }
+ break;
+
+ default:
+ REDEBUG("Invalid state change in PEAP");
+ return RLM_MODULE_REJECT;
+ }
+
+ RDEBUG2("Got tunneled request");
+ rdebug_pair_list(L_DBG_LVL_2, request, fake->packet->vps, NULL);
+
+ /*
+ * Update other items in the REQUEST data structure.
+ */
+ if (!t->username) {
+ /*
+ * There's no User-Name in the tunneled session,
+ * so we add one here, by pulling it out of the
+ * EAP-Identity packet.
+ */
+ if ((data[header] == PW_EAP_IDENTITY) && (data_len > (1 + header))) {
+ t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
+ rad_assert(t->username != NULL);
+
+ fr_pair_value_bstrncpy(t->username, data + header + 1, data_len - header - 1);
+
+ RDEBUG2("Got tunneled identity of %s", t->username->vp_strvalue);
+
+ /*
+ * If there's a default EAP type,
+ * set it here.
+ */
+ if (t->default_method != 0) {
+ RDEBUG2("Setting default EAP type for tunneled EAP session");
+ vp = fr_pair_make(fake, &fake->config, "EAP-Type", "0", T_OP_EQ);
+ vp->vp_integer = t->default_method;
+ }
+ }
+ } /* else there WAS a t->username */
+
+ setup_fake_request(request, fake, t);
+
+ if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
+ fake->server = vp->vp_strvalue;
+
+ } else if (t->virtual_server) {
+ fake->server = t->virtual_server;
+
+ } /* else fake->server == request->server */
+
+ if (fake->server) {
+ RDEBUG2("Sending tunneled request to %s", fake->server);
+ } else {
+ RDEBUG2("Sending tunnelled request");
+ }
+ rdebug_pair_list(L_DBG_LVL_2, request, fake->packet->vps, NULL);
+
+ /*
+ * Call authentication recursively, which will
+ * do PAP, CHAP, MS-CHAP, etc.
+ */
+ rad_virtual_server(fake);
+
+ /*
+ * Note that we don't do *anything* with the reply
+ * attributes.
+ */
+ RDEBUG2("Got tunneled reply code %d", fake->reply->code);
+ rdebug_pair_list(L_DBG_LVL_2, request, fake->reply->vps, NULL);
+
+ /*
+ * Decide what to do with the reply.
+ */
+ switch (fake->reply->code) {
+ case 0: /* No reply code, must be proxied... */
+#ifdef WITH_PROXY
+ vp = fr_pair_find_by_num(fake->config, PW_PROXY_TO_REALM, 0, TAG_ANY);
+
+ if (vp) {
+ eap_tunnel_data_t *tunnel;
+ bool proxy_as_eap = t->proxy_tunneled_request_as_eap;
+ VALUE_PAIR *flag = fr_pair_find_by_num(fake->config, PW_PROXY_TUNNELED_REQUEST_AS_EAP, 0, TAG_ANY);
+
+ if (flag) proxy_as_eap = flag->vp_integer;
+
+ /*
+ * The tunneled request was NOT handled,
+ * it has to be proxied. This means that
+ * the "authenticate" stage was never
+ * performed.
+ *
+ * If we are told to NOT proxy the
+ * tunneled request as EAP, then this
+ * means that we've got to decode it,
+ * which means that we MUST run the
+ * "authenticate" portion by hand, here.
+ *
+ * Once the tunneled EAP session is ALMOST
+ * done, THEN we proxy it...
+ */
+ if (!proxy_as_eap) {
+ fake->options |= RAD_REQUEST_OPTION_PROXY_EAP;
+
+ /*
+ * Hmm... should we check for
+ * Auth-Type & EAP-Message here?
+ */
+
+ if (!auth_type_eap) {
+ RERROR("You must set 'inner_eap_module' in the 'peap' configuration");
+ RERROR("This is required in order to proxy the inner EAP session.");
+ rcode = RLM_MODULE_REJECT;
+ goto done;
+ }
+
+ /*
+ * Run the EAP authentication.
+ */
+ RDEBUG2("Calling authenticate in order to initiate tunneled EAP session");
+ rcode = process_authenticate(auth_type_eap, fake);
+ if (rcode == RLM_MODULE_OK) {
+ /*
+ * Authentication succeeded! Rah!
+ */
+ fake->reply->code = PW_CODE_ACCESS_ACCEPT;
+ goto do_process;
+ }
+
+ if (rcode != RLM_MODULE_HANDLED) {
+ RDEBUG("Can't handle the return code %d", rcode);
+ rcode = RLM_MODULE_REJECT;
+ goto done;
+ }
+
+ /*
+ * The module decided it wasn't
+ * done. Handle it like normal.
+ */
+ if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) == 0) {
+ RDEBUG2("Cancelling proxy to realm %s until the tunneled EAP session "
+ "has been established", vp->vp_strvalue);
+ goto do_process;
+ }
+
+ /*
+ * The module has decoded the
+ * EAP-Message into another set
+ * of attributes.
+ */
+ fr_pair_delete_by_num(&fake->packet->vps,
+ PW_EAP_MESSAGE, 0, TAG_ANY);
+ }
+
+ RDEBUG2("Tunnelled authentication will be proxied to %s", vp->vp_strvalue);
+
+ /*
+ * Tell the original request that it's going
+ * to be proxied.
+ */
+ fr_pair_list_mcopy_by_num(request, &request->config,
+ &fake->config,
+ PW_PROXY_TO_REALM, 0, TAG_ANY);
+
+ /*
+ * Seed the proxy packet with the
+ * tunneled request.
+ */
+ rad_assert(!request->proxy);
+ request->proxy = talloc_steal(request, fake->packet);
+ memset(&request->proxy->src_ipaddr, 0,
+ sizeof(request->proxy->src_ipaddr));
+ memset(&request->proxy->dst_ipaddr, 0,
+ sizeof(request->proxy->dst_ipaddr));
+ request->proxy->src_port = 0;
+ request->proxy->dst_port = 0;
+ fake->packet = NULL;
+ rad_free(&fake->reply);
+ fake->reply = NULL;
+
+ /*
+ * Set up the callbacks for the tunnel
+ */
+ tunnel = talloc_zero(request, eap_tunnel_data_t);
+ tunnel->tls_session = tls_session;
+ tunnel->callback = eappeap_postproxy;
+
+ /*
+ * Associate the callback with the request.
+ */
+ rcode = request_data_add(request,
+ request->proxy,
+ REQUEST_DATA_EAP_TUNNEL_CALLBACK,
+ tunnel, false);
+ rad_assert(rcode == 0);
+
+ /*
+ * We're not proxying it as EAP, so we've got
+ * to do the callback later.
+ */
+ if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) != 0) {
+ RDEBUG2("Remembering to do EAP-MS-CHAP-V2 post-proxy");
+
+ /*
+ * rlm_eap.c has taken care of associating
+ * the handler with the fake request.
+ *
+ * So we associate the fake request with
+ * this request.
+ */
+ rcode = request_data_add(request, request->proxy,
+ REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
+ fake, true);
+ rad_assert(rcode == 0);
+
+ /*
+ * Do NOT free the fake request!
+ */
+ return RLM_MODULE_UPDATED;
+ }
+
+ /*
+ * Didn't authenticate the packet, but
+ * we're proxying it.
+ */
+ rcode = RLM_MODULE_UPDATED;
+
+ } else
+#endif /* WITH_PROXY */
+ {
+ REDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", fake->reply->code);
+ rcode = RLM_MODULE_REJECT;
+ }
+ break;
+
+ default:
+#ifdef WITH_PROXY
+ do_process:
+#endif
+ rcode = process_reply(handler, tls_session, request,
+ fake->reply);
+ break;
+ }
+
+#ifdef WITH_PROXY
+ done:
+#endif
+ talloc_free(fake);
+
+ return rcode;
+}
+
+static int CC_HINT(nonnull) setup_fake_request(REQUEST *request, REQUEST *fake, peap_tunnel_t *t) {
+
+ VALUE_PAIR *vp;
+
+ /*
+ * Tell the request that it's a fake one.
+ */
+ fr_pair_make(fake->packet, &fake->packet->vps, "Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
+
+ if (t->username) {
+ vp = fr_pair_list_copy(fake->packet, t->username);
+ fr_pair_add(&fake->packet->vps, vp);
+ fake->username = vp;
+ RDEBUG2("Setting User-Name to %s", fake->username->vp_strvalue);
+ } else {
+ RDEBUG2("No tunnel username (SSL resumption?)");
+ }
+
+
+ /*
+ * Add the State attribute, too, if it exists.
+ */
+ if (t->state) {
+ vp = fr_pair_list_copy(fake->packet, t->state);
+ if (vp) fr_pair_add(&fake->packet->vps, vp);
+ }
+
+ /*
+ * If this is set, we copy SOME of the request attributes
+ * from outside of the tunnel to inside of the tunnel.
+ *
+ * We copy ONLY those attributes which do NOT already
+ * exist in the tunneled request.
+ *
+ * This code is copied from ../rlm_eap_ttls/ttls.c
+ */
+ if (t->copy_request_to_tunnel) {
+ VALUE_PAIR *copy;
+ vp_cursor_t cursor;
+
+ for (vp = fr_cursor_init(&cursor, &request->packet->vps);
+ vp;
+ vp = fr_cursor_next(&cursor)) {
+ /*
+ * The attribute is a server-side thingy,
+ * don't copy it.
+ */
+ if ((vp->da->attr > 255) && (((vp->da->attr >> 16) & 0xffff) == 0)) {
+ continue;
+ }
+
+ /*
+ * The outside attribute is already in the
+ * tunnel, don't copy it.
+ *
+ * This works for BOTH attributes which
+ * are originally in the tunneled request,
+ * AND attributes which are copied there
+ * from below.
+ */
+ if (fr_pair_find_by_da(fake->packet->vps, vp->da, TAG_ANY)) continue;
+
+ /*
+ * Some attributes are handled specially.
+ */
+ if (!vp->da->vendor) switch (vp->da->attr) {
+ /*
+ * NEVER copy Message-Authenticator,
+ * EAP-Message, or State. They're
+ * only for outside of the tunnel.
+ */
+ case PW_USER_NAME:
+ case PW_USER_PASSWORD:
+ case PW_CHAP_PASSWORD:
+ case PW_CHAP_CHALLENGE:
+ case PW_PROXY_STATE:
+ case PW_MESSAGE_AUTHENTICATOR:
+ case PW_EAP_MESSAGE:
+ case PW_STATE:
+ continue;
+
+ /*
+ * By default, copy it over.
+ */
+ default:
+ break;
+ }
+
+ /*
+ * Don't copy from the head, we've already
+ * checked it.
+ */
+ copy = fr_pair_list_copy_by_num(fake->packet, vp, vp->da->attr, vp->da->vendor, TAG_ANY);
+ fr_pair_add(&fake->packet->vps, copy);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c
new file mode 100644
index 0000000..d9f850c
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c
@@ -0,0 +1,429 @@
+/*
+ * rlm_eap_peap.c contains the interfaces that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+
+#include "eap_peap.h"
+
+typedef struct rlm_eap_peap_t {
+ char const *tls_conf_name; //!< TLS configuration.
+ fr_tls_server_conf_t *tls_conf;
+ char const *default_method_name; //!< Default tunneled EAP type.
+ int default_method;
+
+ char const *inner_eap_module; //!< module name for inner EAP
+ int auth_type_eap;
+ bool use_tunneled_reply; //!< Use the reply attributes from the tunneled session in
+ //!< the non-tunneled reply to the client.
+
+ bool copy_request_to_tunnel; //!< Use SOME of the request attributes from outside of the
+ //!< tunneled session in the tunneled request.
+#ifdef WITH_PROXY
+ bool proxy_tunneled_request_as_eap; //!< Proxy tunneled session as EAP, or as de-capsulated
+ //!< protocol.
+#endif
+ char const *virtual_server; //!< Virtual server for inner tunnel session.
+
+ bool soh; //!< Do we do SoH request?
+ char const *soh_virtual_server;
+ bool req_client_cert; //!< Do we do require a client cert?
+} rlm_eap_peap_t;
+
+
+static CONF_PARSER module_config[] = {
+ { "tls", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_peap_t, tls_conf_name), NULL },
+
+ { "default_eap_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_peap_t, default_method_name), "mschapv2" },
+
+ { "inner_eap_module", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_peap_t, inner_eap_module), NULL },
+
+ { "copy_request_to_tunnel", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_peap_t, copy_request_to_tunnel), "no" },
+
+ { "use_tunneled_reply", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_peap_t, use_tunneled_reply), "no" },
+
+#ifdef WITH_PROXY
+ { "proxy_tunneled_request_as_eap", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_peap_t, proxy_tunneled_request_as_eap), "yes" },
+#endif
+
+ { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_peap_t, virtual_server), NULL },
+
+ { "soh", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_peap_t, soh), "no" },
+
+ { "require_client_cert", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_peap_t, req_client_cert), "no" },
+
+ { "soh_virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_peap_t, soh_virtual_server), NULL },
+
+ CONF_PARSER_TERMINATOR
+};
+
+
+/*
+ * Attach the module.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_peap_t *inst;
+ DICT_VALUE const *dv;
+
+ *instance = inst = talloc_zero(cs, rlm_eap_peap_t);
+ if (!inst) return -1;
+
+ /*
+ * Parse the configuration attributes.
+ */
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ if (!inst->virtual_server) {
+ ERROR("rlm_eap_peap: A 'virtual_server' MUST be defined for security");
+ return -1;
+ }
+
+ /*
+ * Convert the name to an integer, to make it easier to
+ * handle.
+ */
+ inst->default_method = eap_name2type(inst->default_method_name);
+ if (inst->default_method < 0) {
+ ERROR("rlm_eap_peap: Unknown EAP type %s",
+ inst->default_method_name);
+ return -1;
+ }
+
+ /*
+ * Read tls configuration, either from group given by 'tls'
+ * option, or from the eap-tls configuration.
+ */
+ inst->tls_conf = eaptls_conf_parse(cs, "tls");
+
+ if (!inst->tls_conf) {
+ ERROR("rlm_eap_peap: Failed initializing SSL context");
+ return -1;
+ }
+
+ /*
+ * Don't expose this if we don't need it.
+ */
+ if (!inst->inner_eap_module) inst->inner_eap_module = "eap";
+
+ dv = dict_valbyname(PW_AUTH_TYPE, 0, inst->inner_eap_module);
+ if (!dv) {
+ WARN("Failed to find 'Auth-Type %s' section in virtual server %s. The server cannot proxy inner-tunnel EAP packets.",
+ inst->inner_eap_module, inst->virtual_server);
+ } else {
+ inst->auth_type_eap = dv->value;
+ }
+
+ return 0;
+}
+
+/*
+ * Allocate the PEAP per-session data
+ */
+static peap_tunnel_t *peap_alloc(TALLOC_CTX *ctx, rlm_eap_peap_t *inst)
+{
+ peap_tunnel_t *t;
+
+ t = talloc_zero(ctx, peap_tunnel_t);
+
+ t->default_method = inst->default_method;
+ t->copy_request_to_tunnel = inst->copy_request_to_tunnel;
+ t->use_tunneled_reply = inst->use_tunneled_reply;
+#ifdef WITH_PROXY
+ t->proxy_tunneled_request_as_eap = inst->proxy_tunneled_request_as_eap;
+#endif
+ t->virtual_server = inst->virtual_server;
+ t->soh = inst->soh;
+ t->soh_virtual_server = inst->soh_virtual_server;
+ t->session_resumption_state = PEAP_RESUMPTION_MAYBE;
+
+ return t;
+}
+
+/*
+ * Send an initial eap-tls request to the peer, using the libeap functions.
+ */
+static int mod_session_init(void *type_arg, eap_handler_t *handler)
+{
+ int status;
+ tls_session_t *ssn;
+ rlm_eap_peap_t *inst;
+ VALUE_PAIR *vp;
+ bool client_cert;
+ REQUEST *request = handler->request;
+
+ inst = type_arg;
+
+ handler->tls = true;
+
+ /*
+ * Check if we need a client certificate.
+ */
+
+ /*
+ * EAP-TLS-Require-Client-Cert attribute will override
+ * the require_client_cert configuration option.
+ */
+ vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0, TAG_ANY);
+ if (vp) {
+ client_cert = vp->vp_integer ? true : false;
+ } else {
+ client_cert = inst->req_client_cert;
+ }
+
+ /*
+ * Allow TLS 1.3, it works.
+ */
+ ssn = eaptls_session(handler, inst->tls_conf, client_cert, true);
+ if (!ssn) {
+ return 0;
+ }
+
+ handler->opaque = ((void *)ssn);
+
+ /*
+ * Set the label to a fixed string. For TLS 1.3, the
+ * label is the same for all TLS-based EAP methods. If
+ * the client is using TLS 1.3, then eaptls_success()
+ * will over-ride this label with the correct label for
+ * TLS 1.3.
+ */
+ ssn->label = "client EAP encryption";
+
+ /*
+ * As it is a poorly designed protocol, PEAP uses
+ * bits in the TLS header to indicate PEAP
+ * version numbers. For now, we only support
+ * PEAP version 0, so it doesn't matter too much.
+ * However, if we support later versions of PEAP,
+ * we will need this flag to indicate which
+ * version we're currently dealing with.
+ */
+ ssn->peap_flag = 0x00;
+
+ /*
+ * PEAP version 0 requires 'include_length = no',
+ * so rather than hoping the user figures it out,
+ * we force it here.
+ */
+ ssn->length_flag = false;
+
+ /*
+ * TLS session initialization is over. Now handle TLS
+ * related handshaking or application data.
+ */
+ status = eaptls_start(handler->eap_ds, ssn->peap_flag);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+ if (status == 0) return 0;
+
+ /*
+ * The next stage to process the packet.
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+/*
+ * Do authentication, by letting EAP-TLS do most of the work.
+ */
+static int mod_process(void *arg, eap_handler_t *handler)
+{
+ int rcode;
+ int ret = 0;
+ fr_tls_status_t status;
+ rlm_eap_peap_t *inst = (rlm_eap_peap_t *) arg;
+ tls_session_t *tls_session = (tls_session_t *) handler->opaque;
+ peap_tunnel_t *peap = tls_session->opaque;
+ REQUEST *request = handler->request;
+
+ /*
+ * Session resumption requires the storage of data, so
+ * allocate it if it doesn't already exist.
+ */
+ if (!tls_session->opaque) {
+ peap = tls_session->opaque = peap_alloc(tls_session, inst);
+ }
+
+ /*
+ * Negotiate PEAP versions down.
+ */
+ if ((handler->eap_ds->response->type.data[0] & 0x03) < tls_session->peap_flag) {
+ tls_session->peap_flag = handler->eap_ds->response->type.data[0] & 0x03;
+ }
+
+ status = eaptls_process(handler);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+
+ /*
+ * Make request available to any SSL callbacks
+ */
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
+ switch (status) {
+ /*
+ * EAP-TLS handshake was successful, tell the
+ * client to keep talking.
+ *
+ * If this was EAP-TLS, we would just return
+ * an EAP-TLS-Success packet here.
+ */
+ case FR_TLS_SUCCESS:
+ peap->status = PEAP_STATUS_TUNNEL_ESTABLISHED;
+ break;
+
+ /*
+ * The TLS code is still working on the TLS
+ * exchange, and it's a valid TLS request.
+ * do nothing.
+ */
+ case FR_TLS_HANDLED:
+ /*
+ * FIXME: If the SSL session is established, grab the state
+ * and EAP id from the inner tunnel, and update it with
+ * the expected EAP id!
+ */
+ ret = 1;
+ goto done;
+ /*
+ * Handshake is done, proceed with decoding tunneled
+ * data.
+ */
+ case FR_TLS_OK:
+ /*
+ * TLSv1.3 makes application data immediately avaliable
+ */
+ if (tls_session->is_init_finished && (peap->status == PEAP_STATUS_INVALID)) peap->status = PEAP_STATUS_TUNNEL_ESTABLISHED;
+ break;
+
+ /*
+ * Anything else: fail.
+ */
+ default:
+ ret = 0;
+ goto done;
+ }
+
+ /*
+ * Session is established, proceed with decoding
+ * tunneled data.
+ */
+ RDEBUG2("Session established. Decoding tunneled attributes");
+
+ /*
+ * We may need PEAP data associated with the session, so
+ * allocate it here, if it wasn't already alloacted.
+ */
+ if (!tls_session->opaque) {
+ tls_session->opaque = peap_alloc(tls_session, inst);
+ }
+
+ /*
+ * Process the PEAP portion of the request.
+ */
+ rcode = eappeap_process(handler, tls_session, inst->auth_type_eap);
+ switch (rcode) {
+ case RLM_MODULE_REJECT:
+ eaptls_fail(handler, 0);
+ ret = 0;
+ goto done;
+
+ case RLM_MODULE_HANDLED:
+ eaptls_request(handler->eap_ds, tls_session);
+ ret = 1;
+ goto done;
+
+ case RLM_MODULE_OK:
+ /*
+ * Move the saved VP's from the Access-Accept to
+ * our Access-Accept.
+ */
+ peap = tls_session->opaque;
+ if (peap->soh_reply_vps) {
+ RDEBUG2("Using saved attributes from the SoH reply");
+ rdebug_pair_list(L_DBG_LVL_2, request, peap->soh_reply_vps, NULL);
+ fr_pair_list_mcopy_by_num(handler->request->reply,
+ &handler->request->reply->vps,
+ &peap->soh_reply_vps, 0, 0, TAG_ANY);
+ }
+ if (peap->accept_vps) {
+ RDEBUG2("Using saved attributes from the original Access-Accept");
+ rdebug_pair_list(L_DBG_LVL_2, request, peap->accept_vps, NULL);
+ fr_pair_list_mcopy_by_num(handler->request->reply,
+ &handler->request->reply->vps,
+ &peap->accept_vps, 0, 0, TAG_ANY);
+ } else if (peap->use_tunneled_reply) {
+ RDEBUG2("No saved attributes in the original Access-Accept");
+ }
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ ret = eaptls_success(handler, 0);
+ goto done;
+
+ /*
+ * No response packet, MUST be proxying it.
+ * The main EAP module will take care of discovering
+ * that the request now has a "proxy" packet, and
+ * will proxy it, rather than returning an EAP packet.
+ */
+ case RLM_MODULE_UPDATED:
+#ifdef WITH_PROXY
+ rad_assert(handler->request->proxy != NULL);
+#endif
+ ret = 1;
+ goto done;
+
+ default:
+ break;
+ }
+
+ eaptls_fail(handler, 0);
+
+done:
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
+
+ return ret;
+}
+
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_peap;
+rlm_eap_module_t rlm_eap_peap = {
+ .name = "eap_peap",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/.gitignore b/src/modules/rlm_eap/types/rlm_eap_pwd/.gitignore
new file mode 100644
index 0000000..01a5daa
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/.gitignore
@@ -0,0 +1 @@
+all.mk
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/README.md b/src/modules/rlm_eap/types/rlm_eap_pwd/README.md
new file mode 100644
index 0000000..e7ea14b
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/README.md
@@ -0,0 +1,11 @@
+# rlm_eap_pwd
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements EAP-PWD as described by [RFC 5931](https://tools.ietf.org/html/rfc5931).
+
+EAP-PWD allows authentication using a PSK (the user's password). The PSK is not sent in the clear, instead each side
+proves knowledge of the password using Elliptic Curve cryptography.
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/all.mk.in b/src/modules/rlm_eap/types/rlm_eap_pwd/all.mk.in
new file mode 100644
index 0000000..e04ec27
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/all.mk.in
@@ -0,0 +1,16 @@
+TARGETNAME := @targetname@
+
+ifneq "$(OPENSSL_LIBS)" ""
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+endif
+
+SOURCES := $(TARGETNAME).c eap_pwd.c
+
+SRC_CFLAGS := @mod_cflags@
+TGT_LDLIBS := @mod_ldflags@
+
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/configure b/src/modules/rlm_eap/types/rlm_eap_pwd/configure
new file mode 100755
index 0000000..d108e97
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/configure
@@ -0,0 +1,4271 @@
+#! /bin/sh
+# From configure.ac Revision.
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="rlm_eap_pwd.c"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+mod_cflags
+mod_ldflags
+targetname
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_rlm_eap_pwd
+with_openssl_lib_dir
+with_openssl_include_dir
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-rlm_eap_pwd build without rlm_eap_pwd
+ --with-openssl-lib-dir=DIR
+ directory for LDAP library files
+ --with-openssl-include-dir=DIR
+ directory for LDAP include files
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+echo
+echo Running tests for rlm_eap_pwd
+echo
+
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+# Check whether --with-rlm_eap_pwd was given.
+if test "${with_rlm_eap_pwd+set}" = set; then :
+ withval=$with_rlm_eap_pwd;
+fi
+
+
+
+mod_ldflags=
+mod_cflags=
+
+
+fail=
+fr_status=
+fr_features=
+: > "config.report"
+: > "config.report.tmp"
+
+
+
+if test x"$with_rlm_eap_pwd" != xno; then
+
+
+
+openssl_lib_dir=
+
+# Check whether --with-openssl-lib-dir was given.
+if test "${with_openssl_lib_dir+set}" = set; then :
+ withval=$with_openssl_lib_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need openssl-lib-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_lib_dir="$withval"
+ ;;
+ esac
+fi
+
+
+openssl_include_dir=
+
+# Check whether --with-openssl-include-dir was given.
+if test "${with_openssl_include_dir+set}" = set; then :
+ withval=$with_openssl_include_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need openssl-include-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_include_dir="$withval"
+ ;;
+ esac
+fi
+
+
+
+smart_try_dir=$openssl_include_dir
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_safe=`echo "openssl/ec.h" | sed 'y%./+-%__pm%'`
+old_CPPFLAGS="$CPPFLAGS"
+smart_include=
+smart_include_dir="/usr/local/include /opt/include"
+
+_smart_try_dir=
+_smart_include_dir=
+
+for _prefix in $smart_prefix ""; do
+ for _dir in $smart_try_dir; do
+ _smart_try_dir="${_smart_try_dir} ${_dir}/${_prefix}"
+ done
+
+ for _dir in $smart_include_dir; do
+ _smart_include_dir="${_smart_include_dir} ${_dir}/${_prefix}"
+ done
+done
+
+if test "x$_smart_try_dir" != "x"; then
+ for try in $_smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ec.h in $try" >&5
+$as_echo_n "checking for openssl/ec.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" = "x"; then
+ for _prefix in $smart_prefix; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${_prefix}/openssl/ec.h" >&5
+$as_echo_n "checking for ${_prefix}/openssl/ec.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem ${_prefix}/"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+fi
+
+if test "x$smart_include" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ec.h" >&5
+$as_echo_n "checking for openssl/ec.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include=" "
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "x$smart_include" = "x"; then
+
+ for try in $_smart_include_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ec.h in $try" >&5
+$as_echo_n "checking for openssl/ec.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/ec.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" != "x"; then
+ eval "ac_cv_header_$ac_safe=yes"
+ CPPFLAGS="$smart_include $old_CPPFLAGS"
+ SMART_CPPFLAGS="$smart_include $SMART_CPPFLAGS"
+fi
+
+smart_prefix=
+
+if test "$ac_cv_header_openssl_ec_h" != "yes"; then
+
+fail="$fail openssl/ec.h"
+
+fi
+
+smart_try_dir=$openssl_lib_dir
+
+
+sm_lib_safe=`echo "crypto" | sed 'y%./+-%__p_%'`
+sm_func_safe=`echo "EVP_CIPHER_CTX_new" | sed 'y%./+-%__p_%'`
+
+old_LIBS="$LIBS"
+old_CPPFLAGS="$CPPFLAGS"
+smart_lib=
+smart_ldflags=
+smart_lib_dir=
+
+if test "x$smart_try_dir" != "x"; then
+ for try in $smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto in $try" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto in $try... " >&6; }
+ LIBS="-lcrypto $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char EVP_CIPHER_CTX_new();
+int
+main ()
+{
+EVP_CIPHER_CTX_new()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lcrypto"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto... " >&6; }
+ LIBS="-lcrypto $old_LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char EVP_CIPHER_CTX_new();
+int
+main ()
+{
+EVP_CIPHER_CTX_new()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lcrypto"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$old_LIBS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ for try in /usr/local/lib /opt/lib; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_new in -lcrypto in $try" >&5
+$as_echo_n "checking for EVP_CIPHER_CTX_new in -lcrypto in $try... " >&6; }
+ LIBS="-lcrypto $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char EVP_CIPHER_CTX_new();
+int
+main ()
+{
+EVP_CIPHER_CTX_new()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lcrypto"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" != "x"; then
+ eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes"
+ LIBS="$smart_ldflags $smart_lib $old_LIBS"
+ SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS"
+fi
+
+if test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" != "xyes"; then
+
+fail="$fail libssl"
+
+else
+ for ac_func in EVP_sha256
+do :
+ ac_fn_c_check_func "$LINENO" "EVP_sha256" "ac_cv_func_EVP_sha256"
+if test "x$ac_cv_func_EVP_sha256" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_EVP_SHA256 1
+_ACEOF
+
+fi
+done
+
+ if test "x$ac_cv_func_EVP_sha256" != "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: EVP_sha256 not found, may have issues with WiMAX certificates" >&5
+$as_echo "$as_me: WARNING: EVP_sha256 not found, may have issues with WiMAX certificates" >&2;}
+ fi
+
+ for ac_func in EC_GROUP_free
+do :
+ ac_fn_c_check_func "$LINENO" "EC_GROUP_free" "ac_cv_func_EC_GROUP_free"
+if test "x$ac_cv_func_EC_GROUP_free" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_EC_GROUP_FREE 1
+_ACEOF
+
+fi
+done
+
+ if test "x$ac_cv_func_EC_GROUP_free" != "xyes"; then
+
+fail="$fail EC_GROUP_free"
+
+ fi
+fi
+
+
+ targetname=rlm_eap_pwd
+else
+ targetname=
+ echo \*\*\* module rlm_eap_pwd is disabled.
+
+
+fr_status="disabled"
+
+fi
+
+if test x"$fail" != x""; then
+ targetname=""
+
+
+ if test x"${enable_strict_dependencies}" = x"yes"; then
+ as_fn_error $? "set --without-rlm_eap_pwd to disable it explicitly." "$LINENO" 5
+ else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: silently not building rlm_eap_pwd." >&5
+$as_echo "$as_me: WARNING: silently not building rlm_eap_pwd." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: FAILURE: rlm_eap_pwd requires: $fail." >&5
+$as_echo "$as_me: WARNING: FAILURE: rlm_eap_pwd requires: $fail." >&2;};
+ fail="$(echo $fail)"
+
+
+fr_status="skipping (requires $fail)"
+
+ fr_features=
+
+ fi
+
+else
+
+
+fr_status="OK"
+
+fi
+
+if test x"$fr_features" = x""; then
+ $as_echo "$fr_status" > "config.report"
+else
+ $as_echo_n "$fr_status ... " > "config.report"
+ cat "config.report.tmp" >> "config.report"
+fi
+
+rm "config.report.tmp"
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files all.mk"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "all.mk") CONFIG_FILES="$CONFIG_FILES all.mk" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/configure.ac b/src/modules/rlm_eap/types/rlm_eap_pwd/configure.ac
new file mode 100644
index 0000000..1833b38
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/configure.ac
@@ -0,0 +1,80 @@
+AC_PREREQ([2.69])
+AC_INIT
+AC_CONFIG_SRCDIR([rlm_eap_pwd.c])
+AC_REVISION($Revision$)
+FR_INIT_MODULE([rlm_eap_pwd])
+
+mod_ldflags=
+mod_cflags=
+
+FR_MODULE_START_TESTS
+
+dnl ############################################################
+dnl # Check for command line options
+dnl ############################################################
+
+dnl extra argument: --with-openssl-lib-dir
+openssl_lib_dir=
+AC_ARG_WITH(openssl-lib-dir,
+ [AS_HELP_STRING([--with-openssl-lib-dir=DIR],
+ [directory for LDAP library files])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need openssl-lib-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_lib_dir="$withval"
+ ;;
+ esac])
+
+dnl extra argument: --with-openssl-include-dir
+openssl_include_dir=
+AC_ARG_WITH(openssl-include-dir,
+ [AS_HELP_STRING([--with-openssl-include-dir=DIR],
+ [directory for LDAP include files])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need openssl-include-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ openssl_include_dir="$withval"
+ ;;
+ esac])
+
+dnl ############################################################
+dnl # Check for header files
+dnl ############################################################
+
+smart_try_dir=$openssl_include_dir
+FR_SMART_CHECK_INCLUDE(openssl/ec.h)
+if test "$ac_cv_header_openssl_ec_h" != "yes"; then
+ FR_MODULE_FAIL([openssl/ec.h])
+fi
+
+smart_try_dir=$openssl_lib_dir
+FR_SMART_CHECK_LIB(crypto, EVP_CIPHER_CTX_new)
+if test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" != "xyes"; then
+ FR_MODULE_FAIL([libssl])
+else
+ AC_CHECK_FUNCS(EVP_sha256)
+ if test "x$ac_cv_func_EVP_sha256" != "xyes"; then
+ AC_MSG_WARN([EVP_sha256 not found, may have issues with WiMAX certificates])
+ fi
+
+ AC_CHECK_FUNCS(EC_GROUP_free)
+ if test "x$ac_cv_func_EC_GROUP_free" != "xyes"; then
+ FR_MODULE_FAIL([EC_GROUP_free])
+ fi
+fi
+
+FR_MODULE_END_TESTS
+
+AC_SUBST(mod_ldflags)
+AC_SUBST(mod_cflags)
+
+AC_CONFIG_FILES([all.mk])
+AC_OUTPUT
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/const_time.h b/src/modules/rlm_eap/types/rlm_eap_pwd/const_time.h
new file mode 100644
index 0000000..b717dd5
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/const_time.h
@@ -0,0 +1,190 @@
+/*
+ * Helper functions for constant time operations
+ * Copyright (c) 2019, The Linux Foundation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ *
+ * These helper functions can be used to implement logic that needs to minimize
+ * externally visible differences in execution path by avoiding use of branches,
+ * avoiding early termination or other time differences, and forcing same memory
+ * access pattern regardless of values.
+ */
+
+#ifndef CONST_TIME_H
+#define CONST_TIME_H
+
+
+#if defined(__clang__)
+#define NO_UBSAN_UINT_OVERFLOW \
+ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#else
+#define NO_UBSAN_UINT_OVERFLOW
+#endif
+
+/**
+ * const_time_fill_msb - Fill all bits with MSB value
+ * @param val Input value
+ * @return Value with all the bits set to the MSB of the input val
+ */
+static inline unsigned int const_time_fill_msb(unsigned int val)
+{
+ /* Move the MSB to LSB and multiple by -1 to fill in all bits. */
+ return (val >> (sizeof(val) * 8 - 1)) * ~0U;
+}
+
+
+/* @return -1 if val is zero; 0 if val is not zero */
+static inline unsigned int const_time_is_zero(unsigned int val)
+ NO_UBSAN_UINT_OVERFLOW
+{
+ /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
+ return const_time_fill_msb(~val & (val - 1));
+}
+
+
+/* @return -1 if a == b; 0 if a != b */
+static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
+{
+ return const_time_is_zero(a ^ b);
+}
+
+
+/* @return -1 if a == b; 0 if a != b */
+static inline unsigned char const_time_eq_u8(unsigned int a, unsigned int b)
+{
+ return (unsigned char) const_time_eq(a, b);
+}
+
+
+/**
+ * const_time_eq_bin - Constant time memory comparison
+ * @param a First buffer to compare
+ * @param b Second buffer to compare
+ * @param len Number of octets to compare
+ * @return -1 if buffers are equal, 0 if not
+ *
+ * This function is meant for comparing passwords or hash values where
+ * difference in execution time or memory access pattern could provide external
+ * observer information about the location of the difference in the memory
+ * buffers. The return value does not behave like memcmp(), i.e.,
+ * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
+ * memcmp(), the execution time of const_time_eq_bin() does not depend on the
+ * contents of the compared memory buffers, but only on the total compared
+ * length.
+ */
+static inline unsigned int const_time_eq_bin(const void *a, const void *b,
+ size_t len)
+{
+ const unsigned char *aa = a;
+ const unsigned char *bb = b;
+ size_t i;
+ unsigned char res = 0;
+
+ for (i = 0; i < len; i++)
+ res |= aa[i] ^ bb[i];
+
+ return const_time_is_zero(res);
+}
+
+
+/**
+ * const_time_select - Constant time unsigned int selection
+ * @param mask 0 (false) or -1 (true) to identify which value to select
+ * @param true_val Value to select for the true case
+ * @param false_val Value to select for the false case
+ * @return true_val if mask == -1, false_val if mask == 0
+ */
+static inline unsigned int const_time_select(unsigned int mask,
+ unsigned int true_val,
+ unsigned int false_val)
+{
+ return (mask & true_val) | (~mask & false_val);
+}
+
+
+/**
+ * const_time_select_int - Constant time int selection
+ * @param mask 0 (false) or -1 (true) to identify which value to select
+ * @param true_val Value to select for the true case
+ * @param false_val Value to select for the false case
+ * @return true_val if mask == -1, false_val if mask == 0
+ */
+static inline int const_time_select_int(unsigned int mask, int true_val,
+ int false_val)
+{
+ return (int) const_time_select(mask, (unsigned int) true_val,
+ (unsigned int) false_val);
+}
+
+
+/**
+ * const_time_select_u8 - Constant time u8 selection
+ * @param mask 0 (false) or -1 (true) to identify which value to select
+ * @param true_val Value to select for the true case
+ * @param false_val Value to select for the false case
+ * @return true_val if mask == -1, false_val if mask == 0
+ */
+static inline unsigned char const_time_select_u8(unsigned char mask, unsigned char true_val, unsigned char false_val)
+{
+ return (unsigned char) const_time_select(mask, true_val, false_val);
+}
+
+
+/**
+ * const_time_select_s8 - Constant time s8 selection
+ * @param mask 0 (false) or -1 (true) to identify which value to select
+ * @param true_val Value to select for the true case
+ * @param false_val Value to select for the false case
+ * @return true_val if mask == -1, false_val if mask == 0
+ */
+static inline char const_time_select_s8(char mask, char true_val, char false_val)
+{
+ return (char) const_time_select(mask, (unsigned int) true_val,
+ (unsigned int) false_val);
+}
+
+
+/**
+ * const_time_select_bin - Constant time binary buffer selection copy
+ * @param mask 0 (false) or -1 (true) to identify which value to copy
+ * @param true_val Buffer to copy for the true case
+ * @param false_val Buffer to copy for the false case
+ * @param len Number of octets to copy
+ * @param dst Destination buffer for the copy
+ *
+ * This function copies the specified buffer into the destination buffer using
+ * operations with identical memory access pattern regardless of which buffer
+ * is being copied.
+ */
+static inline void const_time_select_bin(unsigned char mask, const unsigned char *true_val,
+ const unsigned char *false_val, size_t len,
+ unsigned char *dst)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
+}
+
+
+static inline int const_time_memcmp(const void *a, const void *b, size_t len)
+{
+ const unsigned char *aa = a;
+ const unsigned char *bb = b;
+ int diff, res = 0;
+ unsigned int mask;
+
+ if (len == 0)
+ return 0;
+ do {
+ len--;
+ diff = (int) aa[len] - (int) bb[len];
+ mask = const_time_is_zero((unsigned int) diff);
+ res = const_time_select_int(mask, res, diff);
+ } while (len);
+
+ return res;
+}
+
+#endif /* CONST_TIME_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c b/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c
new file mode 100644
index 0000000..2626052
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.c
@@ -0,0 +1,933 @@
+/**
+ * copyright holder grants permission for redistribution and use in source
+ * and binary forms, with or without modification, provided that the
+ * following conditions are met:
+ * 1. Redistribution of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in all source files.
+ * 2. Redistribution in binary form must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * "DISCLAIMER OF LIABILITY
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAN HARKINS ``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 INDUSTRIAL LOUNGE 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."
+ *
+ * This license and distribution terms cannot be changed. In other words,
+ * this code cannot simply be copied and put under a different distribution
+ * license (including the GNU public license).
+ *
+ * @copyright (c) Dan Harkins, 2012
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include "eap_pwd.h"
+#include "const_time.h"
+#include <freeradius-devel/openssl3.h>
+
+static uint8_t allzero[SHA256_DIGEST_LENGTH] = { 0x00 };
+
+/* The random function H(x) = HMAC-SHA256(0^32, x) */
+static void pwd_hmac_final(HMAC_CTX *hmac_ctx, uint8_t *digest)
+{
+ unsigned int mdlen = SHA256_DIGEST_LENGTH;
+ HMAC_Final(hmac_ctx, digest, &mdlen);
+// HMAC_CTX_reset(hmac_ctx);
+}
+
+/* a counter-based KDF based on NIST SP800-108 */
+static void eap_pwd_kdf(uint8_t *key, int keylen, char const *label,
+ int label_len, uint8_t *result, int result_bit_len)
+{
+ HMAC_CTX *hmac_ctx;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+ uint16_t i, ctr, L;
+ int result_byte_len, len = 0;
+ unsigned int mdlen = SHA256_DIGEST_LENGTH;
+ uint8_t mask = 0xff;
+
+ MEM(hmac_ctx = HMAC_CTX_new());
+ result_byte_len = (result_bit_len + 7) / 8;
+
+ ctr = 0;
+ L = htons(result_bit_len);
+ while (len < result_byte_len) {
+ ctr++; i = htons(ctr);
+
+ HMAC_Init_ex(hmac_ctx, key, keylen, EVP_sha256(), NULL);
+ if (ctr > 1) HMAC_Update(hmac_ctx, digest, mdlen);
+ HMAC_Update(hmac_ctx, (uint8_t *) &i, sizeof(uint16_t));
+ HMAC_Update(hmac_ctx, (uint8_t const *)label, label_len);
+ HMAC_Update(hmac_ctx, (uint8_t *) &L, sizeof(uint16_t));
+ HMAC_Final(hmac_ctx, digest, &mdlen);
+ if ((len + (int) mdlen) > result_byte_len) {
+ memcpy(result + len, digest, result_byte_len - len);
+ } else {
+ memcpy(result + len, digest, mdlen);
+ }
+ len += mdlen;
+// HMAC_CTX_reset(hmac_ctx);
+ }
+
+ /* since we're expanding to a bit length, mask off the excess */
+ if (result_bit_len % 8) {
+ mask <<= (8 - (result_bit_len % 8));
+ result[result_byte_len - 1] &= mask;
+ }
+
+ HMAC_CTX_free(hmac_ctx);
+}
+
+static BIGNUM *consttime_BN (void)
+{
+ BIGNUM *bn;
+
+ bn = BN_new();
+ if (bn) BN_set_flags(bn, BN_FLG_CONSTTIME);
+ return bn;
+}
+
+/*
+ * compute the legendre symbol in constant time
+ */
+static int legendre(BIGNUM *a, BIGNUM *p, BN_CTX *bnctx)
+{
+ int symbol;
+ unsigned int mask;
+ BIGNUM *res, *pm1over2;
+
+ pm1over2 = consttime_BN();
+ res = consttime_BN();
+
+ if (!BN_sub(pm1over2, p, BN_value_one()) ||
+ !BN_rshift1(pm1over2, pm1over2) ||
+ !BN_mod_exp_mont_consttime(res, a, pm1over2, p, bnctx, NULL)) {
+ BN_free(pm1over2);
+ BN_free(res);
+ return -2;
+ }
+
+ symbol = -1;
+ mask = const_time_eq(BN_is_word(res, 1), 1);
+ symbol = const_time_select_int(mask, 1, symbol);
+ mask = const_time_eq(BN_is_zero(res), 1);
+ symbol = const_time_select_int(mask, -1, symbol);
+
+ BN_free(pm1over2);
+ BN_free(res);
+
+ return symbol;
+}
+
+static void do_equation(EC_GROUP *group, BIGNUM *y2, BIGNUM *x, BN_CTX *bnctx)
+{
+ BIGNUM *p, *a, *b, *tmp1, *pm1;
+
+ tmp1 = BN_new();
+ pm1 = BN_new();
+ p = BN_new();
+ a = BN_new();
+ b = BN_new();
+ EC_GROUP_get_curve(group, p, a, b, bnctx);
+
+ BN_sub(pm1, p, BN_value_one());
+
+ /*
+ * y2 = x^3 + ax + b
+ */
+ BN_mod_sqr(tmp1, x, p, bnctx);
+ BN_mod_mul(y2, tmp1, x, p, bnctx);
+ BN_mod_mul(tmp1, a, x, p, bnctx);
+ BN_mod_add_quick(y2, y2, tmp1, p);
+ BN_mod_add_quick(y2, y2, b, p);
+
+ BN_free(tmp1);
+ BN_free(pm1);
+ BN_free(p);
+ BN_free(a);
+ BN_free(b);
+
+ return;
+}
+
+static int is_quadratic_residue(BIGNUM *val, BIGNUM *p, BIGNUM *qr, BIGNUM *qnr, BN_CTX *bnctx)
+{
+ int offset, check, ret = 0;
+ BIGNUM *r = NULL, *pm1 = NULL, *res = NULL, *qr_or_qnr = NULL;
+ unsigned int mask;
+ unsigned char *qr_bin = NULL, *qnr_bin = NULL, *qr_or_qnr_bin = NULL;
+
+ if (((r = consttime_BN()) == NULL) ||
+ ((res = consttime_BN()) == NULL) ||
+ ((qr_or_qnr = consttime_BN()) == NULL) ||
+ ((pm1 = consttime_BN()) == NULL)) {
+ ret = -2;
+ goto fail;
+ }
+
+ if (((qr_bin = (unsigned char *)malloc(BN_num_bytes(p))) == NULL) ||
+ ((qnr_bin = (unsigned char *)malloc(BN_num_bytes(p))) == NULL) ||
+ ((qr_or_qnr_bin = (unsigned char *)malloc(BN_num_bytes(p))) == NULL)) {
+ ret = -2;
+ goto fail;
+ }
+
+ /*
+ * we select binary in constant time so make them binary
+ */
+ memset(qr_bin, 0, BN_num_bytes(p));
+ memset(qnr_bin, 0, BN_num_bytes(p));
+ memset(qr_or_qnr_bin, 0, BN_num_bytes(p));
+
+ offset = BN_num_bytes(p) - BN_num_bytes(qr);
+ BN_bn2bin(qr, qr_bin + offset);
+
+ offset = BN_num_bytes(p) - BN_num_bytes(qnr);
+ BN_bn2bin(qnr, qnr_bin + offset);
+
+ /*
+ * r = (random() mod p-1) + 1
+ */
+ BN_sub(pm1, p, BN_value_one());
+ BN_rand_range(r, pm1);
+ BN_add(r, r, BN_value_one());
+
+ BN_copy(res, val);
+
+ /*
+ * res = val * r * r which ensures res != val but has same quadratic residocity
+ */
+ BN_mod_mul(res, res, r, p, bnctx);
+ BN_mod_mul(res, res, r, p, bnctx);
+
+ /*
+ * if r is even (mask is -1) then multiply by qnr and our check is qnr
+ * otherwise multiply by qr and our check is qr
+ */
+ mask = const_time_is_zero(BN_is_odd(r));
+ const_time_select_bin(mask, qnr_bin, qr_bin, BN_num_bytes(p), qr_or_qnr_bin);
+ BN_bin2bn(qr_or_qnr_bin, BN_num_bytes(p), qr_or_qnr);
+ BN_mod_mul(res, res, qr_or_qnr, p, bnctx);
+ check = const_time_select_int(mask, -1, 1);
+
+ if ((ret = legendre(res, p, bnctx)) == -2) {
+ ret = -1; /* just say no it's not */
+ goto fail;
+ }
+ mask = const_time_eq(ret, check);
+ ret = const_time_select_int(mask, 1, 0);
+
+fail:
+ if (qr_bin != NULL) free(qr_bin);
+ if (qnr_bin != NULL) free(qnr_bin);
+ if (qr_or_qnr_bin != NULL) free(qr_or_qnr_bin);
+ BN_free(r);
+ BN_free(res);
+ BN_free(qr_or_qnr);
+ BN_free(pm1);
+
+ return ret;
+}
+
+int compute_password_element (REQUEST *request, pwd_session_t *session, uint16_t grp_num,
+ char const *password, int password_len,
+ char const *id_server, int id_server_len,
+ char const *id_peer, int id_peer_len,
+ uint32_t *token)
+{
+ BIGNUM *x_candidate = NULL, *rnd = NULL, *y_sqrd = NULL, *qr = NULL, *qnr = NULL, *y1 = NULL, *y2 = NULL, *y = NULL, *exp = NULL;
+ EVP_MD_CTX *hmac_ctx;
+ EVP_PKEY *hmac_pkey;
+ uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, *xbuf = NULL, *pm1buf = NULL, *y1buf = NULL, *y2buf = NULL, *ybuf = NULL, ctr;
+ int nid, is_odd, primebitlen, primebytelen, ret = 0, found = 0, mask;
+ int save, i, rbits, qr_or_qnr, save_is_odd = 0, cmp;
+ unsigned int skip;
+
+ MEM(hmac_ctx = EVP_MD_CTX_new());
+ MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, allzero, sizeof(allzero)));
+
+ switch (grp_num) { /* from IANA registry for IKE D-H groups */
+ case 19:
+ nid = NID_X9_62_prime256v1;
+ break;
+
+ case 20:
+ nid = NID_secp384r1;
+ break;
+
+ case 21:
+ nid = NID_secp521r1;
+ break;
+
+ case 25:
+ nid = NID_X9_62_prime192v1;
+ break;
+
+ case 26:
+ nid = NID_secp224r1;
+ break;
+
+ default:
+ DEBUG("unknown group %d", grp_num);
+ goto fail;
+ }
+
+ session->pwe = NULL;
+ session->order = NULL;
+ session->prime = NULL;
+
+ if ((session->group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
+ DEBUG("unable to create EC_GROUP");
+ goto fail;
+ }
+
+ if (((rnd = consttime_BN()) == NULL) ||
+ ((session->pwe = EC_POINT_new(session->group)) == NULL) ||
+ ((session->order = consttime_BN()) == NULL) ||
+ ((session->prime = consttime_BN()) == NULL) ||
+ ((qr = consttime_BN()) == NULL) ||
+ ((qnr = consttime_BN()) == NULL) ||
+ ((x_candidate = consttime_BN()) == NULL) ||
+ ((y_sqrd = consttime_BN()) == NULL) ||
+ ((y1 = consttime_BN()) == NULL) ||
+ ((y2 = consttime_BN()) == NULL) ||
+ ((y = consttime_BN()) == NULL) ||
+ ((exp = consttime_BN()) == NULL)) {
+ DEBUG("unable to create bignums");
+ goto fail;
+ }
+
+ if (!EC_GROUP_get_curve(session->group, session->prime, NULL, NULL, NULL)) {
+ DEBUG("unable to get prime for GFp curve");
+ goto fail;
+ }
+
+ if (!EC_GROUP_get_order(session->group, session->order, NULL)) {
+ DEBUG("unable to get order for curve");
+ goto fail;
+ }
+
+ primebitlen = BN_num_bits(session->prime);
+ primebytelen = BN_num_bytes(session->prime);
+ if ((prfbuf = talloc_zero_array(session, uint8_t, primebytelen)) == NULL) {
+ DEBUG("unable to alloc space for prf buffer");
+ goto fail;
+ }
+ if ((xbuf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) {
+ DEBUG("unable to alloc space for x buffer");
+ goto fail;
+ }
+ if ((pm1buf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) {
+ DEBUG("unable to alloc space for pm1 buffer");
+ goto fail;
+ }
+ if ((y1buf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) {
+ DEBUG("unable to alloc space for y1 buffer");
+ goto fail;
+ }
+ if ((y2buf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) {
+ DEBUG("unable to alloc space for y2 buffer");
+ goto fail;
+ }
+ if ((ybuf = talloc_zero_array(request, uint8_t, primebytelen)) == NULL) {
+ DEBUG("unable to alloc space for y buffer");
+ goto fail;
+ }
+
+
+ /*
+ * derive random quadradic residue and quadratic non-residue
+ */
+ do {
+ BN_rand_range(qr, session->prime);
+ } while (legendre(qr, session->prime, session->bnctx) != 1);
+
+ do {
+ BN_rand_range(qnr, session->prime);
+ } while (legendre(qnr, session->prime, session->bnctx) != -1);
+
+ if (!BN_sub(rnd, session->prime, BN_value_one())) {
+ goto fail;
+ }
+ BN_bn2bin(rnd, pm1buf);
+
+ save_is_odd = 0;
+ found = 0;
+ memset(xbuf, 0, primebytelen);
+ ctr = 0;
+ while (ctr < 40) {
+ ctr++;
+
+ /*
+ * compute counter-mode password value and stretch to prime
+ * pwd-seed = H(token | peer-id | server-id | password |
+ * counter)
+ */
+ EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
+ EVP_DigestSignUpdate(hmac_ctx, (uint8_t *)token, sizeof(*token));
+ EVP_DigestSignUpdate(hmac_ctx, (uint8_t const *)id_peer, id_peer_len);
+ EVP_DigestSignUpdate(hmac_ctx, (uint8_t const *)id_server, id_server_len);
+ EVP_DigestSignUpdate(hmac_ctx, (uint8_t const *)password, password_len);
+ EVP_DigestSignUpdate(hmac_ctx, (uint8_t *)&ctr, sizeof(ctr));
+
+ {
+ size_t mdlen = SHA256_DIGEST_LENGTH;
+
+ EVP_DigestSignFinal(hmac_ctx, pwe_digest, &mdlen);
+ EVP_MD_CTX_reset(hmac_ctx);
+ }
+
+ BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd);
+ eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking",
+ strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen);
+
+ /*
+ * eap_pwd_kdf() returns a string of bits 0..primebitlen but
+ * BN_bin2bn will treat that string of bits as a big endian
+ * number. If the primebitlen is not an even multiple of 8
+ * then excessive bits-- those _after_ primebitlen-- so now
+ * we have to shift right the amount we masked off.
+ */
+ if (primebitlen % 8) {
+ rbits = 8 - (primebitlen % 8);
+ for (i = primebytelen - 1; i > 0; i--) {
+ prfbuf[i] = (prfbuf[i - 1] << (8 - rbits)) | (prfbuf[i] >> rbits);
+ }
+ prfbuf[0] >>= rbits;
+ }
+ BN_bin2bn(prfbuf, primebytelen, x_candidate);
+
+ /*
+ * it would've been better if the spec reduced the candidate
+ * modulo the prime but it didn't. So if the candidate >= prime
+ * we need to skip it but still run through the operations below
+ */
+ cmp = const_time_memcmp(pm1buf, prfbuf, primebytelen);
+ skip = const_time_fill_msb((unsigned int)cmp);
+
+ /*
+ * need to unambiguously identify the solution, if there is
+ * one..
+ */
+ is_odd = BN_is_odd(rnd);
+
+ /*
+ * check whether x^3 + a*x + b is a quadratic residue
+ *
+ * save the first quadratic residue we find in the loop but do
+ * it in constant time.
+ */
+ do_equation(session->group, y_sqrd, x_candidate, session->bnctx);
+ qr_or_qnr = is_quadratic_residue(y_sqrd, session->prime, qr, qnr, session->bnctx);
+
+ /*
+ * if the candidate >= prime then we want to skip it
+ */
+ qr_or_qnr = const_time_select(skip, 0, qr_or_qnr);
+
+ /*
+ * if we haven't found PWE yet (found = 0) then mask will be true,
+ * if we have found PWE then mask will be false
+ */
+ mask = const_time_select(found, 0, -1);
+
+ /*
+ * save will be 1 if we want to save this value-- i.e. we haven't
+ * found PWE yet and this is a quadratic residue-- and 0 otherwise
+ */
+ save = const_time_select(mask, qr_or_qnr, 0);
+
+ /*
+ * mask will be true (-1) if we want to save this and false (0)
+ * otherwise
+ */
+ mask = const_time_eq(save, 1);
+
+ const_time_select_bin(mask, prfbuf, xbuf, primebytelen, xbuf);
+ save_is_odd = const_time_select(mask, is_odd, save_is_odd);
+ found = const_time_select(mask, -1, found);
+ }
+
+ /*
+ * now we can savely construct PWE
+ */
+ BN_bin2bn(xbuf, primebytelen, x_candidate);
+ do_equation(session->group, y_sqrd, x_candidate, session->bnctx);
+ if ( !BN_add(exp, session->prime, BN_value_one()) ||
+ !BN_rshift(exp, exp, 2) ||
+ !BN_mod_exp_mont_consttime(y1, y_sqrd, exp, session->prime, session->bnctx, NULL) ||
+ !BN_sub(y2, session->prime, y1) ||
+ !BN_bn2bin(y1, y1buf) ||
+ !BN_bn2bin(y2, y2buf)) {
+ DEBUG("unable to compute y");
+ goto fail;
+ }
+ mask = const_time_eq(save_is_odd, BN_is_odd(y1));
+ const_time_select_bin(mask, y1buf, y2buf, primebytelen, ybuf);
+ if (BN_bin2bn(ybuf, primebytelen, y) == NULL ||
+ !EC_POINT_set_affine_coordinates(session->group, session->pwe, x_candidate, y, session->bnctx)) {
+ DEBUG("unable to set point coordinate");
+ goto fail;
+ }
+
+ session->group_num = grp_num;
+ if (0) {
+ fail: /* DON'T free session, it's in handler->opaque */
+ ret = -1;
+ }
+
+ /* cleanliness and order.... */
+ BN_clear_free(x_candidate);
+ BN_clear_free(y_sqrd);
+ BN_clear_free(qr);
+ BN_clear_free(qnr);
+ BN_clear_free(rnd);
+ BN_clear_free(y1);
+ BN_clear_free(y2);
+ BN_clear_free(y);
+ BN_clear_free(exp);
+
+ if (prfbuf) talloc_free(prfbuf);
+ if (xbuf) talloc_free(xbuf);
+ if (pm1buf) talloc_free(pm1buf);
+ if (y1buf) talloc_free(y1buf);
+ if (y2buf) talloc_free(y2buf);
+ if (ybuf) talloc_free(ybuf);
+
+ EVP_MD_CTX_free(hmac_ctx);
+ EVP_PKEY_free(hmac_pkey);
+
+ return ret;
+}
+
+int compute_scalar_element(REQUEST *request, pwd_session_t *session, BN_CTX *bn_ctx)
+{
+ BIGNUM *mask = NULL;
+ int ret = -1;
+
+ MEM(session->private_value = BN_new());
+ MEM(session->my_element = EC_POINT_new(session->group));
+ MEM(session->my_scalar = BN_new());
+
+ MEM(mask = BN_new());
+
+ if (BN_rand_range(session->private_value, session->order) != 1) {
+ REDEBUG("Unable to get randomness for private_value");
+ goto error;
+ }
+ if (BN_rand_range(mask, session->order) != 1) {
+ REDEBUG("Unable to get randomness for mask");
+ goto error;
+ }
+ BN_add(session->my_scalar, session->private_value, mask);
+ BN_mod(session->my_scalar, session->my_scalar, session->order, bn_ctx);
+
+ if (!EC_POINT_mul(session->group, session->my_element, NULL, session->pwe, mask, bn_ctx)) {
+ REDEBUG("Server element allocation failed");
+ goto error;
+ }
+
+ if (!EC_POINT_invert(session->group, session->my_element, bn_ctx)) {
+ REDEBUG("Server element inversion failed");
+ goto error;
+ }
+
+ ret = 0;
+
+error:
+ BN_clear_free(mask);
+
+ return ret;
+}
+
+int process_peer_commit(REQUEST *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx)
+{
+ uint8_t *ptr;
+ size_t data_len;
+ BIGNUM *x = NULL, *y = NULL, *cofactor = NULL;
+ EC_POINT *K = NULL, *point = NULL;
+ int ret = 1;
+
+ MEM(session->peer_scalar = BN_new());
+ MEM(session->k = BN_new());
+ MEM(session->peer_element = EC_POINT_new(session->group));
+ MEM(point = EC_POINT_new(session->group));
+ MEM(K = EC_POINT_new(session->group));
+
+ MEM(cofactor = BN_new());
+ MEM(x = BN_new());
+ MEM(y = BN_new());
+
+ if (!EC_GROUP_get_cofactor(session->group, cofactor, NULL)) {
+ REDEBUG("Unable to get group co-factor");
+ goto finish;
+ }
+
+ /* element, x then y, followed by scalar */
+ ptr = (uint8_t *)in;
+ data_len = BN_num_bytes(session->prime);
+
+ /*
+ * Did the peer send enough data?
+ */
+ if (in_len < (2 * data_len + BN_num_bytes(session->order))) {
+ REDEBUG("Invalid commit packet");
+ goto finish;
+ }
+
+ BN_bin2bn(ptr, data_len, x);
+ ptr += data_len;
+ BN_bin2bn(ptr, data_len, y);
+ ptr += data_len;
+
+ data_len = BN_num_bytes(session->order);
+ BN_bin2bn(ptr, data_len, session->peer_scalar);
+
+ /* validate received scalar */
+ if (BN_is_zero(session->peer_scalar) ||
+ BN_is_one(session->peer_scalar) ||
+ BN_cmp(session->peer_scalar, session->order) >= 0) {
+ REDEBUG("Peer's scalar is not within the allowed range");
+ goto finish;
+ }
+
+ if (!EC_POINT_set_affine_coordinates(session->group, session->peer_element, x, y, bn_ctx)) {
+ REDEBUG("Unable to get coordinates of peer's element");
+ goto finish;
+ }
+
+ /* validate received element */
+ if (!EC_POINT_is_on_curve(session->group, session->peer_element, bn_ctx) ||
+ EC_POINT_is_at_infinity(session->group, session->peer_element)) {
+ REDEBUG("Peer's element is not a point on the elliptic curve");
+ goto finish;
+ }
+
+ /* check to ensure peer's element is not in a small sub-group */
+ if (BN_cmp(cofactor, BN_value_one())) {
+ if (!EC_POINT_mul(session->group, point, NULL, session->peer_element, cofactor, NULL)) {
+ REDEBUG("Unable to multiply element by co-factor");
+ goto finish;
+ }
+
+ if (EC_POINT_is_at_infinity(session->group, point)) {
+ REDEBUG("Peer's element is in small sub-group");
+ goto finish;
+ }
+ }
+
+ /* detect reflection attacks */
+ if (BN_cmp(session->peer_scalar, session->my_scalar) == 0 ||
+ EC_POINT_cmp(session->group, session->peer_element, session->my_element, bn_ctx) == 0) {
+ REDEBUG("Reflection attack detected");
+ goto finish;
+ }
+
+ /* compute the shared key, k */
+ if ((!EC_POINT_mul(session->group, K, NULL, session->pwe, session->peer_scalar, bn_ctx)) ||
+ (!EC_POINT_add(session->group, K, K, session->peer_element, bn_ctx)) ||
+ (!EC_POINT_mul(session->group, K, NULL, K, session->private_value, bn_ctx))) {
+ REDEBUG("Unable to compute shared key, k");
+ goto finish;
+ }
+
+ /* ensure that the shared key isn't in a small sub-group */
+ if (BN_cmp(cofactor, BN_value_one())) {
+ if (!EC_POINT_mul(session->group, K, NULL, K, cofactor, NULL)) {
+ REDEBUG("Unable to multiply k by co-factor");
+ goto finish;
+ }
+ }
+
+ /*
+ * This check is strictly speaking just for the case above where
+ * co-factor > 1 but it was suggested that even though this is probably
+ * never going to happen it is a simple and safe check "just to be
+ * sure" so let's be safe.
+ */
+ if (EC_POINT_is_at_infinity(session->group, K)) {
+ REDEBUG("K is point-at-infinity");
+ goto finish;
+ }
+
+ if (!EC_POINT_get_affine_coordinates(session->group, K, session->k, NULL, bn_ctx)) {
+ REDEBUG("Unable to get shared secret from K");
+ goto finish;
+ }
+ ret = 0;
+
+finish:
+ EC_POINT_clear_free(K);
+ EC_POINT_clear_free(point);
+ BN_clear_free(cofactor);
+ BN_clear_free(x);
+ BN_clear_free(y);
+
+ return ret;
+}
+
+int compute_server_confirm(REQUEST *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
+{
+ BIGNUM *x = NULL, *y = NULL;
+ HMAC_CTX *hmac_ctx = NULL;
+ uint8_t *cruft = NULL;
+ int offset, req = -1;
+
+ /*
+ * Each component of the cruft will be at most as big as the prime
+ */
+ MEM(cruft = talloc_zero_array(session, uint8_t, BN_num_bytes(session->prime)));
+ MEM(x = BN_new());
+ MEM(y = BN_new());
+
+ /*
+ * commit is H(k | server_element | server_scalar | peer_element |
+ * peer_scalar | ciphersuite)
+ */
+ MEM(hmac_ctx = HMAC_CTX_new());
+ HMAC_Init_ex(hmac_ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256(), NULL);
+
+ /*
+ * Zero the memory each time because this is mod prime math and some
+ * value may start with a few zeros and the previous one did not.
+ *
+ * First is k
+ */
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(session->k);
+ BN_bn2bin(session->k, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ /*
+ * next is server element: x, y
+ */
+ if (!EC_POINT_get_affine_coordinates(session->group, session->my_element, x, y, bn_ctx)) {
+ REDEBUG("Unable to get coordinates of server element");
+ goto finish;
+ }
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ /*
+ * and server scalar
+ */
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar);
+ BN_bn2bin(session->my_scalar, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->order));
+
+ /*
+ * next is peer element: x, y
+ */
+ if (!EC_POINT_get_affine_coordinates(session->group, session->peer_element, x, y, bn_ctx)) {
+ REDEBUG("Unable to get coordinates of peer's element");
+ goto finish;
+ }
+
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ /*
+ * and peer scalar
+ */
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->order) - BN_num_bytes(session->peer_scalar);
+ BN_bn2bin(session->peer_scalar, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->order));
+
+ /*
+ * finally, ciphersuite
+ */
+ HMAC_Update(hmac_ctx, (uint8_t *)&session->ciphersuite, sizeof(session->ciphersuite));
+
+ pwd_hmac_final(hmac_ctx, out);
+
+ req = 0;
+
+finish:
+ HMAC_CTX_free(hmac_ctx);
+ talloc_free(cruft);
+ BN_free(x);
+ BN_free(y);
+
+ return req;
+}
+
+int compute_peer_confirm(REQUEST *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
+{
+ BIGNUM *x = NULL, *y = NULL;
+ HMAC_CTX *hmac_ctx = NULL;
+ uint8_t *cruft = NULL;
+ int offset, req = -1;
+
+ /*
+ * Each component of the cruft will be at most as big as the prime
+ */
+ MEM(cruft = talloc_zero_array(session, uint8_t, BN_num_bytes(session->prime)));
+ MEM(x = BN_new());
+ MEM(y = BN_new());
+
+ /*
+ * commit is H(k | server_element | server_scalar | peer_element |
+ * peer_scalar | ciphersuite)
+ */
+ MEM(hmac_ctx = HMAC_CTX_new());
+ HMAC_Init_ex(hmac_ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256(), NULL);
+
+ /*
+ * Zero the memory each time because this is mod prime math and some
+ * value may start with a few zeros and the previous one did not.
+ *
+ * First is k
+ */
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(session->k);
+ BN_bn2bin(session->k, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ /*
+ * then peer element: x, y
+ */
+ if (!EC_POINT_get_affine_coordinates(session->group, session->peer_element, x, y, bn_ctx)) {
+ REDEBUG("Unable to get coordinates of peer's element");
+ goto finish;
+ }
+
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ /*
+ * and peer scalar
+ */
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->order) - BN_num_bytes(session->peer_scalar);
+ BN_bn2bin(session->peer_scalar, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->order));
+
+ /*
+ * then server element: x, y
+ */
+ if (!EC_POINT_get_affine_coordinates(session->group, session->my_element, x, y, bn_ctx)) {
+ REDEBUG("Unable to get coordinates of server element");
+ goto finish;
+ }
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ /*
+ * and server scalar
+ */
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar);
+ BN_bn2bin(session->my_scalar, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->order));
+
+ /*
+ * finally, ciphersuite
+ */
+ HMAC_Update(hmac_ctx, (uint8_t *)&session->ciphersuite, sizeof(session->ciphersuite));
+
+ pwd_hmac_final(hmac_ctx, out);
+
+ req = 0;
+finish:
+ HMAC_CTX_free(hmac_ctx);
+ talloc_free(cruft);
+ BN_free(x);
+ BN_free(y);
+
+ return req;
+}
+
+int compute_keys(UNUSED REQUEST *request, pwd_session_t *session, uint8_t *peer_confirm, uint8_t *msk, uint8_t *emsk)
+{
+ HMAC_CTX *hmac_ctx;
+ uint8_t mk[SHA256_DIGEST_LENGTH], *cruft;
+ uint8_t session_id[SHA256_DIGEST_LENGTH + 1];
+ uint8_t msk_emsk[128]; /* 64 each */
+ int offset;
+
+ MEM(cruft = talloc_array(session, uint8_t, BN_num_bytes(session->prime)));
+ MEM(hmac_ctx = HMAC_CTX_new());
+
+ /*
+ * first compute the session-id = TypeCode | H(ciphersuite | scal_p |
+ * scal_s)
+ */
+ session_id[0] = PW_EAP_PWD;
+ HMAC_Init_ex(hmac_ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256(), NULL);
+ HMAC_Update(hmac_ctx, (uint8_t *)&session->ciphersuite, sizeof(session->ciphersuite));
+ offset = BN_num_bytes(session->order) - BN_num_bytes(session->peer_scalar);
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ BN_bn2bin(session->peer_scalar, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->order));
+ offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar);
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ BN_bn2bin(session->my_scalar, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->order));
+ pwd_hmac_final(hmac_ctx, (uint8_t *)&session_id[1]);
+
+ /* then compute MK = H(k | commit-peer | commit-server) */
+ HMAC_Init_ex(hmac_ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256(), NULL);
+
+ memset(cruft, 0, BN_num_bytes(session->prime));
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(session->k);
+ BN_bn2bin(session->k, cruft + offset);
+ HMAC_Update(hmac_ctx, cruft, BN_num_bytes(session->prime));
+
+ HMAC_Update(hmac_ctx, peer_confirm, SHA256_DIGEST_LENGTH);
+
+ HMAC_Update(hmac_ctx, session->my_confirm, SHA256_DIGEST_LENGTH);
+
+ pwd_hmac_final(hmac_ctx, mk);
+
+ /* stretch the mk with the session-id to get MSK | EMSK */
+ eap_pwd_kdf(mk, SHA256_DIGEST_LENGTH, (char const *)session_id,
+ SHA256_DIGEST_LENGTH + 1, msk_emsk, 1024); /* it's bits, ((64 + 64) * 8) */
+
+ memcpy(msk, msk_emsk, 64);
+ memcpy(emsk, msk_emsk + 64, 64);
+
+ HMAC_CTX_free(hmac_ctx);
+ talloc_free(cruft);
+ return 0;
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.h b/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.h
new file mode 100644
index 0000000..a40a346
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/eap_pwd.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) Dan Harkins, 2012
+ *
+ * Copyright holder grants permission for redistribution and use in source
+ * and binary forms, with or without modification, provided that the
+ * following conditions are met:
+ * 1. Redistribution of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in all source files.
+ * 2. Redistribution in binary form must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * "DISCLAIMER OF LIABILITY
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAN HARKINS ``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 INDUSTRIAL LOUNGE 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."
+ *
+ * This license and distribution terms cannot be changed. In other words,
+ * this code cannot simply be copied and put under a different distribution
+ * license (including the GNU public license).
+ */
+
+#ifndef _EAP_PWD_H
+#define _EAP_PWD_H
+
+RCSIDH(eap_pwd_h, "$Id$")
+#include "eap.h"
+
+#include <openssl/bn.h>
+#include <openssl/sha.h>
+#include <openssl/ec.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+typedef struct _pwd_hdr {
+ uint8_t lm_exchange;
+#define EAP_PWD_EXCH_ID 1
+#define EAP_PWD_EXCH_COMMIT 2
+#define EAP_PWD_EXCH_CONFIRM 3
+// uint16_t total_length; /* there if the L-bit is set */
+ uint8_t data[];
+} CC_HINT(packed) pwd_hdr;
+
+#define EAP_PWD_GET_LENGTH_BIT(x) ((x)->lm_exchange & 0x80)
+#define EAP_PWD_SET_LENGTH_BIT(x) ((x)->lm_exchange |= 0x80)
+#define EAP_PWD_GET_MORE_BIT(x) ((x)->lm_exchange & 0x40)
+#define EAP_PWD_SET_MORE_BIT(x) ((x)->lm_exchange |= 0x40)
+#define EAP_PWD_GET_EXCHANGE(x) ((x)->lm_exchange & 0x3f)
+#define EAP_PWD_SET_EXCHANGE(x,y) ((x)->lm_exchange |= (y))
+
+typedef struct _pwd_id_packet {
+ uint16_t group_num;
+ uint8_t random_function;
+#define EAP_PWD_DEF_RAND_FUN 1
+ uint8_t prf;
+#define EAP_PWD_DEF_PRF 1
+ uint8_t token[4];
+ uint8_t prep;
+#define EAP_PWD_PREP_NONE 0
+#define EAP_PWD_PREP_MS 1
+#define EAP_PWD_PREP_SASL 2
+ char identity[];
+} CC_HINT(packed) pwd_id_packet_t;
+
+typedef struct _pwd_session_t {
+ uint16_t state;
+#define PWD_STATE_ID_REQ 1
+#define PWD_STATE_COMMIT 2
+#define PWD_STATE_CONFIRM 3
+ uint16_t group_num;
+ uint32_t ciphersuite;
+ uint32_t token;
+ char peer_id[MAX_STRING_LEN];
+ size_t peer_id_len;
+ size_t mtu;
+ uint8_t *in; /* reassembled fragments */
+ size_t in_pos;
+ size_t in_len;
+ uint8_t *out; /* message to fragment */
+ size_t out_pos;
+ size_t out_len;
+ BN_CTX *bnctx;
+ EC_GROUP *group;
+ EC_POINT *pwe;
+ BIGNUM *order;
+ BIGNUM *prime;
+ BIGNUM *k;
+ BIGNUM *private_value;
+ BIGNUM *peer_scalar;
+ BIGNUM *my_scalar;
+ EC_POINT *my_element;
+ EC_POINT *peer_element;
+ uint8_t my_confirm[SHA256_DIGEST_LENGTH];
+ uint8_t prep;
+ uint8_t salt_present;
+ uint8_t salt_len;
+ uint8_t salt[255];
+} pwd_session_t;
+
+int compute_password_element(REQUEST *request, pwd_session_t *sess, uint16_t grp_num,
+ char const *password, int password_len,
+ char const *id_server, int id_server_len,
+ char const *id_peer, int id_peer_len,
+ uint32_t *token);
+int compute_scalar_element(REQUEST *request, pwd_session_t *sess, BN_CTX *bnctx);
+int process_peer_commit(REQUEST *request, pwd_session_t *sess, uint8_t *in, size_t in_len, BN_CTX *bnctx);
+int compute_server_confirm(REQUEST *request, pwd_session_t *sess, uint8_t *out, BN_CTX *bnctx);
+int compute_peer_confirm(REQUEST *request, pwd_session_t *sess, uint8_t *out, BN_CTX *bnctx);
+int compute_keys(REQUEST *request, pwd_session_t *sess, uint8_t *peer_confirm,
+ uint8_t *msk, uint8_t *emsk);
+#ifdef PRINTBUF
+void print_buf(char *str, uint8_t *buf, int len);
+#endif /* PRINTBUF */
+
+#endif /* _EAP_PWD_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c b/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c
new file mode 100644
index 0000000..4992a2a
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c
@@ -0,0 +1,972 @@
+/*
+ * Copyright (c) Dan Harkins, 2012
+ *
+ * Copyright holder grants permission for redistribution and use in source
+ * and binary forms, with or without modification, provided that the
+ * following conditions are met:
+ * 1. Redistribution of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in all source files.
+ * 2. Redistribution in binary form must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * "DISCLAIMER OF LIABILITY
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAN HARKINS ``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 INDUSTRIAL LOUNGE 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."
+ *
+ * This license and distribution terms cannot be changed. In other words,
+ * this code cannot simply be copied and put under a different distribution
+ * license (including the GNU public license).
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include "rlm_eap_pwd.h"
+
+#include "eap_pwd.h"
+
+#define MPPE_KEY_LEN 32
+#define MSK_EMSK_LEN (2*MPPE_KEY_LEN)
+
+/* EAP-PWD can use different preprocessing (prep) modes to mangle the password
+ * before proving to both parties that they both know the same (mangled) password.
+ *
+ * The server advertises a preprocessing mode to the client. Only "none" is
+ * mandatory to implement.
+ *
+ * What is a good selection on the preprocessing mode?
+ *
+ * a) the server uses a hashed password
+ * b) the client uses a hashed password
+ *
+ * a | b | result
+ * --+---+---------------------------------------
+ * n | n | none
+ * n | y | hint needed (cannot know automatically)
+ * y | n | select by hash given
+ * y | y | only works if both have the same hash; select by hash given
+ *
+ * Which hash functions does the server or client need to implement?
+ *
+ * a | b | server | client
+ * --+---+------------------------+----------------------
+ * n | n | none | none
+ * n | y | as configured | none
+ * y | n | none | as selected by server
+ * y | y | none | none
+ *
+ * RFC 5931 defines 3 and RFC 8146 another 8 hash functions to implement.
+ * Can we avoid implementing them all? Only if they are provided as hash by some
+ * other module, e.g. in SQL or statically in password database.
+ *
+ * Therefore we select the preprocessing mode by the type of password given if
+ * in automatic mode:
+ * a) Cleartext-Password or User-Password: None.
+ * If the client only supports a hash (e.g. on Windows it might only have an
+ * NT-Password), do not provide a Cleartext-Password attribute but instead
+ * preprocess the password externally (e.g. hash the Cleartext-Password
+ * into an NT-Password and drop the Cleartext-Password).
+ * b) NT-Password: rfc2759 (prep=MS).
+ * The NT-Password Hash is hashed into a HashNTPasswordHash hash.
+ * c) EAP-Pwd-Password-Hash - provides hash as binary
+ * EAP-Pwd-Password-Salt - (optional) salt to be transmitted to client
+ * (RFC 8146)
+ * EAP-Pwd-Password-Prep - constant to transmit to client in prep field
+ *
+ * Though, there is one issue left. The method needs to be selected in
+ * EAP-PWD-ID/Request, that is the first message from server and thus before
+ * the client sent its peer-id. This is feasable using the EAP-Identity frame
+ * (outer identity); EAP-PWD does transmit its peer-id in plaintext anyway.
+ * So we need a toggle for this, in case anybody needs rlm_eap_pwd to use
+ * only the peer_id (inner identity). This toogle is an integer to also support
+ * setting currently unknown nor not implemented preprocessing methods.
+ *
+ * The toogle is named "prep", is a module configuration item, and accepts the
+ * following values:
+ * prep | meaning
+ * -------+--------------------------------------------------------------------
+ * -1 | [automatic] discover using method described above from EAP-Identity
+ * | as User-Name before EAP-PWD-Id/Request
+ * 0..255 | [static] Fixed password preprocessing method. Expects virtual
+ * | server to provide matching password given EAP-PWD
+ * | peer-id as User-Name. The virtual server is provided
+ * | with EAP-Pwd-Password-Prep containing the configured
+ * | prep value.
+ * else | reserved/invalid
+ *
+ * Attributes to provide Password/Password-Hash and possibly salt.
+ * prep | accepted attributes
+ * -------+--------------------------------------------------------------------
+ * -1 | see above for automatic discovery
+ * 0 | Use Cleartext-Password or give cleartext in EAP-Pwd-Password-Hash
+ * 1 | Use NT-Password, Cleartext-Password, User-Password or
+ * | give hashed NT-Password hash in EAP-Pwd-Password-Hash
+ * 2..255 | Use EAP-Pwd-Password-Hash and possibly EAP-Pwd-Pasword-Salt.
+ *
+ * To be able to pass EAP-Pwd-Password-Hash and EAP-Pwd-Password-Salt als hex
+ * string, they are decoded as hex if module config option unhex=1 (default).
+ * Set it to zero if you provide binary input.
+ */
+
+static CONF_PARSER pwd_module_config[] = {
+ { "group", FR_CONF_OFFSET(PW_TYPE_INTEGER, eap_pwd_t, group), "19" },
+ { "fragment_size", FR_CONF_OFFSET(PW_TYPE_INTEGER, eap_pwd_t, fragment_size), "1020" },
+ { "server_id", FR_CONF_OFFSET(PW_TYPE_STRING, eap_pwd_t, server_id), NULL },
+ { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, eap_pwd_t, virtual_server), NULL },
+ { "prep", FR_CONF_OFFSET(PW_TYPE_SIGNED, eap_pwd_t, prep), "0" },
+ { "unhex", FR_CONF_OFFSET(PW_TYPE_SIGNED, eap_pwd_t, unhex), "1" },
+ CONF_PARSER_TERMINATOR
+};
+
+static int mod_instantiate (CONF_SECTION *cs, void **instance)
+{
+ eap_pwd_t *inst;
+
+ *instance = inst = talloc_zero(cs, eap_pwd_t);
+ if (!inst) return -1;
+
+ if (cf_section_parse(cs, inst, pwd_module_config) < 0) {
+ return -1;
+ }
+
+ if (inst->fragment_size < 100) {
+ cf_log_err_cs(cs, "Fragment size is too small");
+ return -1;
+ }
+
+ if (inst->prep < -1 || inst->prep > 255) {
+ cf_log_err_cs(cs, "Invalid value for password preparation method: %d", inst->prep);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _free_pwd_session (pwd_session_t *session)
+{
+ BN_clear_free(session->private_value);
+ BN_clear_free(session->peer_scalar);
+ BN_clear_free(session->my_scalar);
+ BN_clear_free(session->k);
+ EC_POINT_clear_free(session->my_element);
+ EC_POINT_clear_free(session->peer_element);
+ EC_GROUP_free(session->group);
+ EC_POINT_clear_free(session->pwe);
+ BN_clear_free(session->order);
+ BN_clear_free(session->prime);
+ BN_CTX_free(session->bnctx);
+
+ return 0;
+}
+
+static int send_pwd_request (pwd_session_t *session, EAP_DS *eap_ds)
+{
+ size_t len;
+ uint16_t totlen;
+ pwd_hdr *hdr;
+
+ len = (session->out_len - session->out_pos) + sizeof(pwd_hdr);
+ rad_assert(len > 0);
+ eap_ds->request->code = PW_EAP_REQUEST;
+ eap_ds->request->type.num = PW_EAP_PWD;
+ eap_ds->request->type.length = (len > session->mtu) ? session->mtu : len;
+ eap_ds->request->type.data = talloc_zero_array(eap_ds->request, uint8_t, eap_ds->request->type.length);
+ hdr = (pwd_hdr *)eap_ds->request->type.data;
+
+ switch (session->state) {
+ case PWD_STATE_ID_REQ:
+ EAP_PWD_SET_EXCHANGE(hdr, EAP_PWD_EXCH_ID);
+ break;
+
+ case PWD_STATE_COMMIT:
+ EAP_PWD_SET_EXCHANGE(hdr, EAP_PWD_EXCH_COMMIT);
+ break;
+
+ case PWD_STATE_CONFIRM:
+ EAP_PWD_SET_EXCHANGE(hdr, EAP_PWD_EXCH_CONFIRM);
+ break;
+
+ default:
+ ERROR("rlm_eap_pwd: PWD state is invalid. Can't send request");
+ return 0;
+ }
+ /*
+ * are we fragmenting?
+ */
+ if (((session->out_len - session->out_pos) + sizeof(pwd_hdr)) > session->mtu) {
+ EAP_PWD_SET_MORE_BIT(hdr);
+ if (session->out_pos == 0) {
+ /*
+ * the first fragment, add the total length
+ */
+ EAP_PWD_SET_LENGTH_BIT(hdr);
+ totlen = ntohs(session->out_len);
+ memcpy(hdr->data, (char *)&totlen, sizeof(totlen));
+ memcpy(hdr->data + sizeof(uint16_t),
+ session->out,
+ session->mtu - sizeof(pwd_hdr) - sizeof(uint16_t));
+ session->out_pos += (session->mtu - sizeof(pwd_hdr) - sizeof(uint16_t));
+ } else {
+ /*
+ * an intermediate fragment
+ */
+ memcpy(hdr->data, session->out + session->out_pos, (session->mtu - sizeof(pwd_hdr)));
+ session->out_pos += (session->mtu - sizeof(pwd_hdr));
+ }
+ } else {
+ /*
+ * either it's not a fragment or it's the last fragment.
+ * The out buffer isn't needed anymore though so get rid of it.
+ */
+ memcpy(hdr->data, session->out + session->out_pos,
+ (session->out_len - session->out_pos));
+ talloc_free(session->out);
+ session->out = NULL;
+ session->out_pos = session->out_len = 0;
+ }
+ return 1;
+}
+
+static void normify(REQUEST *request, VALUE_PAIR *vp)
+{
+ size_t decoded;
+ size_t expected_len;
+ uint8_t *buffer;
+
+ rad_assert((vp->da->type == PW_TYPE_OCTETS) || (vp->da->type == PW_TYPE_STRING));
+
+ if (vp->vp_length % 2 != 0 || vp->vp_length == 0) return;
+
+ expected_len = vp->vp_length / 2;
+ buffer = talloc_zero_array(request, uint8_t, expected_len);
+ rad_assert(buffer);
+
+ decoded = fr_hex2bin(buffer, expected_len, vp->vp_strvalue, vp->vp_length);
+ if (decoded == expected_len) {
+ RDEBUG2("Normalizing %s from hex encoding, %zu bytes -> %zu bytes",
+ vp->da->name, vp->vp_length, decoded);
+ fr_pair_value_memcpy(vp, buffer, decoded);
+ } else {
+ RDEBUG2("Normalizing %s from hex encoding, %zu bytes -> %zu bytes failed, got %zu bytes",
+ vp->da->name, vp->vp_length, expected_len, decoded);
+ }
+
+ talloc_free(buffer);
+}
+
+static int fetch_and_process_password(pwd_session_t *session, REQUEST *request, eap_pwd_t *inst) {
+ REQUEST *fake;
+ VALUE_PAIR *vp, *pw;
+ const char *pwbuf;
+ int pw_len;
+ uint8_t nthash[MD4_DIGEST_LENGTH];
+ uint8_t nthashash[MD4_DIGEST_LENGTH];
+ int ret = -1;
+ eap_type_t old_eap_type = 0;
+
+ if ((fake = request_alloc_fake(request)) == NULL) {
+ RDEBUG("pwd unable to create fake request!");
+ return ret;
+ }
+ fake->username = fr_pair_afrom_num(fake->packet, PW_USER_NAME, 0);
+ if (!fake->username) {
+ RDEBUG("Failed creating pair for peer id");
+ goto out;
+ }
+ fr_pair_value_bstrncpy(fake->username, session->peer_id, session->peer_id_len);
+ fr_pair_add(&fake->packet->vps, fake->username);
+
+ if (inst->prep >= 0) {
+ vp = fr_pair_afrom_num(fake->packet, PW_EAP_PWD_PASSWORD_PREP, 0);
+ rad_assert(vp != NULL);
+ vp->vp_byte = inst->prep;
+ fr_pair_add(&fake->packet->vps, vp);
+ }
+
+ if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
+ fake->server = vp->vp_strvalue;
+ } else if (inst->virtual_server) {
+ fake->server = inst->virtual_server;
+ } /* else fake->server == request->server */
+
+ if ((vp = fr_pair_find_by_num(request->packet->vps, PW_EAP_TYPE, 0, TAG_ANY)) != NULL) {
+ /* EAP-Type = NAK here if inst->prep == -1.
+ * But this does not help the virtual server to differentiate
+ * based on which EAP method was selected, that is to properly
+ * prepare session-state: for PWD.
+ * So fake EAP-Type = PWD here for the time of the inner request.
+ */
+ old_eap_type = vp->vp_integer;
+ vp->vp_integer = PW_EAP_PWD;
+ }
+ RDEBUG("Sending tunneled request");
+ rdebug_pair_list(L_DBG_LVL_1, request, fake->packet->vps, NULL);
+
+ if (fake->server) {
+ RDEBUG("server %s {", fake->server);
+ } else {
+ RDEBUG("server {");
+ }
+
+ /*
+ * Call authorization recursively, which will
+ * get the password.
+ */
+ RINDENT();
+ process_authorize(0, fake);
+ REXDENT();
+
+ /*
+ * Note that we don't do *anything* with the reply
+ * attributes.
+ */
+ if (fake->server) {
+ RDEBUG("} # server %s", fake->server);
+ } else {
+ RDEBUG("}");
+ }
+
+ RDEBUG("Got tunneled reply code %d", fake->reply->code);
+ rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);
+
+ if (old_eap_type && (vp = fr_pair_find_by_num(request->packet->vps, PW_EAP_TYPE, 0, TAG_ANY)) != NULL) {
+ vp->vp_integer = old_eap_type;
+ }
+
+ pw = fr_pair_find_by_num(fake->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
+ if (!pw) {
+ pw = fr_pair_find_by_num(fake->config, PW_USER_PASSWORD, 0, TAG_ANY);
+ }
+
+ if (pw && (inst->prep < 0 || inst->prep == EAP_PWD_PREP_NONE)) {
+ VERIFY_VP(pw);
+ session->prep = EAP_PWD_PREP_NONE;
+
+ RDEBUG("Use Cleartext-Password or User-Password for %s to do pwd authentication",
+ session->peer_id);
+
+ pwbuf = pw->vp_strvalue;
+ pw_len = pw->vp_length;
+
+ goto success;
+ }
+
+ pw = fr_pair_find_by_num(fake->config, PW_NT_PASSWORD, 0, TAG_ANY);
+
+ if (pw && (inst->prep < 0 || inst->prep == EAP_PWD_PREP_MS)) {
+ VERIFY_VP(pw);
+ session->prep = EAP_PWD_PREP_MS;
+
+ RDEBUG("Use NT-Password for %s to do pwd authentication",
+ session->peer_id);
+
+ if (pw->vp_length != MD4_DIGEST_LENGTH) {
+ RDEBUG("NT-Password invalid length");
+ goto out;
+ }
+
+ fr_md4_calc(nthashash, pw->vp_octets, pw->vp_length);
+ pwbuf = (const char*) nthashash;
+ pw_len = MD4_DIGEST_LENGTH;
+
+ goto success;
+ }
+
+ pw = fr_pair_find_by_num(fake->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
+ if (!pw) {
+ pw = fr_pair_find_by_num(fake->config, PW_USER_PASSWORD, 0, TAG_ANY);
+ }
+
+ if (pw && inst->prep == EAP_PWD_PREP_MS) {
+ VERIFY_VP(pw);
+ session->prep = EAP_PWD_PREP_NONE;
+
+ RDEBUG("Use Cleartext-Password or User-Password as NT-Password for %s to do pwd authentication",
+ session->peer_id);
+
+ // compute NT-Hash from Cleartext-Password
+ ssize_t len;
+ uint8_t ucs2_password[512];
+ len = fr_utf8_to_ucs2(ucs2_password, sizeof(ucs2_password), pw->vp_strvalue, pw->vp_length);
+ if (len < 0) {
+ ERROR("rlm_eap_pwd: Error converting password to UCS2");
+ goto out;
+ }
+ fr_md4_calc(nthash, ucs2_password, len);
+
+ fr_md4_calc(nthashash, nthash, MD4_DIGEST_LENGTH);
+ pwbuf = (const char*) nthashash;
+ pw_len = MD4_DIGEST_LENGTH;
+
+ goto success;
+ }
+
+ vp = fr_pair_find_by_num(fake->config, PW_EAP_PWD_PASSWORD_PREP, 0, TAG_ANY);
+ if (vp) {
+ VERIFY_VP(vp);
+ }
+ if (vp && inst->prep < 0) {
+ RDEBUG("Use EAP-Pwd-Password-Prep %u for %s to do pwd authentication",
+ vp->vp_byte, session->peer_id);
+ session->prep = vp->vp_byte;
+ } else if (vp && inst->prep != vp->vp_byte) {
+ RDEBUG2("Mismatch of configured password preparation method and provided EAP-Pwd-Password-Prep attribute type for %s",
+ session->peer_id);
+ goto out;
+ } else if (inst->prep < 0) {
+ RDEBUG2("Missing EAP-Pwd-Password-Prep for %s",
+ session->peer_id);
+ goto out;
+ }
+
+ pw = fr_pair_find_by_num(fake->config, PW_EAP_PWD_PASSWORD_SALT, 0, TAG_ANY);
+ if (pw) {
+ VERIFY_VP(pw);
+
+ RDEBUG("Use EAP-Pwd-Password-Salt for %s to do pwd authentication",
+ session->peer_id);
+
+ if (inst->unhex) normify(request, pw);
+
+ if (pw->vp_length > 255) {
+ /* salt len is 1 byte */
+ RDEBUG("EAP-Pwd-Password-Salt too long (more than 255 octets)");
+ goto out;
+ }
+ rad_assert(pw->vp_length <= sizeof(session->salt));
+
+ session->salt_present = 1;
+ session->salt_len = pw->vp_length;
+ memcpy(session->salt, pw->vp_octets, pw->vp_length);
+ }
+
+ pw = fr_pair_find_by_num(fake->config, PW_EAP_PWD_PASSWORD_HASH, 0, TAG_ANY);
+ if (pw) {
+ VERIFY_VP(pw);
+
+ RDEBUG("Use EAP-Pwd-Password-Hash for %s to do pwd authentication",
+ session->peer_id);
+
+ if (inst->unhex) normify(request, pw);
+
+ pwbuf = (const char*) pw->vp_octets;
+ pw_len = pw->vp_length;
+
+ goto success;
+ }
+
+ RDEBUG2("Mismatch of password preparation method and provided password attribute type for %s",
+ session->peer_id);
+ goto out;
+
+success:
+ if (RDEBUG_ENABLED4) {
+ char outbuf[1024];
+ char *p = outbuf;
+ for (int i = 0; i < pw_len && p < outbuf + sizeof(outbuf) - 3; i++) {
+ p += sprintf(p, "%02hhX", pwbuf[i]);
+ }
+ RDEBUG4("hex pw data: %s (%d)", outbuf, pw_len);
+ }
+
+ if (compute_password_element(request, session, session->group_num,
+ pwbuf, pw_len,
+ inst->server_id, strlen(inst->server_id),
+ session->peer_id, strlen(session->peer_id),
+ &session->token)) {
+ RDEBUG("failed to obtain password element");
+ goto out;
+ }
+
+ ret = 0;
+out:
+ talloc_free(fake);
+ return ret;
+}
+
+static int mod_session_init (void *instance, eap_handler_t *handler)
+{
+ pwd_session_t *session;
+ eap_pwd_t *inst = (eap_pwd_t *)instance;
+ VALUE_PAIR *vp;
+ pwd_id_packet_t *packet;
+ REQUEST *request;
+
+ if (!inst || !handler) {
+ ERROR("rlm_eap_pwd: Initiate, NULL data provided");
+ return 0;
+ }
+
+ request = handler->request;
+ if (!request) {
+ ERROR("rlm_eap_pwd: NULL request provided");
+ return 0;
+ }
+
+ /*
+ * make sure the server's been configured properly
+ */
+ if (!inst->server_id) {
+ ERROR("rlm_eap_pwd: Server ID is not configured");
+ return 0;
+ }
+ switch (inst->group) {
+ case 19:
+ case 20:
+ case 21:
+ case 25:
+ case 26:
+ break;
+
+ default:
+ ERROR("rlm_eap_pwd: Group is not supported");
+ return 0;
+ }
+
+ if ((session = talloc_zero(handler, pwd_session_t)) == NULL) return 0;
+ talloc_set_destructor(session, _free_pwd_session);
+ /*
+ * set things up so they can be free'd reliably
+ */
+ session->group_num = inst->group;
+ session->private_value = NULL;
+ session->peer_scalar = NULL;
+ session->my_scalar = NULL;
+ session->k = NULL;
+ session->my_element = NULL;
+ session->peer_element = NULL;
+ session->group = NULL;
+ session->pwe = NULL;
+ session->order = NULL;
+ session->prime = NULL;
+
+ session->bnctx = BN_CTX_new();
+ if (session->bnctx == NULL) {
+ ERROR("rlm_eap_pwd: Failed to get BN context");
+ return 0;
+ }
+
+ /*
+ * The admin can dynamically change the MTU.
+ */
+ session->mtu = inst->fragment_size;
+ vp = fr_pair_find_by_num(handler->request->packet->vps, PW_FRAMED_MTU, 0, TAG_ANY);
+
+ /*
+ * session->mtu is *our* MTU. We need to subtract off the EAP
+ * overhead.
+ *
+ * 9 = 4 (EAPOL header) + 4 (EAP header) + 1 (EAP type)
+ *
+ * The fragmentation code deals with the included length
+ * so we don't need to subtract that here.
+ */
+ if (vp && (vp->vp_integer > 100) && (vp->vp_integer < session->mtu)) {
+ session->mtu = vp->vp_integer - 9;
+ }
+
+ session->state = PWD_STATE_ID_REQ;
+ session->in = NULL;
+ session->out_pos = 0;
+ handler->opaque = session;
+
+ session->token = fr_rand();
+ if (inst->prep < 0) {
+ RDEBUG2("using outer identity %s to configure EAP-PWD", handler->identity);
+ session->peer_id_len = strlen(handler->identity);
+ if (session->peer_id_len >= sizeof(session->peer_id)) {
+ RDEBUG("identity is malformed");
+ return 0;
+ }
+ memcpy(session->peer_id, handler->identity, session->peer_id_len);
+ session->peer_id[session->peer_id_len] = '\0';
+
+ /*
+ * make fake request to get the password for the usable ID
+ * in order to identity prep
+ */
+ if (fetch_and_process_password(session, handler->request, inst) < 0) {
+ RDEBUG("failed to find password for %s to do pwd authentication (init)",
+ session->peer_id);
+ return 0;
+ }
+ } else {
+ session->prep = inst->prep;
+ }
+
+ /*
+ * construct an EAP-pwd-ID/Request
+ */
+ session->out_len = sizeof(pwd_id_packet_t) + strlen(inst->server_id);
+ if ((session->out = talloc_zero_array(session, uint8_t, session->out_len)) == NULL) {
+ return 0;
+ }
+
+ packet = (pwd_id_packet_t *)session->out;
+ packet->group_num = htons(session->group_num);
+ packet->random_function = EAP_PWD_DEF_RAND_FUN;
+ packet->prf = EAP_PWD_DEF_PRF;
+ memcpy(packet->token, (char *)&session->token, 4);
+ packet->prep = session->prep;
+ memcpy(packet->identity, inst->server_id, session->out_len - sizeof(pwd_id_packet_t) );
+
+ handler->stage = PROCESS;
+
+ return send_pwd_request(session, handler->eap_ds);
+}
+
+static int mod_process(void *arg, eap_handler_t *handler)
+{
+ pwd_session_t *session;
+ pwd_hdr *hdr;
+ pwd_id_packet_t *packet;
+ REQUEST *request;
+ eap_packet_t *response;
+ EAP_DS *eap_ds;
+ size_t in_len, peer_id_len;
+ int ret = 0;
+ eap_pwd_t *inst = (eap_pwd_t *)arg;
+ uint16_t offset;
+ uint8_t exch, *in, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN];
+ uint8_t peer_confirm[SHA256_DIGEST_LENGTH];
+ char *peer_id;
+
+ if (((eap_ds = handler->eap_ds) == NULL) || !inst) return 0;
+
+ session = (pwd_session_t *)handler->opaque;
+ request = handler->request;
+ response = handler->eap_ds->response;
+ hdr = (pwd_hdr *)response->type.data;
+
+ /*
+ * The header must be at least one byte.
+ */
+ if (!hdr || (response->type.length < sizeof(pwd_hdr))) {
+ RDEBUG("Packet with insufficient data");
+ return 0;
+ }
+
+ in = hdr->data;
+ in_len = response->type.length - sizeof(pwd_hdr);
+
+ /*
+ * see if we're fragmenting, if so continue until we're done
+ */
+ if (session->out_pos) {
+ if (in_len) RDEBUG2("pwd got something more than an ACK for a fragment");
+
+ return send_pwd_request(session, eap_ds);
+ }
+
+ /*
+ * the first fragment will have a total length, make a
+ * buffer to hold all the fragments
+ */
+ if (EAP_PWD_GET_LENGTH_BIT(hdr)) {
+ if (session->in) {
+ RDEBUG2("pwd already alloced buffer for fragments");
+ return 0;
+ }
+
+ if (in_len < 2) {
+ RDEBUG("Invalid packet: length bit set, but no length field");
+ return 0;
+ }
+
+ session->in_len = ntohs(in[0] * 256 | in[1]);
+ if ((session->in = talloc_zero_array(session, uint8_t, session->in_len)) == NULL) {
+ RDEBUG2("pwd cannot allocate %zd buffer to hold fragments",
+ session->in_len);
+ return 0;
+ }
+ memset(session->in, 0, session->in_len);
+ session->in_pos = 0;
+ in += sizeof(uint16_t);
+ in_len -= sizeof(uint16_t);
+ }
+
+ /*
+ * all fragments, including the 1st will have the M(ore) bit set,
+ * buffer those fragments!
+ */
+ if (EAP_PWD_GET_MORE_BIT(hdr)) {
+ if (!session->in) {
+ RDEBUG2("Unexpected fragment.");
+ return 0;
+ }
+
+ if ((session->in_pos + in_len) > session->in_len) {
+ RDEBUG2("Fragment overflows packet.");
+ return 0;
+ }
+
+ memcpy(session->in + session->in_pos, in, in_len);
+ session->in_pos += in_len;
+
+ /*
+ * send back an ACK for this fragment
+ */
+ exch = EAP_PWD_GET_EXCHANGE(hdr);
+ eap_ds->request->code = PW_EAP_REQUEST;
+ eap_ds->request->type.num = PW_EAP_PWD;
+ eap_ds->request->type.length = sizeof(pwd_hdr);
+ if ((eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, sizeof(pwd_hdr))) == NULL) {
+ return 0;
+ }
+ hdr = (pwd_hdr *)eap_ds->request->type.data;
+ EAP_PWD_SET_EXCHANGE(hdr, exch);
+ return 1;
+ }
+
+
+ if (session->in) {
+ /*
+ * the last fragment...
+ */
+ if ((session->in_pos + in_len) > session->in_len) {
+ RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent");
+ return 0;
+ }
+ memcpy(session->in + session->in_pos, in, in_len);
+ in = session->in;
+ in_len = session->in_len;
+ }
+
+ switch (session->state) {
+ case PWD_STATE_ID_REQ:
+ {
+ BIGNUM *x = NULL, *y = NULL;
+
+ if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) {
+ RDEBUG2("pwd exchange is incorrect: not ID");
+ return 0;
+ }
+
+ packet = (pwd_id_packet_t *) in;
+ if (in_len < sizeof(*packet)) {
+ RDEBUG("Packet is too small (%zd < %zd).", in_len, sizeof(*packet));
+ return 0;
+ }
+
+ if ((packet->prf != EAP_PWD_DEF_PRF) ||
+ (packet->random_function != EAP_PWD_DEF_RAND_FUN) ||
+ (packet->prep != session->prep) ||
+ (CRYPTO_memcmp(packet->token, &session->token, 4)) ||
+ (packet->group_num != ntohs(session->group_num))) {
+ RDEBUG2("pwd id response is invalid");
+ return 0;
+ }
+ /*
+ * we've agreed on the ciphersuite, record it...
+ */
+ ptr = (uint8_t *)&session->ciphersuite;
+ memcpy(ptr, (char *)&packet->group_num, sizeof(uint16_t));
+ ptr += sizeof(uint16_t);
+ *ptr = EAP_PWD_DEF_RAND_FUN;
+ ptr += sizeof(uint8_t);
+ *ptr = EAP_PWD_DEF_PRF;
+
+ peer_id_len = in_len - sizeof(pwd_id_packet_t);
+ if (peer_id_len >= sizeof(session->peer_id)) {
+ RDEBUG2("pwd id response is malformed");
+ return 0;
+ }
+ peer_id = packet->identity;
+
+ if (inst->prep >= 0) {
+ /*
+ * make fake request to get the password for the usable ID
+ */
+
+ session->peer_id_len = peer_id_len;
+ memcpy(session->peer_id, peer_id, peer_id_len);
+ session->peer_id[peer_id_len] = '\0';
+
+ if (fetch_and_process_password(session, request, inst) < 0) {
+ RDEBUG2("failed to find password for %s to do pwd authentication",
+ session->peer_id);
+ return 0;
+ }
+ } else {
+ /* verify inner identity == outer identity */
+ if (session->peer_id_len != peer_id_len ||
+ memcmp(session->peer_id, peer_id, peer_id_len) != 0) {
+ char buf[sizeof(session->peer_id)];
+ memcpy(buf, peer_id, peer_id_len);
+ buf[peer_id_len] = '\0';
+
+ RDEBUG2("inner identity(peer_id) %s does not match outer identity %s",
+ buf, session->peer_id);
+ return 0;
+ }
+ RDEBUG2("inner identity matched for %s", session->peer_id);
+ }
+
+ /*
+ * compute our scalar and element
+ */
+ if (compute_scalar_element(request, session, session->bnctx)) {
+ DEBUG2("failed to compute server's scalar and element");
+ return 0;
+ }
+
+ MEM(x = BN_new());
+ MEM(y = BN_new());
+
+ /*
+ * element is a point, get both coordinates: x and y
+ */
+ if (!EC_POINT_get_affine_coordinates(session->group, session->my_element, x, y,
+ session->bnctx)) {
+ DEBUG2("server point assignment failed");
+ BN_clear_free(x);
+ BN_clear_free(y);
+ return 0;
+ }
+
+ /*
+ * construct request
+ */
+ session->out_len = BN_num_bytes(session->order) + (2 * BN_num_bytes(session->prime));
+ if (session->salt_present)
+ session->out_len += 1 + session->salt_len;
+
+ if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) {
+ return 0;
+ }
+ memset(session->out, 0, session->out_len);
+
+ ptr = session->out;
+ if (session->salt_present) {
+ *ptr = session->salt_len;
+ ptr++;
+
+ memcpy(ptr, session->salt, session->salt_len);
+ ptr += session->salt_len;
+ }
+
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, ptr + offset);
+ BN_clear_free(x);
+
+ ptr += BN_num_bytes(session->prime);
+ offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, ptr + offset);
+ BN_clear_free(y);
+
+ ptr += BN_num_bytes(session->prime);
+ offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar);
+ BN_bn2bin(session->my_scalar, ptr + offset);
+
+ session->state = PWD_STATE_COMMIT;
+ ret = send_pwd_request(session, eap_ds);
+ }
+ break;
+
+ case PWD_STATE_COMMIT:
+ if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) {
+ RDEBUG2("pwd exchange is incorrect: not commit!");
+ return 0;
+ }
+
+ /*
+ * process the peer's commit and generate the shared key, k
+ */
+ if (process_peer_commit(request, session, in, in_len, session->bnctx)) {
+ RDEBUG2("failed to process peer's commit");
+ return 0;
+ }
+
+ /*
+ * compute our confirm blob
+ */
+ if (compute_server_confirm(request, session, session->my_confirm, session->bnctx)) {
+ ERROR("rlm_eap_pwd: failed to compute confirm!");
+ return 0;
+ }
+
+ /*
+ * construct a response...which is just our confirm blob
+ */
+ session->out_len = SHA256_DIGEST_LENGTH;
+ if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) {
+ return 0;
+ }
+
+ memset(session->out, 0, session->out_len);
+ memcpy(session->out, session->my_confirm, SHA256_DIGEST_LENGTH);
+
+ session->state = PWD_STATE_CONFIRM;
+ ret = send_pwd_request(session, eap_ds);
+ break;
+
+ case PWD_STATE_CONFIRM:
+ if (in_len < SHA256_DIGEST_LENGTH) {
+ RDEBUG("Peer confirm is too short (%zd < %d)",
+ in_len, SHA256_DIGEST_LENGTH);
+ return 0;
+ }
+
+ if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) {
+ RDEBUG2("pwd exchange is incorrect: not commit!");
+ return 0;
+ }
+ if (compute_peer_confirm(request, session, peer_confirm, session->bnctx)) {
+ RDEBUG2("pwd exchange cannot compute peer's confirm");
+ return 0;
+ }
+ if (CRYPTO_memcmp(peer_confirm, in, SHA256_DIGEST_LENGTH)) {
+ RDEBUG2("pwd exchange fails: peer confirm is incorrect!");
+ return 0;
+ }
+ if (compute_keys(request, session, peer_confirm, msk, emsk)) {
+ RDEBUG2("pwd exchange cannot generate (E)MSK!");
+ return 0;
+ }
+ eap_ds->request->code = PW_EAP_SUCCESS;
+ /*
+ * return the MSK (in halves)
+ */
+ eap_add_reply(handler->request, "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN);
+ eap_add_reply(handler->request, "MS-MPPE-Send-Key", msk + MPPE_KEY_LEN, MPPE_KEY_LEN);
+
+ ret = 1;
+ break;
+
+ default:
+ RDEBUG2("unknown PWD state");
+ return 0;
+ }
+
+ /*
+ * we processed the buffered fragments, get rid of them
+ */
+ if (session->in) {
+ talloc_free(session->in);
+ session->in = NULL;
+ }
+
+ return ret;
+}
+
+extern rlm_eap_module_t rlm_eap_pwd;
+rlm_eap_module_t rlm_eap_pwd = {
+ .name = "eap_pwd",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Create the initial request */
+ .process = mod_process, /* Process next round of EAP method */
+};
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.h b/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.h
new file mode 100644
index 0000000..966646c
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) Dan Harkins, 2012
+ *
+ * Copyright holder grants permission for redistribution and use in source
+ * and binary forms, with or without modification, provided that the
+ * following conditions are met:
+ * 1. Redistribution of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in all source files.
+ * 2. Redistribution in binary form must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * "DISCLAIMER OF LIABILITY
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAN HARKINS ``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 INDUSTRIAL LOUNGE 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."
+ *
+ * This license and distribution terms cannot be changed. In other words,
+ * this code cannot simply be copied and put under a different distribution
+ * license (including the GNU public license).
+ */
+
+#ifndef _RLM_EAP_PWD_H
+#define _RLM_EAP_PWD_H
+
+#include "eap_pwd.h"
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+typedef struct _eap_pwd_t {
+ uint32_t group;
+ uint32_t fragment_size;
+ char const *server_id;
+ char const *virtual_server;
+ int32_t prep;
+ int32_t unhex;
+} eap_pwd_t;
+
+#endif /* _RLM_EAP_PWD_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/.gitignore b/src/modules/rlm_eap/types/rlm_eap_sim/.gitignore
new file mode 100644
index 0000000..01a5daa
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_sim/.gitignore
@@ -0,0 +1 @@
+all.mk
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/README.md b/src/modules/rlm_eap/types/rlm_eap_sim/README.md
new file mode 100644
index 0000000..76e83e8
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_sim/README.md
@@ -0,0 +1,9 @@
+# rlm_eap_aka
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements [RFC 4186](https://tools.ietf.org/html/rfc4186) EAP-SIM authentication. EAP-SIM provides authentication
+and session keying material for 802.11i (WPA/2 Enterprise) using SIM triplets.
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/all.mk.in b/src/modules/rlm_eap/types/rlm_eap_sim/all.mk.in
new file mode 100644
index 0000000..c13b2ef
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_sim/all.mk.in
@@ -0,0 +1,12 @@
+TARGETNAME := @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c
+
+SRC_CFLAGS := @mod_cflags@
+TGT_LDLIBS := @mod_ldflags@
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/configure b/src/modules/rlm_eap/types/rlm_eap_sim/configure
new file mode 100755
index 0000000..aa7d6ca
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_sim/configure
@@ -0,0 +1,2929 @@
+#! /bin/sh
+# From configure.ac Revision.
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="rlm_eap_sim.c"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+mod_cflags
+mod_ldflags
+targetname
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_rlm_eap_sim
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-rlm_eap_sim build without rlm_eap_sim
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+echo
+echo Running tests for rlm_eap_sim
+echo
+
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+# Check whether --with-rlm_eap_sim was given.
+if test "${with_rlm_eap_sim+set}" = set; then :
+ withval=$with_rlm_eap_sim;
+fi
+
+
+
+mod_ldflags=
+mod_cflags=
+
+
+fail=
+fr_status=
+fr_features=
+: > "config.report"
+: > "config.report.tmp"
+
+
+
+if test x"$with_rlm_eap_sim" != xno; then
+
+
+
+ targetname=rlm_eap_sim
+else
+ targetname=
+ echo \*\*\* module rlm_eap_sim is disabled.
+
+
+fr_status="disabled"
+
+fi
+
+if test x"$fail" != x""; then
+ targetname=""
+
+
+ if test x"${enable_strict_dependencies}" = x"yes"; then
+ as_fn_error $? "set --without-rlm_eap_sim to disable it explicitly." "$LINENO" 5
+ else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: silently not building rlm_eap_sim." >&5
+$as_echo "$as_me: WARNING: silently not building rlm_eap_sim." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: FAILURE: rlm_eap_sim requires: $fail." >&5
+$as_echo "$as_me: WARNING: FAILURE: rlm_eap_sim requires: $fail." >&2;};
+ fail="$(echo $fail)"
+
+
+fr_status="skipping (requires $fail)"
+
+ fr_features=
+
+ fi
+
+else
+
+
+fr_status="OK"
+
+fi
+
+if test x"$fr_features" = x""; then
+ $as_echo "$fr_status" > "config.report"
+else
+ $as_echo_n "$fr_status ... " > "config.report"
+ cat "config.report.tmp" >> "config.report"
+fi
+
+rm "config.report.tmp"
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files all.mk"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "all.mk") CONFIG_FILES="$CONFIG_FILES all.mk" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/configure.ac b/src/modules/rlm_eap/types/rlm_eap_sim/configure.ac
new file mode 100644
index 0000000..e3dac84
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_sim/configure.ac
@@ -0,0 +1,18 @@
+AC_PREREQ([2.69])
+AC_INIT
+AC_CONFIG_SRCDIR([rlm_eap_sim.c])
+AC_REVISION($Revision$)
+FR_INIT_MODULE([rlm_eap_sim])
+
+mod_ldflags=
+mod_cflags=
+
+FR_MODULE_START_TESTS
+
+FR_MODULE_END_TESTS
+
+AC_SUBST(mod_ldflags)
+AC_SUBST(mod_cflags)
+
+AC_CONFIG_FILES([all.mk])
+AC_OUTPUT
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c
new file mode 100644
index 0000000..38fe997
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c
@@ -0,0 +1,697 @@
+/*
+ * rlm_eap_sim.c Handles that are called from eap for SIM
+ *
+ * The development of the EAP/SIM support was funded by Internet Foundation
+ * Austria (http://www.nic.at/ipa).
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ * Copyright 2003,2006 The FreeRADIUS server project
+ *
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../../eap.h"
+#include "eap_types.h"
+#include "eap_sim.h"
+#include "comp128.h"
+
+#include <freeradius-devel/rad_assert.h>
+
+typedef struct eap_sim_server_state {
+ enum eapsim_serverstates state;
+ struct eapsim_keys keys;
+ int sim_id;
+} eap_sim_state_t;
+
+static int eap_sim_sendstart(eap_handler_t *handler)
+{
+ VALUE_PAIR **vps, *newvp;
+ uint16_t words[3];
+ eap_sim_state_t *ess;
+ RADIUS_PACKET *packet;
+ uint8_t *p;
+
+ rad_assert(handler->request != NULL);
+ rad_assert(handler->request->reply);
+
+ ess = (eap_sim_state_t *)handler->opaque;
+
+ /* these are the outgoing attributes */
+ packet = handler->request->reply;
+ vps = &packet->vps;
+ rad_assert(vps != NULL);
+
+
+ /*
+ * Add appropriate TLVs for the EAP things we wish to send.
+ */
+
+ /* the version list. We support only version 1. */
+ words[0] = htons(sizeof(words[1]));
+ words[1] = htons(EAP_SIM_VERSION);
+ words[2] = 0;
+
+ newvp = fr_pair_afrom_num(packet, PW_EAP_SIM_VERSION_LIST, 0);
+ fr_pair_value_memcpy(newvp, (uint8_t const *) words, sizeof(words));
+
+ fr_pair_add(vps, newvp);
+
+ /* set the EAP_ID - new value */
+ newvp = fr_pair_afrom_num(packet, PW_EAP_ID, 0);
+ newvp->vp_integer = ess->sim_id++;
+ fr_pair_replace(vps, newvp);
+
+ /* record it in the ess */
+ ess->keys.versionlistlen = 2;
+ memcpy(ess->keys.versionlist, words + 1, ess->keys.versionlistlen);
+
+ /* the ANY_ID attribute. We do not support re-auth or pseudonym */
+ newvp = fr_pair_afrom_num(packet, PW_EAP_SIM_FULLAUTH_ID_REQ, 0);
+ newvp->vp_length = 2;
+ newvp->vp_octets = p = talloc_array(newvp, uint8_t, 2);
+
+ p[0] = 0;
+ p[0] = 1;
+ fr_pair_add(vps, newvp);
+
+ /* the SUBTYPE, set to start. */
+ newvp = fr_pair_afrom_num(packet, PW_EAP_SIM_SUBTYPE, 0);
+ newvp->vp_integer = EAPSIM_START;
+ fr_pair_replace(vps, newvp);
+
+ return 1;
+}
+
+static int eap_sim_get_challenge(eap_handler_t *handler, VALUE_PAIR *vps, int idx, eap_sim_state_t *ess)
+{
+ REQUEST *request = handler->request;
+ VALUE_PAIR *vp, *ki, *algo_version;
+
+ rad_assert(idx >= 0 && idx < 3);
+
+ /*
+ * Generate a new RAND value, and derive Kc and SRES from Ki
+ */
+ ki = fr_pair_find_by_num(vps, PW_EAP_SIM_KI, 0, TAG_ANY);
+ if (ki) {
+ int i;
+
+ /*
+ * Check to see if have a Ki for the IMSI, this allows us to generate the rest
+ * of the triplets.
+ */
+ algo_version = fr_pair_find_by_num(vps, PW_EAP_SIM_ALGO_VERSION, 0, TAG_ANY);
+ if (!algo_version) {
+ REDEBUG("Found Ki, but missing EAP-Sim-Algo-Version");
+ return 0;
+ }
+
+ for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+ ess->keys.rand[idx][i] = fr_rand();
+ }
+
+ switch (algo_version->vp_integer) {
+ case 1:
+ comp128v1(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx]);
+ break;
+
+ case 2:
+ comp128v23(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx],
+ true);
+ break;
+
+ case 3:
+ comp128v23(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx],
+ false);
+ break;
+
+ case 4:
+ REDEBUG("Comp128-4 algorithm is not supported as details have not yet been published. "
+ "If you have details of this algorithm please contact the FreeRADIUS "
+ "maintainers");
+ return 0;
+
+ default:
+ REDEBUG("Unknown/unsupported algorithm Comp128-%i", algo_version->vp_integer);
+ }
+
+ if (RDEBUG_ENABLED2) {
+ char buffer[33]; /* 32 hexits (16 bytes) + 1 */
+ char *p;
+
+ RDEBUG2("Generated following triplets for round %i:", idx);
+
+ RINDENT();
+ p = buffer;
+ for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+ p += sprintf(p, "%02x", ess->keys.rand[idx][i]);
+ }
+ RDEBUG2("RAND : 0x%s", buffer);
+
+ p = buffer;
+ for (i = 0; i < EAPSIM_SRES_SIZE; i++) {
+ p += sprintf(p, "%02x", ess->keys.sres[idx][i]);
+ }
+ RDEBUG2("SRES : 0x%s", buffer);
+
+ p = buffer;
+ for (i = 0; i < EAPSIM_KC_SIZE; i++) {
+ p += sprintf(p, "%02x", ess->keys.Kc[idx][i]);
+ }
+ RDEBUG2("Kc : 0x%s", buffer);
+ REXDENT();
+ }
+ return 1;
+ }
+
+ /*
+ * Use known RAND, SRES, and Kc values, these may of been pulled in from an AuC,
+ * or created by sending challenges to the SIM directly.
+ */
+ vp = fr_pair_find_by_num(vps, PW_EAP_SIM_RAND1 + idx, 0, TAG_ANY);
+ /* Hack for backwards compatibility */
+ if (!vp) {
+ vp = fr_pair_find_by_num(request->reply->vps, PW_EAP_SIM_RAND1 + idx, 0, TAG_ANY);
+ }
+ if (!vp) {
+ /* bad, we can't find stuff! */
+ REDEBUG("EAP-SIM-RAND%i not found", idx + 1);
+ return 0;
+ }
+ if (vp->vp_length != EAPSIM_RAND_SIZE) {
+ REDEBUG("EAP-SIM-RAND%i is not " STRINGIFY(EAPSIM_RAND_SIZE) " bytes, got %zu bytes",
+ idx + 1, vp->vp_length);
+ return 0;
+ }
+ memcpy(ess->keys.rand[idx], vp->vp_strvalue, EAPSIM_RAND_SIZE);
+
+ vp = fr_pair_find_by_num(vps, PW_EAP_SIM_SRES1 + idx, 0, TAG_ANY);
+ /* Hack for backwards compatibility */
+ if (!vp) {
+ vp = fr_pair_find_by_num(request->reply->vps, PW_EAP_SIM_SRES1 + idx, 0, TAG_ANY);
+ }
+ if (!vp) {
+ /* bad, we can't find stuff! */
+ REDEBUG("EAP-SIM-SRES%i not found", idx + 1);
+ return 0;
+ }
+
+ if (vp->vp_length != EAPSIM_SRES_SIZE) {
+ REDEBUG("EAP-SIM-SRES%i is not " STRINGIFY(EAPSIM_SRES_SIZE) " bytes, got %zu bytes",
+ idx + 1, vp->vp_length);
+ return 0;
+ }
+ memcpy(ess->keys.sres[idx], vp->vp_strvalue, EAPSIM_SRES_SIZE);
+
+ vp = fr_pair_find_by_num(vps, PW_EAP_SIM_KC1 + idx, 0, TAG_ANY);
+ /* Hack for backwards compatibility */
+ if (!vp) {
+ vp = fr_pair_find_by_num(request->reply->vps, PW_EAP_SIM_KC1 + idx, 0, TAG_ANY);
+ }
+
+ if (!vp) {
+ /* bad, we can't find stuff! */
+ REDEBUG("EAP-SIM-Kc%i not found", idx + 1);
+ return 0;
+ }
+ if (vp->vp_length != EAPSIM_KC_SIZE) {
+ REDEBUG("EAP-SIM-Kc%i is not " STRINGIFY(EAPSIM_KC_SIZE) " bytes, got %zu bytes",
+ idx + 1, vp->vp_length);
+ return 0;
+ }
+ memcpy(ess->keys.Kc[idx], vp->vp_strvalue, EAPSIM_KC_SIZE);
+
+ return 1;
+}
+
+/** Send the challenge itself
+ *
+ * Challenges will come from one of three places eventually:
+ *
+ * 1 from attributes like PW_EAP_SIM_RANDx
+ * (these might be retrieved from a database)
+ *
+ * 2 from internally implemented SIM authenticators
+ * (a simple one based upon XOR will be provided)
+ *
+ * 3 from some kind of SS7 interface.
+ *
+ * For now, they only come from attributes.
+ * It might be that the best way to do 2/3 will be with a different
+ * module to generate/calculate things.
+ *
+ */
+static int eap_sim_sendchallenge(eap_handler_t *handler)
+{
+ REQUEST *request = handler->request;
+ eap_sim_state_t *ess;
+ VALUE_PAIR **invps, **outvps, *newvp;
+ RADIUS_PACKET *packet;
+ uint8_t *p;
+
+ ess = (eap_sim_state_t *)handler->opaque;
+ rad_assert(handler->request != NULL);
+ rad_assert(handler->request->reply);
+
+ /*
+ * Invps is the data from the client but this is for non-protocol data here.
+ * We should already have consumed any client originated data.
+ */
+ invps = &handler->request->packet->vps;
+
+ /*
+ * Outvps is the data to the client
+ */
+ packet = handler->request->reply;
+ outvps = &packet->vps;
+
+ if (RDEBUG_ENABLED2) {
+ RDEBUG2("EAP-SIM decoded packet");
+ rdebug_pair_list(L_DBG_LVL_2, request, *invps, NULL);
+ }
+
+ /*
+ * Okay, we got the challenges! Put them into an attribute.
+ */
+ newvp = fr_pair_afrom_num(packet, PW_EAP_SIM_RAND, 0);
+ newvp->vp_length = 2 + (EAPSIM_RAND_SIZE * 3);
+ newvp->vp_octets = p = talloc_array(newvp, uint8_t, newvp->vp_length);
+
+ memset(p, 0, 2); /* clear reserved bytes */
+ p += 2;
+ memcpy(p, ess->keys.rand[0], EAPSIM_RAND_SIZE);
+ p += EAPSIM_RAND_SIZE;
+ memcpy(p, ess->keys.rand[1], EAPSIM_RAND_SIZE);
+ p += EAPSIM_RAND_SIZE;
+ memcpy(p, ess->keys.rand[2], EAPSIM_RAND_SIZE);
+ fr_pair_add(outvps, newvp);
+
+ /*
+ * Set the EAP_ID - new value
+ */
+ newvp = fr_pair_afrom_num(packet, PW_EAP_ID, 0);
+ newvp->vp_integer = ess->sim_id++;
+ fr_pair_replace(outvps, newvp);
+
+ /*
+ * Make a copy of the identity
+ */
+ ess->keys.identitylen = strlen(handler->identity);
+ memcpy(ess->keys.identity, handler->identity, ess->keys.identitylen);
+
+ /*
+ * Use the SIM identity, if available
+ */
+ newvp = fr_pair_find_by_num(*invps, PW_EAP_SIM_IDENTITY, 0, TAG_ANY);
+ if (newvp && newvp->vp_length > 2) {
+ uint16_t len;
+
+ memcpy(&len, newvp->vp_octets, sizeof(uint16_t));
+ len = ntohs(len);
+ if (len <= newvp->vp_length - 2 && len <= MAX_STRING_LEN) {
+ ess->keys.identitylen = len;
+ memcpy(ess->keys.identity, newvp->vp_octets + 2, ess->keys.identitylen);
+ }
+ }
+
+ /*
+ * All set, calculate keys!
+ */
+ eapsim_calculate_keys(&ess->keys);
+
+#ifdef EAP_SIM_DEBUG_PRF
+ eapsim_dump_mk(&ess->keys);
+#endif
+
+ /*
+ * Need to include an AT_MAC attribute so that it will get
+ * calculated. The NONCE_MT and the MAC are both 16 bytes, so
+ * We store the NONCE_MT in the MAC for the encoder, which
+ * will pull it out before it does the operation.
+ */
+ newvp = fr_pair_afrom_num(packet, PW_EAP_SIM_MAC, 0);
+ fr_pair_value_memcpy(newvp, ess->keys.nonce_mt, 16);
+ fr_pair_replace(outvps, newvp);
+
+ newvp = fr_pair_afrom_num(packet, PW_EAP_SIM_KEY, 0);
+ fr_pair_value_memcpy(newvp, ess->keys.K_aut, 16);
+ fr_pair_replace(outvps, newvp);
+
+ /* the SUBTYPE, set to challenge. */
+ newvp = fr_pair_afrom_num(packet, PW_EAP_SIM_SUBTYPE, 0);
+ newvp->vp_integer = EAPSIM_CHALLENGE;
+ fr_pair_replace(outvps, newvp);
+
+ return 1;
+}
+
+#ifndef EAPTLS_MPPE_KEY_LEN
+#define EAPTLS_MPPE_KEY_LEN 32
+#endif
+
+/*
+ * this code sends the success message.
+ *
+ * the only work to be done is the add the appropriate SEND/RECV
+ * radius attributes derived from the MSK.
+ *
+ */
+static int eap_sim_sendsuccess(eap_handler_t *handler)
+{
+ unsigned char *p;
+ eap_sim_state_t *ess;
+ VALUE_PAIR *vp;
+ RADIUS_PACKET *packet;
+
+ /* outvps is the data to the client. */
+ packet = handler->request->reply;
+ ess = (eap_sim_state_t *)handler->opaque;
+
+ /* set the EAP_ID - new value */
+ vp = fr_pair_afrom_num(packet, PW_EAP_ID, 0);
+ vp->vp_integer = ess->sim_id++;
+ fr_pair_replace(&handler->request->reply->vps, vp);
+
+ p = ess->keys.msk;
+ eap_add_reply(handler->request, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN);
+ p += EAPTLS_MPPE_KEY_LEN;
+ eap_add_reply(handler->request, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN);
+
+ return 1;
+}
+
+
+/** Run the server state machine
+ *
+ */
+static void eap_sim_state_enter(REQUEST *request, eap_handler_t *handler,
+ eap_sim_state_t *ess,
+ enum eapsim_serverstates newstate)
+{
+ switch (newstate) {
+ /*
+ * Send the EAP-SIM Start message, listing the versions that we support.
+ */
+ case EAPSIM_SERVER_START:
+ eap_sim_sendstart(handler);
+ break;
+ /*
+ * Send the EAP-SIM Challenge message.
+ */
+ case EAPSIM_SERVER_CHALLENGE:
+ eap_sim_sendchallenge(handler);
+ break;
+
+ /*
+ * Send the EAP Success message
+ */
+ case EAPSIM_SERVER_SUCCESS:
+ eap_sim_sendsuccess(handler);
+ handler->eap_ds->request->code = PW_EAP_SUCCESS;
+ break;
+ /*
+ * Nothing to do for this transition.
+ */
+ default:
+
+ break;
+ }
+
+ ess->state = newstate;
+
+ /* build the target packet */
+ /* we will set the ID on requests, since we have to HMAC it */
+ handler->eap_ds->set_request_id = 1;
+
+ if (!map_eapsim_basictypes(handler->request->reply,
+ handler->eap_ds->request)) {
+ REDEBUG("Failed encoding EAP-SIM packet");
+ }
+}
+
+/*
+ * Initiate the EAP-SIM session by starting the state machine
+ * and initiating the state.
+ */
+static int mod_session_init(UNUSED void *instance, eap_handler_t *handler)
+{
+ REQUEST *request = handler->request;
+ eap_sim_state_t *ess;
+ time_t n;
+
+ ess = talloc_zero(handler, eap_sim_state_t);
+ if (!ess) {
+ RDEBUG2("No space for EAP-SIM state");
+ return 0;
+ }
+
+ handler->opaque = ess;
+ handler->stage = PROCESS;
+
+ /*
+ * Save the keying material, because it could change on a subsequent retrival.
+ */
+ if (!eap_sim_get_challenge(handler, request->config, 0, ess) ||
+ !eap_sim_get_challenge(handler, request->config, 1, ess) ||
+ !eap_sim_get_challenge(handler, request->config, 2, ess)) {
+ return 0; /* already printed error */
+ }
+
+ /*
+ * This value doesn't have be strong, but it is good if it is different now and then.
+ */
+ time(&n);
+ ess->sim_id = (n & 0xff);
+
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_START);
+
+ return 1;
+}
+
+
+/** Process an EAP-Sim/Response/Start
+ *
+ * Verify that client chose a version, and provided a NONCE_MT,
+ * and if so, then change states to challenge, and send the new
+ * challenge, else, resend the Request/Start.
+ */
+static int process_eap_sim_start(eap_handler_t *handler, VALUE_PAIR *vps)
+{
+ REQUEST *request = handler->request;
+ VALUE_PAIR *nonce_vp, *selectedversion_vp;
+ eap_sim_state_t *ess;
+ uint16_t simversion;
+ ess = (eap_sim_state_t *)handler->opaque;
+
+ nonce_vp = fr_pair_find_by_num(vps, PW_EAP_SIM_NONCE_MT, 0, TAG_ANY);
+ selectedversion_vp = fr_pair_find_by_num(vps, PW_EAP_SIM_SELECTED_VERSION, 0, TAG_ANY);
+ if (!nonce_vp || !selectedversion_vp) {
+ RDEBUG2("Client did not select a version and send a NONCE");
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_START);
+ return 1;
+ }
+
+ /*
+ * Okay, good got stuff that we need. Check the version we found.
+ */
+ if (selectedversion_vp->vp_length < 2) {
+ REDEBUG("EAP-SIM version field is too short");
+ return 0;
+ }
+ memcpy(&simversion, selectedversion_vp->vp_strvalue, sizeof(simversion));
+ simversion = ntohs(simversion);
+ if(simversion != EAP_SIM_VERSION) {
+ REDEBUG("EAP-SIM version %i is unknown", simversion);
+ return 0;
+ }
+
+ /*
+ * Record it for later keying
+ */
+ memcpy(ess->keys.versionselect, selectedversion_vp->vp_strvalue, sizeof(ess->keys.versionselect));
+
+ /*
+ * Double check the nonce size.
+ */
+ if(nonce_vp->vp_length != 18) {
+ REDEBUG("EAP-SIM nonce_mt must be 16 bytes (+2 bytes padding), not %zu", nonce_vp->vp_length);
+ return 0;
+ }
+ memcpy(ess->keys.nonce_mt, nonce_vp->vp_strvalue + 2, 16);
+
+ /*
+ * Everything looks good, change states
+ */
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_CHALLENGE);
+
+ return 1;
+}
+
+
+/** Process an EAP-Sim/Response/Challenge
+ *
+ * Verify that MAC that we received matches what we would have
+ * calculated from the packet with the SRESx appended.
+ *
+ */
+static int process_eap_sim_challenge(eap_handler_t *handler, VALUE_PAIR *vps)
+{
+ REQUEST *request = handler->request;
+ eap_sim_state_t *ess = handler->opaque;
+
+ uint8_t srescat[EAPSIM_SRES_SIZE * 3];
+ uint8_t *p = srescat;
+
+ uint8_t calcmac[EAPSIM_CALCMAC_SIZE];
+
+ memcpy(p, ess->keys.sres[0], EAPSIM_SRES_SIZE);
+ p += EAPSIM_SRES_SIZE;
+ memcpy(p, ess->keys.sres[1], EAPSIM_SRES_SIZE);
+ p += EAPSIM_SRES_SIZE;
+ memcpy(p, ess->keys.sres[2], EAPSIM_SRES_SIZE);
+
+ /*
+ * Verify the MAC, now that we have all the keys
+ */
+ if (eapsim_checkmac(handler, vps, ess->keys.K_aut, srescat, sizeof(srescat), calcmac)) {
+ RDEBUG2("MAC check succeed");
+ } else {
+ int i, j;
+ char macline[20*3];
+ char *m = macline;
+
+ j=0;
+ for (i = 0; i < EAPSIM_CALCMAC_SIZE; i++) {
+ if(j==4) {
+ *m++ = '_';
+ j=0;
+ }
+ j++;
+
+ sprintf(m, "%02x", calcmac[i]);
+ m = m + strlen(m);
+ }
+ REDEBUG("Calculated MAC (%s) did not match", macline);
+ return 0;
+ }
+
+ /* everything looks good, change states */
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_SUCCESS);
+ return 1;
+}
+
+
+/** Authenticate a previously sent challenge
+ *
+ */
+static int mod_process(UNUSED void *arg, eap_handler_t *handler)
+{
+ REQUEST *request = handler->request;
+ eap_sim_state_t *ess = handler->opaque;
+
+ VALUE_PAIR *vp, *vps;
+
+ enum eapsim_subtype subtype;
+
+ int success;
+
+ /*
+ * VPS is the data from the client
+ */
+ vps = handler->request->packet->vps;
+
+ success = unmap_eapsim_basictypes(handler->request->packet,
+ handler->eap_ds->response->type.data,
+ handler->eap_ds->response->type.length);
+
+ if (!success) {
+ REDEBUG("Failed decoding EAP-SIM packet: %s", fr_strerror());
+ return 0;
+ }
+
+ /*
+ * See what kind of message we have gotten
+ */
+ vp = fr_pair_find_by_num(vps, PW_EAP_SIM_SUBTYPE, 0, TAG_ANY);
+ if (!vp) {
+ REDEBUG2("No subtype attribute was created, message dropped");
+ return 0;
+ }
+ subtype = vp->vp_integer;
+
+ /*
+ * Client error supersedes anything else.
+ */
+ if (subtype == EAPSIM_CLIENT_ERROR) {
+ return 0;
+ }
+
+ switch (ess->state) {
+ case EAPSIM_SERVER_START:
+ switch (subtype) {
+ /*
+ * Pretty much anything else here is illegal, so we will retransmit the request.
+ */
+ default:
+
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_START);
+ return 1;
+ /*
+ * A response to our EAP-Sim/Request/Start!
+ */
+ case EAPSIM_START:
+ return process_eap_sim_start(handler, vps);
+ }
+
+ case EAPSIM_SERVER_CHALLENGE:
+ switch (subtype) {
+ /*
+ * Pretty much anything else here is illegal, so we will retransmit the request.
+ */
+ default:
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_CHALLENGE);
+ return 1;
+ /*
+ * A response to our EAP-Sim/Request/Challenge!
+ */
+ case EAPSIM_CHALLENGE:
+ return process_eap_sim_challenge(handler, vps);
+ }
+
+ default:
+ rad_assert(0 == 1);
+ }
+
+ return 0;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_sim;
+rlm_eap_module_t rlm_eap_sim = {
+ .name = "eap_sim",
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process, /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/README.md b/src/modules/rlm_eap/types/rlm_eap_tls/README.md
new file mode 100644
index 0000000..afb80f2
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/README.md
@@ -0,0 +1,9 @@
+# rlm_eap_tls
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements [RFC 5216](https://tools.ietf.org/html/rfc5216) EAP-TLS authentication. EAP-TLS provides mutual
+authentication and session keying material for 802.11i (WPA/2 Enterprise) using certificates.
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/all.mk b/src/modules/rlm_eap/types/rlm_eap_tls/all.mk
new file mode 100644
index 0000000..fdb7c4b
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/all.mk
@@ -0,0 +1,10 @@
+TARGETNAME := rlm_eap_tls
+
+ifneq "$(OPENSSL_LIBS)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c
+
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
new file mode 100644
index 0000000..d327c57
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
@@ -0,0 +1,303 @@
+/*
+ * rlm_eap_tls.c contains the interfaces that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ *
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#ifdef HAVE_OPENSSL_RAND_H
+#include <openssl/rand.h>
+#endif
+
+#ifdef HAVE_OPENSSL_EVP_H
+#include <openssl/evp.h>
+#endif
+
+#include "rlm_eap_tls.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+static CONF_PARSER module_config[] = {
+ { "tls", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_tls_t, tls_conf_name), NULL },
+ { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_tls_t, virtual_server), NULL },
+ { "configurable_client_cert", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_tls_t, configurable_client_cert), NULL },
+ CONF_PARSER_TERMINATOR
+};
+
+
+/*
+ * Attach the EAP-TLS module.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_tls_t *inst;
+
+ /*
+ * Parse the config file & get all the configured values
+ */
+ *instance = inst = talloc_zero(cs, rlm_eap_tls_t);
+ if (!inst) return -1;
+
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ inst->tls_conf = eaptls_conf_parse(cs, "tls");
+
+ if (!inst->tls_conf) {
+ ERROR("rlm_eap_tls: Failed initializing SSL context");
+ return -1;
+ }
+
+#ifdef TLS1_3_VERSION
+ if ((inst->tls_conf->max_version == TLS1_3_VERSION) ||
+ (inst->tls_conf->min_version == TLS1_3_VERSION)) {
+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ WARN("!! Most supplicants do not support EAP-TLS with TLS 1.3");
+ WARN("!! Please set tls_max_version = \"1.2\"");
+ WARN("!! FreeRADIUS only supports TLS 1.3 for special builds of wpa_supplicant and Windows");
+ WARN("!! This limitation is likely to change in late 2021.");
+ WARN("!! If you are using this version of FreeRADIUS after 2021, you will probably need to upgrade");
+ WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ }
+#endif
+
+ return 0;
+}
+
+
+/*
+ * Send an initial eap-tls request to the peer, using the libeap functions.
+ */
+static int mod_session_init(void *type_arg, eap_handler_t *handler)
+{
+ int status;
+ tls_session_t *ssn;
+ rlm_eap_tls_t *inst;
+ REQUEST *request = handler->request;
+ bool require_client_cert = true;
+
+ inst = type_arg;
+
+ handler->tls = true;
+
+ /*
+ * Respect EAP-TLS-Require-Client-Cert, but only if
+ * enabled in the module configuration.
+ *
+ * We can't change behavior of existing systems, so this
+ * change has to be enabled via a new configuration
+ * option.
+ */
+ if (inst->configurable_client_cert) {
+ VALUE_PAIR *vp;
+
+ vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0, TAG_ANY);
+ if (vp && !vp->vp_integer) require_client_cert = false;
+ }
+
+ /*
+ * EAP-TLS always requires a client certificate, and
+ * allows for TLS 1.3 if permitted.
+ */
+ ssn = eaptls_session(handler, inst->tls_conf, require_client_cert, true);
+ if (!ssn) {
+ return 0;
+ }
+
+ handler->opaque = ((void *)ssn);
+ ssn->quick_session_tickets = true; /* send as soon as we've seen the client cert */
+
+ /*
+ * TLS session initialization is over. Now handle TLS
+ * related handshaking or application data.
+ */
+ status = eaptls_start(handler->eap_ds, ssn->peap_flag);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+ if (status == 0) return 0;
+
+ /*
+ * The next stage to process the packet.
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+/*
+ * Do authentication, by letting EAP-TLS do most of the work.
+ */
+static int CC_HINT(nonnull) mod_process(void *type_arg, eap_handler_t *handler)
+{
+ fr_tls_status_t status;
+ int ret;
+ tls_session_t *tls_session = (tls_session_t *) handler->opaque;
+ REQUEST *request = handler->request;
+ rlm_eap_tls_t *inst;
+
+ inst = type_arg;
+
+ status = eaptls_process(handler);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+
+
+ /*
+ * Make request available to any SSL callbacks
+ */
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
+ switch (status) {
+ /*
+ * EAP-TLS handshake was successful, return an
+ * EAP-TLS-Success packet here.
+ *
+ * If a virtual server was configured, check that
+ * it accepts the certificates, too.
+ */
+ case FR_TLS_SUCCESS:
+ if (inst->virtual_server) {
+ VALUE_PAIR *vp;
+ REQUEST *fake;
+
+ /* create a fake request */
+ fake = request_alloc_fake(request);
+ rad_assert(!fake->packet->vps);
+
+ fake->packet->vps = fr_pair_list_copy(fake->packet, request->packet->vps);
+
+ /* set the virtual server to use */
+ if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
+ fake->server = vp->vp_strvalue;
+ } else {
+ fake->server = inst->virtual_server;
+ }
+
+ RDEBUG2("Validating certificate");
+ rad_virtual_server(fake);
+
+ /* copy the reply vps back to our reply */
+ fr_pair_list_mcopy_by_num(request->reply, &request->reply->vps,
+ &fake->reply->vps, 0, 0, TAG_ANY);
+
+ /* reject if virtual server didn't return accept */
+ if (fake->reply->code != PW_CODE_ACCESS_ACCEPT) {
+ RDEBUG2("Certificate rejected by the virtual server");
+ talloc_free(fake);
+ eaptls_fail(handler, 0);
+ ret = 0;
+ goto done;
+ }
+
+ talloc_free(fake);
+ /* success */
+ }
+
+ /*
+ * Set the label to a fixed string. For TLS 1.3,
+ * the label is the same for all TLS-based EAP
+ * methods.
+ */
+ tls_session->label = "client EAP encryption";
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ ret = eaptls_success(handler, 0);
+ break;
+
+ /*
+ * The TLS code is still working on the TLS
+ * exchange, and it's a valid TLS request.
+ * do nothing.
+ */
+ case FR_TLS_HANDLED:
+ ret = 1;
+ break;
+
+ /*
+ * Handshake is done, proceed with decoding tunneled
+ * data.
+ */
+ case FR_TLS_OK:
+ RDEBUG2("Received unexpected tunneled data after successful handshake");
+#ifndef NDEBUG
+ if ((rad_debug_lvl > 2) && fr_log_fp) {
+ unsigned int i;
+ unsigned int data_len;
+ unsigned char buffer[1024];
+
+ data_len = (tls_session->record_minus)(&tls_session->dirty_in,
+ buffer, sizeof(buffer));
+ DEBUG(" Tunneled data (%u bytes)", data_len);
+ for (i = 0; i < data_len; i++) {
+ if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, " %x: ", i);
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+
+ fprintf(fr_log_fp, "%02x ", buffer[i]);
+ }
+ fprintf(fr_log_fp, "\n");
+ }
+#endif
+
+ eaptls_fail(handler, 0);
+ ret = 0;
+ break;
+
+ /*
+ * Anything else: fail.
+ *
+ * Also, remove the session from the cache so that
+ * the client can't re-use it.
+ */
+ default:
+ tls_fail(tls_session);
+ ret = 0;
+ }
+
+done:
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
+
+ return ret;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_tls;
+rlm_eap_module_t rlm_eap_tls = {
+ .name = "eap_tls",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
new file mode 100644
index 0000000..550cbbd
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
@@ -0,0 +1,52 @@
+/*
+ * rlm_eap_tls.h
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _RLM_EAP_TLS_H
+#define _RLM_EAP_TLS_H
+
+RCSIDH(rlm_eap_tls_h, "$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+#include "eap_tls.h"
+
+typedef struct rlm_eap_tls_t {
+ /*
+ * TLS configuration
+ */
+ char const *tls_conf_name;
+ fr_tls_server_conf_t *tls_conf;
+
+ /*
+ * Virtual server for checking certificates
+ */
+ char const *virtual_server;
+
+ /*
+ * Configurable EAP-TLS-Require-Client-Cert
+ */
+ bool configurable_client_cert;
+} rlm_eap_tls_t;
+
+#endif /* _RLM_EAP_TLS_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_tnc/.gitignore b/src/modules/rlm_eap/types/rlm_eap_tnc/.gitignore
new file mode 100644
index 0000000..01a5daa
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tnc/.gitignore
@@ -0,0 +1 @@
+all.mk
diff --git a/src/modules/rlm_eap/types/rlm_eap_tnc/README.md b/src/modules/rlm_eap/types/rlm_eap_tnc/README.md
new file mode 100644
index 0000000..ed23d8d
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tnc/README.md
@@ -0,0 +1,9 @@
+# rlm_eap_tnc
+## Metadata
+<dl>
+ <dt>category</dt><dd>obsolete</dd>
+</dl>
+
+## Summary
+Implements EAP-TNC. Has not been tested in years and should not be
+used.
diff --git a/src/modules/rlm_eap/types/rlm_eap_tnc/all.mk.in b/src/modules/rlm_eap/types/rlm_eap_tnc/all.mk.in
new file mode 100644
index 0000000..59b902e
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tnc/all.mk.in
@@ -0,0 +1,14 @@
+TARGETNAME := @targetname@
+
+ifneq "$(TARGETNAME)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c
+
+SRC_CFLAGS := @mod_cflags@
+TGT_LDLIBS := @mod_ldflags@
+
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_tnc/configure b/src/modules/rlm_eap/types/rlm_eap_tnc/configure
new file mode 100755
index 0000000..cbb7d20
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tnc/configure
@@ -0,0 +1,4199 @@
+#! /bin/sh
+# From configure.ac Revision.
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="rlm_eap_tnc.c"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+mod_cflags
+mod_ldflags
+targetname
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_rlm_eap_tnc
+with_eap_tnc_include_dir
+with_eap_tnc_lib_dir
+with_eap_tnc_dir
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-rlm_eap_tnc build without rlm_eap_tnc
+ --with-eap-tnc-include-dir=DIR
+ Directory where the libtnc includes may be found
+ --with-eap-tnc-lib-dir=DIR
+ Directory where the libtnc libraries may be found
+ --with-eap-tnc-dir=DIR Base directory where libtnc is installed
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+echo
+echo Running tests for rlm_eap_tnc
+echo
+
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+# Check whether --with-rlm_eap_tnc was given.
+if test "${with_rlm_eap_tnc+set}" = set; then :
+ withval=$with_rlm_eap_tnc;
+fi
+
+
+
+
+fail=
+fr_status=
+fr_features=
+: > "config.report"
+: > "config.report.tmp"
+
+
+
+if test x"$with_rlm_eap_tnc" != xno; then
+
+
+eap_tnc_include_dir=
+
+# Check whether --with-eap-tnc-include-dir was given.
+if test "${with_eap_tnc_include_dir+set}" = set; then :
+ withval=$with_eap_tnc_include_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need eap-tnc-include-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ eap_tnc_include_dir="$withval"
+ ;;
+ esac
+fi
+
+
+eap_tnc_lib_dir=
+
+# Check whether --with-eap-tnc-lib-dir was given.
+if test "${with_eap_tnc_lib_dir+set}" = set; then :
+ withval=$with_eap_tnc_lib_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need eap-tnc-lib-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ eap_tnc_lib_dir="$withval"
+ ;;
+ esac
+fi
+
+
+
+# Check whether --with-eap-tnc-dir was given.
+if test "${with_eap_tnc_dir+set}" = set; then :
+ withval=$with_eap_tnc_dir; case "$withval" in
+ no)
+ as_fn_error $? "Need eap-tnc-dir" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ eap_tnc_lib_dir="$withval/lib"
+ eap_tnc_include_dir="$withval/include"
+ ;;
+ esac
+fi
+
+
+
+smart_try_dir="$eap_tnc_include_dir"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_safe=`echo "naaeap/naaeap.h" | sed 'y%./+-%__pm%'`
+old_CPPFLAGS="$CPPFLAGS"
+smart_include=
+smart_include_dir="/usr/local/include /opt/include"
+
+_smart_try_dir=
+_smart_include_dir=
+
+for _prefix in $smart_prefix ""; do
+ for _dir in $smart_try_dir; do
+ _smart_try_dir="${_smart_try_dir} ${_dir}/${_prefix}"
+ done
+
+ for _dir in $smart_include_dir; do
+ _smart_include_dir="${_smart_include_dir} ${_dir}/${_prefix}"
+ done
+done
+
+if test "x$_smart_try_dir" != "x"; then
+ for try in $_smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for naaeap/naaeap.h in $try" >&5
+$as_echo_n "checking for naaeap/naaeap.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <naaeap/naaeap.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" = "x"; then
+ for _prefix in $smart_prefix; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${_prefix}/naaeap/naaeap.h" >&5
+$as_echo_n "checking for ${_prefix}/naaeap/naaeap.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <naaeap/naaeap.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem ${_prefix}/"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+fi
+
+if test "x$smart_include" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for naaeap/naaeap.h" >&5
+$as_echo_n "checking for naaeap/naaeap.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <naaeap/naaeap.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include=" "
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "x$smart_include" = "x"; then
+
+ for try in $_smart_include_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for naaeap/naaeap.h in $try" >&5
+$as_echo_n "checking for naaeap/naaeap.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <naaeap/naaeap.h>
+int
+main ()
+{
+int a = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ smart_include="-isystem $try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+
+ smart_include=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_include" != "x"; then
+ eval "ac_cv_header_$ac_safe=yes"
+ CPPFLAGS="$smart_include $old_CPPFLAGS"
+ SMART_CPPFLAGS="$smart_include $SMART_CPPFLAGS"
+fi
+
+smart_prefix=
+
+if test "x$ac_cv_header_naaeap_naaeap_h" != "xyes"; then
+
+fail="$fail naaeap.h"
+
+fi
+
+
+smart_try_dir="$eap_tnc_lib_dir"
+
+
+sm_lib_safe=`echo "naaeap" | sed 'y%./+-%__p_%'`
+sm_func_safe=`echo "processEAPTNCData" | sed 'y%./+-%__p_%'`
+
+old_LIBS="$LIBS"
+old_CPPFLAGS="$CPPFLAGS"
+smart_lib=
+smart_ldflags=
+smart_lib_dir=
+
+if test "x$smart_try_dir" != "x"; then
+ for try in $smart_try_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for processEAPTNCData in -lnaaeap in $try" >&5
+$as_echo_n "checking for processEAPTNCData in -lnaaeap in $try... " >&6; }
+ LIBS="-lnaaeap $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char processEAPTNCData();
+int
+main ()
+{
+processEAPTNCData()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lnaaeap"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for processEAPTNCData in -lnaaeap" >&5
+$as_echo_n "checking for processEAPTNCData in -lnaaeap... " >&6; }
+ LIBS="-lnaaeap $old_LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char processEAPTNCData();
+int
+main ()
+{
+processEAPTNCData()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lnaaeap"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$old_LIBS"
+fi
+
+if test "x$smart_lib" = "x"; then
+ for try in /usr/local/lib /opt/lib; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for processEAPTNCData in -lnaaeap in $try" >&5
+$as_echo_n "checking for processEAPTNCData in -lnaaeap in $try... " >&6; }
+ LIBS="-lnaaeap $old_LIBS"
+ CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char processEAPTNCData();
+int
+main ()
+{
+processEAPTNCData()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ smart_lib="-lnaaeap"
+ smart_ldflags="-L$try -Wl,-rpath,$try"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ LIBS="$old_LIBS"
+ CPPFLAGS="$old_CPPFLAGS"
+fi
+
+if test "x$smart_lib" != "x"; then
+ eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes"
+ LIBS="$smart_ldflags $smart_lib $old_LIBS"
+ SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS"
+fi
+
+if test "x$ac_cv_lib_naaeap_processEAPTNCData" != "xyes"; then
+
+fail="$fail libnaaeap"
+
+fi
+
+
+ targetname=rlm_eap_tnc
+else
+ targetname=
+ echo \*\*\* module rlm_eap_tnc is disabled.
+
+
+fr_status="disabled"
+
+fi
+
+if test x"$fail" != x""; then
+ targetname=""
+
+
+ if test x"${enable_strict_dependencies}" = x"yes"; then
+ as_fn_error $? "set --without-rlm_eap_tnc to disable it explicitly." "$LINENO" 5
+ else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: silently not building rlm_eap_tnc." >&5
+$as_echo "$as_me: WARNING: silently not building rlm_eap_tnc." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: FAILURE: rlm_eap_tnc requires: $fail." >&5
+$as_echo "$as_me: WARNING: FAILURE: rlm_eap_tnc requires: $fail." >&2;};
+ fail="$(echo $fail)"
+
+
+fr_status="skipping (requires $fail)"
+
+ fr_features=
+
+ fi
+
+else
+
+
+fr_status="OK"
+
+fi
+
+if test x"$fr_features" = x""; then
+ $as_echo "$fr_status" > "config.report"
+else
+ $as_echo_n "$fr_status ... " > "config.report"
+ cat "config.report.tmp" >> "config.report"
+fi
+
+rm "config.report.tmp"
+
+
+
+
+
+if test x"$fail" != x""; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Required libraries are available from https://github.com/trustatfhh/tnc-fhh" >&5
+$as_echo "$as_me: WARNING: Required libraries are available from https://github.com/trustatfhh/tnc-fhh" >&2;};
+
+fi
+
+
+mod_ldflags="$SMART_LIBS"
+mod_cflags="$SMART_CPPFLAGS"
+
+
+
+
+ac_config_files="$ac_config_files all.mk"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "all.mk") CONFIG_FILES="$CONFIG_FILES all.mk" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_tnc/configure.ac b/src/modules/rlm_eap/types/rlm_eap_tnc/configure.ac
new file mode 100644
index 0000000..ae20ddd
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tnc/configure.ac
@@ -0,0 +1,90 @@
+AC_PREREQ([2.69])
+AC_INIT
+AC_CONFIG_SRCDIR([rlm_eap_tnc.c])
+AC_REVISION($Revision$)
+FR_INIT_MODULE([rlm_eap_tnc])
+
+FR_MODULE_START_TESTS
+
+dnl extra argument: --with-eap-tnc-include-dir=DIR
+eap_tnc_include_dir=
+AC_ARG_WITH(eap-tnc-include-dir,
+ [AS_HELP_STRING([--with-eap-tnc-include-dir=DIR],
+ [Directory where the libtnc includes may be found])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need eap-tnc-include-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ eap_tnc_include_dir="$withval"
+ ;;
+ esac])
+
+dnl extra argument: --with-eap-tnc-lib-dir=DIR
+eap_tnc_lib_dir=
+AC_ARG_WITH(eap-tnc-lib-dir,
+[AS_HELP_STRING([--with-eap-tnc-lib-dir=DIR],
+ [Directory where the libtnc libraries may be found])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need eap-tnc-lib-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ eap_tnc_lib_dir="$withval"
+ ;;
+ esac])
+
+dnl extra argument: --with-eap-tnc-dir=DIR
+AC_ARG_WITH(eap-tnc-dir,
+[AS_HELP_STRING([--with-eap-tnc-dir=DIR],
+ [Base directory where libtnc is installed])],
+ [case "$withval" in
+ no)
+ AC_MSG_ERROR(Need eap-tnc-dir)
+ ;;
+ yes)
+ ;;
+ *)
+ eap_tnc_lib_dir="$withval/lib"
+ eap_tnc_include_dir="$withval/include"
+ ;;
+ esac])
+
+dnl ############################################################
+dnl # Check for eap-tnc includes
+dnl ############################################################
+
+smart_try_dir="$eap_tnc_include_dir"
+FR_SMART_CHECK_INCLUDE([naaeap/naaeap.h])
+if test "x$ac_cv_header_naaeap_naaeap_h" != "xyes"; then
+ FR_MODULE_FAIL([naaeap.h])
+fi
+
+dnl ############################################################
+dnl # Check for eap-tnc library
+dnl ############################################################
+
+smart_try_dir="$eap_tnc_lib_dir"
+FR_SMART_CHECK_LIB([naaeap],[processEAPTNCData])
+if test "x$ac_cv_lib_naaeap_processEAPTNCData" != "xyes"; then
+ FR_MODULE_FAIL([libnaaeap])
+fi
+
+FR_MODULE_END_TESTS
+
+FR_MODULE_TEST_FAIL_DO([
+ AC_MSG_WARN([Required libraries are available from https://github.com/trustatfhh/tnc-fhh]);
+])
+
+mod_ldflags="$SMART_LIBS"
+mod_cflags="$SMART_CPPFLAGS"
+
+AC_SUBST(mod_ldflags)
+AC_SUBST(mod_cflags)
+
+AC_CONFIG_FILES([all.mk])
+AC_OUTPUT
diff --git a/src/modules/rlm_eap/types/rlm_eap_tnc/rlm_eap_tnc.c b/src/modules/rlm_eap/types/rlm_eap_tnc/rlm_eap_tnc.c
new file mode 100644
index 0000000..a1fdbc0
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_tnc/rlm_eap_tnc.c
@@ -0,0 +1,357 @@
+/*
+ * Portions of this code unrelated to FreeRADIUS are available
+ * separately under a commercial license. If you require an
+ * implementation of EAP-TNC that is not under the GPLv2, please
+ * contact trust@f4-i.fh-hannover.de for details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+/**
+ * $Id$
+ * @file rlm_eap_tnc.c
+ * @brief Interfaces with the naeap library to provide EAP-TNC inner method.
+ *
+ * @copyright 2013 The FreeRADIUS project
+ * @copyright 2007 Alan DeKok <aland@deployingradius.com>
+ * @copyright 2006-2009 FH Hannover
+ */
+
+/*
+ * EAP-TNC Packet with EAP Header, general structure
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Flags | Ver | Data Length |
+ * | |L M S R R| =1 | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Data Length | Data ...
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <freeradius-devel/rad_assert.h>
+
+#include "eap.h"
+#include <naaeap/naaeap.h>
+#include <netinet/in.h>
+
+#define VERSION "0.7.0"
+#define SET_START(x) ((x) | (0x20))
+
+typedef struct rlm_eap_tnc {
+ char const *connection_string;
+} rlm_eap_tnc_t;
+
+static CONF_PARSER module_config[] = {
+ { "connection_string", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_eap_tnc_t, connection_string), "NAS Port: %{NAS-Port} NAS IP: %{NAS-IP-Address} NAS_PORT_TYPE: %{NAS-Port-Type}" },
+ CONF_PARSER_TERMINATOR
+};
+
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_tnc_t *inst;
+ TNC_Result result;
+
+ *instance = inst = talloc_zero(cs, rlm_eap_tnc_t);
+ if (!inst) return -1;
+
+ /*
+ * Parse the configuration attributes.
+ */
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ result = initializeDefault();
+ if (result != TNC_RESULT_SUCCESS) {
+ ERROR("rlm_eap_tnc: NAA-EAP initializeDefault returned an "
+ "error code");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mod_detach(void *instance)
+{
+ TNC_Result result;
+
+ talloc_free(instance);
+
+ result = terminate();
+ if (result != TNC_RESULT_SUCCESS) {
+ ERROR("rlm_eap_tnc: NAA-EAP terminate returned an "
+ "error code whilst detaching");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * This function is called when the first EAP_IDENTITY_RESPONSE message
+ * was received.
+ *
+ * Initiates the EPA_TNC session by sending the first EAP_TNC_RESPONSE
+ * to the peer. The packet has the Start-Bit set and contains no data.
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Code | Identifier | Length |
+ * | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Flags | Ver |
+ * | |0 0 1 0 0|0 0 1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * For this package, only 'Identifier' has to be set dynamically. Any
+ * other information is static.
+ */
+static int mod_session_init(void *instance, eap_handler_t *handler)
+{
+ rlm_eap_tnc_t *inst = instance;
+ REQUEST *request = NULL;
+
+ char buff[71];
+ ssize_t len = 0;
+
+ TNC_Result result;
+ TNC_ConnectionID conn_id;
+
+ TNC_BufferReference eap_tnc_request;
+ TNC_BufferReference eap_tnc_user;
+
+ VALUE_PAIR *username;
+
+ /*
+ * Check if we run inside a secure EAP method.
+ * FIXME check concrete outer EAP method.
+ */
+ if (!handler->request || !handler->request->parent) {
+ ERROR("rlm_eap_tnc: EAP_TNC must only be used as an "
+ "inner method within a protected tunneled EAP created "
+ "by an outer EAP method");
+
+ return 0;
+ }
+
+ request = handler->request->parent;
+
+ /*
+ * Build the connection string
+ */
+ len = radius_xlat(buff, sizeof(buff), request, inst->connection_string, NULL, NULL);
+ if (len < 0){
+ return 0;
+ }
+
+ RDEBUG("Getting connection from NAA-EAP");
+
+ /*
+ * Get connection (uses a function from the NAA-EAP-library)
+ */
+ result = getConnection(buff, &conn_id);
+ if (result != TNC_RESULT_SUCCESS) {
+ ERROR("rlm_eap_tnc: NAA-EAP getConnection returned an "
+ "error code");
+
+ return 0;
+ }
+
+ /*
+ * Previous code manually parsed the EAP identity response
+ * this was wrong. rlm_eap will *always* create the Username
+ * from the EAP Identity response.
+ *
+ * Something has gone very wrong if the User-Name doesn't exist.
+ */
+ username = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+
+ RDEBUG("Username for TNC connection: %s", username->vp_strvalue);
+
+ /*
+ * Stores the username associated with the connection
+ *
+ * What becomes of username? Who knows... but we don't free it
+ * so not safe to use talloc.
+ */
+ MEM(eap_tnc_user = (TNC_BufferReference) strdup(username->vp_strvalue));
+
+ result = storeUsername(conn_id, eap_tnc_user, username->vp_length);
+ if (result != TNC_RESULT_SUCCESS) {
+ ERROR("rlm_eap_tnc: NAA-EAP storeUsername returned an "
+ "error code");
+
+ return 0;
+ }
+
+ /*
+ * Set connection ID
+ */
+ handler->opaque = talloc(handler, TNC_ConnectionID);
+ memcpy(handler->opaque, &conn_id, sizeof(TNC_ConnectionID));
+
+ /*
+ * Bild first EAP TNC request
+ */
+
+ MEM(eap_tnc_request = talloc_array(handler->eap_ds->request, uint8_t, 1));
+ *eap_tnc_request = SET_START(1);
+
+ handler->eap_ds->request->code = PW_EAP_REQUEST;
+ handler->eap_ds->request->type.num = PW_EAP_TNC;
+
+ handler->eap_ds->request->type.length = 1;
+
+ talloc_free(handler->eap_ds->request->type.data);
+ handler->eap_ds->request->type.data = eap_tnc_request;
+
+ /*
+ * We don't need to authorize the user at this point.
+ *
+ * We also don't need to keep the challenge, as it's
+ * stored in 'handler->eap_ds', which will be given back
+ * to us...
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+/**
+ * This function is called when a EAP_TNC_RESPONSE was received.
+ * It basically forwards the EAP_TNC data to NAA-TNCS and forms
+ * and appropriate EAP_RESPONSE. Furthermore, it sets the VlanID
+ * based on the TNC_ConnectionState determined by NAA-TNCS.
+ *
+ * @param instance The configuration data.
+ * @param handler The eap_handler_t.
+ * @return True, if successfully, else false.
+ */
+static int mod_process(UNUSED void *instance, eap_handler_t *handler)
+{
+ TNC_ConnectionID conn_id;
+ TNC_Result result;
+
+ TNC_BufferReference data = NULL;
+ TNC_UInt32 datalen = 0;
+
+ TNC_ConnectionState connection_state;
+ uint8_t code = 0;
+ REQUEST *request = handler->request;
+
+ if (handler->eap_ds->response->type.num != PW_EAP_TNC) {
+ ERROR("rlm_eap_tnc: Incorrect response type");
+
+ return 0;
+ }
+
+ /*
+ * Retrieve connection ID
+ */
+ conn_id = *((TNC_ConnectionID *) (handler->opaque));
+
+ RDEBUG2("Starting authentication for connection ID %lX",
+ conn_id);
+
+ /*
+ * Pass EAP_TNC data to NAA-EAP and get answer data
+ */
+ connection_state = TNC_CONNECTION_STATE_CREATE;
+
+ /*
+ * Forwards the eap_tnc data to NAA-EAP and gets the response
+ */
+ result = processEAPTNCData(conn_id, handler->eap_ds->response->type.data,
+ handler->eap_ds->response->type.length,
+ &data, &datalen, &connection_state);
+ if (result != TNC_RESULT_SUCCESS) {
+ RDEBUG("NAA-EAP processEAPTNCData returned "
+ "an error code");
+
+ return 0;
+ }
+ /*
+ * Determine eap code for the response
+ */
+ switch (connection_state) {
+ case TNC_CONNECTION_STATE_HANDSHAKE:
+ code = PW_EAP_REQUEST;
+ break;
+
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ code = PW_EAP_FAILURE;
+ pair_make_config("TNC-Status", "None", T_OP_SET);
+ break;
+
+ case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+ code = PW_EAP_SUCCESS;
+ pair_make_config("TNC-Status", "Access", T_OP_SET);
+ break;
+
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ code = PW_EAP_SUCCESS;
+ pair_make_config("TNC-Status", "Isolate", T_OP_SET);
+ break;
+
+ default:
+ ERROR("rlm_eap_tnc: Invalid connection state");
+ return 0;
+ }
+
+ /*
+ * Build the TNC EAP request
+ */
+ handler->eap_ds->request->code = code;
+ handler->eap_ds->request->type.num = PW_EAP_TNC;
+
+ handler->eap_ds->request->type.length = datalen;
+
+ talloc_free(handler->eap_ds->request->type.data);
+
+ /*
+ * "data" is not talloc'd memory.
+ */
+ handler->eap_ds->request->type.data = talloc_array(handler->eap_ds->request,
+ uint8_t, datalen);
+ memcpy(handler->eap_ds->request->type.data, data, datalen);
+ free(data);
+
+ return 1;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_tnc;
+rlm_eap_module_t rlm_eap_tnc = {
+ .name = "eap_tnc",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process, /* Process next round of EAP method */
+ .detach = mod_detach /* detach */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/README.md b/src/modules/rlm_eap/types/rlm_eap_ttls/README.md
new file mode 100644
index 0000000..fe89c6e
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ttls/README.md
@@ -0,0 +1,10 @@
+# rlm_eap_ttls
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+Implements [RFC 5281](https://tools.ietf.org/html/rfc5281) EAP-TTLS authentication. EAP-TTLS provides mutual
+authentication and session keying material for 802.11i (WPA/2 Enterprise) using an inner method, and optionally,
+client certificates.
diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/all.mk b/src/modules/rlm_eap/types/rlm_eap_ttls/all.mk
new file mode 100644
index 0000000..2c7af7d
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ttls/all.mk
@@ -0,0 +1,10 @@
+TARGETNAME := rlm_eap_ttls
+
+ifneq "$(OPENSSL_LIBS)" ""
+TARGET := $(TARGETNAME).a
+endif
+
+SOURCES := $(TARGETNAME).c ttls.c
+
+SRC_INCDIRS := ../../ ../../libeap/
+TGT_PREREQS := libfreeradius-eap.a
diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/eap_ttls.h b/src/modules/rlm_eap/types/rlm_eap_ttls/eap_ttls.h
new file mode 100644
index 0000000..ff9a814
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ttls/eap_ttls.h
@@ -0,0 +1,46 @@
+/*
+ * eap_ttls.h
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+#ifndef _EAP_TTLS_H
+#define _EAP_TTLS_H
+
+RCSIDH(eap_ttls_h, "$Id$")
+
+#include "eap_tls.h"
+
+typedef struct ttls_tunnel_t {
+ VALUE_PAIR *username;
+ VALUE_PAIR *state;
+ VALUE_PAIR *accept_vps;
+ bool authenticated;
+ int default_method;
+ bool copy_request_to_tunnel;
+ bool use_tunneled_reply;
+ char const *virtual_server;
+} ttls_tunnel_t;
+
+/*
+ * Process the TTLS portion of an EAP-TTLS request.
+ */
+int eapttls_process(eap_handler_t *handler, tls_session_t *tls_session) CC_HINT(nonnull);
+
+#endif /* _EAP_TTLS_H */
diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c
new file mode 100644
index 0000000..4e53c92
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c
@@ -0,0 +1,392 @@
+/*
+ * rlm_eap_ttls.c contains the interfaces that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+#include "eap_ttls.h"
+
+typedef struct rlm_eap_ttls_t {
+ /*
+ * TLS configuration
+ */
+ char const *tls_conf_name;
+ fr_tls_server_conf_t *tls_conf;
+
+ /*
+ * Default tunneled EAP type
+ */
+ char const *default_method_name;
+ int default_method;
+
+ /*
+ * Use the reply attributes from the tunneled session in
+ * the non-tunneled reply to the client.
+ */
+ bool use_tunneled_reply;
+
+ /*
+ * Use SOME of the request attributes from outside of the
+ * tunneled session in the tunneled request
+ */
+ bool copy_request_to_tunnel;
+
+ /*
+ * RFC 5281 (TTLS) says that the length field MUST NOT be
+ * in fragments after the first one. However, we've done
+ * it that way for years, and no one has complained.
+ *
+ * In the interests of allowing the server to follow the
+ * RFC, we add the option here. If set to "no", it sends
+ * the length field in ONLY the first fragment.
+ */
+ bool include_length;
+
+ /*
+ * Virtual server for inner tunnel session.
+ */
+ char const *virtual_server;
+
+ /*
+ * Do we do require a client cert?
+ */
+ bool req_client_cert;
+} rlm_eap_ttls_t;
+
+
+static CONF_PARSER module_config[] = {
+ { "tls", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ttls_t, tls_conf_name), NULL },
+ { "default_eap_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ttls_t, default_method_name), "md5" },
+ { "copy_request_to_tunnel", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_ttls_t, copy_request_to_tunnel), "no" },
+ { "use_tunneled_reply", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_ttls_t, use_tunneled_reply), "no" },
+ { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_ttls_t, virtual_server), NULL },
+ { "include_length", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_ttls_t, include_length), "yes" },
+ { "require_client_cert", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_ttls_t, req_client_cert), "no" },
+ CONF_PARSER_TERMINATOR
+};
+
+
+/*
+ * Attach the module.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_ttls_t *inst;
+
+ *instance = inst = talloc_zero(cs, rlm_eap_ttls_t);
+ if (!inst) return -1;
+
+ /*
+ * Parse the configuration attributes.
+ */
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ if (!inst->virtual_server) {
+ ERROR("rlm_eap_ttls: A 'virtual_server' MUST be defined for security");
+ return -1;
+ }
+
+ /*
+ * Convert the name to an integer, to make it easier to
+ * handle.
+ */
+ inst->default_method = eap_name2type(inst->default_method_name);
+ if (inst->default_method < 0) {
+ ERROR("rlm_eap_ttls: Unknown EAP type %s",
+ inst->default_method_name);
+ return -1;
+ }
+
+ /*
+ * Read tls configuration, either from group given by 'tls'
+ * option, or from the eap-tls configuration.
+ */
+ inst->tls_conf = eaptls_conf_parse(cs, "tls");
+
+ if (!inst->tls_conf) {
+ ERROR("rlm_eap_ttls: Failed initializing SSL context");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Allocate the TTLS per-session data
+ */
+static ttls_tunnel_t *ttls_alloc(TALLOC_CTX *ctx, rlm_eap_ttls_t *inst)
+{
+ ttls_tunnel_t *t;
+
+ t = talloc_zero(ctx, ttls_tunnel_t);
+
+ t->default_method = inst->default_method;
+ t->copy_request_to_tunnel = inst->copy_request_to_tunnel;
+ t->use_tunneled_reply = inst->use_tunneled_reply;
+ t->virtual_server = inst->virtual_server;
+ return t;
+}
+
+
+/*
+ * Send an initial eap-tls request to the peer, using the libeap functions.
+ */
+static int mod_session_init(void *type_arg, eap_handler_t *handler)
+{
+ int status;
+ tls_session_t *ssn;
+ rlm_eap_ttls_t *inst;
+ VALUE_PAIR *vp;
+ bool client_cert;
+ REQUEST *request = handler->request;
+
+ inst = type_arg;
+
+ handler->tls = true;
+
+ /*
+ * Check if we need a client certificate.
+ */
+
+ /*
+ * EAP-TLS-Require-Client-Cert attribute will override
+ * the require_client_cert configuration option.
+ */
+ vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0, TAG_ANY);
+ if (vp) {
+ client_cert = vp->vp_integer ? true : false;
+ } else {
+ client_cert = inst->req_client_cert;
+ }
+
+ /*
+ * Allow TLS 1.3, it works.
+ */
+ ssn = eaptls_session(handler, inst->tls_conf, client_cert, true);
+ if (!ssn) {
+ return 0;
+ }
+
+ handler->opaque = ((void *)ssn);
+
+ /*
+ * Set the label to a fixed string. For TLS 1.3, the
+ * label is the same for all TLS-based EAP methods. If
+ * the client is using TLS 1.3, then eaptls_success()
+ * will over-ride this label with the correct label for
+ * TLS 1.3.
+ */
+ ssn->label = "ttls keying material";
+
+ /*
+ * TLS session initialization is over. Now handle TLS
+ * related handshaking or application data.
+ */
+ status = eaptls_start(handler->eap_ds, ssn->peap_flag);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+ if (status == 0) return 0;
+
+ /*
+ * The next stage to process the packet.
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+
+/*
+ * Do authentication, by letting EAP-TLS do most of the work.
+ */
+static int mod_process(void *arg, eap_handler_t *handler)
+{
+ int rcode;
+ int ret = 0;
+ fr_tls_status_t status;
+ rlm_eap_ttls_t *inst = (rlm_eap_ttls_t *) arg;
+ tls_session_t *tls_session = (tls_session_t *) handler->opaque;
+ ttls_tunnel_t *t = (ttls_tunnel_t *) tls_session->opaque;
+ REQUEST *request = handler->request;
+
+ RDEBUG2("Authenticate");
+
+ tls_session->length_flag = inst->include_length;
+
+ /*
+ * Process TLS layer until done.
+ */
+ status = eaptls_process(handler);
+ if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
+ REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ } else {
+ RDEBUG3("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+
+ /*
+ * Make request available to any SSL callbacks
+ */
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
+ switch (status) {
+ /*
+ * EAP-TLS handshake was successful, tell the
+ * client to keep talking.
+ *
+ * If this was EAP-TLS, we would just return
+ * an EAP-TLS-Success packet here.
+ */
+ case FR_TLS_SUCCESS:
+ if (SSL_session_reused(tls_session->ssl)) {
+ RDEBUG("Skipping Phase2 due to session resumption");
+ goto do_keys;
+ }
+
+ if (t && t->authenticated) {
+ if (t->accept_vps) {
+ RDEBUG2("Using saved attributes from the original Access-Accept");
+ rdebug_pair_list(L_DBG_LVL_2, request, t->accept_vps, NULL);
+ fr_pair_list_mcopy_by_num(handler->request->reply,
+ &handler->request->reply->vps,
+ &t->accept_vps, 0, 0, TAG_ANY);
+ } else if (t->use_tunneled_reply) {
+ RDEBUG2("No saved attributes in the original Access-Accept");
+ }
+
+ do_keys:
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ ret = eaptls_success(handler, 0);
+ goto done;
+ } else {
+ eaptls_request(handler->eap_ds, tls_session);
+ }
+ ret = 1;
+ goto done;
+
+ /*
+ * The TLS code is still working on the TLS
+ * exchange, and it's a valid TLS request.
+ * do nothing.
+ */
+ case FR_TLS_HANDLED:
+ ret = 1;
+ goto done;
+
+ /*
+ * Handshake is done, proceed with decoding tunneled
+ * data.
+ */
+ case FR_TLS_OK:
+ break;
+
+ /*
+ * Anything else: fail.
+ */
+ default:
+ ret = 0;
+ goto done;
+ }
+
+ /*
+ * Session is established, proceed with decoding
+ * tunneled data.
+ */
+ RDEBUG2("Session established. Proceeding to decode tunneled attributes");
+
+ /*
+ * We may need TTLS data associated with the session, so
+ * allocate it here, if it wasn't already alloacted.
+ */
+ if (!tls_session->opaque) {
+ tls_session->opaque = ttls_alloc(tls_session, inst);
+ }
+
+ /*
+ * Process the TTLS portion of the request.
+ */
+ rcode = eapttls_process(handler, tls_session);
+ switch (rcode) {
+ case PW_CODE_ACCESS_REJECT:
+ eaptls_fail(handler, 0);
+ ret = 0;
+ goto done;
+
+ /*
+ * Access-Challenge, continue tunneled conversation.
+ */
+ case PW_CODE_ACCESS_CHALLENGE:
+ eaptls_request(handler->eap_ds, tls_session);
+ ret = 1;
+ goto done;
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ case PW_CODE_ACCESS_ACCEPT:
+ goto do_keys;
+
+ /*
+ * No response packet, MUST be proxying it.
+ * The main EAP module will take care of discovering
+ * that the request now has a "proxy" packet, and
+ * will proxy it, rather than returning an EAP packet.
+ */
+ case PW_CODE_STATUS_CLIENT:
+#ifdef WITH_PROXY
+ rad_assert(handler->request->proxy != NULL);
+#endif
+ ret = 1;
+ goto done;
+
+ default:
+ break;
+ }
+
+ /*
+ * Something we don't understand: Reject it.
+ */
+ eaptls_fail(handler, 0);
+
+done:
+ SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
+
+ return ret;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_ttls;
+rlm_eap_module_t rlm_eap_ttls = {
+ .name = "eap_ttls",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c
new file mode 100644
index 0000000..cbe4239
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c
@@ -0,0 +1,1321 @@
+/*
+ * rlm_eap_ttls.c contains the interfaces that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+
+#include "eap_ttls.h"
+#include "eap_chbind.h"
+
+/*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | AVP Code |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |V M r r r r r r| AVP Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Vendor-ID (opt) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Data ...
+ * +-+-+-+-+-+-+-+-+
+ */
+
+/*
+ * Verify that the diameter packet is valid.
+ */
+static int diameter_verify(REQUEST *request, uint8_t const *data, unsigned int data_len)
+{
+ uint32_t attr;
+ uint32_t length;
+ unsigned int hdr_len;
+ unsigned int remaining = data_len;
+
+ while (remaining > 0) {
+ hdr_len = 12;
+
+ if (remaining < hdr_len) {
+ RDEBUG2("Diameter attribute is too small (%u) to contain a Diameter header", remaining);
+ return 0;
+ }
+
+ memcpy(&attr, data, sizeof(attr));
+ attr = ntohl(attr);
+ memcpy(&length, data + 4, sizeof(length));
+ length = ntohl(length);
+
+ if ((data[4] & 0x80) != 0) {
+ if (remaining < 16) {
+ RDEBUG2("Diameter attribute is too small to contain a Diameter header with Vendor-Id");
+ return 0;
+ }
+
+ hdr_len = 16;
+ }
+
+ /*
+ * Get the length. If it's too big, die.
+ */
+ length &= 0x00ffffff;
+
+ /*
+ * Too short or too long is bad.
+ */
+ if (length <= (hdr_len - 4)) {
+ RDEBUG2("Tunneled attribute %u is too short (%u < %u) to contain anything useful.", attr,
+ length, hdr_len);
+ return 0;
+ }
+
+ if (length > remaining) {
+ RDEBUG2("Tunneled attribute %u is longer than room remaining in the packet (%u > %u).", attr,
+ length, remaining);
+ return 0;
+ }
+
+ /*
+ * Check for broken implementations, which don't
+ * pad the AVP to a 4-octet boundary.
+ */
+ if (remaining == length) break;
+
+ /*
+ * The length does NOT include the padding, so
+ * we've got to account for it here by rounding up
+ * to the nearest 4-byte boundary.
+ */
+ length += 0x03;
+ length &= ~0x03;
+
+ /*
+ * If the rest of the diameter packet is larger than
+ * this attribute, continue.
+ *
+ * Otherwise, if the attribute over-flows the end
+ * of the packet, die.
+ */
+ if (remaining < length) {
+ REDEBUG2("Diameter attribute overflows packet!");
+ return 0;
+ }
+
+ /*
+ * remaining > length, continue.
+ */
+ remaining -= length;
+ data += length;
+ }
+
+ /*
+ * We got this far. It looks OK.
+ */
+ return 1;
+}
+
+
+/*
+ * Convert diameter attributes to our VALUE_PAIR's
+ */
+static VALUE_PAIR *diameter2vp(REQUEST *request, REQUEST *fake, SSL *ssl,
+ uint8_t const *data, size_t data_len)
+{
+ uint32_t attr;
+ uint32_t vendor;
+ uint32_t length;
+ size_t offset;
+ size_t size;
+ size_t data_left = data_len;
+ VALUE_PAIR *first = NULL;
+ VALUE_PAIR *vp = NULL;
+ RADIUS_PACKET *packet = fake->packet; /* FIXME: api issues */
+ vp_cursor_t out;
+ DICT_ATTR const *da;
+
+ fr_cursor_init(&out, &first);
+
+ /*
+ * Parse while there's still data.
+ */
+ while (data_left >= 9) {
+ size_t attr_len;
+
+ rad_assert(data_left <= data_len);
+ memcpy(&attr, data, sizeof(attr));
+ data += 4;
+ attr = ntohl(attr);
+ vendor = 0;
+
+ memcpy(&length, data, sizeof(length));
+ data += 4;
+ length = ntohl(length);
+
+ /*
+ * Length is *value* length. The actual
+ * attributes are aligned on 4 octets.
+ */
+ attr_len = length & 0x00ffffff;
+ attr_len += 0x03;
+ attr_len &= ~(uint32_t) 0x03;
+
+ /*
+ * A "vendor" flag, with a vendor ID of zero,
+ * is equivalent to no vendor. This is stupid.
+ */
+ offset = 8;
+ if ((length & ((uint32_t)1 << 31)) != 0) {
+ memcpy(&vendor, data, sizeof(vendor));
+ vendor = ntohl(vendor);
+
+ data += 4; /* skip the vendor field, it's zero */
+ offset += 4; /* offset to value field */
+
+ if (attr > 65535) {
+ DEBUG("Skipping Diameter attribute %08x", attr);
+ goto next_attr;
+ }
+ if (vendor > FR_MAX_VENDOR) {
+ DEBUG("Skipping large vendor ID %08x", vendor);
+ goto next_attr;
+ }
+ }
+
+ /*
+ * FIXME: Handle the M bit. For now, we assume that
+ * some other module takes care of any attribute
+ * with the M bit set.
+ */
+
+ /*
+ * Get the length.
+ */
+ length &= 0x00ffffff;
+
+ /*
+ * Get the size of the value portion of the
+ * attribute.
+ */
+ size = length - offset;
+
+ /*
+ * Vendor attributes can be larger than 255.
+ * Normal attributes cannot be.
+ */
+ if ((attr > 255) && (vendor == 0)) {
+ RWDEBUG2("Skipping Diameter attribute %u", attr);
+ goto next_attr;
+ }
+
+ /*
+ * EAP-Message AVPs can be larger than 253 octets.
+ *
+ * For now, we rely on the main decoder in
+ * src/lib/radius to decode data into VPs. This
+ * means putting the data into a RADIUS attribute
+ * format. It also means that we can't handle
+ * "extended" attributes in the Diameter space. Oh well...
+ */
+ if ((size > 253) && !((vendor == 0) && (attr == PW_EAP_MESSAGE))) {
+ RWDEBUG2("diameter2vp skipping long attribute %u", attr);
+ goto next_attr;
+ }
+
+ /*
+ * RADIUS VSAs are handled as Diameter attributes
+ * with Vendor-Id == 0, and the VSA data packed
+ * into the "String" field as per normal.
+ *
+ * EXCEPT for the MS-CHAP attributes.
+ */
+ if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
+ ssize_t decoded;
+ uint8_t buffer[256];
+
+ buffer[0] = PW_VENDOR_SPECIFIC;
+ buffer[1] = size + 2;
+ memcpy(buffer + 2, data, size);
+
+ vp = NULL;
+ decoded = rad_attr2vp(packet, NULL, NULL, NULL,
+ buffer, size + 2, &vp);
+ if (decoded < 0) {
+ REDEBUG2("diameter2vp failed decoding attr: %s",
+ fr_strerror());
+ goto raw;
+ }
+
+ if ((size_t) decoded != size + 2) {
+ REDEBUG2("diameter2vp failed to entirely decode VSA");
+ fr_pair_list_free(&vp);
+ goto raw;
+ }
+
+ fr_cursor_merge(&out, vp);
+
+ goto next_attr;
+ }
+
+ /*
+ * Create it. If this fails, it's because we're OOM.
+ */
+ da = dict_attrbyvalue(attr, vendor);
+ if (!da) goto raw;
+
+ vp = fr_pair_afrom_da(packet, da);
+ if (!vp) {
+ RDEBUG2("Failure in creating VP");
+ fr_pair_list_free(&first);
+ return NULL;
+ }
+
+ /*
+ * If it's a type from our dictionary, then
+ * we need to put the data in a relevant place.
+ *
+ * @todo: Export the lib/radius.c decoder, and use it here!
+ */
+ switch (vp->da->type) {
+ case PW_TYPE_INTEGER:
+ case PW_TYPE_DATE:
+ if (size != vp->vp_length) {
+ /*
+ * Bad format. Create a "raw"
+ * attribute.
+ */
+ raw:
+ if (vp) fr_pair_list_free(&vp);
+ da = dict_unknown_afrom_fields(packet, attr, vendor);
+ if (!da) return NULL;
+ vp = fr_pair_afrom_da(packet, da);
+ if (!vp) return NULL;
+ fr_pair_value_memcpy(vp, data, size);
+ break;
+ }
+ memcpy(&vp->vp_integer, data, vp->vp_length);
+
+ /*
+ * Stored in host byte order: change it.
+ */
+ vp->vp_integer = ntohl(vp->vp_integer);
+ break;
+
+ case PW_TYPE_INTEGER64:
+ if (size != vp->vp_length) goto raw;
+ memcpy(&vp->vp_integer64, data, vp->vp_length);
+
+ /*
+ * Stored in host byte order: change it.
+ */
+ vp->vp_integer64 = ntohll(vp->vp_integer64);
+ break;
+
+ case PW_TYPE_IPV4_ADDR:
+ if (size != vp->vp_length) {
+ RDEBUG2("Invalid length attribute %d",
+ attr);
+ fr_pair_list_free(&first);
+ fr_pair_list_free(&vp);
+ return NULL;
+ }
+ memcpy(&vp->vp_ipaddr, data, vp->vp_length);
+
+ /*
+ * Stored in network byte order: don't change it.
+ */
+ break;
+
+ case PW_TYPE_BYTE:
+ if (size != vp->vp_length) goto raw;
+ vp->vp_byte = data[0];
+ break;
+
+ case PW_TYPE_SHORT:
+ if (size != vp->vp_length) goto raw;
+ vp->vp_short = (data[0] * 256) + data[1];
+ break;
+
+ case PW_TYPE_SIGNED:
+ if (size != vp->vp_length) goto raw;
+ memcpy(&vp->vp_signed, data, vp->vp_length);
+ vp->vp_signed = ntohl(vp->vp_signed);
+ break;
+
+ case PW_TYPE_IPV6_ADDR:
+ if (size != vp->vp_length) goto raw;
+ memcpy(&vp->vp_ipv6addr, data, vp->vp_length);
+ break;
+
+ case PW_TYPE_IPV6_PREFIX:
+ if (size != vp->vp_length) goto raw;
+ memcpy(vp->vp_ipv6prefix, data, vp->vp_length);
+ break;
+
+ case PW_TYPE_STRING:
+ fr_pair_value_bstrncpy(vp, data, size);
+ vp->vp_length = strlen(vp->vp_strvalue); /* embedded zeros are NOT allowed */
+ break;
+
+ /*
+ * Copy it over verbatim.
+ */
+ case PW_TYPE_OCTETS:
+ default:
+ fr_pair_value_memcpy(vp, data, size);
+ break;
+ }
+
+ /*
+ * Ensure that the client is using the
+ * correct challenge. This weirdness is
+ * to protect against against replay
+ * attacks, where anyone observing the
+ * CHAP exchange could pose as that user,
+ * by simply choosing to use the same
+ * challenge.
+ *
+ * By using a challenge based on
+ * information from the current session,
+ * we can guarantee that the client is
+ * not *choosing* a challenge.
+ *
+ * We're a little forgiving in that we
+ * have loose checks on the length, and
+ * we do NOT check the Id (first octet of
+ * the response to the challenge)
+ *
+ * But if the client gets the challenge correct,
+ * we're not too worried about the Id.
+ */
+ if (((vp->da->vendor == 0) && (vp->da->attr == PW_CHAP_CHALLENGE)) ||
+ ((vp->da->vendor == VENDORPEC_MICROSOFT) && (vp->da->attr == PW_MSCHAP_CHALLENGE))) {
+ uint8_t challenge[17];
+
+ if ((vp->vp_length < 8) ||
+ (vp->vp_length > 16)) {
+ RDEBUG("Tunneled challenge has invalid length");
+ fr_pair_list_free(&first);
+ fr_pair_list_free(&vp);
+ return NULL;
+ }
+
+ /*
+ * TLSv1.3 exports a different key depending on the length
+ * requested so ask for *exactly* what the spec requires
+ */
+ eapttls_gen_challenge(ssl, challenge, vp->vp_length + 1);
+
+ if (memcmp(challenge, vp->vp_octets,
+ vp->vp_length) != 0) {
+ RDEBUG("Tunneled challenge is incorrect");
+ fr_pair_list_free(&first);
+ fr_pair_list_free(&vp);
+ return NULL;
+ }
+ }
+
+ /*
+ * Update the list.
+ */
+ fr_cursor_insert(&out, vp);
+
+ next_attr:
+ if (data_left <= attr_len) break;
+
+ data_left -= attr_len;
+ data += (attr_len - offset);
+ }
+
+ /*
+ * We got this far. It looks OK.
+ */
+ return first;
+}
+
+/*
+ * Convert VALUE_PAIR's to diameter attributes, and write them
+ * to an SSL session.
+ *
+ * The ONLY VALUE_PAIR's which may be passed to this function
+ * are ones which can go inside of a RADIUS (i.e. diameter)
+ * packet. So no server-configuration attributes, or the like.
+ */
+static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *first)
+{
+ /*
+ * RADIUS packets are no more than 4k in size, so if
+ * we've got more than 4k of data to write, it's very
+ * bad.
+ */
+ uint8_t buffer[4096];
+ uint8_t *p;
+ uint32_t attr;
+ uint32_t length;
+ uint32_t vendor;
+ size_t total;
+ uint64_t attr64;
+ VALUE_PAIR *vp;
+ vp_cursor_t cursor;
+
+ p = buffer;
+ total = 0;
+
+ for (vp = fr_cursor_init(&cursor, &first); vp; vp = fr_cursor_next(&cursor)) {
+ /*
+ * Too much data: die.
+ */
+ if ((total + vp->vp_length + 12) >= sizeof(buffer)) {
+ RDEBUG2("output buffer is full!");
+ return 0;
+ }
+
+ /*
+ * Hmm... we don't group multiple EAP-Messages
+ * together. Maybe we should...
+ */
+
+ length = vp->vp_length;
+ vendor = vp->da->vendor;
+ if (vendor != 0) {
+ attr = vp->da->attr & 0xffff;
+ length |= ((uint32_t)1 << 31);
+ } else {
+ attr = vp->da->attr;
+ }
+
+ /*
+ * Hmm... set the M bit for all attributes?
+ */
+ length |= (1 << 30);
+
+ attr = ntohl(attr);
+
+ memcpy(p, &attr, sizeof(attr));
+ p += 4;
+ total += 4;
+
+ length += 8; /* includes 8 bytes of attr & length */
+
+ if (vendor != 0) {
+ length += 4; /* include 4 bytes of vendor */
+
+ length = ntohl(length);
+ memcpy(p, &length, sizeof(length));
+ p += 4;
+ total += 4;
+
+ vendor = ntohl(vendor);
+ memcpy(p, &vendor, sizeof(vendor));
+ p += 4;
+ total += 4;
+ } else {
+ length = ntohl(length);
+ memcpy(p, &length, sizeof(length));
+ p += 4;
+ total += 4;
+ }
+
+ switch (vp->da->type) {
+ case PW_TYPE_INTEGER:
+ case PW_TYPE_DATE:
+ attr = htonl(vp->vp_integer); /* stored in host order */
+ memcpy(p, &attr, sizeof(attr));
+ length = 4;
+ break;
+
+ case PW_TYPE_INTEGER64:
+ attr64 = htonll(vp->vp_integer64); /* stored in host order */
+ memcpy(p, &attr64, sizeof(attr64));
+ length = 8;
+ break;
+
+ case PW_TYPE_IPV4_ADDR:
+ memcpy(p, &vp->vp_ipaddr, 4); /* network order */
+ length = 4;
+ break;
+
+ case PW_TYPE_STRING:
+ case PW_TYPE_OCTETS:
+ default:
+ memcpy(p, vp->vp_strvalue, vp->vp_length);
+ length = vp->vp_length;
+ break;
+ }
+
+ /*
+ * Skip to the end of the data.
+ */
+ p += length;
+ total += length;
+
+ /*
+ * Align the data to a multiple of 4 bytes.
+ */
+ if ((total & 0x03) != 0) {
+ size_t i;
+
+ length = 4 - (total & 0x03);
+ for (i = 0; i < length; i++) {
+ *p = '\0';
+ p++;
+ total++;
+ }
+ }
+ } /* loop over the VP's to write. */
+
+ /*
+ * Write the data in the buffer to the SSL session.
+ */
+ if (total > 0) {
+#ifndef NDEBUG
+ size_t i;
+
+ if ((rad_debug_lvl > 2) && fr_log_fp) {
+ for (i = 0; i < total; i++) {
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, " TTLS tunnel data out %04x: ", (int) i);
+
+ fprintf(fr_log_fp, "%02x ", buffer[i]);
+
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+ }
+ if ((total & 0x0f) != 0) fprintf(fr_log_fp, "\n");
+ }
+#endif
+
+ (tls_session->record_plus)(&tls_session->clean_in, buffer, total);
+
+ /*
+ * FIXME: Check the return code.
+ */
+ tls_handshake_send(request, tls_session);
+ }
+
+ /*
+ * Everything's OK.
+ */
+ return 1;
+}
+
+/*
+ * Use a reply packet to determine what to do.
+ */
+static rlm_rcode_t CC_HINT(nonnull) process_reply(eap_handler_t *handler, tls_session_t *tls_session,
+ REQUEST *request, RADIUS_PACKET *reply)
+{
+ rlm_rcode_t rcode = RLM_MODULE_REJECT;
+ VALUE_PAIR *vp;
+ ttls_tunnel_t *t = tls_session->opaque;
+
+ rad_assert(handler->request == request);
+
+ /*
+ * If the response packet was Access-Accept, then
+ * we're OK. If not, die horribly.
+ *
+ * FIXME: Take MS-CHAP2-Success attribute, and
+ * tunnel it back to the client, to authenticate
+ * ourselves to the client.
+ *
+ * FIXME: If we have an Access-Challenge, then
+ * the Reply-Message is tunneled back to the client.
+ *
+ * FIXME: If we have an EAP-Message, then that message
+ * must be tunneled back to the client.
+ *
+ * FIXME: If we have an Access-Challenge with a State
+ * attribute, then do we tunnel that to the client, or
+ * keep track of it ourselves?
+ *
+ * FIXME: EAP-Messages can only start with 'identity',
+ * NOT 'eap start', so we should check for that....
+ */
+ switch (reply->code) {
+ case PW_CODE_ACCESS_ACCEPT:
+ tls_session->authentication_success = true;
+ RDEBUG("Got tunneled Access-Accept");
+
+ rcode = RLM_MODULE_OK;
+
+ /*
+ * Always delete MPPE keys & encryption policy
+ * from the tunneled reply. These never get sent
+ * back to the user.
+ */
+ fr_pair_delete_by_num(&reply->vps, 7, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 8, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 16, VENDORPEC_MICROSOFT, TAG_ANY);
+ fr_pair_delete_by_num(&reply->vps, 17, VENDORPEC_MICROSOFT, TAG_ANY);
+
+ /*
+ * MS-CHAP2-Success means that we do NOT return
+ * an Access-Accept, but instead tunnel that
+ * attribute to the client, and keep going with
+ * the TTLS session. Once the client accepts
+ * our identity, it will respond with an empty
+ * packet, and we will send EAP-Success.
+ */
+ vp = NULL;
+ fr_pair_list_mcopy_by_num(tls_session, &vp, &reply->vps, PW_MSCHAP2_SUCCESS, VENDORPEC_MICROSOFT, TAG_ANY);
+ if (vp) {
+ RDEBUG("Got MS-CHAP2-Success, tunneling it to the client in a challenge");
+ rcode = RLM_MODULE_HANDLED;
+ t->authenticated = true;
+
+ /*
+ * Use the tunneled reply, but not now.
+ */
+ if (t->use_tunneled_reply) {
+ rad_assert(!t->accept_vps);
+ fr_pair_list_mcopy_by_num(t, &t->accept_vps, &reply->vps,
+ 0, 0, TAG_ANY);
+ rad_assert(!reply->vps);
+ }
+
+ } else { /* no MS-CHAP2-Success */
+ /*
+ * Can only have EAP-Message if there's
+ * no MS-CHAP2-Success.
+ *
+ * We also do NOT tunnel the EAP-Success
+ * attribute back to the client, as the client
+ * can figure it out, from the non-tunneled
+ * EAP-Success packet.
+ */
+ fr_pair_list_mcopy_by_num(tls_session, &vp, &reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ fr_pair_list_free(&vp);
+ }
+
+ /* move channel binding responses; we need to send them */
+ fr_pair_list_mcopy_by_num(tls_session, &vp, &reply->vps, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY);
+ if (fr_pair_find_by_num(vp, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY) != NULL) {
+ t->authenticated = true;
+ /*
+ * Use the tunneled reply, but not now.
+ */
+ if (t->use_tunneled_reply) {
+ rad_assert(!t->accept_vps);
+ fr_pair_list_mcopy_by_num(t, &t->accept_vps, &reply->vps,
+ 0, 0, TAG_ANY);
+ rad_assert(!reply->vps);
+ }
+ rcode = RLM_MODULE_HANDLED;
+ }
+
+ /*
+ * Handle the ACK, by tunneling any necessary reply
+ * VP's back to the client.
+ */
+ if (vp) {
+ RDEBUG("Sending tunneled reply attributes");
+ rdebug_pair_list(L_DBG_LVL_1, request, vp, NULL);
+
+ vp2diameter(request, tls_session, vp);
+ fr_pair_list_free(&vp);
+ }
+
+ /*
+ * If we've been told to use the attributes from
+ * the reply, then do so.
+ *
+ * WARNING: This may leak information about the
+ * tunneled user!
+ */
+ if (t->use_tunneled_reply) {
+ fr_pair_delete_by_num(&reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
+ fr_pair_list_mcopy_by_num(request->reply, &request->reply->vps,
+ &reply->vps, 0, 0, TAG_ANY);
+ }
+ break;
+
+
+ case PW_CODE_ACCESS_REJECT:
+ RDEBUG("Got tunneled Access-Reject");
+ rcode = RLM_MODULE_REJECT;
+ break;
+
+ /*
+ * Handle Access-Challenge, but only if we
+ * send tunneled reply data. This is because
+ * an Access-Challenge means that we MUST tunnel
+ * a Reply-Message to the client.
+ */
+ case PW_CODE_ACCESS_CHALLENGE:
+ RDEBUG("Got tunneled Access-Challenge");
+
+ /*
+ * Keep the State attribute, if necessary.
+ *
+ * Get rid of the old State, too.
+ */
+ fr_pair_list_free(&t->state);
+ fr_pair_list_mcopy_by_num(t, &t->state, &reply->vps, PW_STATE, 0, TAG_ANY);
+
+ /*
+ * We should really be a bit smarter about this,
+ * and move over only those attributes which
+ * are relevant to the authentication request,
+ * but that's a lot more work, and this "dumb"
+ * method works in 99.9% of the situations.
+ */
+ vp = NULL;
+ fr_pair_list_mcopy_by_num(t, &vp, &reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+
+ /*
+ * There MUST be a Reply-Message in the challenge,
+ * which we tunnel back to the client.
+ *
+ * If there isn't one in the reply VP's, then
+ * we MUST create one, with an empty string as
+ * it's value.
+ */
+ fr_pair_list_mcopy_by_num(t, &vp, &reply->vps, PW_REPLY_MESSAGE, 0, TAG_ANY);
+
+ /* also move chbind messages, if any */
+ fr_pair_list_mcopy_by_num(t, &vp, &reply->vps, PW_UKERNA_CHBIND, VENDORPEC_UKERNA,
+ TAG_ANY);
+
+ /*
+ * Handle the ACK, by tunneling any necessary reply
+ * VP's back to the client.
+ */
+ if (vp) {
+ vp2diameter(request, tls_session, vp);
+ fr_pair_list_free(&vp);
+ }
+ rcode = RLM_MODULE_HANDLED;
+ break;
+
+ default:
+ RDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
+ rcode = RLM_MODULE_INVALID;
+ break;
+ }
+
+ return rcode;
+}
+
+
+#ifdef WITH_PROXY
+/*
+ * Do post-proxy processing,
+ */
+static int CC_HINT(nonnull) eapttls_postproxy(eap_handler_t *handler, void *data)
+{
+ int rcode;
+ tls_session_t *tls_session = (tls_session_t *) data;
+ REQUEST *fake, *request = handler->request;
+
+ RDEBUG("Passing reply from proxy back into the tunnel");
+
+ /*
+ * If there was a fake request associated with the proxied
+ * request, do more processing of it.
+ */
+ fake = (REQUEST *) request_data_get(handler->request,
+ handler->request->proxy,
+ REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);
+
+ /*
+ * Do the callback, if it exists, and if it was a success.
+ */
+ if (fake && (handler->request->proxy_reply->code == PW_CODE_ACCESS_ACCEPT)) {
+ /*
+ * Terrible hacks.
+ */
+ rad_assert(!fake->packet);
+ fake->packet = talloc_steal(fake, request->proxy);
+ fake->packet->src_ipaddr = request->packet->src_ipaddr;
+ request->proxy = NULL;
+
+ rad_assert(!fake->reply);
+ fake->reply = talloc_steal(fake, request->proxy_reply);
+ request->proxy_reply = NULL;
+
+ if ((rad_debug_lvl > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "server %s {\n",
+ (!fake->server) ? "" : fake->server);
+ }
+
+ /*
+ * Perform a post-auth stage for the tunneled
+ * session.
+ */
+ fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
+ rcode = rad_postauth(fake);
+ RDEBUG2("post-auth returns %d", rcode);
+
+ if ((rad_debug_lvl > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "} # server %s\n",
+ (!fake->server) ? "" : fake->server);
+
+ RDEBUG("Final reply from tunneled session code %d", fake->reply->code);
+ rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);
+ }
+
+ /*
+ * Terrible hacks.
+ */
+ request->proxy = talloc_steal(request, fake->packet);
+ fake->packet = NULL;
+ request->proxy_reply = talloc_steal(request, fake->reply);
+ fake->reply = NULL;
+
+ /*
+ * And we're done with this request.
+ */
+
+ switch (rcode) {
+ case RLM_MODULE_FAIL:
+ talloc_free(fake);
+ eaptls_fail(handler, 0);
+ return 0;
+
+ default: /* Don't Do Anything */
+ RDEBUG2("Got reply %d",
+ request->proxy_reply->code);
+ break;
+ }
+ }
+ talloc_free(fake); /* robust if !fake */
+
+ /*
+ * Process the reply from the home server.
+ */
+ rcode = process_reply(handler, tls_session, handler->request, handler->request->proxy_reply);
+
+ /*
+ * The proxy code uses the reply from the home server as
+ * the basis for the reply to the NAS. We don't want that,
+ * so we toss it, after we've had our way with it.
+ */
+ fr_pair_list_free(&handler->request->proxy_reply->vps);
+
+ switch (rcode) {
+ case RLM_MODULE_REJECT:
+ RDEBUG("Reply was rejected");
+ break;
+
+ case RLM_MODULE_HANDLED:
+ RDEBUG("Reply was handled");
+ eaptls_request(handler->eap_ds, tls_session);
+ request->proxy_reply->code = PW_CODE_ACCESS_CHALLENGE;
+ return 1;
+
+ case RLM_MODULE_OK:
+ RDEBUG("Reply was OK");
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ return eaptls_success(handler, 0);
+
+ default:
+ RDEBUG("Reply was unknown");
+ break;
+ }
+
+ eaptls_fail(handler, 0);
+ return 0;
+}
+
+#endif /* WITH_PROXY */
+
+/*
+ * Process the "diameter" contents of the tunneled data.
+ */
+int eapttls_process(eap_handler_t *handler, tls_session_t *tls_session)
+{
+ PW_CODE code = PW_CODE_ACCESS_REJECT;
+ rlm_rcode_t rcode;
+ REQUEST *fake;
+ VALUE_PAIR *vp;
+ ttls_tunnel_t *t;
+ uint8_t const *data;
+ size_t data_len;
+ REQUEST *request = handler->request;
+ chbind_packet_t *chbind;
+
+ /*
+ * Just look at the buffer directly, without doing
+ * record_minus.
+ */
+ data_len = tls_session->clean_out.used;
+ tls_session->clean_out.used = 0;
+ data = tls_session->clean_out.data;
+
+ t = (ttls_tunnel_t *) tls_session->opaque;
+
+ /*
+ * If there's no data, maybe this is an ACK to an
+ * MS-CHAP2-Success.
+ */
+ if (data_len == 0) {
+ if (t->authenticated) {
+ RDEBUG("Got ACK, and the user was already authenticated");
+ return PW_CODE_ACCESS_ACCEPT;
+ } /* else no session, no data, die. */
+
+ /*
+ * FIXME: Call SSL_get_error() to see what went
+ * wrong.
+ */
+ RDEBUG2("SSL_read Error");
+ return PW_CODE_ACCESS_REJECT;
+ }
+
+#ifndef NDEBUG
+ if ((rad_debug_lvl > 2) && fr_log_fp) {
+ size_t i;
+
+ for (i = 0; i < data_len; i++) {
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, " TTLS tunnel data in %04x: ", (int) i);
+
+ fprintf(fr_log_fp, "%02x ", data[i]);
+
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+ }
+ if ((data_len & 0x0f) != 0) fprintf(fr_log_fp, "\n");
+ }
+#endif
+
+ if (!diameter_verify(request, data, data_len)) {
+ return PW_CODE_ACCESS_REJECT;
+ }
+
+ /*
+ * Allocate a fake REQUEST structure.
+ */
+ fake = request_alloc_fake(request);
+
+ rad_assert(!fake->packet->vps);
+
+ /*
+ * Add the tunneled attributes to the fake request.
+ */
+ fake->packet->vps = diameter2vp(request, fake, tls_session->ssl, data, data_len);
+ if (!fake->packet->vps) {
+ talloc_free(fake);
+ return PW_CODE_ACCESS_REJECT;
+ }
+
+ /*
+ * Tell the request that it's a fake one.
+ */
+ fr_pair_make(fake->packet, &fake->packet->vps, "Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
+
+ RDEBUG("Got tunneled request");
+ rdebug_pair_list(L_DBG_LVL_1, request, fake->packet->vps, NULL);
+
+ /*
+ * Update other items in the REQUEST data structure.
+ */
+ fake->username = fr_pair_find_by_num(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ fake->password = fr_pair_find_by_num(fake->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
+
+ /*
+ * No User-Name, try to create one from stored data.
+ */
+ if (!fake->username) {
+ /*
+ * No User-Name in the stored data, look for
+ * an EAP-Identity, and pull it out of there.
+ */
+ if (!t->username) {
+ vp = fr_pair_find_by_num(fake->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
+ if (vp &&
+ (vp->vp_length >= EAP_HEADER_LEN + 2) &&
+ (vp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
+ (vp->vp_strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY) &&
+ (vp->vp_strvalue[EAP_HEADER_LEN + 1] != 0)) {
+ /*
+ * Create & remember a User-Name
+ */
+ t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
+ rad_assert(t->username != NULL);
+
+ fr_pair_value_bstrncpy(t->username, vp->vp_octets + 5, vp->vp_length - 5);
+
+ RDEBUG("Got tunneled identity of %s",
+ t->username->vp_strvalue);
+
+ /*
+ * If there's a default EAP type,
+ * set it here.
+ */
+ if (t->default_method != 0) {
+ RDEBUG("Setting default EAP type for tunneled EAP session");
+ vp = fr_pair_afrom_num(fake, PW_EAP_TYPE, 0);
+ rad_assert(vp != NULL);
+ vp->vp_integer = t->default_method;
+ fr_pair_add(&fake->config, vp);
+ }
+
+ } else {
+ /*
+ * Don't reject the request outright,
+ * as it's permitted to do EAP without
+ * user-name.
+ */
+ RWDEBUG2("No EAP-Identity found to start EAP conversation");
+ }
+ } /* else there WAS a t->username */
+
+ if (t->username) {
+ vp = fr_pair_list_copy(fake->packet, t->username);
+ fr_pair_add(&fake->packet->vps, vp);
+ fake->username = fr_pair_find_by_num(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ }
+ } /* else the request ALREADY had a User-Name */
+
+ /*
+ * Add the State attribute, too, if it exists.
+ */
+ if (t->state) {
+ vp = fr_pair_list_copy(fake->packet, t->state);
+ if (vp) fr_pair_add(&fake->packet->vps, vp);
+ }
+
+ /*
+ * If this is set, we copy SOME of the request attributes
+ * from outside of the tunnel to inside of the tunnel.
+ *
+ * We copy ONLY those attributes which do NOT already
+ * exist in the tunneled request.
+ */
+ if (t->copy_request_to_tunnel) {
+ VALUE_PAIR *copy;
+ vp_cursor_t cursor;
+
+ for (vp = fr_cursor_init(&cursor, &request->packet->vps); vp; vp = fr_cursor_next(&cursor)) {
+ /*
+ * The attribute is a server-side thingy,
+ * don't copy it.
+ */
+ if ((vp->da->attr > 255) &&
+ (vp->da->vendor == 0)) {
+ continue;
+ }
+
+ /*
+ * The outside attribute is already in the
+ * tunnel, don't copy it.
+ *
+ * This works for BOTH attributes which
+ * are originally in the tunneled request,
+ * AND attributes which are copied there
+ * from below.
+ */
+ if (fr_pair_find_by_da(fake->packet->vps, vp->da, TAG_ANY)) {
+ continue;
+ }
+
+ /*
+ * Some attributes are handled specially.
+ */
+ if (!vp->da->vendor) switch (vp->da->attr) {
+ /*
+ * NEVER copy Message-Authenticator,
+ * EAP-Message, or State. They're
+ * only for outside of the tunnel.
+ */
+ case PW_USER_NAME:
+ case PW_USER_PASSWORD:
+ case PW_CHAP_PASSWORD:
+ case PW_CHAP_CHALLENGE:
+ case PW_PROXY_STATE:
+ case PW_MESSAGE_AUTHENTICATOR:
+ case PW_EAP_MESSAGE:
+ case PW_STATE:
+ continue;
+
+ /*
+ * By default, copy it over.
+ */
+ default:
+ break;
+ }
+
+ /*
+ * Don't copy from the head, we've already
+ * checked it.
+ */
+ copy = fr_pair_list_copy_by_num(fake->packet, vp, vp->da->attr, vp->da->vendor, TAG_ANY);
+ fr_pair_add(&fake->packet->vps, copy);
+ }
+ }
+
+ if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
+ fake->server = vp->vp_strvalue;
+
+ } else if (t->virtual_server) {
+ fake->server = t->virtual_server;
+
+ } /* else fake->server == request->server */
+
+
+ if ((rad_debug_lvl > 0) && fr_log_fp) {
+ RDEBUG("Sending tunneled request");
+ }
+
+ /*
+ * Process channel binding.
+ */
+ chbind = eap_chbind_vp2packet(fake, fake->packet->vps);
+ if (chbind) {
+ PW_CODE chbind_code;
+ CHBIND_REQ *req = talloc_zero(fake, CHBIND_REQ);
+
+ RDEBUG("received chbind request");
+ req->request = chbind;
+ if (fake->username) {
+ req->username = fake->username;
+ } else {
+ req->username = NULL;
+ }
+ chbind_code = chbind_process(request, req);
+
+ /* encapsulate response here */
+ if (req->response) {
+ RDEBUG("sending chbind response");
+ fr_pair_add(&fake->reply->vps,
+ eap_chbind_packet2vp(fake->reply, req->response));
+ } else {
+ RDEBUG("no chbind response");
+ }
+
+ /* clean up chbind req */
+ talloc_free(req);
+
+ if (chbind_code != PW_CODE_ACCESS_ACCEPT) {
+ return chbind_code;
+ }
+ }
+
+ /*
+ * Call authentication recursively, which will
+ * do PAP, CHAP, MS-CHAP, etc.
+ */
+ rad_virtual_server(fake);
+
+ /*
+ * Decide what to do with the reply.
+ */
+ switch (fake->reply->code) {
+ case 0: /* No reply code, must be proxied... */
+#ifdef WITH_PROXY
+ vp = fr_pair_find_by_num(fake->config, PW_PROXY_TO_REALM, 0, TAG_ANY);
+ if (vp) {
+ eap_tunnel_data_t *tunnel;
+ RDEBUG("Tunneled authentication will be proxied to %s", vp->vp_strvalue);
+
+ /*
+ * Tell the original request that it's going
+ * to be proxied.
+ */
+ fr_pair_list_mcopy_by_num(request, &request->config,
+ &fake->config,
+ PW_PROXY_TO_REALM, 0, TAG_ANY);
+
+ /*
+ * Seed the proxy packet with the
+ * tunneled request.
+ */
+ rad_assert(!request->proxy);
+ request->proxy = talloc_steal(request, fake->packet);
+ memset(&request->proxy->src_ipaddr, 0,
+ sizeof(request->proxy->src_ipaddr));
+ memset(&request->proxy->src_ipaddr, 0,
+ sizeof(request->proxy->src_ipaddr));
+ request->proxy->src_port = 0;
+ request->proxy->dst_port = 0;
+ fake->packet = NULL;
+ rad_free(&fake->reply);
+ fake->reply = NULL;
+
+ /*
+ * Set up the callbacks for the tunnel
+ */
+ tunnel = talloc_zero(request, eap_tunnel_data_t);
+ tunnel->tls_session = tls_session;
+ tunnel->callback = eapttls_postproxy;
+
+ /*
+ * Associate the callback with the request.
+ */
+ code = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK,
+ tunnel, false);
+ rad_assert(code == 0);
+
+ /*
+ * rlm_eap.c has taken care of associating
+ * the handler with the fake request.
+ *
+ * So we associate the fake request with
+ * this request.
+ */
+ code = request_data_add(request, request->proxy, REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
+ fake, true);
+ rad_assert(code == 0);
+ fake = NULL;
+
+ /*
+ * Didn't authenticate the packet, but
+ * we're proxying it.
+ */
+ code = PW_CODE_STATUS_CLIENT;
+
+ } else
+#endif /* WITH_PROXY */
+ {
+ RDEBUG("No tunneled reply was found for request %d , and the request was not proxied: rejecting the user.",
+ request->number);
+ code = PW_CODE_ACCESS_REJECT;
+ }
+ break;
+
+ default:
+ /*
+ * Returns RLM_MODULE_FOO, and we want to return PW_FOO
+ */
+ rcode = process_reply(handler, tls_session, request, fake->reply);
+ switch (rcode) {
+ case RLM_MODULE_REJECT:
+ code = PW_CODE_ACCESS_REJECT;
+ break;
+
+ case RLM_MODULE_HANDLED:
+ code = PW_CODE_ACCESS_CHALLENGE;
+ break;
+
+ case RLM_MODULE_OK:
+ code = PW_CODE_ACCESS_ACCEPT;
+ break;
+
+ default:
+ code = PW_CODE_ACCESS_REJECT;
+ break;
+ }
+ break;
+ }
+
+ talloc_free(fake);
+
+ return code;
+}