* text=auto
* ident
+*.h linguist-language=c
+*.c linguist-language=c
+doc/* linguist-documentation
CC = @CC@
RANLIB = @RANLIB@
-INCLUDE = -I${top_srcdir} -I${top_srcdir}/src \
- -include ${top_srcdir}/src/freeradius-devel/autoconf.h \
- -include ${top_srcdir}/src/freeradius-devel/build.h \
- -include ${top_srcdir}/src/freeradius-devel/features.h \
- -include ${top_srcdir}/src/freeradius-devel/radpaths.h
+INCLUDE = -I. -Isrc \
+ -include src/freeradius-devel/autoconf.h \
+ -include src/freeradius-devel/build.h \
+ -include src/freeradius-devel/features.h \
+ -include src/freeradius-devel/radpaths.h
CFLAGS = $(INCLUDE) -fno-strict-aliasing @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LIBPREFIX = @LIBPREFIX@
#
ifeq "$(USE_SHARED_LIBS)" "yes"
TESTBINDIR = ./$(BUILD_DIR)/bin/local
- TESTBIN = $(JLIBTOOL) --quiet --mode=execute $(TESTBINDIR)
+ TESTBIN = FR_LIBRARY_PATH=./build/lib/.libs $(JLIBTOOL) --quiet --mode=execute $(TESTBINDIR)
else
TESTBINDIR = ./$(BUILD_DIR)/bin
TESTBIN = ./$(BUILD_DIR)/bin
# Version: $Id$
#
+#
+# The default rule is "all".
+#
+all:
+
$(if $(wildcard Make.inc),,$(error Missing 'Make.inc' Run './configure [options]' and retry))
include Make.inc
$(BUILD_DIR)/tests/radiusd-c: raddb/test.conf ${BUILD_DIR}/bin/radiusd | build.raddb
@$(MAKE) -C raddb/certs
@printf "radiusd -C... "
- @if ! ./build/make/jlibtool --mode=execute ./build/bin/radiusd -XCMd ./raddb -D ./share -n test > $(BUILD_DIR)/tests/radiusd.config.log; then \
+ @if ! FR_LIBRARY_PATH=./build/lib/local/.libs/ ./build/make/jlibtool --mode=execute ./build/bin/radiusd -XCMd ./raddb -D ./share -n test > $(BUILD_DIR)/tests/radiusd.config.log; then \
rm -f raddb/test.conf; \
cat $(BUILD_DIR)/tests/radiusd.config.log; \
echo "fail"; \
# Â the above tests
ifneq "$(findstring travis,${prefix})" ""
travis-test: raddb/test.conf test
- @./build/make/jlibtool --mode=execute ./build/bin/radiusd -xxxv -n test
+ @FR_LIBRARY_PATH=./build/lib/local/.libs/ ./build/make/jlibtool --mode=execute ./build/bin/radiusd -xxxv -n test
@rm -f raddb/test.conf
@$(MAKE) install
@perl -p -i -e 's/allow_vulnerable_openssl = no/allow_vulnerable_openssl = yes/' ${raddbdir}/radiusd.conf
#
export DESTDIR := $(R)
-.PHONY: install.bindir
-install.bindir:
- @[ -d $(R)$(bindir) ] || $(INSTALL) -d -m 755 $(R)$(bindir)
-
-.PHONY: install.sbindir
-install.sbindir:
- @[ -d $(R)$(sbindir) ] || $(INSTALL) -d -m 755 $(R)$(sbindir)
-
-.PHONY: install.dirs
-install.dirs: install.bindir install.sbindir
- @$(INSTALL) -d -m 755 $(R)$(mandir)
- @$(INSTALL) -d -m 755 $(R)$(RUNDIR)
- @$(INSTALL) -d -m 700 $(R)$(logdir)
- @$(INSTALL) -d -m 700 $(R)$(radacctdir)
- @$(INSTALL) -d -m 755 $(R)$(datadir)
- @$(INSTALL) -d -m 755 $(R)$(dictdir)
-
DICTIONARIES := $(wildcard share/dictionary*)
install.share: $(addprefix $(R)$(dictdir)/,$(notdir $(DICTIONARIES)))
$(R)$(mandir)/%: man/%
@echo INSTALL $(notdir $<)
- @$(INSTALL) -m 644 $< $@
+ @sed -e "s,/etc/raddb,$(raddbdir),g" \
+ -e "s,/usr/local/share,$(datarootdir),g" \
+ $< > $<.subst
+ @$(INSTALL) -m 644 $<.subst $@
+ @rm $<.subst
#
# Don't install rlm_test
#
ALL_INSTALL := $(patsubst %rlm_test.la,,$(ALL_INSTALL))
-install: install.dirs install.share install.man
+install: install.share install.man
+ @$(INSTALL) -d -m 700 $(R)$(logdir)
+ @$(INSTALL) -d -m 700 $(R)$(radacctdir)
ifneq ($(RADMIN),)
ifneq ($(RGROUP),)
freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz: .git
git archive --format=tar --prefix=freeradius-server-$(RADIUSD_VERSION_STRING)/ $(BRANCH) | gzip > $@
-freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz.sig: freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz
- gpg --default-key aland@freeradius.org -b $<
-
freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2: .git
git archive --format=tar --prefix=freeradius-server-$(RADIUSD_VERSION_STRING)/ $(BRANCH) | bzip2 > $@
-freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2.sig: freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2
- gpg --default-key aland@freeradius.org -b $<
+%.sig: %
+ gpg --default-key packages@freeradius.org -b $<
# high-level targets
.PHONY: dist-check
-# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-# 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
-# Inc.
-# Written by Gordon Matzigkeit, 1996
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-m4_define([_LT_COPYING], [dnl
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-# 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
-# Inc.
-# Written by Gordon Matzigkeit, 1996
-#
-# This file is part of GNU Libtool.
-#
-# GNU Libtool 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.
-#
-# As a special exception to the GNU General Public License,
-# if you distribute this file as part of a program or library that
-# is built using GNU Libtool, you may include this file under the
-# same distribution terms that you use for the rest of that program.
-#
-# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy
-# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
-# obtained by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-])
-
-# serial 57 LT_INIT
-
-
-# LT_PREREQ(VERSION)
-# ------------------
-# Complain and exit if this libtool version is less that VERSION.
-m4_defun([LT_PREREQ],
-[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
- [m4_default([$3],
- [m4_fatal([Libtool version $1 or higher is required],
- 63)])],
- [$2])])
-
-
-# _LT_CHECK_BUILDDIR
-# ------------------
-# Complain if the absolute build directory name contains unusual characters
-m4_defun([_LT_CHECK_BUILDDIR],
-[case `pwd` in
- *\ * | *\ *)
- AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
-esac
-])
-
-
-# LT_INIT([OPTIONS])
-# ------------------
-AC_DEFUN([LT_INIT],
-[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
-AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
-AC_BEFORE([$0], [LT_LANG])dnl
-AC_BEFORE([$0], [LT_OUTPUT])dnl
-AC_BEFORE([$0], [LTDL_INIT])dnl
-m4_require([_LT_CHECK_BUILDDIR])dnl
-
-dnl Autoconf doesn't catch unexpanded LT_ macros by default:
-m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
-m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
-dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
-dnl unless we require an AC_DEFUNed macro:
-AC_REQUIRE([LTOPTIONS_VERSION])dnl
-AC_REQUIRE([LTSUGAR_VERSION])dnl
-AC_REQUIRE([LTVERSION_VERSION])dnl
-AC_REQUIRE([LTOBSOLETE_VERSION])dnl
-
-_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
-
-dnl Parse OPTIONS
-_LT_SET_OPTIONS([$0], [$1])
-
-_LT_SETUP
-
-# Only expand once:
-m4_define([LT_INIT])
-])# LT_INIT
-
-# Old names:
-AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
-AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
-dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
-
-
-# _LT_CC_BASENAME(CC)
-# -------------------
-# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
-m4_defun([_LT_CC_BASENAME],
-[for cc_temp in $1""; do
- case $cc_temp in
- compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
- distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
-])
-
-
-# _LT_FILEUTILS_DEFAULTS
-# ----------------------
-# It is okay to use these file commands and assume they have been set
-# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
-m4_defun([_LT_FILEUTILS_DEFAULTS],
-[: ${CP="cp -f"}
-: ${MV="mv -f"}
-: ${RM="rm -f"}
-])# _LT_FILEUTILS_DEFAULTS
-
-
-# _LT_SETUP
-# ---------
-m4_defun([_LT_SETUP],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
-AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
-
-_LT_DECL([], [host_alias], [0], [The host system])dnl
-_LT_DECL([], [host], [0])dnl
-_LT_DECL([], [host_os], [0])dnl
-dnl
-_LT_DECL([], [build_alias], [0], [The build system])dnl
-_LT_DECL([], [build], [0])dnl
-_LT_DECL([], [build_os], [0])dnl
-dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([LT_PATH_LD])dnl
-AC_REQUIRE([LT_PATH_NM])dnl
-dnl
-AC_REQUIRE([AC_PROG_LN_S])dnl
-test -z "$LN_S" && LN_S="ln -s"
-_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
-dnl
-AC_REQUIRE([LT_CMD_MAX_LEN])dnl
-_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
-_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
-dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_CHECK_SHELL_FEATURES])dnl
-m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
-m4_require([_LT_CMD_RELOAD])dnl
-m4_require([_LT_CHECK_MAGIC_METHOD])dnl
-m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
-m4_require([_LT_CMD_OLD_ARCHIVE])dnl
-m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
-m4_require([_LT_WITH_SYSROOT])dnl
-
-_LT_CONFIG_LIBTOOL_INIT([
-# See if we are running on zsh, and set the options which allow our
-# commands through without removal of \ escapes INIT.
-if test -n "\${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-])
-if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-
-_LT_CHECK_OBJDIR
-
-m4_require([_LT_TAG_COMPILER])dnl
-
-case $host_os in
-aix3*)
- # AIX sometimes has problems with the GCC collect2 program. For some
- # reason, if we set the COLLECT_NAMES environment variable, the problems
- # vanish in a puff of smoke.
- if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
- fi
- ;;
-esac
-
-# Global variables:
-ofile=libtool
-can_build_shared=yes
-
-# All known linkers require a `.a' archive for static linking (except MSVC,
-# which needs '.lib').
-libext=a
-
-with_gnu_ld="$lt_cv_prog_gnu_ld"
-
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-
-# Set sane defaults for various variables
-test -z "$CC" && CC=cc
-test -z "$LTCC" && LTCC=$CC
-test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
-test -z "$LD" && LD=ld
-test -z "$ac_objext" && ac_objext=o
-
-_LT_CC_BASENAME([$compiler])
-
-# Only perform the check for file, if the check method requires it
-test -z "$MAGIC_CMD" && MAGIC_CMD=file
-case $deplibs_check_method in
-file_magic*)
- if test "$file_magic_cmd" = '$MAGIC_CMD'; then
- _LT_PATH_MAGIC
- fi
- ;;
-esac
-
-# Use C for the default configuration in the libtool script
-LT_SUPPORTED_TAG([CC])
-_LT_LANG_C_CONFIG
-_LT_LANG_DEFAULT_CONFIG
-_LT_CONFIG_COMMANDS
-])# _LT_SETUP
-
-
-# _LT_PREPARE_SED_QUOTE_VARS
-# --------------------------
-# Define a few sed substitution that help us do robust quoting.
-m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
-[# Backslashify metacharacters that are still active within
-# double-quoted strings.
-sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([["`\\]]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to delay expansion of an escaped single quote.
-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-])
-
-
-# So that we can recreate a full libtool script including additional
-# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
-# in macros and then make a single call at the end using the `libtool'
-# label.
-
-
-# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
-# ----------------------------------------
-# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
-m4_define([_LT_CONFIG_LIBTOOL_INIT],
-[m4_ifval([$1],
- [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
- [$1
-])])])
-
-# Initialize.
-m4_define([_LT_OUTPUT_LIBTOOL_INIT])
-
-
-# _LT_CONFIG_LIBTOOL([COMMANDS])
-# ------------------------------
-# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
-m4_define([_LT_CONFIG_LIBTOOL],
-[m4_ifval([$1],
- [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
- [$1
-])])])
-
-# Initialize.
-m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
-
-
-# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
-# -----------------------------------------------------
-m4_defun([_LT_CONFIG_SAVE_COMMANDS],
-[_LT_CONFIG_LIBTOOL([$1])
-_LT_CONFIG_LIBTOOL_INIT([$2])
-])
-
-
-# _LT_FORMAT_COMMENT([COMMENT])
-# -----------------------------
-# Add leading comment marks to the start of each line, and a trailing
-# full-stop to the whole comment if one is not present already.
-m4_define([_LT_FORMAT_COMMENT],
-[m4_ifval([$1], [
-m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
- [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
-)])
-
-
-
-
-
-# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
-# -------------------------------------------------------------------
-# CONFIGNAME is the name given to the value in the libtool script.
-# VARNAME is the (base) name used in the configure script.
-# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
-# VARNAME. Any other value will be used directly.
-m4_define([_LT_DECL],
-[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
- [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
- [m4_ifval([$1], [$1], [$2])])
- lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
- m4_ifval([$4],
- [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
- lt_dict_add_subkey([lt_decl_dict], [$2],
- [tagged?], [m4_ifval([$5], [yes], [no])])])
-])
-
-
-# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
-# --------------------------------------------------------
-m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
-
-
-# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
-# ------------------------------------------------
-m4_define([lt_decl_tag_varnames],
-[_lt_decl_filter([tagged?], [yes], $@)])
-
-
-# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
-# ---------------------------------------------------------
-m4_define([_lt_decl_filter],
-[m4_case([$#],
- [0], [m4_fatal([$0: too few arguments: $#])],
- [1], [m4_fatal([$0: too few arguments: $#: $1])],
- [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
- [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
- [lt_dict_filter([lt_decl_dict], $@)])[]dnl
-])
-
-
-# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
-# --------------------------------------------------
-m4_define([lt_decl_quote_varnames],
-[_lt_decl_filter([value], [1], $@)])
-
-
-# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
-# ---------------------------------------------------
-m4_define([lt_decl_dquote_varnames],
-[_lt_decl_filter([value], [2], $@)])
-
-
-# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
-# ---------------------------------------------------
-m4_define([lt_decl_varnames_tagged],
-[m4_assert([$# <= 2])dnl
-_$0(m4_quote(m4_default([$1], [[, ]])),
- m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
- m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
-m4_define([_lt_decl_varnames_tagged],
-[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
-
-
-# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
-# ------------------------------------------------
-m4_define([lt_decl_all_varnames],
-[_$0(m4_quote(m4_default([$1], [[, ]])),
- m4_if([$2], [],
- m4_quote(lt_decl_varnames),
- m4_quote(m4_shift($@))))[]dnl
-])
-m4_define([_lt_decl_all_varnames],
-[lt_join($@, lt_decl_varnames_tagged([$1],
- lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
-])
-
-
-# _LT_CONFIG_STATUS_DECLARE([VARNAME])
-# ------------------------------------
-# Quote a variable value, and forward it to `config.status' so that its
-# declaration there will have the same value as in `configure'. VARNAME
-# must have a single quote delimited value for this to work.
-m4_define([_LT_CONFIG_STATUS_DECLARE],
-[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
-
-
-# _LT_CONFIG_STATUS_DECLARATIONS
-# ------------------------------
-# We delimit libtool config variables with single quotes, so when
-# we write them to config.status, we have to be sure to quote all
-# embedded single quotes properly. In configure, this macro expands
-# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
-#
-# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
-m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
-[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
- [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
-
-
-# _LT_LIBTOOL_TAGS
-# ----------------
-# Output comment and list of tags supported by the script
-m4_defun([_LT_LIBTOOL_TAGS],
-[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
-available_tags="_LT_TAGS"dnl
-])
-
-
-# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
-# -----------------------------------
-# Extract the dictionary values for VARNAME (optionally with TAG) and
-# expand to a commented shell variable setting:
-#
-# # Some comment about what VAR is for.
-# visible_name=$lt_internal_name
-m4_define([_LT_LIBTOOL_DECLARE],
-[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
- [description])))[]dnl
-m4_pushdef([_libtool_name],
- m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
-m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
- [0], [_libtool_name=[$]$1],
- [1], [_libtool_name=$lt_[]$1],
- [2], [_libtool_name=$lt_[]$1],
- [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
-m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
-])
-
-
-# _LT_LIBTOOL_CONFIG_VARS
-# -----------------------
-# Produce commented declarations of non-tagged libtool config variables
-# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
-# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
-# section) are produced by _LT_LIBTOOL_TAG_VARS.
-m4_defun([_LT_LIBTOOL_CONFIG_VARS],
-[m4_foreach([_lt_var],
- m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
- [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
-
-
-# _LT_LIBTOOL_TAG_VARS(TAG)
-# -------------------------
-m4_define([_LT_LIBTOOL_TAG_VARS],
-[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
- [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
-
-
-# _LT_TAGVAR(VARNAME, [TAGNAME])
-# ------------------------------
-m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
-
-
-# _LT_CONFIG_COMMANDS
-# -------------------
-# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
-# variables for single and double quote escaping we saved from calls
-# to _LT_DECL, we can put quote escaped variables declarations
-# into `config.status', and then the shell code to quote escape them in
-# for loops in `config.status'. Finally, any additional code accumulated
-# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
-m4_defun([_LT_CONFIG_COMMANDS],
-[AC_PROVIDE_IFELSE([LT_OUTPUT],
- dnl If the libtool generation code has been placed in $CONFIG_LT,
- dnl instead of duplicating it all over again into config.status,
- dnl then we will have config.status run $CONFIG_LT later, so it
- dnl needs to know what name is stored there:
- [AC_CONFIG_COMMANDS([libtool],
- [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
- dnl If the libtool generation code is destined for config.status,
- dnl expand the accumulated commands and init code now:
- [AC_CONFIG_COMMANDS([libtool],
- [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
-])#_LT_CONFIG_COMMANDS
-
-
-# Initialize.
-m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
-[
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-sed_quote_subst='$sed_quote_subst'
-double_quote_subst='$double_quote_subst'
-delay_variable_subst='$delay_variable_subst'
-_LT_CONFIG_STATUS_DECLARATIONS
-LTCC='$LTCC'
-LTCFLAGS='$LTCFLAGS'
-compiler='$compiler_DEFAULT'
-
-# A function that is used when there is no print builtin or printf.
-func_fallback_echo ()
-{
- eval 'cat <<_LTECHO_EOF
-\$[]1
-_LTECHO_EOF'
-}
-
-# Quote evaled strings.
-for var in lt_decl_all_varnames([[ \
-]], lt_decl_quote_varnames); do
- case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
- *[[\\\\\\\`\\"\\\$]]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-# Double-quote double-evaled strings.
-for var in lt_decl_all_varnames([[ \
-]], lt_decl_dquote_varnames); do
- case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
- *[[\\\\\\\`\\"\\\$]]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-_LT_OUTPUT_LIBTOOL_INIT
-])
-
-# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
-# ------------------------------------
-# Generate a child script FILE with all initialization necessary to
-# reuse the environment learned by the parent script, and make the
-# file executable. If COMMENT is supplied, it is inserted after the
-# `#!' sequence but before initialization text begins. After this
-# macro, additional text can be appended to FILE to form the body of
-# the child script. The macro ends with non-zero status if the
-# file could not be fully written (such as if the disk is full).
-m4_ifdef([AS_INIT_GENERATED],
-[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
-[m4_defun([_LT_GENERATED_FILE_INIT],
-[m4_require([AS_PREPARE])]dnl
-[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
-[lt_write_fail=0
-cat >$1 <<_ASEOF || lt_write_fail=1
-#! $SHELL
-# Generated by $as_me.
-$2
-SHELL=\${CONFIG_SHELL-$SHELL}
-export SHELL
-_ASEOF
-cat >>$1 <<\_ASEOF || lt_write_fail=1
-AS_SHELL_SANITIZE
-_AS_PREPARE
-exec AS_MESSAGE_FD>&1
-_ASEOF
-test $lt_write_fail = 0 && chmod +x $1[]dnl
-m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
-
-# LT_OUTPUT
-# ---------
-# This macro allows early generation of the libtool script (before
-# AC_OUTPUT is called), incase it is used in configure for compilation
-# tests.
-AC_DEFUN([LT_OUTPUT],
-[: ${CONFIG_LT=./config.lt}
-AC_MSG_NOTICE([creating $CONFIG_LT])
-_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
-[# Run this file to recreate a libtool stub with the current configuration.])
-
-cat >>"$CONFIG_LT" <<\_LTEOF
-lt_cl_silent=false
-exec AS_MESSAGE_LOG_FD>>config.log
-{
- echo
- AS_BOX([Running $as_me.])
-} >&AS_MESSAGE_LOG_FD
-
-lt_cl_help="\
-\`$as_me' creates a local libtool stub from the current configuration,
-for use in further configure time tests before the real libtool is
-generated.
-
-Usage: $[0] [[OPTIONS]]
-
- -h, --help print this help, then exit
- -V, --version print version number, then exit
- -q, --quiet do not print progress messages
- -d, --debug don't remove temporary files
-
-Report bugs to <bug-libtool@gnu.org>."
-
-lt_cl_version="\
-m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
-m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
-configured by $[0], generated by m4_PACKAGE_STRING.
-
-Copyright (C) 2010 Free Software Foundation, Inc.
-This config.lt script is free software; the Free Software Foundation
-gives unlimited permision to copy, distribute and modify it."
-
-while test $[#] != 0
-do
- case $[1] in
- --version | --v* | -V )
- echo "$lt_cl_version"; exit 0 ;;
- --help | --h* | -h )
- echo "$lt_cl_help"; exit 0 ;;
- --debug | --d* | -d )
- debug=: ;;
- --quiet | --q* | --silent | --s* | -q )
- lt_cl_silent=: ;;
-
- -*) AC_MSG_ERROR([unrecognized option: $[1]
-Try \`$[0] --help' for more information.]) ;;
-
- *) AC_MSG_ERROR([unrecognized argument: $[1]
-Try \`$[0] --help' for more information.]) ;;
- esac
- shift
-done
-
-if $lt_cl_silent; then
- exec AS_MESSAGE_FD>/dev/null
-fi
-_LTEOF
-
-cat >>"$CONFIG_LT" <<_LTEOF
-_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
-_LTEOF
-
-cat >>"$CONFIG_LT" <<\_LTEOF
-AC_MSG_NOTICE([creating $ofile])
-_LT_OUTPUT_LIBTOOL_COMMANDS
-AS_EXIT(0)
-_LTEOF
-chmod +x "$CONFIG_LT"
-
-# configure is writing to config.log, but config.lt does its own redirection,
-# appending to config.log, which fails on DOS, as config.log is still kept
-# open by configure. Here we exec the FD to /dev/null, effectively closing
-# config.log, so it can be properly (re)opened and appended to by config.lt.
-lt_cl_success=:
-test "$silent" = yes &&
- lt_config_lt_args="$lt_config_lt_args --quiet"
-exec AS_MESSAGE_LOG_FD>/dev/null
-$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
-exec AS_MESSAGE_LOG_FD>>config.log
-$lt_cl_success || AS_EXIT(1)
-])# LT_OUTPUT
-
-
-# _LT_CONFIG(TAG)
-# ---------------
-# If TAG is the built-in tag, create an initial libtool script with a
-# default configuration from the untagged config vars. Otherwise add code
-# to config.status for appending the configuration named by TAG from the
-# matching tagged config vars.
-m4_defun([_LT_CONFIG],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-_LT_CONFIG_SAVE_COMMANDS([
- m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
- m4_if(_LT_TAG, [C], [
- # See if we are running on zsh, and set the options which allow our
- # commands through without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
-
- cfgfile="${ofile}T"
- trap "$RM \"$cfgfile\"; exit 1" 1 2 15
- $RM "$cfgfile"
-
- cat <<_LT_EOF >> "$cfgfile"
-#! $SHELL
-
-# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
-#
-_LT_COPYING
-_LT_LIBTOOL_TAGS
-
-# ### BEGIN LIBTOOL CONFIG
-_LT_LIBTOOL_CONFIG_VARS
-_LT_LIBTOOL_TAG_VARS
-# ### END LIBTOOL CONFIG
-
-_LT_EOF
-
- case $host_os in
- aix3*)
- cat <<\_LT_EOF >> "$cfgfile"
-# AIX sometimes has problems with the GCC collect2 program. For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
-fi
-_LT_EOF
- ;;
- esac
-
- _LT_PROG_LTMAIN
-
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
- sed '$q' "$ltmain" >> "$cfgfile" \
- || (rm -f "$cfgfile"; exit 1)
-
- _LT_PROG_REPLACE_SHELLFNS
-
- mv -f "$cfgfile" "$ofile" ||
- (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
- chmod +x "$ofile"
-],
-[cat <<_LT_EOF >> "$ofile"
-
-dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
-dnl in a comment (ie after a #).
-# ### BEGIN LIBTOOL TAG CONFIG: $1
-_LT_LIBTOOL_TAG_VARS(_LT_TAG)
-# ### END LIBTOOL TAG CONFIG: $1
-_LT_EOF
-])dnl /m4_if
-],
-[m4_if([$1], [], [
- PACKAGE='$PACKAGE'
- VERSION='$VERSION'
- TIMESTAMP='$TIMESTAMP'
- RM='$RM'
- ofile='$ofile'], [])
-])dnl /_LT_CONFIG_SAVE_COMMANDS
-])# _LT_CONFIG
-
-
-# LT_SUPPORTED_TAG(TAG)
-# ---------------------
-# Trace this macro to discover what tags are supported by the libtool
-# --tag option, using:
-# autoconf --trace 'LT_SUPPORTED_TAG:$1'
-AC_DEFUN([LT_SUPPORTED_TAG], [])
-
-
-# C support is built-in for now
-m4_define([_LT_LANG_C_enabled], [])
-m4_define([_LT_TAGS], [])
-
-
-# LT_LANG(LANG)
-# -------------
-# Enable libtool support for the given language if not already enabled.
-AC_DEFUN([LT_LANG],
-[AC_BEFORE([$0], [LT_OUTPUT])dnl
-m4_case([$1],
- [C], [_LT_LANG(C)],
- [C++], [_LT_LANG(CXX)],
- [Java], [_LT_LANG(GCJ)],
- [Fortran 77], [_LT_LANG(F77)],
- [Fortran], [_LT_LANG(FC)],
- [Windows Resource], [_LT_LANG(RC)],
- [m4_ifdef([_LT_LANG_]$1[_CONFIG],
- [_LT_LANG($1)],
- [m4_fatal([$0: unsupported language: "$1"])])])dnl
-])# LT_LANG
-
-
-# _LT_LANG(LANGNAME)
-# ------------------
-m4_defun([_LT_LANG],
-[m4_ifdef([_LT_LANG_]$1[_enabled], [],
- [LT_SUPPORTED_TAG([$1])dnl
- m4_append([_LT_TAGS], [$1 ])dnl
- m4_define([_LT_LANG_]$1[_enabled], [])dnl
- _LT_LANG_$1_CONFIG($1)])dnl
-])# _LT_LANG
-
-
-# _LT_LANG_DEFAULT_CONFIG
-# -----------------------
-m4_defun([_LT_LANG_DEFAULT_CONFIG],
-[AC_PROVIDE_IFELSE([AC_PROG_CXX],
- [LT_LANG(CXX)],
- [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
-
-AC_PROVIDE_IFELSE([AC_PROG_F77],
- [LT_LANG(F77)],
- [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
-
-AC_PROVIDE_IFELSE([AC_PROG_FC],
- [LT_LANG(FC)],
- [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
-
-dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
-dnl pulling things in needlessly.
-AC_PROVIDE_IFELSE([AC_PROG_GCJ],
- [LT_LANG(GCJ)],
- [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
- [LT_LANG(GCJ)],
- [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
- [LT_LANG(GCJ)],
- [m4_ifdef([AC_PROG_GCJ],
- [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
- m4_ifdef([A][M_PROG_GCJ],
- [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
- m4_ifdef([LT_PROG_GCJ],
- [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
-
-AC_PROVIDE_IFELSE([LT_PROG_RC],
- [LT_LANG(RC)],
- [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
-])# _LT_LANG_DEFAULT_CONFIG
-
-# Obsolete macros:
-AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
-AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
-AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
-AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
-AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
-dnl AC_DEFUN([AC_LIBTOOL_F77], [])
-dnl AC_DEFUN([AC_LIBTOOL_FC], [])
-dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
-dnl AC_DEFUN([AC_LIBTOOL_RC], [])
-
-
-# _LT_TAG_COMPILER
-# ----------------
-m4_defun([_LT_TAG_COMPILER],
-[AC_REQUIRE([AC_PROG_CC])dnl
-
-_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
-_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
-_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
-_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-])# _LT_TAG_COMPILER
-
-
-# _LT_COMPILER_BOILERPLATE
-# ------------------------
-# Check for compiler boilerplate output or warnings with
-# the simple compiler test code.
-m4_defun([_LT_COMPILER_BOILERPLATE],
-[m4_require([_LT_DECL_SED])dnl
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$RM conftest*
-])# _LT_COMPILER_BOILERPLATE
-
-
-# _LT_LINKER_BOILERPLATE
-# ----------------------
-# Check for linker boilerplate output or warnings with
-# the simple link test code.
-m4_defun([_LT_LINKER_BOILERPLATE],
-[m4_require([_LT_DECL_SED])dnl
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$RM -r conftest*
-])# _LT_LINKER_BOILERPLATE
-
-# _LT_REQUIRED_DARWIN_CHECKS
-# -------------------------
-m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
- case $host_os in
- rhapsody* | darwin*)
- AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
- AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
- AC_CHECK_TOOL([LIPO], [lipo], [:])
- AC_CHECK_TOOL([OTOOL], [otool], [:])
- AC_CHECK_TOOL([OTOOL64], [otool64], [:])
- _LT_DECL([], [DSYMUTIL], [1],
- [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
- _LT_DECL([], [NMEDIT], [1],
- [Tool to change global to local symbols on Mac OS X])
- _LT_DECL([], [LIPO], [1],
- [Tool to manipulate fat objects and archives on Mac OS X])
- _LT_DECL([], [OTOOL], [1],
- [ldd/readelf like tool for Mach-O binaries on Mac OS X])
- _LT_DECL([], [OTOOL64], [1],
- [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
-
- AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
- [lt_cv_apple_cc_single_mod=no
- if test -z "${LT_MULTI_MODULE}"; then
- # By default we will add the -single_module flag. You can override
- # by either setting the environment variable LT_MULTI_MODULE
- # non-empty at configure time, or by adding -multi_module to the
- # link flags.
- rm -rf libconftest.dylib*
- echo "int foo(void){return 1;}" > conftest.c
- echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
--dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
- $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
- -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
- _lt_result=$?
- if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
- lt_cv_apple_cc_single_mod=yes
- else
- cat conftest.err >&AS_MESSAGE_LOG_FD
- fi
- rm -rf libconftest.dylib*
- rm -f conftest.*
- fi])
- AC_CACHE_CHECK([for -exported_symbols_list linker flag],
- [lt_cv_ld_exported_symbols_list],
- [lt_cv_ld_exported_symbols_list=no
- save_LDFLAGS=$LDFLAGS
- echo "_main" > conftest.sym
- LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
- AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
- [lt_cv_ld_exported_symbols_list=yes],
- [lt_cv_ld_exported_symbols_list=no])
- LDFLAGS="$save_LDFLAGS"
- ])
- AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
- [lt_cv_ld_force_load=no
- cat > conftest.c << _LT_EOF
-int forced_loaded() { return 2;}
-_LT_EOF
- echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
- $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
- echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
- $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
- echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
- $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
- cat > conftest.c << _LT_EOF
-int main() { return 0;}
-_LT_EOF
- echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
- $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
- _lt_result=$?
- if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
- lt_cv_ld_force_load=yes
- else
- cat conftest.err >&AS_MESSAGE_LOG_FD
- fi
- rm -f conftest.err libconftest.a conftest conftest.c
- rm -rf conftest.dSYM
- ])
- case $host_os in
- rhapsody* | darwin1.[[012]])
- _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
- darwin1.*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- 10.[[012]]*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- 10.*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- esac
- ;;
- esac
- if test "$lt_cv_apple_cc_single_mod" = "yes"; then
- _lt_dar_single_mod='$single_module'
- fi
- if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
- _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
- else
- _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
- fi
- if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
- _lt_dsymutil='~$DSYMUTIL $lib || :'
- else
- _lt_dsymutil=
- fi
- ;;
- esac
-])
-
-
-# _LT_DARWIN_LINKER_FEATURES
-# --------------------------
-# Checks for linker and compiler features on darwin
-m4_defun([_LT_DARWIN_LINKER_FEATURES],
-[
- m4_require([_LT_REQUIRED_DARWIN_CHECKS])
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_automatic, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
- if test "$lt_cv_ld_force_load" = "yes"; then
- _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
- else
- _LT_TAGVAR(whole_archive_flag_spec, $1)=''
- fi
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
- case $cc_basename in
- ifort*) _lt_dar_can_shared=yes ;;
- *) _lt_dar_can_shared=$GCC ;;
- esac
- if test "$_lt_dar_can_shared" = "yes"; then
- output_verbose_link_cmd=func_echo_all
- _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
- _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
- _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
- _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
- m4_if([$1], [CXX],
-[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
- _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
- _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
- fi
-],[])
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
-])
-
-# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
-# ----------------------------------
-# Links a minimal program and checks the executable
-# for the system default hardcoded library path. In most cases,
-# this is /usr/lib:/lib, but when the MPI compilers are used
-# the location of the communication and MPI libs are included too.
-# If we don't find anything, use the default library path according
-# to the aix ld manual.
-# Store the results from the different compilers for each TAGNAME.
-# Allow to override them for all tags through lt_cv_aix_libpath.
-m4_defun([_LT_SYS_MODULE_PATH_AIX],
-[m4_require([_LT_DECL_SED])dnl
-if test "${lt_cv_aix_libpath+set}" = set; then
- aix_libpath=$lt_cv_aix_libpath
-else
- AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
- [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
- lt_aix_libpath_sed='[
- /Import File Strings/,/^$/ {
- /^0/ {
- s/^0 *\([^ ]*\) *$/\1/
- p
- }
- }]'
- _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
- # Check for a 64-bit object if we didn't find anything.
- if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
- _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
- fi],[])
- if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
- _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib"
- fi
- ])
- aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
-fi
-])# _LT_SYS_MODULE_PATH_AIX
-
-
-# _LT_SHELL_INIT(ARG)
-# -------------------
-m4_define([_LT_SHELL_INIT],
-[m4_divert_text([M4SH-INIT], [$1
-])])# _LT_SHELL_INIT
-
-
-
-# _LT_PROG_ECHO_BACKSLASH
-# -----------------------
-# Find how we can fake an echo command that does not interpret backslash.
-# In particular, with Autoconf 2.60 or later we add some code to the start
-# of the generated configure script which will find a shell with a builtin
-# printf (which we can use as an echo command).
-m4_defun([_LT_PROG_ECHO_BACKSLASH],
-[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
-
-AC_MSG_CHECKING([how to print strings])
-# Test print first, because it will be a builtin if present.
-if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
- test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
- ECHO='print -r --'
-elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
- ECHO='printf %s\n'
-else
- # Use this function as a fallback that always works.
- func_fallback_echo ()
- {
- eval 'cat <<_LTECHO_EOF
-$[]1
-_LTECHO_EOF'
- }
- ECHO='func_fallback_echo'
-fi
-
-# func_echo_all arg...
-# Invoke $ECHO with all args, space-separated.
-func_echo_all ()
-{
- $ECHO "$*"
-}
-
-case "$ECHO" in
- printf*) AC_MSG_RESULT([printf]) ;;
- print*) AC_MSG_RESULT([print -r]) ;;
- *) AC_MSG_RESULT([cat]) ;;
-esac
-
-m4_ifdef([_AS_DETECT_SUGGESTED],
-[_AS_DETECT_SUGGESTED([
- test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
- ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
- ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
- ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
- PATH=/empty FPATH=/empty; export PATH FPATH
- test "X`printf %s $ECHO`" = "X$ECHO" \
- || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
-
-_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
-_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
-])# _LT_PROG_ECHO_BACKSLASH
-
-
-# _LT_WITH_SYSROOT
-# ----------------
-AC_DEFUN([_LT_WITH_SYSROOT],
-[AC_MSG_CHECKING([for sysroot])
-AC_ARG_WITH([sysroot],
-[ --with-sysroot[=DIR] Search for dependent libraries within DIR
- (or the compiler's sysroot if not specified).],
-[], [with_sysroot=no])
-
-dnl lt_sysroot will always be passed unquoted. We quote it here
-dnl in case the user passed a directory name.
-lt_sysroot=
-case ${with_sysroot} in #(
- yes)
- if test "$GCC" = yes; then
- lt_sysroot=`$CC --print-sysroot 2>/dev/null`
- fi
- ;; #(
- /*)
- lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
- ;; #(
- no|'')
- ;; #(
- *)
- AC_MSG_RESULT([${with_sysroot}])
- AC_MSG_ERROR([The sysroot must be an absolute path.])
- ;;
-esac
-
- AC_MSG_RESULT([${lt_sysroot:-no}])
-_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
-[dependent libraries, and in which our libraries should be installed.])])
-
-# _LT_ENABLE_LOCK
-# ---------------
-m4_defun([_LT_ENABLE_LOCK],
-[AC_ARG_ENABLE([libtool-lock],
- [AS_HELP_STRING([--disable-libtool-lock],
- [avoid locking (might break parallel builds)])])
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case $host in
-ia64-*-hpux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.$ac_objext` in
- *ELF-32*)
- HPUX_IA64_MODE="32"
- ;;
- *ELF-64*)
- HPUX_IA64_MODE="64"
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-*-*-irix6*)
- # Find out which ABI we are using.
- echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- if test "$lt_cv_prog_gnu_ld" = yes; then
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -melf32bsmip"
- ;;
- *N32*)
- LD="${LD-ld} -melf32bmipn32"
- ;;
- *64-bit*)
- LD="${LD-ld} -melf64bmip"
- ;;
- esac
- else
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -32"
- ;;
- *N32*)
- LD="${LD-ld} -n32"
- ;;
- *64-bit*)
- LD="${LD-ld} -64"
- ;;
- esac
- fi
- fi
- rm -rf conftest*
- ;;
-
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
-s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.o` in
- *32-bit*)
- case $host in
- x86_64-*kfreebsd*-gnu)
- LD="${LD-ld} -m elf_i386_fbsd"
- ;;
- x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
- ;;
- ppc64-*linux*|powerpc64-*linux*)
- LD="${LD-ld} -m elf32ppclinux"
- ;;
- s390x-*linux*)
- LD="${LD-ld} -m elf_s390"
- ;;
- sparc64-*linux*)
- LD="${LD-ld} -m elf32_sparc"
- ;;
- esac
- ;;
- *64-bit*)
- case $host in
- x86_64-*kfreebsd*-gnu)
- LD="${LD-ld} -m elf_x86_64_fbsd"
- ;;
- x86_64-*linux*)
- LD="${LD-ld} -m elf_x86_64"
- ;;
- ppc*-*linux*|powerpc*-*linux*)
- LD="${LD-ld} -m elf64ppc"
- ;;
- s390*-*linux*|s390*-*tpf*)
- LD="${LD-ld} -m elf64_s390"
- ;;
- sparc*-*linux*)
- LD="${LD-ld} -m elf64_sparc"
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-
-*-*-sco3.2v5*)
- # On SCO OpenServer 5, we need -belf to get full-featured binaries.
- SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -belf"
- AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
- [AC_LANG_PUSH(C)
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
- AC_LANG_POP])
- if test x"$lt_cv_cc_needs_belf" != x"yes"; then
- # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
- CFLAGS="$SAVE_CFLAGS"
- fi
- ;;
-sparc*-*solaris*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.o` in
- *64-bit*)
- case $lt_cv_prog_gnu_ld in
- yes*) LD="${LD-ld} -m elf64_sparc" ;;
- *)
- if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
- LD="${LD-ld} -64"
- fi
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-esac
-
-need_locks="$enable_libtool_lock"
-])# _LT_ENABLE_LOCK
-
-
-# _LT_PROG_AR
-# -----------
-m4_defun([_LT_PROG_AR],
-[AC_CHECK_TOOLS(AR, [ar], false)
-: ${AR=ar}
-: ${AR_FLAGS=cru}
-_LT_DECL([], [AR], [1], [The archiver])
-_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
-
-AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
- [lt_cv_ar_at_file=no
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
- [echo conftest.$ac_objext > conftest.lst
- lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
- AC_TRY_EVAL([lt_ar_try])
- if test "$ac_status" -eq 0; then
- # Ensure the archiver fails upon bogus file names.
- rm -f conftest.$ac_objext libconftest.a
- AC_TRY_EVAL([lt_ar_try])
- if test "$ac_status" -ne 0; then
- lt_cv_ar_at_file=@
- fi
- fi
- rm -f conftest.* libconftest.a
- ])
- ])
-
-if test "x$lt_cv_ar_at_file" = xno; then
- archiver_list_spec=
-else
- archiver_list_spec=$lt_cv_ar_at_file
-fi
-_LT_DECL([], [archiver_list_spec], [1],
- [How to feed a file listing to the archiver])
-])# _LT_PROG_AR
-
-
-# _LT_CMD_OLD_ARCHIVE
-# -------------------
-m4_defun([_LT_CMD_OLD_ARCHIVE],
-[_LT_PROG_AR
-
-AC_CHECK_TOOL(STRIP, strip, :)
-test -z "$STRIP" && STRIP=:
-_LT_DECL([], [STRIP], [1], [A symbol stripping program])
-
-AC_CHECK_TOOL(RANLIB, ranlib, :)
-test -z "$RANLIB" && RANLIB=:
-_LT_DECL([], [RANLIB], [1],
- [Commands used to install an old-style archive])
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-if test -n "$RANLIB"; then
- case $host_os in
- openbsd*)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
- ;;
- *)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
- ;;
- esac
- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-fi
-
-case $host_os in
- darwin*)
- lock_old_archive_extraction=yes ;;
- *)
- lock_old_archive_extraction=no ;;
-esac
-_LT_DECL([], [old_postinstall_cmds], [2])
-_LT_DECL([], [old_postuninstall_cmds], [2])
-_LT_TAGDECL([], [old_archive_cmds], [2],
- [Commands used to build an old-style archive])
-_LT_DECL([], [lock_old_archive_extraction], [0],
- [Whether to use a lock for old archive extraction])
-])# _LT_CMD_OLD_ARCHIVE
-
-
-# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
-# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
-# ----------------------------------------------------------------
-# Check whether the given compiler option works
-AC_DEFUN([_LT_COMPILER_OPTION],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_SED])dnl
-AC_CACHE_CHECK([$1], [$2],
- [$2=no
- m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$3"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&AS_MESSAGE_LOG_FD
- echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- $2=yes
- fi
- fi
- $RM conftest*
-])
-
-if test x"[$]$2" = xyes; then
- m4_if([$5], , :, [$5])
-else
- m4_if([$6], , :, [$6])
-fi
-])# _LT_COMPILER_OPTION
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
-
-
-# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
-# [ACTION-SUCCESS], [ACTION-FAILURE])
-# ----------------------------------------------------
-# Check whether the given linker option works
-AC_DEFUN([_LT_LINKER_OPTION],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_SED])dnl
-AC_CACHE_CHECK([$1], [$2],
- [$2=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $3"
- echo "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&AS_MESSAGE_LOG_FD
- $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- $2=yes
- fi
- else
- $2=yes
- fi
- fi
- $RM -r conftest*
- LDFLAGS="$save_LDFLAGS"
-])
-
-if test x"[$]$2" = xyes; then
- m4_if([$4], , :, [$4])
-else
- m4_if([$5], , :, [$5])
-fi
-])# _LT_LINKER_OPTION
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
-
-
-# LT_CMD_MAX_LEN
-#---------------
-AC_DEFUN([LT_CMD_MAX_LEN],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-# find the maximum length of command line arguments
-AC_MSG_CHECKING([the maximum length of command line arguments])
-AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
- i=0
- teststring="ABCD"
-
- case $build_os in
- msdosdjgpp*)
- # On DJGPP, this test can blow up pretty badly due to problems in libc
- # (any single argument exceeding 2000 bytes causes a buffer overrun
- # during glob expansion). Even if it were fixed, the result of this
- # check would be larger than it should be.
- lt_cv_sys_max_cmd_len=12288; # 12K is about right
- ;;
-
- gnu*)
- # Under GNU Hurd, this test is not required because there is
- # no limit to the length of command line arguments.
- # Libtool will interpret -1 as no limit whatsoever
- lt_cv_sys_max_cmd_len=-1;
- ;;
-
- cygwin* | mingw* | cegcc*)
- # On Win9x/ME, this test blows up -- it succeeds, but takes
- # about 5 minutes as the teststring grows exponentially.
- # Worse, since 9x/ME are not pre-emptively multitasking,
- # you end up with a "frozen" computer, even though with patience
- # the test eventually succeeds (with a max line length of 256k).
- # Instead, let's just punt: use the minimum linelength reported by
- # all of the supported platforms: 8192 (on NT/2K/XP).
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- mint*)
- # On MiNT this can take a long time and run out of memory.
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- amigaos*)
- # On AmigaOS with pdksh, this test takes hours, literally.
- # So we just punt and use a minimum line length of 8192.
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
- # This has been around since 386BSD, at least. Likely further.
- if test -x /sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
- elif test -x /usr/sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
- else
- lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
- fi
- # And add a safety zone
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- ;;
-
- interix*)
- # We know the value 262144 and hardcode it with a safety zone (like BSD)
- lt_cv_sys_max_cmd_len=196608
- ;;
-
- osf*)
- # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
- # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
- # nice to cause kernel panics so lets avoid the loop below.
- # First set a reasonable default.
- lt_cv_sys_max_cmd_len=16384
- #
- if test -x /sbin/sysconfig; then
- case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
- *1*) lt_cv_sys_max_cmd_len=-1 ;;
- esac
- fi
- ;;
- sco3.2v5*)
- lt_cv_sys_max_cmd_len=102400
- ;;
- sysv5* | sco5v6* | sysv4.2uw2*)
- kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
- if test -n "$kargmax"; then
- lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
- else
- lt_cv_sys_max_cmd_len=32768
- fi
- ;;
- *)
- lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
- if test -n "$lt_cv_sys_max_cmd_len"; then
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- else
- # Make teststring a little bigger before we do anything with it.
- # a 1K string should be a reasonable start.
- for i in 1 2 3 4 5 6 7 8 ; do
- teststring=$teststring$teststring
- done
- SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
- # If test is not a shell built-in, we'll probably end up computing a
- # maximum length that is only half of the actual maximum length, but
- # we can't tell.
- while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
- = "X$teststring$teststring"; } >/dev/null 2>&1 &&
- test $i != 17 # 1/2 MB should be enough
- do
- i=`expr $i + 1`
- teststring=$teststring$teststring
- done
- # Only check the string length outside the loop.
- lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
- teststring=
- # Add a significant safety factor because C++ compilers can tack on
- # massive amounts of additional arguments before passing them to the
- # linker. It appears as though 1/2 is a usable value.
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
- fi
- ;;
- esac
-])
-if test -n $lt_cv_sys_max_cmd_len ; then
- AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
-else
- AC_MSG_RESULT(none)
-fi
-max_cmd_len=$lt_cv_sys_max_cmd_len
-_LT_DECL([], [max_cmd_len], [0],
- [What is the maximum length of a command?])
-])# LT_CMD_MAX_LEN
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
-
-
-# _LT_HEADER_DLFCN
-# ----------------
-m4_defun([_LT_HEADER_DLFCN],
-[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
-])# _LT_HEADER_DLFCN
-
-
-# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
-# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
-# ----------------------------------------------------------------
-m4_defun([_LT_TRY_DLOPEN_SELF],
-[m4_require([_LT_HEADER_DLFCN])dnl
-if test "$cross_compiling" = yes; then :
- [$4]
-else
- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
- lt_status=$lt_dlunknown
- cat > conftest.$ac_ext <<_LT_EOF
-[#line $LINENO "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LT_DLGLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LT_DLGLOBAL DL_GLOBAL
-# else
-# define LT_DLGLOBAL 0
-# endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_DLLAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_DLLAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LT_DLLAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_DLLAZY_OR_NOW DL_NOW
-# else
-# define LT_DLLAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-/* When -fvisbility=hidden is used, assume the code has been annotated
- correspondingly for the symbols needed. */
-#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
-int fnord () __attribute__((visibility("default")));
-#endif
-
-int fnord () { return 42; }
-int main ()
-{
- void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
- int status = $lt_dlunknown;
-
- if (self)
- {
- if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
- else
- {
- if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
- else puts (dlerror ());
- }
- /* dlclose (self); */
- }
- else
- puts (dlerror ());
-
- return status;
-}]
-_LT_EOF
- if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
- (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
- lt_status=$?
- case x$lt_status in
- x$lt_dlno_uscore) $1 ;;
- x$lt_dlneed_uscore) $2 ;;
- x$lt_dlunknown|x*) $3 ;;
- esac
- else :
- # compilation failed
- $3
- fi
-fi
-rm -fr conftest*
-])# _LT_TRY_DLOPEN_SELF
-
-
-# LT_SYS_DLOPEN_SELF
-# ------------------
-AC_DEFUN([LT_SYS_DLOPEN_SELF],
-[m4_require([_LT_HEADER_DLFCN])dnl
-if test "x$enable_dlopen" != xyes; then
- enable_dlopen=unknown
- enable_dlopen_self=unknown
- enable_dlopen_self_static=unknown
-else
- lt_cv_dlopen=no
- lt_cv_dlopen_libs=
-
- case $host_os in
- beos*)
- lt_cv_dlopen="load_add_on"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ;;
-
- mingw* | pw32* | cegcc*)
- lt_cv_dlopen="LoadLibrary"
- lt_cv_dlopen_libs=
- ;;
-
- cygwin*)
- lt_cv_dlopen="dlopen"
- lt_cv_dlopen_libs=
- ;;
-
- darwin*)
- # if libdl is installed we need to link against it
- AC_CHECK_LIB([dl], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
- lt_cv_dlopen="dyld"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ])
- ;;
-
- *)
- AC_CHECK_FUNC([shl_load],
- [lt_cv_dlopen="shl_load"],
- [AC_CHECK_LIB([dld], [shl_load],
- [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
- [AC_CHECK_FUNC([dlopen],
- [lt_cv_dlopen="dlopen"],
- [AC_CHECK_LIB([dl], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
- [AC_CHECK_LIB([svld], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
- [AC_CHECK_LIB([dld], [dld_link],
- [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
- ])
- ])
- ])
- ])
- ])
- ;;
- esac
-
- if test "x$lt_cv_dlopen" != xno; then
- enable_dlopen=yes
- else
- enable_dlopen=no
- fi
-
- case $lt_cv_dlopen in
- dlopen)
- save_CPPFLAGS="$CPPFLAGS"
- test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-
- save_LDFLAGS="$LDFLAGS"
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-
- save_LIBS="$LIBS"
- LIBS="$lt_cv_dlopen_libs $LIBS"
-
- AC_CACHE_CHECK([whether a program can dlopen itself],
- lt_cv_dlopen_self, [dnl
- _LT_TRY_DLOPEN_SELF(
- lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
- lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
- ])
-
- if test "x$lt_cv_dlopen_self" = xyes; then
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
- AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
- lt_cv_dlopen_self_static, [dnl
- _LT_TRY_DLOPEN_SELF(
- lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
- lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
- ])
- fi
-
- CPPFLAGS="$save_CPPFLAGS"
- LDFLAGS="$save_LDFLAGS"
- LIBS="$save_LIBS"
- ;;
- esac
-
- case $lt_cv_dlopen_self in
- yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
- *) enable_dlopen_self=unknown ;;
- esac
-
- case $lt_cv_dlopen_self_static in
- yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
- *) enable_dlopen_self_static=unknown ;;
- esac
-fi
-_LT_DECL([dlopen_support], [enable_dlopen], [0],
- [Whether dlopen is supported])
-_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
- [Whether dlopen of programs is supported])
-_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
- [Whether dlopen of statically linked programs is supported])
-])# LT_SYS_DLOPEN_SELF
-
-# Old name:
-AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
-
-
-# _LT_COMPILER_C_O([TAGNAME])
-# ---------------------------
-# Check to see if options -c and -o are simultaneously supported by compiler.
-# This macro does not hard code the compiler like AC_PROG_CC_C_O.
-m4_defun([_LT_COMPILER_C_O],
-[m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_TAG_COMPILER])dnl
-AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
- [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
- [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
- $RM -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&AS_MESSAGE_LOG_FD
- echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
- fi
- fi
- chmod u+w . 2>&AS_MESSAGE_LOG_FD
- $RM conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
- $RM out/* && rmdir out
- cd ..
- $RM -r conftest
- $RM conftest*
-])
-_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
- [Does compiler simultaneously support -c and -o options?])
-])# _LT_COMPILER_C_O
-
-
-# _LT_COMPILER_FILE_LOCKS([TAGNAME])
-# ----------------------------------
-# Check to see if we can do hard links to lock some files if needed
-m4_defun([_LT_COMPILER_FILE_LOCKS],
-[m4_require([_LT_ENABLE_LOCK])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-_LT_COMPILER_C_O([$1])
-
-hard_links="nottested"
-if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- AC_MSG_CHECKING([if we can lock with hard links])
- hard_links=yes
- $RM conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- AC_MSG_RESULT([$hard_links])
- if test "$hard_links" = no; then
- AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
-])# _LT_COMPILER_FILE_LOCKS
-
-
-# _LT_CHECK_OBJDIR
-# ----------------
-m4_defun([_LT_CHECK_OBJDIR],
-[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
-[rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
- lt_cv_objdir=.libs
-else
- # MS-DOS does not allow filenames that begin with a dot.
- lt_cv_objdir=_libs
-fi
-rmdir .libs 2>/dev/null])
-objdir=$lt_cv_objdir
-_LT_DECL([], [objdir], [0],
- [The name of the directory that contains temporary libtool files])dnl
-m4_pattern_allow([LT_OBJDIR])dnl
-AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
- [Define to the sub-directory in which libtool stores uninstalled libraries.])
-])# _LT_CHECK_OBJDIR
-
-
-# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
-# --------------------------------------
-# Check hardcoding attributes.
-m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
-[AC_MSG_CHECKING([how to hardcode library paths into programs])
-_LT_TAGVAR(hardcode_action, $1)=
-if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
- test -n "$_LT_TAGVAR(runpath_var, $1)" ||
- test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
-
- # We can hardcode non-existent directories.
- if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
- test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
- # Linking always hardcodes the temporary library directory.
- _LT_TAGVAR(hardcode_action, $1)=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- _LT_TAGVAR(hardcode_action, $1)=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- _LT_TAGVAR(hardcode_action, $1)=unsupported
-fi
-AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
-
-if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
- test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-_LT_TAGDECL([], [hardcode_action], [0],
- [How to hardcode a shared library path into an executable])
-])# _LT_LINKER_HARDCODE_LIBPATH
-
-
-# _LT_CMD_STRIPLIB
-# ----------------
-m4_defun([_LT_CMD_STRIPLIB],
-[m4_require([_LT_DECL_EGREP])
-striplib=
-old_striplib=
-AC_MSG_CHECKING([whether stripping libraries is possible])
-if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
- test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
- test -z "$striplib" && striplib="$STRIP --strip-unneeded"
- AC_MSG_RESULT([yes])
-else
-# FIXME - insert some real tests, host_os isn't really good enough
- case $host_os in
- darwin*)
- if test -n "$STRIP" ; then
- striplib="$STRIP -x"
- old_striplib="$STRIP -S"
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- fi
- ;;
- *)
- AC_MSG_RESULT([no])
- ;;
- esac
-fi
-_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
-_LT_DECL([], [striplib], [1])
-])# _LT_CMD_STRIPLIB
-
-
-# _LT_SYS_DYNAMIC_LINKER([TAG])
-# -----------------------------
-# PORTME Fill in your ld.so characteristics
-m4_defun([_LT_SYS_DYNAMIC_LINKER],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_OBJDUMP])dnl
-m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_CHECK_SHELL_FEATURES])dnl
-AC_MSG_CHECKING([dynamic linker characteristics])
-m4_if([$1],
- [], [
-if test "$GCC" = yes; then
- case $host_os in
- darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
- *) lt_awk_arg="/^libraries:/" ;;
- esac
- case $host_os in
- mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;;
- *) lt_sed_strip_eq="s,=/,/,g" ;;
- esac
- lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
- case $lt_search_path_spec in
- *\;*)
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
- ;;
- *)
- lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
- ;;
- esac
- # Ok, now we have the path, separated by spaces, we can step through it
- # and add multilib dir if necessary.
- lt_tmp_lt_search_path_spec=
- lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
- for lt_sys_path in $lt_search_path_spec; do
- if test -d "$lt_sys_path/$lt_multi_os_dir"; then
- lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
- else
- test -d "$lt_sys_path" && \
- lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
- fi
- done
- lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
-BEGIN {RS=" "; FS="/|\n";} {
- lt_foo="";
- lt_count=0;
- for (lt_i = NF; lt_i > 0; lt_i--) {
- if ($lt_i != "" && $lt_i != ".") {
- if ($lt_i == "..") {
- lt_count++;
- } else {
- if (lt_count == 0) {
- lt_foo="/" $lt_i lt_foo;
- } else {
- lt_count--;
- }
- }
- }
- }
- if (lt_foo != "") { lt_freq[[lt_foo]]++; }
- if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
-}'`
- # AWK program above erroneously prepends '/' to C:/dos/paths
- # for these hosts.
- case $host_os in
- mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
- $SED 's,/\([[A-Za-z]]:\),\1,g'` ;;
- esac
- sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi])
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix[[4-9]]*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[[01]] | aix4.[[01]].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- case $host_cpu in
- powerpc)
- # Since July 2007 AmigaOS4 officially supports .so libraries.
- # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- ;;
- m68k)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
- esac
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[[45]]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32* | cegcc*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$cc_basename in
- yes,*)
- # gcc
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname~
- if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
- eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
- fi'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $RM \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
-m4_if([$1], [],[
- sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
- ;;
- mingw* | cegcc*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- ;;
-
- *,cl*)
- # Native MSVC
- libname_spec='$name'
- soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- library_names_spec='${libname}.dll.lib'
-
- case $build_os in
- mingw*)
- sys_lib_search_path_spec=
- lt_save_ifs=$IFS
- IFS=';'
- for lt_path in $LIB
- do
- IFS=$lt_save_ifs
- # Let DOS variable expansion print the short 8.3 style file name.
- lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
- sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
- done
- IFS=$lt_save_ifs
- # Convert to MSYS style.
- sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
- ;;
- cygwin*)
- # Convert to unix form, then to dos form, then back to unix form
- # but this time dos style (no spaces!) so that the unix form looks
- # like /cygdrive/c/PROGRA~1:/cygdr...
- sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
- sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
- sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- ;;
- *)
- sys_lib_search_path_spec="$LIB"
- if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
- # It is most probably a Windows format PATH.
- sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- # FIXME: find the short name or the path components, as spaces are
- # common. (e.g. "Program Files" -> "PROGRA~1")
- ;;
- esac
-
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $RM \$dlpath'
- shlibpath_overrides_runpath=yes
- dynamic_linker='Win32 link.exe'
- ;;
-
- *)
- # Assume MSVC wrapper
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
- dynamic_linker='Win32 ld.exe'
- ;;
- esac
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
-m4_if([$1], [],[
- sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[[123]]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- version_type=freebsd-$objformat
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[[01]]* | freebsdelf3.[[01]]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
- freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- *) # from 4.6 on, and DragonFly
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-haiku*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- dynamic_linker="$host_os runtime_loader"
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
- postinstall_cmds='chmod 555 $lib'
- # or fails outright, so override atomically:
- install_override_mode=555
- ;;
-
-interix[[3-9]]*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
-
- # Some binutils ld are patched to set DT_RUNPATH
- AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
- [lt_cv_shlibpath_overrides_runpath=no
- save_LDFLAGS=$LDFLAGS
- save_libdir=$libdir
- eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
- LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
- AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
- [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
- [lt_cv_shlibpath_overrides_runpath=yes])])
- LDFLAGS=$save_LDFLAGS
- libdir=$save_libdir
- ])
- shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
-
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-*nto* | *qnx*)
- version_type=qnx
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='ldqnx.so'
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[[89]] | openbsd2.[[89]].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-rdos*)
- dynamic_linker=no
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-tpf*)
- # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-AC_MSG_RESULT([$dynamic_linker])
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
- sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
-fi
-if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
- sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
-fi
-
-_LT_DECL([], [variables_saved_for_relink], [1],
- [Variables whose values should be saved in libtool wrapper scripts and
- restored at link time])
-_LT_DECL([], [need_lib_prefix], [0],
- [Do we need the "lib" prefix for modules?])
-_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
-_LT_DECL([], [version_type], [0], [Library versioning type])
-_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
-_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
-_LT_DECL([], [shlibpath_overrides_runpath], [0],
- [Is shlibpath searched before the hard-coded library search path?])
-_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
-_LT_DECL([], [library_names_spec], [1],
- [[List of archive names. First name is the real one, the rest are links.
- The last name is the one that the linker finds with -lNAME]])
-_LT_DECL([], [soname_spec], [1],
- [[The coded name of the library, if different from the real name]])
-_LT_DECL([], [install_override_mode], [1],
- [Permission mode override for installation of shared libraries])
-_LT_DECL([], [postinstall_cmds], [2],
- [Command to use after installation of a shared archive])
-_LT_DECL([], [postuninstall_cmds], [2],
- [Command to use after uninstallation of a shared archive])
-_LT_DECL([], [finish_cmds], [2],
- [Commands used to finish a libtool library installation in a directory])
-_LT_DECL([], [finish_eval], [1],
- [[As "finish_cmds", except a single script fragment to be evaled but
- not shown]])
-_LT_DECL([], [hardcode_into_libs], [0],
- [Whether we should hardcode library paths into libraries])
-_LT_DECL([], [sys_lib_search_path_spec], [2],
- [Compile-time system search path for libraries])
-_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
- [Run-time system search path for libraries])
-])# _LT_SYS_DYNAMIC_LINKER
-
-
-# _LT_PATH_TOOL_PREFIX(TOOL)
-# --------------------------
-# find a file program which can recognize shared library
-AC_DEFUN([_LT_PATH_TOOL_PREFIX],
-[m4_require([_LT_DECL_EGREP])dnl
-AC_MSG_CHECKING([for $1])
-AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
-[case $MAGIC_CMD in
-[[\\/*] | ?:[\\/]*])
- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
- ;;
-*)
- lt_save_MAGIC_CMD="$MAGIC_CMD"
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-dnl $ac_dummy forces splitting on constant user-supplied paths.
-dnl POSIX.2 word splitting is done only on the output of word expansions,
-dnl not every word. This closes a longstanding sh security hole.
- ac_dummy="m4_if([$2], , $PATH, [$2])"
- for ac_dir in $ac_dummy; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$1; then
- lt_cv_path_MAGIC_CMD="$ac_dir/$1"
- if test -n "$file_magic_test_file"; then
- case $deplibs_check_method in
- "file_magic "*)
- file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- $EGREP "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<_LT_EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-_LT_EOF
- fi ;;
- esac
- fi
- break
- fi
- done
- IFS="$lt_save_ifs"
- MAGIC_CMD="$lt_save_MAGIC_CMD"
- ;;
-esac])
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
- AC_MSG_RESULT($MAGIC_CMD)
-else
- AC_MSG_RESULT(no)
-fi
-_LT_DECL([], [MAGIC_CMD], [0],
- [Used to examine libraries when file_magic_cmd begins with "file"])dnl
-])# _LT_PATH_TOOL_PREFIX
-
-# Old name:
-AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
-
-
-# _LT_PATH_MAGIC
-# --------------
-# find a file program which can recognize a shared library
-m4_defun([_LT_PATH_MAGIC],
-[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
-if test -z "$lt_cv_path_MAGIC_CMD"; then
- if test -n "$ac_tool_prefix"; then
- _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
- else
- MAGIC_CMD=:
- fi
-fi
-])# _LT_PATH_MAGIC
-
-
-# LT_PATH_LD
-# ----------
-# find the pathname to the GNU or non-GNU linker
-AC_DEFUN([LT_PATH_LD],
-[AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
-
-AC_ARG_WITH([gnu-ld],
- [AS_HELP_STRING([--with-gnu-ld],
- [assume the C compiler uses GNU ld @<:@default=no@:>@])],
- [test "$withval" = no || with_gnu_ld=yes],
- [with_gnu_ld=no])dnl
-
-ac_prog=ld
-if test "$GCC" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- AC_MSG_CHECKING([for ld used by $CC])
- case $host in
- *-*-mingw*)
- # gcc leaves a trailing carriage return which upsets mingw
- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
- *)
- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
- esac
- case $ac_prog in
- # Accept absolute paths.
- [[\\/]]* | ?:[[\\/]]*)
- re_direlt='/[[^/]][[^/]]*/\.\./'
- # Canonicalize the pathname of ld
- ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
- while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we aren't using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
-elif test "$with_gnu_ld" = yes; then
- AC_MSG_CHECKING([for GNU ld])
-else
- AC_MSG_CHECKING([for non-GNU ld])
-fi
-AC_CACHE_VAL(lt_cv_path_LD,
-[if test -z "$LD"; then
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- lt_cv_path_LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some variants of GNU ld only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
- *GNU* | *'with BFD'*)
- test "$with_gnu_ld" != no && break
- ;;
- *)
- test "$with_gnu_ld" != yes && break
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
-else
- lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi])
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
- AC_MSG_RESULT($LD)
-else
- AC_MSG_RESULT(no)
-fi
-test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
-_LT_PATH_LD_GNU
-AC_SUBST([LD])
-
-_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
-])# LT_PATH_LD
-
-# Old names:
-AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
-AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_PROG_LD], [])
-dnl AC_DEFUN([AC_PROG_LD], [])
-
-
-# _LT_PATH_LD_GNU
-#- --------------
-m4_defun([_LT_PATH_LD_GNU],
-[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
-[# I'd rather use --version here, but apparently some GNU lds only accept -v.
-case `$LD -v 2>&1 </dev/null` in
-*GNU* | *'with BFD'*)
- lt_cv_prog_gnu_ld=yes
- ;;
-*)
- lt_cv_prog_gnu_ld=no
- ;;
-esac])
-with_gnu_ld=$lt_cv_prog_gnu_ld
-])# _LT_PATH_LD_GNU
-
-
-# _LT_CMD_RELOAD
-# --------------
-# find reload flag for linker
-# -- PORTME Some linkers may need a different reload flag.
-m4_defun([_LT_CMD_RELOAD],
-[AC_CACHE_CHECK([for $LD option to reload object files],
- lt_cv_ld_reload_flag,
- [lt_cv_ld_reload_flag='-r'])
-reload_flag=$lt_cv_ld_reload_flag
-case $reload_flag in
-"" | " "*) ;;
-*) reload_flag=" $reload_flag" ;;
-esac
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-case $host_os in
- cygwin* | mingw* | pw32* | cegcc*)
- if test "$GCC" != yes; then
- reload_cmds=false
- fi
- ;;
- darwin*)
- if test "$GCC" = yes; then
- reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
- else
- reload_cmds='$LD$reload_flag -o $output$reload_objs'
- fi
- ;;
-esac
-_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
-_LT_TAGDECL([], [reload_cmds], [2])dnl
-])# _LT_CMD_RELOAD
-
-
-# _LT_CHECK_MAGIC_METHOD
-# ----------------------
-# how to check for library dependencies
-# -- PORTME fill in with the dynamic library characteristics
-m4_defun([_LT_CHECK_MAGIC_METHOD],
-[m4_require([_LT_DECL_EGREP])
-m4_require([_LT_DECL_OBJDUMP])
-AC_CACHE_CHECK([how to recognize dependent libraries],
-lt_cv_deplibs_check_method,
-[lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [[regex]]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given extended regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-
-case $host_os in
-aix[[4-9]]*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-beos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-bsdi[[45]]*)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
- lt_cv_file_magic_cmd='/usr/bin/file -L'
- lt_cv_file_magic_test_file=/shlib/libc.so
- ;;
-
-cygwin*)
- # func_win32_libid is a shell function defined in ltmain.sh
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- ;;
-
-mingw* | pw32*)
- # Base MSYS/MinGW do not provide the 'file' command needed by
- # func_win32_libid shell function, so use a weaker test based on 'objdump',
- # unless we find 'file', for example because we are cross-compiling.
- # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
- if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- else
- # Keep this pattern in sync with the one in func_win32_libid.
- lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- fi
- ;;
-
-cegcc*)
- # use the weaker test based on 'objdump'. See mingw*.
- lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- ;;
-
-darwin* | rhapsody*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-freebsd* | dragonfly*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
- case $host_cpu in
- i*86 )
- # Not sure whether the presence of OpenBSD here was a mistake.
- # Let's accept both of them until this is cleared up.
- lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
- ;;
- esac
- else
- lt_cv_deplibs_check_method=pass_all
- fi
- ;;
-
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-haiku*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-hpux10.20* | hpux11*)
- lt_cv_file_magic_cmd=/usr/bin/file
- case $host_cpu in
- ia64*)
- lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
- lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
- ;;
- hppa*64*)
- [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
- lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
- ;;
- *)
- lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
- lt_cv_file_magic_test_file=/usr/lib/libc.sl
- ;;
- esac
- ;;
-
-interix[[3-9]]*)
- # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $LD in
- *-32|*"-32 ") libmagic=32-bit;;
- *-n32|*"-n32 ") libmagic=N32;;
- *-64|*"-64 ") libmagic=64-bit;;
- *) libmagic=never-match;;
- esac
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-# This must be Linux ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
- fi
- ;;
-
-newos6*)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=/usr/lib/libnls.so
- ;;
-
-*nto* | *qnx*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-openbsd*)
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
- fi
- ;;
-
-osf3* | osf4* | osf5*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-rdos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-solaris*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv4 | sysv4.3*)
- case $host_vendor in
- motorola)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
- ;;
- ncr)
- lt_cv_deplibs_check_method=pass_all
- ;;
- sequent)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
- ;;
- sni)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
- lt_cv_file_magic_test_file=/lib/libc.so
- ;;
- siemens)
- lt_cv_deplibs_check_method=pass_all
- ;;
- pc)
- lt_cv_deplibs_check_method=pass_all
- ;;
- esac
- ;;
-
-tpf*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-esac
-])
-
-file_magic_glob=
-want_nocaseglob=no
-if test "$build" = "$host"; then
- case $host_os in
- mingw* | pw32*)
- if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
- want_nocaseglob=yes
- else
- file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
- fi
- ;;
- esac
-fi
-
-file_magic_cmd=$lt_cv_file_magic_cmd
-deplibs_check_method=$lt_cv_deplibs_check_method
-test -z "$deplibs_check_method" && deplibs_check_method=unknown
-
-_LT_DECL([], [deplibs_check_method], [1],
- [Method to check whether dependent libraries are shared objects])
-_LT_DECL([], [file_magic_cmd], [1],
- [Command to use when deplibs_check_method = "file_magic"])
-_LT_DECL([], [file_magic_glob], [1],
- [How to find potential files when deplibs_check_method = "file_magic"])
-_LT_DECL([], [want_nocaseglob], [1],
- [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
-])# _LT_CHECK_MAGIC_METHOD
-
-
-# LT_PATH_NM
-# ----------
-# find the pathname to a BSD- or MS-compatible name lister
-AC_DEFUN([LT_PATH_NM],
-[AC_REQUIRE([AC_PROG_CC])dnl
-AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
-[if test -n "$NM"; then
- # Let the user override the test.
- lt_cv_path_NM="$NM"
-else
- lt_nm_to_check="${ac_tool_prefix}nm"
- if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
- lt_nm_to_check="$lt_nm_to_check nm"
- fi
- for lt_tmp_nm in $lt_nm_to_check; do
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- tmp_nm="$ac_dir/$lt_tmp_nm"
- if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
- # Check to see if the nm accepts a BSD-compat flag.
- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
- # nm: unknown option "B" ignored
- # Tru64's nm complains that /dev/null is an invalid object file
- case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
- */dev/null* | *'Invalid file or object type'*)
- lt_cv_path_NM="$tmp_nm -B"
- break
- ;;
- *)
- case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
- */dev/null*)
- lt_cv_path_NM="$tmp_nm -p"
- break
- ;;
- *)
- lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
- continue # so that we can try to find one that supports BSD flags
- ;;
- esac
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
- done
- : ${lt_cv_path_NM=no}
-fi])
-if test "$lt_cv_path_NM" != "no"; then
- NM="$lt_cv_path_NM"
-else
- # Didn't find any BSD compatible name lister, look for dumpbin.
- if test -n "$DUMPBIN"; then :
- # Let the user override the test.
- else
- AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
- case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
- *COFF*)
- DUMPBIN="$DUMPBIN -symbols"
- ;;
- *)
- DUMPBIN=:
- ;;
- esac
- fi
- AC_SUBST([DUMPBIN])
- if test "$DUMPBIN" != ":"; then
- NM="$DUMPBIN"
- fi
-fi
-test -z "$NM" && NM=nm
-AC_SUBST([NM])
-_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
-
-AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
- [lt_cv_nm_interface="BSD nm"
- echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$ac_compile" 2>conftest.err)
- cat conftest.err >&AS_MESSAGE_LOG_FD
- (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
- (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
- cat conftest.err >&AS_MESSAGE_LOG_FD
- (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
- cat conftest.out >&AS_MESSAGE_LOG_FD
- if $GREP 'External.*some_variable' conftest.out > /dev/null; then
- lt_cv_nm_interface="MS dumpbin"
- fi
- rm -f conftest*])
-])# LT_PATH_NM
-
-# Old names:
-AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
-AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_PROG_NM], [])
-dnl AC_DEFUN([AC_PROG_NM], [])
-
-# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
-# --------------------------------
-# how to determine the name of the shared library
-# associated with a specific link library.
-# -- PORTME fill in with the dynamic library characteristics
-m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
-[m4_require([_LT_DECL_EGREP])
-m4_require([_LT_DECL_OBJDUMP])
-m4_require([_LT_DECL_DLLTOOL])
-AC_CACHE_CHECK([how to associate runtime and link libraries],
-lt_cv_sharedlib_from_linklib_cmd,
-[lt_cv_sharedlib_from_linklib_cmd='unknown'
-
-case $host_os in
-cygwin* | mingw* | pw32* | cegcc*)
- # two different shell functions defined in ltmain.sh
- # decide which to use based on capabilities of $DLLTOOL
- case `$DLLTOOL --help 2>&1` in
- *--identify-strict*)
- lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
- ;;
- *)
- lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
- ;;
- esac
- ;;
-*)
- # fallback: assume linklib IS sharedlib
- lt_cv_sharedlib_from_linklib_cmd="$ECHO"
- ;;
-esac
-])
-sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
-test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
-
-_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
- [Command to associate shared and link libraries])
-])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
-
-
-# _LT_PATH_MANIFEST_TOOL
-# ----------------------
-# locate the manifest tool
-m4_defun([_LT_PATH_MANIFEST_TOOL],
-[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
-test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
-AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
- [lt_cv_path_mainfest_tool=no
- echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
- $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
- cat conftest.err >&AS_MESSAGE_LOG_FD
- if $GREP 'Manifest Tool' conftest.out > /dev/null; then
- lt_cv_path_mainfest_tool=yes
- fi
- rm -f conftest*])
-if test "x$lt_cv_path_mainfest_tool" != xyes; then
- MANIFEST_TOOL=:
-fi
-_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
-])# _LT_PATH_MANIFEST_TOOL
-
-
-# LT_LIB_M
-# --------
-# check for math library
-AC_DEFUN([LT_LIB_M],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-LIBM=
-case $host in
-*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
- # These system don't have libm, or don't need it
- ;;
-*-ncr-sysv4.3*)
- AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
- AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
- ;;
-*)
- AC_CHECK_LIB(m, cos, LIBM="-lm")
- ;;
-esac
-AC_SUBST([LIBM])
-])# LT_LIB_M
-
-# Old name:
-AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_CHECK_LIBM], [])
-
-
-# _LT_COMPILER_NO_RTTI([TAGNAME])
-# -------------------------------
-m4_defun([_LT_COMPILER_NO_RTTI],
-[m4_require([_LT_TAG_COMPILER])dnl
-
-_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
-
-if test "$GCC" = yes; then
- case $cc_basename in
- nvcc*)
- _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
- esac
-
- _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
- lt_cv_prog_compiler_rtti_exceptions,
- [-fno-rtti -fno-exceptions], [],
- [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
-fi
-_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
- [Compiler flag to turn off builtin functions])
-])# _LT_COMPILER_NO_RTTI
-
-
-# _LT_CMD_GLOBAL_SYMBOLS
-# ----------------------
-m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_PROG_AWK])dnl
-AC_REQUIRE([LT_PATH_NM])dnl
-AC_REQUIRE([LT_PATH_LD])dnl
-m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_TAG_COMPILER])dnl
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-AC_MSG_CHECKING([command to parse $NM output from $compiler object])
-AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
-[
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[[BCDEGRST]]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
-
-# Define system-specific variables.
-case $host_os in
-aix*)
- symcode='[[BCDT]]'
- ;;
-cygwin* | mingw* | pw32* | cegcc*)
- symcode='[[ABCDGISTW]]'
- ;;
-hpux*)
- if test "$host_cpu" = ia64; then
- symcode='[[ABCDEGRST]]'
- fi
- ;;
-irix* | nonstopux*)
- symcode='[[BCDEGRST]]'
- ;;
-osf*)
- symcode='[[BCDEGQRST]]'
- ;;
-solaris*)
- symcode='[[BDRT]]'
- ;;
-sco3.2v5*)
- symcode='[[DT]]'
- ;;
-sysv4.2uw2*)
- symcode='[[DT]]'
- ;;
-sysv5* | sco5v6* | unixware* | OpenUNIX*)
- symcode='[[ABDT]]'
- ;;
-sysv4)
- symcode='[[DFNSTU]]'
- ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-case `$NM -V 2>&1` in
-*GNU* | *'with BFD'*)
- symcode='[[ABCDGIRSTW]]' ;;
-esac
-
-# Transform an extracted symbol line into a proper C declaration.
-# Some systems (esp. on ia64) link data and code symbols differently,
-# so use this general approach.
-lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
-
-# Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
-
-# Handle CRLF in mingw tool chain
-opt_cr=
-case $build_os in
-mingw*)
- opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
- ;;
-esac
-
-# Try without a prefix underscore, then with it.
-for ac_symprfx in "" "_"; do
-
- # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
- symxfrm="\\1 $ac_symprfx\\2 \\2"
-
- # Write the raw and C identifiers.
- if test "$lt_cv_nm_interface" = "MS dumpbin"; then
- # Fake it for dumpbin and say T for any non-static function
- # and D for any global variable.
- # Also find C++ and __fastcall symbols from MSVC++,
- # which start with @ or ?.
- lt_cv_sys_global_symbol_pipe="$AWK ['"\
-" {last_section=section; section=\$ 3};"\
-" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
-" \$ 0!~/External *\|/{next};"\
-" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
-" {if(hide[section]) next};"\
-" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
-" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
-" s[1]~/^[@?]/{print s[1], s[1]; next};"\
-" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
-" ' prfx=^$ac_symprfx]"
- else
- lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
- fi
- lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
-
- # Check to see that the pipe works correctly.
- pipe_works=no
-
- rm -f conftest*
- cat > conftest.$ac_ext <<_LT_EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(void);
-void nm_test_func(void){}
-#ifdef __cplusplus
-}
-#endif
-int main(){nm_test_var='a';nm_test_func();return(0);}
-_LT_EOF
-
- if AC_TRY_EVAL(ac_compile); then
- # Now try to grab the symbols.
- nlist=conftest.nm
- if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
- # Try sorting and uniquifying the output.
- if sort "$nlist" | uniq > "$nlist"T; then
- mv -f "$nlist"T "$nlist"
- else
- rm -f "$nlist"T
- fi
-
- # Make sure that we snagged all the symbols we need.
- if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
- if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
- cat <<_LT_EOF > conftest.$ac_ext
-/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
-#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
-/* DATA imports from DLLs on WIN32 con't be const, because runtime
- relocations are performed -- see ld's documentation on pseudo-relocs. */
-# define LT@&t@_DLSYM_CONST
-#elif defined(__osf__)
-/* This system does not cope well with relocations in const data. */
-# define LT@&t@_DLSYM_CONST
-#else
-# define LT@&t@_DLSYM_CONST const
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-_LT_EOF
- # Now generate the symbol file.
- eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
-
- cat <<_LT_EOF >> conftest.$ac_ext
-
-/* The mapping between symbol names and symbols. */
-LT@&t@_DLSYM_CONST struct {
- const char *name;
- void *address;
-}
-lt__PROGRAM__LTX_preloaded_symbols[[]] =
-{
- { "@PROGRAM@", (void *) 0 },
-_LT_EOF
- $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
- cat <<\_LT_EOF >> conftest.$ac_ext
- {0, (void *) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt__PROGRAM__LTX_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-_LT_EOF
- # Now try linking the two files.
- mv conftest.$ac_objext conftstm.$ac_objext
- lt_globsym_save_LIBS=$LIBS
- lt_globsym_save_CFLAGS=$CFLAGS
- LIBS="conftstm.$ac_objext"
- CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
- if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
- pipe_works=yes
- fi
- LIBS=$lt_globsym_save_LIBS
- CFLAGS=$lt_globsym_save_CFLAGS
- else
- echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
- cat conftest.$ac_ext >&5
- fi
- rm -rf conftest* conftst*
-
- # Do not use the global_symbol_pipe unless it works.
- if test "$pipe_works" = yes; then
- break
- else
- lt_cv_sys_global_symbol_pipe=
- fi
-done
-])
-if test -z "$lt_cv_sys_global_symbol_pipe"; then
- lt_cv_sys_global_symbol_to_cdecl=
-fi
-if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
- AC_MSG_RESULT(failed)
-else
- AC_MSG_RESULT(ok)
-fi
-
-# Response file support.
-if test "$lt_cv_nm_interface" = "MS dumpbin"; then
- nm_file_list_spec='@'
-elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
- nm_file_list_spec='@'
-fi
-
-_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
- [Take the output of nm and produce a listing of raw symbols and C names])
-_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
- [Transform the output of nm in a proper C declaration])
-_LT_DECL([global_symbol_to_c_name_address],
- [lt_cv_sys_global_symbol_to_c_name_address], [1],
- [Transform the output of nm in a C name address pair])
-_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
- [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
- [Transform the output of nm in a C name address pair when lib prefix is needed])
-_LT_DECL([], [nm_file_list_spec], [1],
- [Specify filename containing input files for $NM])
-]) # _LT_CMD_GLOBAL_SYMBOLS
-
-
-# _LT_COMPILER_PIC([TAGNAME])
-# ---------------------------
-m4_defun([_LT_COMPILER_PIC],
-[m4_require([_LT_TAG_COMPILER])dnl
-_LT_TAGVAR(lt_prog_compiler_wl, $1)=
-_LT_TAGVAR(lt_prog_compiler_pic, $1)=
-_LT_TAGVAR(lt_prog_compiler_static, $1)=
-
-m4_if([$1], [CXX], [
- # C++ specific cases for pic, static, wl, etc.
- if test "$GXX" = yes; then
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- m68k)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
- ;;
- esac
- ;;
-
- beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
- mingw* | cygwin* | os2* | pw32* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- # Although the cygwin gcc ignores -fPIC, still need this for old-style
- # (--disable-auto-import) libraries
- m4_if([$1], [GCJ], [],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
- ;;
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
- ;;
- *djgpp*)
- # DJGPP does not support shared libraries at all
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- ;;
- haiku*)
- # PIC is the default for Haiku.
- # The "-static" flag exists, but is broken.
- _LT_TAGVAR(lt_prog_compiler_static, $1)=
- ;;
- interix[[3-9]]*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
- fi
- ;;
- hpux*)
- # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
- # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
- # sets the default TLS model and affects inlining.
- case $host_cpu in
- hppa*64*)
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- ;;
- *qnx* | *nto*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- else
- case $host_os in
- aix[[4-9]]*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- else
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- chorus*)
- case $cc_basename in
- cxch68*)
- # Green Hills C++ Compiler
- # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
- ;;
- esac
- ;;
- mingw* | cygwin* | os2* | pw32* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- m4_if([$1], [GCJ], [],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
- ;;
- dgux*)
- case $cc_basename in
- ec++*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- freebsd* | dragonfly*)
- # FreeBSD uses GNU C++
- ;;
- hpux9* | hpux10* | hpux11*)
- case $cc_basename in
- CC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- if test "$host_cpu" != ia64; then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- fi
- ;;
- aCC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- ;;
- esac
- ;;
- *)
- ;;
- esac
- ;;
- interix*)
- # This is c89, which is MS Visual C++ (no shared libs)
- # Anyone wants to do a port?
- ;;
- irix5* | irix6* | nonstopux*)
- case $cc_basename in
- CC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- # CC pic flag -KPIC is the default.
- ;;
- *)
- ;;
- esac
- ;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
- case $cc_basename in
- KCC*)
- # KAI C++ Compiler
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- ecpc* )
- # old Intel C++ for x86_64 which still supported -KPIC.
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- icpc* )
- # Intel C++, used to be incompatible with GCC.
- # ICC 10 doesn't accept -KPIC any more.
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- pgCC* | pgcpp*)
- # Portland Group C++ compiler
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- cxx*)
- # Compaq C++
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
- # IBM XL 8.0, 9.0 on PPC and BlueGene
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
- ;;
- *)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C++ 5.9
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- ;;
- esac
- ;;
- esac
- ;;
- lynxos*)
- ;;
- m88k*)
- ;;
- mvs*)
- case $cc_basename in
- cxx*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
- ;;
- *)
- ;;
- esac
- ;;
- netbsd*)
- ;;
- *qnx* | *nto*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
- osf3* | osf4* | osf5*)
- case $cc_basename in
- KCC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
- ;;
- RCC*)
- # Rational C++ 2.4.1
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- cxx*)
- # Digital/Compaq C++
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- *)
- ;;
- esac
- ;;
- psos*)
- ;;
- solaris*)
- case $cc_basename in
- CC* | sunCC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- ;;
- gcx*)
- # Green Hills C++ Compiler
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
- ;;
- *)
- ;;
- esac
- ;;
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- lcc*)
- # Lucid
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- case $cc_basename in
- CC*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- esac
- ;;
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- ;;
- *)
- ;;
- esac
- ;;
- vxworks*)
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
- esac
- fi
-],
-[
- if test "$GCC" = yes; then
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- m68k)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
- ;;
- esac
- ;;
-
- beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
-
- mingw* | cygwin* | pw32* | os2* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- # Although the cygwin gcc ignores -fPIC, still need this for old-style
- # (--disable-auto-import) libraries
- m4_if([$1], [GCJ], [],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
- ;;
-
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
- ;;
-
- haiku*)
- # PIC is the default for Haiku.
- # The "-static" flag exists, but is broken.
- _LT_TAGVAR(lt_prog_compiler_static, $1)=
- ;;
-
- hpux*)
- # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
- # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
- # sets the default TLS model and affects inlining.
- case $host_cpu in
- hppa*64*)
- # +Z the default
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- ;;
-
- interix[[3-9]]*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
-
- msdosdjgpp*)
- # Just because we use GCC doesn't mean we suddenly get shared libraries
- # on systems that don't support them.
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- enable_shared=no
- ;;
-
- *nto* | *qnx*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
- fi
- ;;
-
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
-
- case $cc_basename in
- nvcc*) # Cuda Compiler Driver 2.2
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC'
- ;;
- esac
- else
- # PORTME Check for flag to pass linker flags through the system compiler.
- case $host_os in
- aix*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- else
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
-
- mingw* | cygwin* | pw32* | os2* | cegcc*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- m4_if([$1], [GCJ], [],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
- ;;
-
- hpux9* | hpux10* | hpux11*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- ;;
- esac
- # Is there a better lt_prog_compiler_static that works with the bundled CC?
- _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- ;;
-
- irix5* | irix6* | nonstopux*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # PIC (with -KPIC) is the default.
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
- case $cc_basename in
- # old Intel for x86_64 which still supported -KPIC.
- ecc*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- # icc used to be incompatible with GCC.
- # ICC 10 doesn't accept -KPIC any more.
- icc* | ifort*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- # Lahey Fortran 8.1.
- lf95*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
- ;;
- nagfor*)
- # NAG Fortran compiler
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
- # Portland Group compilers (*not* the Pentium gcc compiler,
- # which looks to be a dead project)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- ccc*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # All Alpha code is PIC.
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- xl* | bgxl* | bgf* | mpixl*)
- # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
- ;;
- *)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ F* | *Sun*Fortran*)
- # Sun Fortran 8.3 passes all unrecognized flags to the linker
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
- ;;
- *Sun\ C*)
- # Sun C 5.9
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- ;;
- esac
- ;;
- esac
- ;;
-
- newsos6)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- *nto* | *qnx*)
- # QNX uses GNU C++, but need to define -shared option too, otherwise
- # it will coredump.
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
- ;;
-
- osf3* | osf4* | osf5*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # All OSF/1 code is PIC.
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- rdos*)
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- solaris*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- case $cc_basename in
- f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
- *)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
- esac
- ;;
-
- sunos4*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec ;then
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- unicos*)
- _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
-
- uts4*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- *)
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
- esac
- fi
-])
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)=
- ;;
- *)
- _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
- ;;
-esac
-
-AC_CACHE_CHECK([for $compiler option to produce PIC],
- [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
- [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
-_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
- _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
- [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
- [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
- [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
- "" | " "*) ;;
- *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
- esac],
- [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
-fi
-_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
- [Additional compiler flags for building library objects])
-
-_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
- [How to pass a linker flag through the compiler])
-#
-# Check to make sure the static flag actually works.
-#
-wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
-_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
- _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
- $lt_tmp_static_flag,
- [],
- [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
-_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
- [Compiler flag to prevent dynamic linking])
-])# _LT_COMPILER_PIC
-
-
-# _LT_LINKER_SHLIBS([TAGNAME])
-# ----------------------------
-# See if the linker supports building shared libraries.
-m4_defun([_LT_LINKER_SHLIBS],
-[AC_REQUIRE([LT_PATH_LD])dnl
-AC_REQUIRE([LT_PATH_NM])dnl
-m4_require([_LT_PATH_MANIFEST_TOOL])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_DECL_SED])dnl
-m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
-m4_require([_LT_TAG_COMPILER])dnl
-AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
-m4_if([$1], [CXX], [
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
- case $host_os in
- aix[[4-9]]*)
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- # Also, AIX nm treats weak defined symbols like other global defined
- # symbols, whereas GNU nm marks them as "W".
- if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- else
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- fi
- ;;
- pw32*)
- _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
- ;;
- cygwin* | mingw* | cegcc*)
- case $cc_basename in
- cl*) ;;
- *)
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
- _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
- ;;
- esac
- ;;
- *)
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- ;;
- esac
-], [
- runpath_var=
- _LT_TAGVAR(allow_undefined_flag, $1)=
- _LT_TAGVAR(always_export_symbols, $1)=no
- _LT_TAGVAR(archive_cmds, $1)=
- _LT_TAGVAR(archive_expsym_cmds, $1)=
- _LT_TAGVAR(compiler_needs_object, $1)=no
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
- _LT_TAGVAR(export_dynamic_flag_spec, $1)=
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- _LT_TAGVAR(hardcode_automatic, $1)=no
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_direct_absolute, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
- _LT_TAGVAR(hardcode_libdir_separator, $1)=
- _LT_TAGVAR(hardcode_minus_L, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
- _LT_TAGVAR(inherit_rpath, $1)=no
- _LT_TAGVAR(link_all_deplibs, $1)=unknown
- _LT_TAGVAR(module_cmds, $1)=
- _LT_TAGVAR(module_expsym_cmds, $1)=
- _LT_TAGVAR(old_archive_from_new_cmds, $1)=
- _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
- _LT_TAGVAR(thread_safe_flag_spec, $1)=
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- # include_expsyms should be a list of space-separated symbols to be *always*
- # included in the symbol list
- _LT_TAGVAR(include_expsyms, $1)=
- # exclude_expsyms can be an extended regexp of symbols to exclude
- # it will be wrapped by ` (' and `)$', so one must not match beginning or
- # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
- # as well as any symbol that contains `d'.
- _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
- # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
- # platforms (ab)use it in PIC code, but their linkers get confused if
- # the symbol is explicitly referenced. Since portable code cannot
- # rely on this symbol name, it's probably fine to never include it in
- # preloaded symbol tables.
- # Exclude shared library initialization/finalization symbols.
-dnl Note also adjust exclude_expsyms for C++ above.
- extract_expsyms_cmds=
-
- case $host_os in
- cygwin* | mingw* | pw32* | cegcc*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$GCC" != yes; then
- with_gnu_ld=no
- fi
- ;;
- interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
- with_gnu_ld=yes
- ;;
- openbsd*)
- with_gnu_ld=no
- ;;
- esac
-
- _LT_TAGVAR(ld_shlibs, $1)=yes
-
- # On some targets, GNU ld is compatible enough with the native linker
- # that we're better off using the native interface for both.
- lt_use_gnu_ld_interface=no
- if test "$with_gnu_ld" = yes; then
- case $host_os in
- aix*)
- # The AIX port of GNU ld has always aspired to compatibility
- # with the native linker. However, as the warning in the GNU ld
- # block says, versions before 2.19.5* couldn't really create working
- # shared libraries, regardless of the interface used.
- case `$LD -v 2>&1` in
- *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
- *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
- *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
- *)
- lt_use_gnu_ld_interface=yes
- ;;
- esac
- ;;
- *)
- lt_use_gnu_ld_interface=yes
- ;;
- esac
- fi
-
- if test "$lt_use_gnu_ld_interface" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # Set some defaults for GNU ld with shared library support. These
- # are reset later if shared libraries are not supported. Putting them
- # here allows them to be overridden if necessary.
- runpath_var=LD_RUN_PATH
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
- _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- supports_anon_versioning=no
- case `$LD -v 2>&1` in
- *GNU\ gold*) supports_anon_versioning=yes ;;
- *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
- *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
- *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
- *\ 2.11.*) ;; # other 2.11 versions
- *) supports_anon_versioning=yes ;;
- esac
-
- # See if GNU ld supports shared libraries.
- case $host_os in
- aix[[3-9]]*)
- # On AIX/PPC, the GNU linker is very broken
- if test "$host_cpu" != ia64; then
- _LT_TAGVAR(ld_shlibs, $1)=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.19, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to install binutils
-*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
-*** You will then need to restart the configuration process.
-
-_LT_EOF
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)=''
- ;;
- m68k)
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- ;;
- esac
- ;;
-
- beos*)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
- # as there is no search path for DLLs.
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=no
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
- _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
-
- if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- haiku*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- interix[[3-9]]*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
-
- gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
- tmp_diet=no
- if test "$host_os" = linux-dietlibc; then
- case $cc_basename in
- diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
- esac
- fi
- if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
- && test "$tmp_diet" = no
- then
- tmp_addflag=' $pic_flag'
- tmp_sharedflag='-shared'
- case $cc_basename,$host_cpu in
- pgcc*) # Portland Group C compiler
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag'
- ;;
- pgf77* | pgf90* | pgf95* | pgfortran*)
- # Portland Group f77 and f90 compilers
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag -Mnomain' ;;
- ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
- tmp_addflag=' -i_dynamic' ;;
- efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
- tmp_addflag=' -i_dynamic -nofor_main' ;;
- ifc* | ifort*) # Intel Fortran compiler
- tmp_addflag=' -nofor_main' ;;
- lf95*) # Lahey Fortran 8.1
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- tmp_sharedflag='--shared' ;;
- xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
- tmp_sharedflag='-qmkshrobj'
- tmp_addflag= ;;
- nvcc*) # Cuda Compiler Driver 2.2
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
- _LT_TAGVAR(compiler_needs_object, $1)=yes
- ;;
- esac
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*) # Sun C 5.9
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
- _LT_TAGVAR(compiler_needs_object, $1)=yes
- tmp_sharedflag='-G' ;;
- *Sun\ F*) # Sun Fortran 8.3
- tmp_sharedflag='-G' ;;
- esac
- _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
- if test "x$supports_anon_versioning" = xyes; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
-
- case $cc_basename in
- xlf* | bgf* | bgxlf* | mpixlf*)
- # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
- _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
- _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
- if test "x$supports_anon_versioning" = xyes; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
- fi
- ;;
- esac
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
- wlarc=
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- fi
- ;;
-
- solaris*)
- if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
- _LT_TAGVAR(ld_shlibs, $1)=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
- case `$LD -v 2>&1` in
- *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
- _LT_TAGVAR(ld_shlibs, $1)=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- ;;
- *)
- # For security reasons, it is highly recommended that you always
- # use absolute paths for naming shared libraries, and exclude the
- # DT_RUNPATH tag from executables and libraries. But doing so
- # requires that you compile everything twice, which is a pain.
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- sunos4*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- wlarc=
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
-
- if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
- runpath_var=
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_TAGVAR(export_dynamic_flag_spec, $1)=
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case $host_os in
- aix3*)
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=yes
- _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- _LT_TAGVAR(hardcode_direct, $1)=unsupported
- fi
- ;;
-
- aix[[4-9]]*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- # Also, AIX nm treats weak defined symbols like other global
- # defined symbols, whereas GNU nm marks them as "W".
- if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- else
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
- fi
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
- for ld_flag in $LDFLAGS; do
- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
- aix_use_runtimelinking=yes
- break
- fi
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- _LT_TAGVAR(archive_cmds, $1)=''
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
-
- if test "$GCC" = yes; then
- case $host_os in aix4.[[012]]|aix4.[[012]].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" &&
- strings "$collect2name" | $GREP resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- :
- else
- # We have old collect2
- _LT_TAGVAR(hardcode_direct, $1)=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- _LT_TAGVAR(always_export_symbols, $1)=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
- # Determine the default libpath from the value encoded in an
- # empty executable.
- _LT_SYS_MODULE_PATH_AIX([$1])
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
- _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an
- # empty executable.
- _LT_SYS_MODULE_PATH_AIX([$1])
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
- if test "$with_gnu_ld" = yes; then
- # We only use this code for GNU lds that support --whole-archive.
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
- else
- # Exported symbols can be pulled into shared objects from archives
- _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- amigaos*)
- case $host_cpu in
- powerpc)
- # see comment about AmigaOS4 .so support
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)=''
- ;;
- m68k)
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- ;;
- esac
- ;;
-
- bsdi[[45]]*)
- _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- case $cc_basename in
- cl*)
- # Native MSVC
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=yes
- _LT_TAGVAR(file_list_spec, $1)='@'
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
- _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
- else
- sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
- fi~
- $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
- linknames='
- # The linker will not automatically build a static lib if we build a DLL.
- # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
- # Don't use ranlib
- _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
- _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
- lt_tool_outputfile="@TOOL_OUTPUT@"~
- case $lt_outputfile in
- *.exe|*.EXE) ;;
- *)
- lt_outputfile="$lt_outputfile.exe"
- lt_tool_outputfile="$lt_tool_outputfile.exe"
- ;;
- esac~
- if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
- $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
- $RM "$lt_outputfile.manifest";
- fi'
- ;;
- *)
- # Assume MSVC wrapper
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
- # FIXME: Should let the user specify the lib program.
- _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- ;;
- esac
- ;;
-
- darwin* | rhapsody*)
- _LT_DARWIN_LINKER_FEATURES($1)
- ;;
-
- dgux*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- freebsd1*)
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd* | dragonfly*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- hpux9*)
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(hardcode_direct, $1)=yes
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- ;;
-
- hpux10*)
- if test "$GCC" = yes && test "$with_gnu_ld" = no; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
- fi
- if test "$with_gnu_ld" = no; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- fi
- ;;
-
- hpux11*)
- if test "$GCC" = yes && test "$with_gnu_ld" = no; then
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- else
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- m4_if($1, [], [
- # Older versions of the 11.00 compiler do not understand -b yet
- # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
- _LT_LINKER_OPTION([if $CC understands -b],
- _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
- [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
- [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
- [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
- ;;
- esac
- fi
- if test "$with_gnu_ld" = no; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
- *)
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- ;;
- esac
- fi
- ;;
-
- irix5* | irix6* | nonstopux*)
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- # Try to use the -exported_symbol ld option, if it does not
- # work, assume that -exports_file does not work either and
- # implicitly export all symbols.
- # This should be the same for all languages, so no per-tag cache variable.
- AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
- [lt_cv_irix_exported_symbol],
- [save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
- AC_LINK_IFELSE(
- [AC_LANG_SOURCE(
- [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
- [C++], [[int foo (void) { return 0; }]],
- [Fortran 77], [[
- subroutine foo
- end]],
- [Fortran], [[
- subroutine foo
- end]])])],
- [lt_cv_irix_exported_symbol=yes],
- [lt_cv_irix_exported_symbol=no])
- LDFLAGS="$save_LDFLAGS"])
- if test "$lt_cv_irix_exported_symbol" = yes; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
- fi
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(inherit_rpath, $1)=yes
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
- else
- _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- newsos6)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *nto* | *qnx*)
- ;;
-
- openbsd*)
- if test -f /usr/libexec/ld.so; then
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- else
- case $host_os in
- openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- ;;
- esac
- fi
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- os2*)
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
- _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$GCC" = yes; then
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- ;;
-
- osf4* | osf5*) # as osf3* with the addition of -msym flag
- if test "$GCC" = yes; then
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- else
- _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
- $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
-
- # Both c and cxx compiler support -rpath directly
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- ;;
-
- solaris*)
- _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
- if test "$GCC" = yes; then
- wlarc='${wl}'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
- else
- case `$CC -V 2>&1` in
- *"Compilers 5.0"*)
- wlarc=''
- _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
- ;;
- *)
- wlarc='${wl}'
- _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
- ;;
- esac
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- # The compiler driver will combine and reorder linker options,
- # but understands `-z linker_flag'. GCC discards it without `$wl',
- # but is careful enough not to reorder.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- if test "$GCC" = yes; then
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
- else
- _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
- fi
- ;;
- esac
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- sunos4*)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
- fi
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- sysv4)
- case $host_vendor in
- sni)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
- ;;
- siemens)
- ## LD is ld it makes a PLAMLIB
- ## CC just makes a GrossModule.
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
- _LT_TAGVAR(hardcode_direct, $1)=no
- ;;
- motorola)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
- ;;
- esac
- runpath_var='LD_RUN_PATH'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- sysv4.3*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- _LT_TAGVAR(ld_shlibs, $1)=yes
- fi
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- uts4*)
- _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *)
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
-
- if test x$host_vendor = xsni; then
- case $host in
- sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
- ;;
- esac
- fi
- fi
-])
-AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
-test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
-
-_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
-
-_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
-_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
-_LT_DECL([], [extract_expsyms_cmds], [2],
- [The commands to extract the exported symbol list from a shared archive])
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
-x|xyes)
- # Assume -lc should be added
- _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $_LT_TAGVAR(archive_cmds, $1) in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- AC_CACHE_CHECK([whether -lc should be explicitly linked in],
- [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
- [$RM conftest*
- echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
- pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
- _LT_TAGVAR(allow_undefined_flag, $1)=
- if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
- then
- lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
- else
- lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
- fi
- _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $RM conftest*
- ])
- _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
- ;;
- esac
- fi
- ;;
-esac
-
-_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
- [Whether or not to add -lc for building shared libraries])
-_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
- [enable_shared_with_static_runtimes], [0],
- [Whether or not to disallow shared libs when runtime libs are static])
-_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
- [Compiler flag to allow reflexive dlopens])
-_LT_TAGDECL([], [whole_archive_flag_spec], [1],
- [Compiler flag to generate shared objects directly from archives])
-_LT_TAGDECL([], [compiler_needs_object], [1],
- [Whether the compiler copes with passing no objects directly])
-_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
- [Create an old-style archive from a shared archive])
-_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
- [Create a temporary old-style archive to link instead of a shared archive])
-_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
-_LT_TAGDECL([], [archive_expsym_cmds], [2])
-_LT_TAGDECL([], [module_cmds], [2],
- [Commands used to build a loadable module if different from building
- a shared archive.])
-_LT_TAGDECL([], [module_expsym_cmds], [2])
-_LT_TAGDECL([], [with_gnu_ld], [1],
- [Whether we are building with GNU ld or not])
-_LT_TAGDECL([], [allow_undefined_flag], [1],
- [Flag that allows shared libraries with undefined symbols to be built])
-_LT_TAGDECL([], [no_undefined_flag], [1],
- [Flag that enforces no undefined symbols])
-_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
- [Flag to hardcode $libdir into a binary during linking.
- This must work even if $libdir does not exist])
-_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
- [[If ld is used when linking, flag to hardcode $libdir into a binary
- during linking. This must work even if $libdir does not exist]])
-_LT_TAGDECL([], [hardcode_libdir_separator], [1],
- [Whether we need a single "-rpath" flag with a separated argument])
-_LT_TAGDECL([], [hardcode_direct], [0],
- [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
- DIR into the resulting binary])
-_LT_TAGDECL([], [hardcode_direct_absolute], [0],
- [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
- DIR into the resulting binary and the resulting library dependency is
- "absolute", i.e impossible to change by setting ${shlibpath_var} if the
- library is relocated])
-_LT_TAGDECL([], [hardcode_minus_L], [0],
- [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
- into the resulting binary])
-_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
- [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
- into the resulting binary])
-_LT_TAGDECL([], [hardcode_automatic], [0],
- [Set to "yes" if building a shared library automatically hardcodes DIR
- into the library and all subsequent libraries and executables linked
- against it])
-_LT_TAGDECL([], [inherit_rpath], [0],
- [Set to yes if linker adds runtime paths of dependent libraries
- to runtime path list])
-_LT_TAGDECL([], [link_all_deplibs], [0],
- [Whether libtool must link a program against all its dependency libraries])
-_LT_TAGDECL([], [always_export_symbols], [0],
- [Set to "yes" if exported symbols are required])
-_LT_TAGDECL([], [export_symbols_cmds], [2],
- [The commands to list exported symbols])
-_LT_TAGDECL([], [exclude_expsyms], [1],
- [Symbols that should not be listed in the preloaded symbols])
-_LT_TAGDECL([], [include_expsyms], [1],
- [Symbols that must always be exported])
-_LT_TAGDECL([], [prelink_cmds], [2],
- [Commands necessary for linking programs (against libraries) with templates])
-_LT_TAGDECL([], [postlink_cmds], [2],
- [Commands necessary for finishing linking programs])
-_LT_TAGDECL([], [file_list_spec], [1],
- [Specify filename containing input files])
-dnl FIXME: Not yet implemented
-dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
-dnl [Compiler flag to generate thread safe objects])
-])# _LT_LINKER_SHLIBS
-
-
-# _LT_LANG_C_CONFIG([TAG])
-# ------------------------
-# Ensure that the configuration variables for a C compiler are suitably
-# defined. These variables are subsequently used by _LT_CONFIG to write
-# the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_C_CONFIG],
-[m4_require([_LT_DECL_EGREP])dnl
-lt_save_CC="$CC"
-AC_LANG_PUSH(C)
-
-# Source file extension for C test sources.
-ac_ext=c
-
-# Object file extension for compiled C test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(){return(0);}'
-
-_LT_TAG_COMPILER
-# Save the default compiler, since it gets overwritten when the other
-# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
-compiler_DEFAULT=$CC
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-if test -n "$compiler"; then
- _LT_COMPILER_NO_RTTI($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
- LT_SYS_DLOPEN_SELF
- _LT_CMD_STRIPLIB
-
- # Report which library types will actually be built
- AC_MSG_CHECKING([if libtool supports shared libraries])
- AC_MSG_RESULT([$can_build_shared])
-
- AC_MSG_CHECKING([whether to build shared libraries])
- test "$can_build_shared" = "no" && enable_shared=no
-
- # On AIX, shared libraries and static libraries use the same namespace, and
- # are all built from PIC.
- case $host_os in
- aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-
- aix[[4-9]]*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
- esac
- AC_MSG_RESULT([$enable_shared])
-
- AC_MSG_CHECKING([whether to build static libraries])
- # Make sure either enable_shared or enable_static is yes.
- test "$enable_shared" = yes || enable_static=yes
- AC_MSG_RESULT([$enable_static])
-
- _LT_CONFIG($1)
-fi
-AC_LANG_POP
-CC="$lt_save_CC"
-])# _LT_LANG_C_CONFIG
-
-
-# _LT_LANG_CXX_CONFIG([TAG])
-# --------------------------
-# Ensure that the configuration variables for a C++ compiler are suitably
-# defined. These variables are subsequently used by _LT_CONFIG to write
-# the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_CXX_CONFIG],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-m4_require([_LT_DECL_EGREP])dnl
-m4_require([_LT_PATH_MANIFEST_TOOL])dnl
-if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
- ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
- (test "X$CXX" != "Xg++"))) ; then
- AC_PROG_CXXCPP
-else
- _lt_caught_CXX_error=yes
-fi
-
-AC_LANG_PUSH(C++)
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_TAGVAR(allow_undefined_flag, $1)=
-_LT_TAGVAR(always_export_symbols, $1)=no
-_LT_TAGVAR(archive_expsym_cmds, $1)=
-_LT_TAGVAR(compiler_needs_object, $1)=no
-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_TAGVAR(hardcode_direct, $1)=no
-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_TAGVAR(hardcode_minus_L, $1)=no
-_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
-_LT_TAGVAR(hardcode_automatic, $1)=no
-_LT_TAGVAR(inherit_rpath, $1)=no
-_LT_TAGVAR(module_cmds, $1)=
-_LT_TAGVAR(module_expsym_cmds, $1)=
-_LT_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_TAGVAR(reload_flag, $1)=$reload_flag
-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
-_LT_TAGVAR(no_undefined_flag, $1)=
-_LT_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Source file extension for C++ test sources.
-ac_ext=cpp
-
-# Object file extension for compiled C++ test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# No sense in running all these tests if we already determined that
-# the CXX compiler isn't working. Some variables (like enable_shared)
-# are currently assumed to apply to all compilers on this platform,
-# and will be corrupted by setting them based on a non-working compiler.
-if test "$_lt_caught_CXX_error" != yes; then
- # Code to be used in simple compile tests
- lt_simple_compile_test_code="int some_variable = 0;"
-
- # Code to be used in simple link tests
- lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
-
- # ltmain only uses $CC for tagged configurations so make sure $CC is set.
- _LT_TAG_COMPILER
-
- # save warnings/boilerplate of simple test code
- _LT_COMPILER_BOILERPLATE
- _LT_LINKER_BOILERPLATE
-
- # Allow CC to be a program name with arguments.
- lt_save_CC=$CC
- lt_save_CFLAGS=$CFLAGS
- lt_save_LD=$LD
- lt_save_GCC=$GCC
- GCC=$GXX
- lt_save_with_gnu_ld=$with_gnu_ld
- lt_save_path_LD=$lt_cv_path_LD
- if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
- lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
- else
- $as_unset lt_cv_prog_gnu_ld
- fi
- if test -n "${lt_cv_path_LDCXX+set}"; then
- lt_cv_path_LD=$lt_cv_path_LDCXX
- else
- $as_unset lt_cv_path_LD
- fi
- test -z "${LDCXX+set}" || LD=$LDCXX
- CC=${CXX-"c++"}
- CFLAGS=$CXXFLAGS
- compiler=$CC
- _LT_TAGVAR(compiler, $1)=$CC
- _LT_CC_BASENAME([$compiler])
-
- if test -n "$compiler"; then
- # We don't want -fno-exception when compiling C++ code, so set the
- # no_builtin_flag separately
- if test "$GXX" = yes; then
- _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
- else
- _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
- fi
-
- if test "$GXX" = yes; then
- # Set up default GNU C++ configuration
-
- LT_PATH_LD
-
- # Check if GNU C++ uses GNU ld as the underlying linker, since the
- # archiving commands below assume that GNU ld is being used.
- if test "$with_gnu_ld" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-
- # If archive_cmds runs LD, not CC, wlarc should be empty
- # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
- # investigate it a little bit more. (MM)
- wlarc='${wl}'
-
- # ancient GNU ld didn't support --whole-archive et. al.
- if eval "`$CC -print-prog-name=ld` --help 2>&1" |
- $GREP 'no-whole-archive' > /dev/null; then
- _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- _LT_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- else
- with_gnu_ld=no
- wlarc=
-
- # A generic and very simple default shared library creation
- # command for GNU C++ for the case where it uses the native
- # linker, instead of GNU ld. If possible, this setting should
- # overridden to take advantage of the native linker features on
- # the platform it is being used on.
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- fi
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
-
- else
- GXX=no
- with_gnu_ld=no
- wlarc=
- fi
-
- # PORTME: fill in a description of your system's C++ link characteristics
- AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
- _LT_TAGVAR(ld_shlibs, $1)=yes
- case $host_os in
- aix3*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- aix[[4-9]]*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
- for ld_flag in $LDFLAGS; do
- case $ld_flag in
- *-brtl*)
- aix_use_runtimelinking=yes
- break
- ;;
- esac
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- _LT_TAGVAR(archive_cmds, $1)=''
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
-
- if test "$GXX" = yes; then
- case $host_os in aix4.[[012]]|aix4.[[012]].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" &&
- strings "$collect2name" | $GREP resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- :
- else
- # We have old collect2
- _LT_TAGVAR(hardcode_direct, $1)=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- _LT_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=
- fi
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to
- # export.
- _LT_TAGVAR(always_export_symbols, $1)=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
- # Determine the default libpath from the value encoded in an empty
- # executable.
- _LT_SYS_MODULE_PATH_AIX([$1])
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
-
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
- _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an
- # empty executable.
- _LT_SYS_MODULE_PATH_AIX([$1])
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
- if test "$with_gnu_ld" = yes; then
- # We only use this code for GNU lds that support --whole-archive.
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
- else
- # Exported symbols can be pulled into shared objects from archives
- _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
- fi
- _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
- # This is similar to how AIX traditionally builds its shared
- # libraries.
- _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- beos*)
- if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- chorus*)
- case $cc_basename in
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- cygwin* | mingw* | pw32* | cegcc*)
- case $GXX,$cc_basename in
- ,cl* | no,cl*)
- # Native MSVC
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=yes
- _LT_TAGVAR(file_list_spec, $1)='@'
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
- _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
- else
- $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
- fi~
- $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
- linknames='
- # The linker will not automatically build a static lib if we build a DLL.
- # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- # Don't use ranlib
- _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
- _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
- lt_tool_outputfile="@TOOL_OUTPUT@"~
- case $lt_outputfile in
- *.exe|*.EXE) ;;
- *)
- lt_outputfile="$lt_outputfile.exe"
- lt_tool_outputfile="$lt_tool_outputfile.exe"
- ;;
- esac~
- func_to_tool_file "$lt_outputfile"~
- if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
- $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
- $RM "$lt_outputfile.manifest";
- fi'
- ;;
- *)
- # g++
- # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
- # as there is no search path for DLLs.
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
- _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_TAGVAR(always_export_symbols, $1)=no
- _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
-
- if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
- darwin* | rhapsody*)
- _LT_DARWIN_LINKER_FEATURES($1)
- ;;
-
- dgux*)
- case $cc_basename in
- ec++*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- freebsd[[12]]*)
- # C++ shared libraries reported to be fairly broken before
- # switch to ELF
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- freebsd-elf*)
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- ;;
-
- freebsd* | dragonfly*)
- # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
- # conventions
- _LT_TAGVAR(ld_shlibs, $1)=yes
- ;;
-
- gnu*)
- ;;
-
- haiku*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- hpux9*)
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
- # but as the default
- # location of the library.
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- aCC*)
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
- ;;
- *)
- if test "$GXX" = yes; then
- _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- hpux10*|hpux11*)
- if test $with_gnu_ld = no; then
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- ;;
- *)
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- ;;
- esac
- fi
- case $host_cpu in
- hppa*64*|ia64*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
- *)
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
- # but as the default
- # location of the library.
- ;;
- esac
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- aCC*)
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
- ;;
- *)
- if test "$GXX" = yes; then
- if test $with_gnu_ld = no; then
- case $host_cpu in
- hppa*64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- fi
- else
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- interix[[3-9]]*)
- _LT_TAGVAR(hardcode_direct, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
- irix5* | irix6*)
- case $cc_basename in
- CC*)
- # SGI C++
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
-
- # Archives containing C++ object files must be created using
- # "CC -ar", where "CC" is the IRIX C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
- ;;
- *)
- if test "$GXX" = yes; then
- if test "$with_gnu_ld" = no; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
- fi
- fi
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- ;;
- esac
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_TAGVAR(inherit_rpath, $1)=yes
- ;;
-
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-
- # Archives containing C++ object files must be created using
- # "CC -Bstatic", where "CC" is the KAI C++ compiler.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
- ;;
- icpc* | ecpc* )
- # Intel C++
- with_gnu_ld=yes
- # version 8.0 and above of icpc choke on multiply defined symbols
- # if we add $predep_objects and $postdep_objects, however 7.1 and
- # earlier do not add the objects themselves.
- case `$CC -V 2>&1` in
- *"Version 7."*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- *) # Version 8.0 or newer
- tmp_idyn=
- case $host_cpu in
- ia64*) tmp_idyn=' -i_dynamic';;
- esac
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- esac
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
- ;;
- pgCC* | pgcpp*)
- # Portland Group C++ compiler
- case `$CC -V` in
- *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
- _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
- compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
- _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
- $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
- $RANLIB $oldlib'
- _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
- $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
- rm -rf $tpldir~
- $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
- $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
- ;;
- *) # Version 6 and above use weak symbols
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
- ;;
- esac
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
- ;;
- cxx*)
- # Compaq C++
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
-
- runpath_var=LD_RUN_PATH
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
- ;;
- xl* | mpixl* | bgxl*)
- # IBM XL 8.0 on PPC, with GNU ld
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- if test "x$supports_anon_versioning" = xyes; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
- ;;
- *)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C++ 5.9
- _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
- _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
- _LT_TAGVAR(compiler_needs_object, $1)=yes
-
- # Not sure whether something based on
- # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
- # would be better.
- output_verbose_link_cmd='func_echo_all'
-
- # Archives containing C++ object files must be created using
- # "CC -xar", where "CC" is the Sun C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
- ;;
- esac
- ;;
- esac
- ;;
-
- lynxos*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- m88k*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- mvs*)
- case $cc_basename in
- cxx*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
- wlarc=
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- fi
- # Workaround some broken pre-1.5 toolchains
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
- ;;
-
- *nto* | *qnx*)
- _LT_TAGVAR(ld_shlibs, $1)=yes
- ;;
-
- openbsd2*)
- # C++ shared libraries are fairly broken
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- openbsd*)
- if test -f /usr/libexec/ld.so; then
- _LT_TAGVAR(hardcode_direct, $1)=yes
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- fi
- output_verbose_link_cmd=func_echo_all
- else
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- osf3* | osf4* | osf5*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Archives containing C++ object files must be created using
- # the KAI C++ compiler.
- case $host in
- osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
- *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
- esac
- ;;
- RCC*)
- # Rational C++ 2.4.1
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- cxx*)
- case $host in
- osf3*)
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- ;;
- *)
- _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
- echo "-hidden">> $lib.exp~
- $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
- $RM $lib.exp'
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- ;;
- esac
-
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
- ;;
- *)
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- case $host in
- osf3*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- ;;
- esac
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
-
- else
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- psos*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- lcc*)
- # Lucid
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- solaris*)
- case $cc_basename in
- CC* | sunCC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
- _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
- _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- # The compiler driver will combine and reorder linker options,
- # but understands `-z linker_flag'.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
- ;;
- esac
- _LT_TAGVAR(link_all_deplibs, $1)=yes
-
- output_verbose_link_cmd='func_echo_all'
-
- # Archives containing C++ object files must be created using
- # "CC -xar", where "CC" is the Sun C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
- ;;
- gcx*)
- # Green Hills C++ Compiler
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
-
- # The C++ compiler must be used to create the archive.
- _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
- ;;
- *)
- # GNU C++ compiler with Solaris linker
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
- if $CC --version | $GREP -v '^2\.7' > /dev/null; then
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
- else
- # g++ 2.7 appears to require `-G' NOT `-shared' on this
- # platform.
- _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
- $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
- fi
-
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
- ;;
- esac
- fi
- ;;
- esac
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
- _LT_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
- _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_TAGVAR(link_all_deplibs, $1)=yes
- _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
- '"$_LT_TAGVAR(old_archive_cmds, $1)"
- _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
- '"$_LT_TAGVAR(reload_cmds, $1)"
- ;;
- *)
- _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
-
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- vxworks*)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- *)
- # FIXME: insert proper C++ library support
- _LT_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
-
- AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
- test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
-
- _LT_TAGVAR(GCC, $1)="$GXX"
- _LT_TAGVAR(LD, $1)="$LD"
-
- ## CAVEAT EMPTOR:
- ## There is no encapsulation within the following macros, do not change
- ## the running order or otherwise move them around unless you know exactly
- ## what you are doing...
- _LT_SYS_HIDDEN_LIBDEPS($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
- fi # test -n "$compiler"
-
- CC=$lt_save_CC
- CFLAGS=$lt_save_CFLAGS
- LDCXX=$LD
- LD=$lt_save_LD
- GCC=$lt_save_GCC
- with_gnu_ld=$lt_save_with_gnu_ld
- lt_cv_path_LDCXX=$lt_cv_path_LD
- lt_cv_path_LD=$lt_save_path_LD
- lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
- lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
-fi # test "$_lt_caught_CXX_error" != yes
-
-AC_LANG_POP
-])# _LT_LANG_CXX_CONFIG
-
-
-# _LT_FUNC_STRIPNAME_CNF
-# ----------------------
-# func_stripname_cnf prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-#
-# This function is identical to the (non-XSI) version of func_stripname,
-# except this one can be used by m4 code that may be executed by configure,
-# rather than the libtool script.
-m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
-AC_REQUIRE([_LT_DECL_SED])
-AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
-func_stripname_cnf ()
-{
- case ${2} in
- .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
- *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
- esac
-} # func_stripname_cnf
-])# _LT_FUNC_STRIPNAME_CNF
-
-# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
-# ---------------------------------
-# Figure out "hidden" library dependencies from verbose
-# compiler output when linking a shared library.
-# Parse the compiler output and extract the necessary
-# objects, libraries and library flags.
-m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
-AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
-# Dependencies to place before and after the object being linked:
-_LT_TAGVAR(predep_objects, $1)=
-_LT_TAGVAR(postdep_objects, $1)=
-_LT_TAGVAR(predeps, $1)=
-_LT_TAGVAR(postdeps, $1)=
-_LT_TAGVAR(compiler_lib_search_path, $1)=
-
-dnl we can't use the lt_simple_compile_test_code here,
-dnl because it contains code intended for an executable,
-dnl not a library. It's possible we should let each
-dnl tag define a new lt_????_link_test_code variable,
-dnl but it's only used here...
-m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
-int a;
-void foo (void) { a = 0; }
-_LT_EOF
-], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
-class Foo
-{
-public:
- Foo (void) { a = 0; }
-private:
- int a;
-};
-_LT_EOF
-], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
- subroutine foo
- implicit none
- integer*4 a
- a=0
- return
- end
-_LT_EOF
-], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
- subroutine foo
- implicit none
- integer a
- a=0
- return
- end
-_LT_EOF
-], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
-public class foo {
- private int a;
- public void bar (void) {
- a = 0;
- }
-};
-_LT_EOF
-])
-
-_lt_libdeps_save_CFLAGS=$CFLAGS
-case "$CC $CFLAGS " in #(
-*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
-*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
-esac
-
-dnl Parse the compiler output and extract the necessary
-dnl objects, libraries and library flags.
-if AC_TRY_EVAL(ac_compile); then
- # Parse the compiler output and extract the necessary
- # objects, libraries and library flags.
-
- # Sentinel used to keep track of whether or not we are before
- # the conftest object file.
- pre_test_object_deps_done=no
-
- for p in `eval "$output_verbose_link_cmd"`; do
- case ${prev}${p} in
-
- -L* | -R* | -l*)
- # Some compilers place space between "-{L,R}" and the path.
- # Remove the space.
- if test $p = "-L" ||
- test $p = "-R"; then
- prev=$p
- continue
- fi
-
- # Expand the sysroot to ease extracting the directories later.
- if test -z "$prev"; then
- case $p in
- -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
- -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
- -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
- esac
- fi
- case $p in
- =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
- esac
- if test "$pre_test_object_deps_done" = no; then
- case ${prev} in
- -L | -R)
- # Internal compiler library paths should come after those
- # provided the user. The postdeps already come after the
- # user supplied libs so there is no need to process them.
- if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
- _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
- else
- _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
- fi
- ;;
- # The "-l" case would never come before the object being
- # linked, so don't bother handling this case.
- esac
- else
- if test -z "$_LT_TAGVAR(postdeps, $1)"; then
- _LT_TAGVAR(postdeps, $1)="${prev}${p}"
- else
- _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
- fi
- fi
- prev=
- ;;
-
- *.lto.$objext) ;; # Ignore GCC LTO objects
- *.$objext)
- # This assumes that the test object file only shows up
- # once in the compiler output.
- if test "$p" = "conftest.$objext"; then
- pre_test_object_deps_done=yes
- continue
- fi
-
- if test "$pre_test_object_deps_done" = no; then
- if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
- _LT_TAGVAR(predep_objects, $1)="$p"
- else
- _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
- fi
- else
- if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
- _LT_TAGVAR(postdep_objects, $1)="$p"
- else
- _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
- fi
- fi
- ;;
-
- *) ;; # Ignore the rest.
-
- esac
- done
-
- # Clean up.
- rm -f a.out a.exe
-else
- echo "libtool.m4: error: problem compiling $1 test program"
-fi
-
-$RM -f confest.$objext
-CFLAGS=$_lt_libdeps_save_CFLAGS
-
-# PORTME: override above test on systems where it is broken
-m4_if([$1], [CXX],
-[case $host_os in
-interix[[3-9]]*)
- # Interix 3.5 installs completely hosed .la files for C++, so rather than
- # hack all around it, let's just trust "g++" to DTRT.
- _LT_TAGVAR(predep_objects,$1)=
- _LT_TAGVAR(postdep_objects,$1)=
- _LT_TAGVAR(postdeps,$1)=
- ;;
-
-linux*)
- case `$CC -V 2>&1 | sed 5q` in
- *Sun\ C*)
- # Sun C++ 5.9
-
- # The more standards-conforming stlport4 library is
- # incompatible with the Cstd library. Avoid specifying
- # it if it's in CXXFLAGS. Ignore libCrun as
- # -library=stlport4 depends on it.
- case " $CXX $CXXFLAGS " in
- *" -library=stlport4 "*)
- solaris_use_stlport4=yes
- ;;
- esac
-
- if test "$solaris_use_stlport4" != yes; then
- _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
- fi
- ;;
- esac
- ;;
-
-solaris*)
- case $cc_basename in
- CC* | sunCC*)
- # The more standards-conforming stlport4 library is
- # incompatible with the Cstd library. Avoid specifying
- # it if it's in CXXFLAGS. Ignore libCrun as
- # -library=stlport4 depends on it.
- case " $CXX $CXXFLAGS " in
- *" -library=stlport4 "*)
- solaris_use_stlport4=yes
- ;;
- esac
-
- # Adding this requires a known-good setup of shared libraries for
- # Sun compiler versions before 5.6, else PIC objects from an old
- # archive will be linked into the output, leading to subtle bugs.
- if test "$solaris_use_stlport4" != yes; then
- _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
- fi
- ;;
- esac
- ;;
-esac
-])
-
-case " $_LT_TAGVAR(postdeps, $1) " in
-*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
-esac
- _LT_TAGVAR(compiler_lib_search_dirs, $1)=
-if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
- _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
-fi
-_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
- [The directories searched by this compiler when creating a shared library])
-_LT_TAGDECL([], [predep_objects], [1],
- [Dependencies to place before and after the objects being linked to
- create a shared library])
-_LT_TAGDECL([], [postdep_objects], [1])
-_LT_TAGDECL([], [predeps], [1])
-_LT_TAGDECL([], [postdeps], [1])
-_LT_TAGDECL([], [compiler_lib_search_path], [1],
- [The library search path used internally by the compiler when linking
- a shared library])
-])# _LT_SYS_HIDDEN_LIBDEPS
-
-
-# _LT_LANG_F77_CONFIG([TAG])
-# --------------------------
-# Ensure that the configuration variables for a Fortran 77 compiler are
-# suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_F77_CONFIG],
-[AC_LANG_PUSH(Fortran 77)
-if test -z "$F77" || test "X$F77" = "Xno"; then
- _lt_disable_F77=yes
-fi
-
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_TAGVAR(allow_undefined_flag, $1)=
-_LT_TAGVAR(always_export_symbols, $1)=no
-_LT_TAGVAR(archive_expsym_cmds, $1)=
-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_TAGVAR(hardcode_direct, $1)=no
-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_TAGVAR(hardcode_minus_L, $1)=no
-_LT_TAGVAR(hardcode_automatic, $1)=no
-_LT_TAGVAR(inherit_rpath, $1)=no
-_LT_TAGVAR(module_cmds, $1)=
-_LT_TAGVAR(module_expsym_cmds, $1)=
-_LT_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_TAGVAR(reload_flag, $1)=$reload_flag
-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
-_LT_TAGVAR(no_undefined_flag, $1)=
-_LT_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Source file extension for f77 test sources.
-ac_ext=f
-
-# Object file extension for compiled f77 test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# No sense in running all these tests if we already determined that
-# the F77 compiler isn't working. Some variables (like enable_shared)
-# are currently assumed to apply to all compilers on this platform,
-# and will be corrupted by setting them based on a non-working compiler.
-if test "$_lt_disable_F77" != yes; then
- # Code to be used in simple compile tests
- lt_simple_compile_test_code="\
- subroutine t
- return
- end
-"
-
- # Code to be used in simple link tests
- lt_simple_link_test_code="\
- program t
- end
-"
-
- # ltmain only uses $CC for tagged configurations so make sure $CC is set.
- _LT_TAG_COMPILER
-
- # save warnings/boilerplate of simple test code
- _LT_COMPILER_BOILERPLATE
- _LT_LINKER_BOILERPLATE
-
- # Allow CC to be a program name with arguments.
- lt_save_CC="$CC"
- lt_save_GCC=$GCC
- lt_save_CFLAGS=$CFLAGS
- CC=${F77-"f77"}
- CFLAGS=$FFLAGS
- compiler=$CC
- _LT_TAGVAR(compiler, $1)=$CC
- _LT_CC_BASENAME([$compiler])
- GCC=$G77
- if test -n "$compiler"; then
- AC_MSG_CHECKING([if libtool supports shared libraries])
- AC_MSG_RESULT([$can_build_shared])
-
- AC_MSG_CHECKING([whether to build shared libraries])
- test "$can_build_shared" = "no" && enable_shared=no
-
- # On AIX, shared libraries and static libraries use the same namespace, and
- # are all built from PIC.
- case $host_os in
- aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
- aix[[4-9]]*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
- esac
- AC_MSG_RESULT([$enable_shared])
-
- AC_MSG_CHECKING([whether to build static libraries])
- # Make sure either enable_shared or enable_static is yes.
- test "$enable_shared" = yes || enable_static=yes
- AC_MSG_RESULT([$enable_static])
-
- _LT_TAGVAR(GCC, $1)="$G77"
- _LT_TAGVAR(LD, $1)="$LD"
-
- ## CAVEAT EMPTOR:
- ## There is no encapsulation within the following macros, do not change
- ## the running order or otherwise move them around unless you know exactly
- ## what you are doing...
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
- fi # test -n "$compiler"
-
- GCC=$lt_save_GCC
- CC="$lt_save_CC"
- CFLAGS="$lt_save_CFLAGS"
-fi # test "$_lt_disable_F77" != yes
-
-AC_LANG_POP
-])# _LT_LANG_F77_CONFIG
-
-
-# _LT_LANG_FC_CONFIG([TAG])
-# -------------------------
-# Ensure that the configuration variables for a Fortran compiler are
-# suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_FC_CONFIG],
-[AC_LANG_PUSH(Fortran)
-
-if test -z "$FC" || test "X$FC" = "Xno"; then
- _lt_disable_FC=yes
-fi
-
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_TAGVAR(allow_undefined_flag, $1)=
-_LT_TAGVAR(always_export_symbols, $1)=no
-_LT_TAGVAR(archive_expsym_cmds, $1)=
-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_TAGVAR(hardcode_direct, $1)=no
-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_TAGVAR(hardcode_minus_L, $1)=no
-_LT_TAGVAR(hardcode_automatic, $1)=no
-_LT_TAGVAR(inherit_rpath, $1)=no
-_LT_TAGVAR(module_cmds, $1)=
-_LT_TAGVAR(module_expsym_cmds, $1)=
-_LT_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_TAGVAR(reload_flag, $1)=$reload_flag
-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
-_LT_TAGVAR(no_undefined_flag, $1)=
-_LT_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Source file extension for fc test sources.
-ac_ext=${ac_fc_srcext-f}
-
-# Object file extension for compiled fc test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# No sense in running all these tests if we already determined that
-# the FC compiler isn't working. Some variables (like enable_shared)
-# are currently assumed to apply to all compilers on this platform,
-# and will be corrupted by setting them based on a non-working compiler.
-if test "$_lt_disable_FC" != yes; then
- # Code to be used in simple compile tests
- lt_simple_compile_test_code="\
- subroutine t
- return
- end
-"
-
- # Code to be used in simple link tests
- lt_simple_link_test_code="\
- program t
- end
-"
-
- # ltmain only uses $CC for tagged configurations so make sure $CC is set.
- _LT_TAG_COMPILER
-
- # save warnings/boilerplate of simple test code
- _LT_COMPILER_BOILERPLATE
- _LT_LINKER_BOILERPLATE
-
- # Allow CC to be a program name with arguments.
- lt_save_CC="$CC"
- lt_save_GCC=$GCC
- lt_save_CFLAGS=$CFLAGS
- CC=${FC-"f95"}
- CFLAGS=$FCFLAGS
- compiler=$CC
- GCC=$ac_cv_fc_compiler_gnu
-
- _LT_TAGVAR(compiler, $1)=$CC
- _LT_CC_BASENAME([$compiler])
-
- if test -n "$compiler"; then
- AC_MSG_CHECKING([if libtool supports shared libraries])
- AC_MSG_RESULT([$can_build_shared])
-
- AC_MSG_CHECKING([whether to build shared libraries])
- test "$can_build_shared" = "no" && enable_shared=no
-
- # On AIX, shared libraries and static libraries use the same namespace, and
- # are all built from PIC.
- case $host_os in
- aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
- aix[[4-9]]*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
- esac
- AC_MSG_RESULT([$enable_shared])
-
- AC_MSG_CHECKING([whether to build static libraries])
- # Make sure either enable_shared or enable_static is yes.
- test "$enable_shared" = yes || enable_static=yes
- AC_MSG_RESULT([$enable_static])
-
- _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
- _LT_TAGVAR(LD, $1)="$LD"
-
- ## CAVEAT EMPTOR:
- ## There is no encapsulation within the following macros, do not change
- ## the running order or otherwise move them around unless you know exactly
- ## what you are doing...
- _LT_SYS_HIDDEN_LIBDEPS($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_SYS_DYNAMIC_LINKER($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
- fi # test -n "$compiler"
-
- GCC=$lt_save_GCC
- CC=$lt_save_CC
- CFLAGS=$lt_save_CFLAGS
-fi # test "$_lt_disable_FC" != yes
-
-AC_LANG_POP
-])# _LT_LANG_FC_CONFIG
-
-
-# _LT_LANG_GCJ_CONFIG([TAG])
-# --------------------------
-# Ensure that the configuration variables for the GNU Java Compiler compiler
-# are suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_GCJ_CONFIG],
-[AC_REQUIRE([LT_PROG_GCJ])dnl
-AC_LANG_SAVE
-
-# Source file extension for Java test sources.
-ac_ext=java
-
-# Object file extension for compiled Java test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="class foo {}"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_TAG_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC=$CC
-lt_save_CFLAGS=$CFLAGS
-lt_save_GCC=$GCC
-GCC=yes
-CC=${GCJ-"gcj"}
-CFLAGS=$GCJFLAGS
-compiler=$CC
-_LT_TAGVAR(compiler, $1)=$CC
-_LT_TAGVAR(LD, $1)="$LD"
-_LT_CC_BASENAME([$compiler])
-
-# GCJ did not exist at the time GCC didn't implicitly link libc in.
-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
-
-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_TAGVAR(reload_flag, $1)=$reload_flag
-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
-
-if test -n "$compiler"; then
- _LT_COMPILER_NO_RTTI($1)
- _LT_COMPILER_PIC($1)
- _LT_COMPILER_C_O($1)
- _LT_COMPILER_FILE_LOCKS($1)
- _LT_LINKER_SHLIBS($1)
- _LT_LINKER_HARDCODE_LIBPATH($1)
-
- _LT_CONFIG($1)
-fi
-
-AC_LANG_RESTORE
-
-GCC=$lt_save_GCC
-CC=$lt_save_CC
-CFLAGS=$lt_save_CFLAGS
-])# _LT_LANG_GCJ_CONFIG
-
-
-# _LT_LANG_RC_CONFIG([TAG])
-# -------------------------
-# Ensure that the configuration variables for the Windows resource compiler
-# are suitably defined. These variables are subsequently used by _LT_CONFIG
-# to write the compiler configuration to `libtool'.
-m4_defun([_LT_LANG_RC_CONFIG],
-[AC_REQUIRE([LT_PROG_RC])dnl
-AC_LANG_SAVE
-
-# Source file extension for RC test sources.
-ac_ext=rc
-
-# Object file extension for compiled RC test sources.
-objext=o
-_LT_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
-
-# Code to be used in simple link tests
-lt_simple_link_test_code="$lt_simple_compile_test_code"
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_TAG_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-lt_save_CFLAGS=$CFLAGS
-lt_save_GCC=$GCC
-GCC=
-CC=${RC-"windres"}
-CFLAGS=
-compiler=$CC
-_LT_TAGVAR(compiler, $1)=$CC
-_LT_CC_BASENAME([$compiler])
-_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
-
-if test -n "$compiler"; then
- :
- _LT_CONFIG($1)
-fi
-
-GCC=$lt_save_GCC
-AC_LANG_RESTORE
-CC=$lt_save_CC
-CFLAGS=$lt_save_CFLAGS
-])# _LT_LANG_RC_CONFIG
-
-
-# LT_PROG_GCJ
-# -----------
-AC_DEFUN([LT_PROG_GCJ],
-[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
- [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
- [AC_CHECK_TOOL(GCJ, gcj,)
- test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
- AC_SUBST(GCJFLAGS)])])[]dnl
-])
-
-# Old name:
-AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
-
-
-# LT_PROG_RC
-# ----------
-AC_DEFUN([LT_PROG_RC],
-[AC_CHECK_TOOL(RC, windres,)
-])
-
-# Old name:
-AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([LT_AC_PROG_RC], [])
-
-
-# _LT_DECL_EGREP
-# --------------
-# If we don't have a new enough Autoconf to choose the best grep
-# available, choose the one first in the user's PATH.
-m4_defun([_LT_DECL_EGREP],
-[AC_REQUIRE([AC_PROG_EGREP])dnl
-AC_REQUIRE([AC_PROG_FGREP])dnl
-test -z "$GREP" && GREP=grep
-_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
-_LT_DECL([], [EGREP], [1], [An ERE matcher])
-_LT_DECL([], [FGREP], [1], [A literal string matcher])
-dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
-AC_SUBST([GREP])
-])
-
-
-# _LT_DECL_OBJDUMP
-# --------------
-# If we don't have a new enough Autoconf to choose the best objdump
-# available, choose the one first in the user's PATH.
-m4_defun([_LT_DECL_OBJDUMP],
-[AC_CHECK_TOOL(OBJDUMP, objdump, false)
-test -z "$OBJDUMP" && OBJDUMP=objdump
-_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
-AC_SUBST([OBJDUMP])
-])
-
-# _LT_DECL_DLLTOOL
-# ----------------
-# Ensure DLLTOOL variable is set.
-m4_defun([_LT_DECL_DLLTOOL],
-[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
-AC_SUBST([DLLTOOL])
-])
-
-# _LT_DECL_SED
-# ------------
-# Check for a fully-functional sed program, that truncates
-# as few characters as possible. Prefer GNU sed if found.
-m4_defun([_LT_DECL_SED],
-[AC_PROG_SED
-test -z "$SED" && SED=sed
-Xsed="$SED -e 1s/^X//"
-_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
-_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
- [Sed that helps us avoid accidentally triggering echo(1) options like -n])
-])# _LT_DECL_SED
-
-m4_ifndef([AC_PROG_SED], [
-# NOTE: This macro has been submitted for inclusion into #
-# GNU Autoconf as AC_PROG_SED. When it is available in #
-# a released version of Autoconf we should remove this #
-# macro and use it instead. #
-
-m4_defun([AC_PROG_SED],
-[AC_MSG_CHECKING([for a sed that does not truncate output])
-AC_CACHE_VAL(lt_cv_path_SED,
-[# Loop through the user's path and test for sed and gsed.
-# Then use that list of sed's as ones to test for truncation.
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for lt_ac_prog in sed gsed; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
- lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
- fi
- done
- done
-done
-IFS=$as_save_IFS
-lt_ac_max=0
-lt_ac_count=0
-# Add /usr/xpg4/bin/sed as it is typically found on Solaris
-# along with /bin/sed that truncates output.
-for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
- test ! -f $lt_ac_sed && continue
- cat /dev/null > conftest.in
- lt_ac_count=0
- echo $ECHO_N "0123456789$ECHO_C" >conftest.in
- # Check for GNU sed and select it if it is found.
- if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
- lt_cv_path_SED=$lt_ac_sed
- break
- fi
- while true; do
- cat conftest.in conftest.in >conftest.tmp
- mv conftest.tmp conftest.in
- cp conftest.in conftest.nl
- echo >>conftest.nl
- $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
- cmp -s conftest.out conftest.nl || break
- # 10000 chars as input seems more than enough
- test $lt_ac_count -gt 10 && break
- lt_ac_count=`expr $lt_ac_count + 1`
- if test $lt_ac_count -gt $lt_ac_max; then
- lt_ac_max=$lt_ac_count
- lt_cv_path_SED=$lt_ac_sed
- fi
- done
-done
-])
-SED=$lt_cv_path_SED
-AC_SUBST([SED])
-AC_MSG_RESULT([$SED])
-])#AC_PROG_SED
-])#m4_ifndef
-
-# Old name:
-AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([LT_AC_PROG_SED], [])
-
-
-# _LT_CHECK_SHELL_FEATURES
-# ------------------------
-# Find out whether the shell is Bourne or XSI compatible,
-# or has some other useful features.
-m4_defun([_LT_CHECK_SHELL_FEATURES],
-[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
-# Try some XSI features
-xsi_shell=no
-( _lt_dummy="a/b/c"
- test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
- = c,a/b,b/c, \
- && eval 'test $(( 1 + 1 )) -eq 2 \
- && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
- && xsi_shell=yes
-AC_MSG_RESULT([$xsi_shell])
-_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
-
-AC_MSG_CHECKING([whether the shell understands "+="])
-lt_shell_append=no
-( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
- >/dev/null 2>&1 \
- && lt_shell_append=yes
-AC_MSG_RESULT([$lt_shell_append])
-_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
-
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- lt_unset=unset
-else
- lt_unset=false
-fi
-_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
-
-# test EBCDIC or ASCII
-case `echo X|tr X '\101'` in
- A) # ASCII based system
- # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
- lt_SP2NL='tr \040 \012'
- lt_NL2SP='tr \015\012 \040\040'
- ;;
- *) # EBCDIC based system
- lt_SP2NL='tr \100 \n'
- lt_NL2SP='tr \r\n \100\100'
- ;;
-esac
-_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
-_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
-])# _LT_CHECK_SHELL_FEATURES
-
-
-# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY)
-# ------------------------------------------------------
-# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and
-# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY.
-m4_defun([_LT_PROG_FUNCTION_REPLACE],
-[dnl {
-sed -e '/^$1 ()$/,/^} # $1 /c\
-$1 ()\
-{\
-m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1])
-} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \
- && mv -f "$cfgfile.tmp" "$cfgfile" \
- || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-])
-
-
-# _LT_PROG_REPLACE_SHELLFNS
-# -------------------------
-# Replace existing portable implementations of several shell functions with
-# equivalent extended shell implementations where those features are available..
-m4_defun([_LT_PROG_REPLACE_SHELLFNS],
-[if test x"$xsi_shell" = xyes; then
- _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac])
-
- _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl
- func_basename_result="${1##*/}"])
-
- _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac
- func_basename_result="${1##*/}"])
-
- _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl
- # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
- # positional parameters, so assign one to ordinary parameter first.
- func_stripname_result=${3}
- func_stripname_result=${func_stripname_result#"${1}"}
- func_stripname_result=${func_stripname_result%"${2}"}])
-
- _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl
- func_split_long_opt_name=${1%%=*}
- func_split_long_opt_arg=${1#*=}])
-
- _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl
- func_split_short_opt_arg=${1#??}
- func_split_short_opt_name=${1%"$func_split_short_opt_arg"}])
-
- _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl
- case ${1} in
- *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
- *) func_lo2o_result=${1} ;;
- esac])
-
- _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo])
-
- _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))])
-
- _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}])
-fi
-
-if test x"$lt_shell_append" = xyes; then
- _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"])
-
- _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl
- func_quote_for_eval "${2}"
-dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \
- eval "${1}+=\\\\ \\$func_quote_for_eval_result"])
-
- # Save a `func_append' function call where possible by direct use of '+='
- sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
- && mv -f "$cfgfile.tmp" "$cfgfile" \
- || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
- test 0 -eq $? || _lt_function_replace_fail=:
-else
- # Save a `func_append' function call even when '+=' is not available
- sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
- && mv -f "$cfgfile.tmp" "$cfgfile" \
- || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
- test 0 -eq $? || _lt_function_replace_fail=:
-fi
-
-if test x"$_lt_function_replace_fail" = x":"; then
- AC_MSG_WARN([Unable to substitute extended shell functions in $ofile])
-fi
-])
-
-# _LT_PATH_CONVERSION_FUNCTIONS
-# -----------------------------
-# Determine which file name conversion functions should be used by
-# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
-# for certain cross-compile configurations and native mingw.
-m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-AC_MSG_CHECKING([how to convert $build file names to $host format])
-AC_CACHE_VAL(lt_cv_to_host_file_cmd,
-[case $host in
- *-*-mingw* )
- case $build in
- *-*-mingw* ) # actually msys
- lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
- ;;
- *-*-cygwin* )
- lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
- ;;
- * ) # otherwise, assume *nix
- lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
- ;;
- esac
- ;;
- *-*-cygwin* )
- case $build in
- *-*-mingw* ) # actually msys
- lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
- ;;
- *-*-cygwin* )
- lt_cv_to_host_file_cmd=func_convert_file_noop
- ;;
- * ) # otherwise, assume *nix
- lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
- ;;
- esac
- ;;
- * ) # unhandled hosts (and "normal" native builds)
- lt_cv_to_host_file_cmd=func_convert_file_noop
- ;;
-esac
-])
-to_host_file_cmd=$lt_cv_to_host_file_cmd
-AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
-_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
- [0], [convert $build file names to $host format])dnl
-
-AC_MSG_CHECKING([how to convert $build file names to toolchain format])
-AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
-[#assume ordinary cross tools, or native build.
-lt_cv_to_tool_file_cmd=func_convert_file_noop
-case $host in
- *-*-mingw* )
- case $build in
- *-*-mingw* ) # actually msys
- lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
- ;;
- esac
- ;;
-esac
-])
-to_tool_file_cmd=$lt_cv_to_tool_file_cmd
-AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
-_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
- [0], [convert $build files to toolchain format])dnl
-])# _LT_PATH_CONVERSION_FUNCTIONS
-
-# Helper functions for option handling. -*- Autoconf -*-
-#
-# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
-# Written by Gary V. Vaughan, 2004
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# serial 7 ltoptions.m4
-
-# This is to help aclocal find these macros, as it can't see m4_define.
-AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
-# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
-# ------------------------------------------
-m4_define([_LT_MANGLE_OPTION],
-[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
-
-
-# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
-# ---------------------------------------
-# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
-# matching handler defined, dispatch to it. Other OPTION-NAMEs are
-# saved as a flag.
-m4_define([_LT_SET_OPTION],
-[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
-m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
- _LT_MANGLE_DEFUN([$1], [$2]),
- [m4_warning([Unknown $1 option `$2'])])[]dnl
-])
-
-
-# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
-# ------------------------------------------------------------
-# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
-m4_define([_LT_IF_OPTION],
-[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
-
-
-# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
-# -------------------------------------------------------
-# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
-# are set.
-m4_define([_LT_UNLESS_OPTIONS],
-[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
- [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
- [m4_define([$0_found])])])[]dnl
-m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
-])[]dnl
-])
-
-
-# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
-# ----------------------------------------
-# OPTION-LIST is a space-separated list of Libtool options associated
-# with MACRO-NAME. If any OPTION has a matching handler declared with
-# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
-# the unknown option and exit.
-m4_defun([_LT_SET_OPTIONS],
-[# Set options
-m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
- [_LT_SET_OPTION([$1], _LT_Option)])
-
-m4_if([$1],[LT_INIT],[
- dnl
- dnl Simply set some default values (i.e off) if boolean options were not
- dnl specified:
- _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
- ])
- _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
- ])
- dnl
- dnl If no reference was made to various pairs of opposing options, then
- dnl we run the default mode handler for the pair. For example, if neither
- dnl `shared' nor `disable-shared' was passed, we enable building of shared
- dnl archives by default:
- _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
- _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
- _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
- _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
- [_LT_ENABLE_FAST_INSTALL])
- ])
-])# _LT_SET_OPTIONS
-
-
-
-# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
-# -----------------------------------------
-m4_define([_LT_MANGLE_DEFUN],
-[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
-
-
-# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
-# -----------------------------------------------
-m4_define([LT_OPTION_DEFINE],
-[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
-])# LT_OPTION_DEFINE
-
-
-# dlopen
-# ------
-LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
-])
-
-AU_DEFUN([AC_LIBTOOL_DLOPEN],
-[_LT_SET_OPTION([LT_INIT], [dlopen])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you
-put the `dlopen' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
-
-
-# win32-dll
-# ---------
-# Declare package support for building win32 dll's.
-LT_OPTION_DEFINE([LT_INIT], [win32-dll],
-[enable_win32_dll=yes
-
-case $host in
-*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
- AC_CHECK_TOOL(AS, as, false)
- AC_CHECK_TOOL(DLLTOOL, dlltool, false)
- AC_CHECK_TOOL(OBJDUMP, objdump, false)
- ;;
-esac
-
-test -z "$AS" && AS=as
-_LT_DECL([], [AS], [1], [Assembler program])dnl
-
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
-
-test -z "$OBJDUMP" && OBJDUMP=objdump
-_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
-])# win32-dll
-
-AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-_LT_SET_OPTION([LT_INIT], [win32-dll])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you
-put the `win32-dll' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
-
-
-# _LT_ENABLE_SHARED([DEFAULT])
-# ----------------------------
-# implement the --enable-shared flag, and supports the `shared' and
-# `disable-shared' LT_INIT options.
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-m4_define([_LT_ENABLE_SHARED],
-[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
-AC_ARG_ENABLE([shared],
- [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
- [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_shared=yes ;;
- no) enable_shared=no ;;
- *)
- enable_shared=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_shared=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
-
- _LT_DECL([build_libtool_libs], [enable_shared], [0],
- [Whether or not to build shared libraries])
-])# _LT_ENABLE_SHARED
-
-LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
-LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
-
-# Old names:
-AC_DEFUN([AC_ENABLE_SHARED],
-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
-])
-
-AC_DEFUN([AC_DISABLE_SHARED],
-[_LT_SET_OPTION([LT_INIT], [disable-shared])
-])
-
-AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
-AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_ENABLE_SHARED], [])
-dnl AC_DEFUN([AM_DISABLE_SHARED], [])
-
-
-
-# _LT_ENABLE_STATIC([DEFAULT])
-# ----------------------------
-# implement the --enable-static flag, and support the `static' and
-# `disable-static' LT_INIT options.
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-m4_define([_LT_ENABLE_STATIC],
-[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
-AC_ARG_ENABLE([static],
- [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
- [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_static=yes ;;
- no) enable_static=no ;;
- *)
- enable_static=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_static=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
-
- _LT_DECL([build_old_libs], [enable_static], [0],
- [Whether or not to build static libraries])
-])# _LT_ENABLE_STATIC
-
-LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
-LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
-
-# Old names:
-AC_DEFUN([AC_ENABLE_STATIC],
-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
-])
-
-AC_DEFUN([AC_DISABLE_STATIC],
-[_LT_SET_OPTION([LT_INIT], [disable-static])
-])
-
-AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
-AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AM_ENABLE_STATIC], [])
-dnl AC_DEFUN([AM_DISABLE_STATIC], [])
-
-
-
-# _LT_ENABLE_FAST_INSTALL([DEFAULT])
-# ----------------------------------
-# implement the --enable-fast-install flag, and support the `fast-install'
-# and `disable-fast-install' LT_INIT options.
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-m4_define([_LT_ENABLE_FAST_INSTALL],
-[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
-AC_ARG_ENABLE([fast-install],
- [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
- [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_fast_install=yes ;;
- no) enable_fast_install=no ;;
- *)
- enable_fast_install=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_fast_install=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
-
-_LT_DECL([fast_install], [enable_fast_install], [0],
- [Whether or not to optimize for fast installation])dnl
-])# _LT_ENABLE_FAST_INSTALL
-
-LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
-LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
-
-# Old names:
-AU_DEFUN([AC_ENABLE_FAST_INSTALL],
-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you put
-the `fast-install' option into LT_INIT's first parameter.])
-])
-
-AU_DEFUN([AC_DISABLE_FAST_INSTALL],
-[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you put
-the `disable-fast-install' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
-dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
-
-
-# _LT_WITH_PIC([MODE])
-# --------------------
-# implement the --with-pic flag, and support the `pic-only' and `no-pic'
-# LT_INIT options.
-# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
-m4_define([_LT_WITH_PIC],
-[AC_ARG_WITH([pic],
- [AS_HELP_STRING([--with-pic],
- [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
- [pic_mode="$withval"],
- [pic_mode=default])
-
-test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
-
-_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
-])# _LT_WITH_PIC
-
-LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
-LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
-
-# Old name:
-AU_DEFUN([AC_LIBTOOL_PICMODE],
-[_LT_SET_OPTION([LT_INIT], [pic-only])
-AC_DIAGNOSE([obsolete],
-[$0: Remove this warning and the call to _LT_SET_OPTION when you
-put the `pic-only' option into LT_INIT's first parameter.])
-])
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
-
-
-m4_define([_LTDL_MODE], [])
-LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
- [m4_define([_LTDL_MODE], [nonrecursive])])
-LT_OPTION_DEFINE([LTDL_INIT], [recursive],
- [m4_define([_LTDL_MODE], [recursive])])
-LT_OPTION_DEFINE([LTDL_INIT], [subproject],
- [m4_define([_LTDL_MODE], [subproject])])
-
-m4_define([_LTDL_TYPE], [])
-LT_OPTION_DEFINE([LTDL_INIT], [installable],
- [m4_define([_LTDL_TYPE], [installable])])
-LT_OPTION_DEFINE([LTDL_INIT], [convenience],
- [m4_define([_LTDL_TYPE], [convenience])])
-
-# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
-#
-# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
-# Written by Gary V. Vaughan, 2004
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# serial 6 ltsugar.m4
-
-# This is to help aclocal find these macros, as it can't see m4_define.
-AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
-
-
-# lt_join(SEP, ARG1, [ARG2...])
-# -----------------------------
-# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
-# associated separator.
-# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
-# versions in m4sugar had bugs.
-m4_define([lt_join],
-[m4_if([$#], [1], [],
- [$#], [2], [[$2]],
- [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
-m4_define([_lt_join],
-[m4_if([$#$2], [2], [],
- [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
-
-
-# lt_car(LIST)
-# lt_cdr(LIST)
-# ------------
-# Manipulate m4 lists.
-# These macros are necessary as long as will still need to support
-# Autoconf-2.59 which quotes differently.
-m4_define([lt_car], [[$1]])
-m4_define([lt_cdr],
-[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
- [$#], 1, [],
- [m4_dquote(m4_shift($@))])])
-m4_define([lt_unquote], $1)
-
-
-# lt_append(MACRO-NAME, STRING, [SEPARATOR])
-# ------------------------------------------
-# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
-# Note that neither SEPARATOR nor STRING are expanded; they are appended
-# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
-# No SEPARATOR is output if MACRO-NAME was previously undefined (different
-# than defined and empty).
-#
-# This macro is needed until we can rely on Autoconf 2.62, since earlier
-# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
-m4_define([lt_append],
-[m4_define([$1],
- m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
-
-
-
-# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
-# ----------------------------------------------------------
-# Produce a SEP delimited list of all paired combinations of elements of
-# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
-# has the form PREFIXmINFIXSUFFIXn.
-# Needed until we can rely on m4_combine added in Autoconf 2.62.
-m4_define([lt_combine],
-[m4_if(m4_eval([$# > 3]), [1],
- [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
-[[m4_foreach([_Lt_prefix], [$2],
- [m4_foreach([_Lt_suffix],
- ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
- [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
-
-
-# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
-# -----------------------------------------------------------------------
-# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
-# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
-m4_define([lt_if_append_uniq],
-[m4_ifdef([$1],
- [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
- [lt_append([$1], [$2], [$3])$4],
- [$5])],
- [lt_append([$1], [$2], [$3])$4])])
-
-
-# lt_dict_add(DICT, KEY, VALUE)
-# -----------------------------
-m4_define([lt_dict_add],
-[m4_define([$1($2)], [$3])])
-
-
-# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
-# --------------------------------------------
-m4_define([lt_dict_add_subkey],
-[m4_define([$1($2:$3)], [$4])])
-
-
-# lt_dict_fetch(DICT, KEY, [SUBKEY])
-# ----------------------------------
-m4_define([lt_dict_fetch],
-[m4_ifval([$3],
- m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
- m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
-
-
-# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
-# -----------------------------------------------------------------
-m4_define([lt_if_dict_fetch],
-[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
- [$5],
- [$6])])
-
-
-# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
-# --------------------------------------------------------------
-m4_define([lt_dict_filter],
-[m4_if([$5], [], [],
- [lt_join(m4_quote(m4_default([$4], [[, ]])),
- lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
- [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
-])
-
-# ltversion.m4 -- version numbers -*- Autoconf -*-
-#
-# Copyright (C) 2004 Free Software Foundation, Inc.
-# Written by Scott James Remnant, 2004
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# @configure_input@
-
-# serial 3293 ltversion.m4
-# This file is part of GNU Libtool
-
-m4_define([LT_PACKAGE_VERSION], [2.4])
-m4_define([LT_PACKAGE_REVISION], [1.3293])
-
-AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.4'
-macro_revision='1.3293'
-_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
-_LT_DECL(, macro_revision, 0)
-])
-
-# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
-#
-# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
-# Written by Scott James Remnant, 2004.
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# serial 5 lt~obsolete.m4
-
-# These exist entirely to fool aclocal when bootstrapping libtool.
-#
-# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
-# which have later been changed to m4_define as they aren't part of the
-# exported API, or moved to Autoconf or Automake where they belong.
-#
-# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
-# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
-# using a macro with the same name in our local m4/libtool.m4 it'll
-# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
-# and doesn't know about Autoconf macros at all.)
-#
-# So we provide this file, which has a silly filename so it's always
-# included after everything else. This provides aclocal with the
-# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
-# because those macros already exist, or will be overwritten later.
-# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
-#
-# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
-# Yes, that means every name once taken will need to remain here until
-# we give up compatibility with versions before 1.7, at which point
-# we need to keep only those names which we still refer to.
-
-# This is to help aclocal find these macros, as it can't see m4_define.
-AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
-m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
-m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
-m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
-m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
-m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
-m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
-m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
-m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
-m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
-m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
-m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
-m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
-m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
-m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
-m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
-m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
-m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
-m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
-m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
-m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
-m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
-m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
-m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
-m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
-m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
-m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
-m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
-m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
-m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
-m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
-m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
-m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
-m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
-m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
-m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
-m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
-m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
-m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
-m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
-m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
-m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
-m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
-m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
-m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
-m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
-m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
-m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
-m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
-m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
-m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
-m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
-m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
-m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
-m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
-m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
-# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
-# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
-# harmless because $srcdir is `.', but things will broke when you
+# harmless because $srcdir is '.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
-[dnl Rely on autoconf to set up CDPATH properly.
-AC_PREREQ([2.50])dnl
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
-# Free Software Foundation, Inc.
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 6
-
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
-
# AM_MISSING_HAS_RUN
# ------------------
-# Define MISSING if not defined so far and test if it supports --run.
-# If it does, set am_missing_run to use it, otherwise, to nothing.
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
esac
fi
# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
else
am_missing_run=
- AC_MSG_WARN([`missing' script is too old or missing])
+ AC_MSG_WARN(['missing' script is too old or missing])
fi
])
RADIUSD_MINOR_VERSION=`cat VERSION | cut -f2 -d.`
RADIUSD_INCRM_VERSION=`cat VERSION | cut -f3 -d. | sed 's/[\.-].*$//'`
-RADIUSD_VERSION=`echo | awk -v major="$RADIUSD_MAJOR_VERSION" \
--v minor="$RADIUSD_MINOR_VERSION" \
--v incrm="$RADIUSD_INCRM_VERSION" \
-'{ printf "%02i%02i%02i", major, minor, incrm }'`
+RADIUSD_VERSION=`printf "%02i%02i%02i" $RADIUSD_MAJOR_VERSION $RADIUSD_MINOR_VERSION $RADIUSD_INCRM_VERSION`
RADIUSD_VERSION_STRING=`cat VERSION`
missing_dir=`cd $ac_aux_dir && pwd`
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
esac
fi
# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
else
am_missing_run=
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
-$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
fi
for ac_header in \
- dlfcn.h \
- unistd.h \
+ arpa/inet.h \
crypt.h \
+ dlfcn.h \
errno.h \
- resource.h \
- sys/resource.h \
+ fcntl.h \
+ features.h \
+ fnmatch.h \
getopt.h \
+ glob.h \
+ grp.h \
+ inttypes.h \
+ limits.h \
malloc.h \
- utmp.h \
- utmpx.h \
+ netdb.h \
+ netinet/in.h \
+ prot.h \
+ pwd.h \
+ resource.h \
+ semaphore.h \
+ sia.h \
+ siad.h \
signal.h \
- sys/select.h \
- syslog.h \
- inttypes.h \
- stdint.h \
stdbool.h \
+ stddef.h \
+ stdint.h \
stdio.h \
- netdb.h \
- semaphore.h \
- arpa/inet.h \
- netinet/in.h \
- sys/types.h \
- sys/socket.h \
- winsock.h \
- utime.h \
- sys/time.h \
- sys/wait.h \
- sys/security.h \
- fcntl.h \
+ sys/event.h \
sys/fcntl.h \
sys/prctl.h \
sys/ptrace.h \
+ sys/resource.h \
+ sys/security.h \
+ sys/select.h \
+ sys/socket.h \
+ sys/time.h \
+ sys/types.h \
sys/un.h \
- glob.h \
- prot.h \
- pwd.h \
- grp.h \
- stddef.h \
- fnmatch.h \
- sia.h \
- siad.h \
- features.h \
- limits.h \
- sys/event.h
+ sys/wait.h \
+ syslog.h \
+ unistd.h \
+ utime.h \
+ utmp.h \
+ utmpx.h \
+ winsock.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL library and header version consistency" >&5
$as_echo_n "checking OpenSSL library and header version consistency... " >&6; }
if test "$cross_compiling" = yes; then :
- { { $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 test program while cross compiling
-See \`config.log' for more details" "$LINENO" 5; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling (assuming yes)" >&5
+$as_echo "cross-compiling (assuming yes)" >&6; }
+
+
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
as_fn_error $? "OpenSSL library version does not match header version
See \`config.log' for more details" "$LINENO" 5; }
-
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
export OPENSSL_LIBS OPENSSL_LDFLAGS OPENSSL_CPPFLAGS
+ for ac_func in SSL_get_client_random
+do :
+ ac_fn_c_check_func "$LINENO" "SSL_get_client_random" "ac_cv_func_SSL_get_client_random"
+if test "x$ac_cv_func_SSL_get_client_random" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SSL_GET_CLIENT_RANDOM 1
+_ACEOF
+ SSL_get_server_random
+fi
+done
+
fi
if test "x$PCAP_LIBS" = x; then
conftest$ac_exeext conftest.$ac_ext
for ac_func in \
- getopt_long \
- fcntl \
- strsignal \
- sigaction \
- sigprocmask \
- pthread_sigmask \
- snprintf \
- vsnprintf \
- setsid \
- strncasecmp \
- strcasecmp \
- localtime_r \
+ bindat \
+ clock_gettime \
+ closefrom \
ctime_r \
+ dladdr \
+ fcntl \
+ fopencookie \
+ funopen \
+ getaddrinfo \
+ getnameinfo \
+ getopt_long \
+ getpeereid \
+ getresuid \
+ gettimeofday \
+ getusershell \
gmtime_r \
- strsep \
+ if_indextoname \
inet_aton \
- inet_pton \
inet_ntop \
+ inet_pton \
+ initgroups \
+ kqueue \
+ localtime_r \
mallopt \
+ mkdirat \
+ openat \
+ pthread_sigmask \
setlinebuf \
- setvbuf \
- getusershell \
- initgroups \
- getaddrinfo \
- getnameinfo \
- closefrom \
- gettimeofday \
- getpeereid \
- setuid \
setresuid \
- getresuid \
+ setsid \
+ setuid \
+ setvbuf \
+ sigaction \
+ sigprocmask \
+ snprintf \
+ strcasecmp \
strlcat \
strlcpy \
- kqueue \
- openat \
- mkdirat \
+ strncasecmp \
+ strsep \
+ strsignal \
unlinkat \
- bindat \
- dladdr
+ vdprintf \
+ vsnprintf
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
$as_echo "$ax_cv_cc_weverything_flag" >&6; }
if test "x$ax_cv_cc_weverything_flag" = "xyes"; then
- devflags="$devflags -W -Weverything -Wformat=2 -Wno-missing-field-initializers -Wno-date-time -Wno-padded -Wno-gnu-zero-variadic-macro-arguments -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-conversion -Wno-switch-enum -Wno-gnu-statement-expression -Wno-extended-offsetof -Wno-cast-align -Wno-documentation-unknown-command -Wno-covered-switch-default -Wno-packed -Wno-reserved-id-macro -DWITH_VERIFY_PTR=1"
+ devflags="$devflags -W -Weverything -Wformat=2 -Wno-missing-field-initializers -Wno-date-time -Wno-padded -Wno-gnu-zero-variadic-macro-arguments -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-conversion -Wno-switch-enum -Wno-gnu-statement-expression -Wno-extended-offsetof -Wno-cast-align -Wno-documentation-unknown-command -Wno-covered-switch-default -Wno-packed -DWITH_VERIFY_PTR=1"
else
if test "x$GCC" = "xyes"; then
devflags="$devflags -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -W -Wredundant-decls -Wundef -Wformat-y2k -Wno-format-extra-args -Wno-format-zero-length -Wno-cast-align -Wformat-nonliteral -Wformat-security -Wformat=2 -DWITH_VERIFY_PTR=1"
RADIUSD_MINOR_VERSION=`cat VERSION | cut -f2 -d.`
RADIUSD_INCRM_VERSION=`cat VERSION | cut -f3 -d. | sed 's/[[\.-]].*$//'`
-RADIUSD_VERSION=`echo | awk -v major="$RADIUSD_MAJOR_VERSION" \
--v minor="$RADIUSD_MINOR_VERSION" \
--v incrm="$RADIUSD_INCRM_VERSION" \
-'{ printf "%02i%02i%02i", major, minor, incrm }'`
+RADIUSD_VERSION=`printf "%02i%02i%02i" $RADIUSD_MAJOR_VERSION $RADIUSD_MINOR_VERSION $RADIUSD_INCRM_VERSION`
dnl #
dnl # Still useful for custom builds
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS( \
- dlfcn.h \
- unistd.h \
+ arpa/inet.h \
crypt.h \
+ dlfcn.h \
errno.h \
- resource.h \
- sys/resource.h \
+ fcntl.h \
+ features.h \
+ fnmatch.h \
getopt.h \
+ glob.h \
+ grp.h \
+ inttypes.h \
+ limits.h \
malloc.h \
- utmp.h \
- utmpx.h \
+ netdb.h \
+ netinet/in.h \
+ prot.h \
+ pwd.h \
+ resource.h \
+ semaphore.h \
+ sia.h \
+ siad.h \
signal.h \
- sys/select.h \
- syslog.h \
- inttypes.h \
- stdint.h \
stdbool.h \
+ stddef.h \
+ stdint.h \
stdio.h \
- netdb.h \
- semaphore.h \
- arpa/inet.h \
- netinet/in.h \
- sys/types.h \
- sys/socket.h \
- winsock.h \
- utime.h \
- sys/time.h \
- sys/wait.h \
- sys/security.h \
- fcntl.h \
+ sys/event.h \
sys/fcntl.h \
sys/prctl.h \
sys/ptrace.h \
+ sys/resource.h \
+ sys/security.h \
+ sys/select.h \
+ sys/socket.h \
+ sys/time.h \
+ sys/types.h \
sys/un.h \
- glob.h \
- prot.h \
- pwd.h \
- grp.h \
- stddef.h \
- fnmatch.h \
- sia.h \
- siad.h \
- features.h \
- limits.h \
- sys/event.h
+ sys/wait.h \
+ syslog.h \
+ unistd.h \
+ utime.h \
+ utmp.h \
+ utmpx.h \
+ winsock.h
)
dnl #
[
AC_MSG_RESULT(no)
AC_MSG_FAILURE([OpenSSL library version does not match header version])
+ ],
+ [
+ AC_MSG_RESULT([cross-compiling (assuming yes)])
]
)
CPPFLAGS="$old_CPPFLAGS"
AC_SUBST(OPENSSL_LDFLAGS)
AC_SUBST(OPENSSL_CPPFLAGS)
export OPENSSL_LIBS OPENSSL_LDFLAGS OPENSSL_CPPFLAGS
+ AC_CHECK_FUNCS(SSL_get_client_random,SSL_get_server_random)
fi
dnl #
dnl #
dnl #############################################################
AC_CHECK_FUNCS( \
- getopt_long \
- fcntl \
- strsignal \
- sigaction \
- sigprocmask \
- pthread_sigmask \
- snprintf \
- vsnprintf \
- setsid \
- strncasecmp \
- strcasecmp \
- localtime_r \
+ bindat \
+ clock_gettime \
+ closefrom \
ctime_r \
+ dladdr \
+ fcntl \
+ fopencookie \
+ funopen \
+ getaddrinfo \
+ getnameinfo \
+ getopt_long \
+ getpeereid \
+ getresuid \
+ gettimeofday \
+ getusershell \
gmtime_r \
- strsep \
+ if_indextoname \
inet_aton \
- inet_pton \
inet_ntop \
+ inet_pton \
+ initgroups \
+ kqueue \
+ localtime_r \
mallopt \
+ mkdirat \
+ openat \
+ pthread_sigmask \
setlinebuf \
- setvbuf \
- getusershell \
- initgroups \
- getaddrinfo \
- getnameinfo \
- closefrom \
- gettimeofday \
- getpeereid \
- setuid \
setresuid \
- getresuid \
+ setsid \
+ setuid \
+ setvbuf \
+ sigaction \
+ sigprocmask \
+ snprintf \
+ strcasecmp \
strlcat \
strlcpy \
- kqueue \
- openat \
- mkdirat \
+ strncasecmp \
+ strsep \
+ strsignal \
unlinkat \
- bindat \
- dladdr
+ vdprintf \
+ vsnprintf
)
AC_TYPE_SIGNAL
dnl #
AX_CC_WEVERYTHING_FLAG
if test "x$ax_cv_cc_weverything_flag" = "xyes"; then
- devflags="$devflags -W -Weverything -Wformat=2 -Wno-missing-field-initializers -Wno-date-time -Wno-padded -Wno-gnu-zero-variadic-macro-arguments -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-conversion -Wno-switch-enum -Wno-gnu-statement-expression -Wno-extended-offsetof -Wno-cast-align -Wno-documentation-unknown-command -Wno-covered-switch-default -Wno-packed -Wno-reserved-id-macro -DWITH_VERIFY_PTR=1"
+ devflags="$devflags -W -Weverything -Wformat=2 -Wno-missing-field-initializers -Wno-date-time -Wno-padded -Wno-gnu-zero-variadic-macro-arguments -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-conversion -Wno-switch-enum -Wno-gnu-statement-expression -Wno-extended-offsetof -Wno-cast-align -Wno-documentation-unknown-command -Wno-covered-switch-default -Wno-packed -DWITH_VERIFY_PTR=1"
else
if test "x$GCC" = "xyes"; then
devflags="$devflags -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -W -Wredundant-decls -Wundef -Wformat-y2k -Wno-format-extra-args -Wno-format-zero-length -Wno-cast-align -Wformat-nonliteral -Wformat-security -Wformat=2 -DWITH_VERIFY_PTR=1"
+freeradius (3.0.12+git) unstable; urgency=medium
+
+ * New upstream version.
+
+ -- Alan DeKok <aland@freeradius.org> Mon, 25 Jan 2016 14:00:00 -0400
+
+freeradius (3.0.11+git) unstable; urgency=medium
+
+ * New upstream version.
+
+ -- Alan DeKok <aland@freeradius.org> Mon, 05 Oct 2015 15:00:00 -0400
+
freeradius (3.0.10+git) unstable; urgency=medium
* New upstream version.
libiodbc2-dev,
libjson0 | libjson-c2,
libjson0-dev | libjson-c-dev,
- libkrb5-dev,
+ libkrb5-dev | heimdal-dev,
libldap2-dev,
libpam0g-dev,
libpcap-dev,
libykclient-dev,
libmemcached-dev,
libhiredis-dev,
- python-dev
+ python-dev,
+ samba-dev | samba4-dev
Section: net
Priority: optional
Maintainer: Josip Rodin <joy-packages@debian.org>
Package: freeradius-config
Architecture: any
-Depends: freeradius-common (>= 3), ${misc:Depends}, openssl
+Depends: freeradius-common (>= 3), ${misc:Depends}, openssl, make
Breaks: freeradius-config
Description: FreeRADIUS default config files
This package should be used as a base for a site local packages
-# Options for the FreeRADIUS deamon.
+# Options passed to the FreeRADIUS deamon.
+#
+FREERADIUS_OPTIONS=""
+
+
+# If FreeRADIUS is being used on a SysVinit system
+# and FREERADIUS_OPTIONS has not been set and the
+# following location exists, then it will be used
+# for the config directory rather than the default.
+#
+# This option has no effect when systemd is in
+# use, or if FREERADIUS_OPTIONS is set above.
+#
FREERADIUS_CONF_LOCAL="/usr/local/etc/freeradius"
-if [ -d "$FREERADIUS_CONF_LOCAL" ]; then
- FREERADIUS_OPTIONS="-d $FREERADIUS_CONF_LOCAL"
-fi
chown freerad:freerad /var/run/freeradius
fi
+if [ -d "$FREERADIUS_CONF_LOCAL" -a -z "$FREERADIUS_OPTIONS" ]; then
+ FREERADIUS_OPTIONS="-d $FREERADIUS_CONF_LOCAL"
+fi
+
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
ret=0
-# You can use this to rotate the /var/log/radius/* files, simply copy
+# You can use this to rotate the /var/log/freeradius/* files, simply copy
# it to /etc/logrotate.d/radiusd
#
#
# The main server log
#
-/var/log/radius/radius.log {
+/var/log/freeradius/radius.log {
copytruncate
}
#
# Session monitoring utilities
#
-/var/log/radius/checkrad.log /var/log/radius/radwatch.log {
+/var/log/freeradius/checkrad.log /var/log/freeradius/radwatch.log {
nocreate
}
#
# Session database modules
#
-/var/log/radius/radutmp /var/log/radius/radwtmp {
+/var/log/freeradius/radutmp /var/log/freeradius/radwtmp {
nocreate
}
#
# SQL log files
#
-/var/log/radius/sqllog.sql {
+/var/log/freeradius/sqllog.sql {
nocreate
}
# (or similar) in radiusd.conf, without rotation. If you go with the
# second technique, you will need another cron job that removes old
# detail files. You do not need to comment out the below for method #2.
-/var/log/radius/radacct/*/detail {
+/var/log/freeradius/radacct/*/detail {
nocreate
}
--- /dev/null
+[Unit]
+Description=FreeRADIUS multi-protocol policy server
+After=syslog.target network.target
+Documentation=man:radiusd(8) man:radiusd.conf(5) http://wiki.freeradius.org/ http://networkradius.com/doc/
+
+[Service]
+Type=forking
+PIDFile=/run/freeradius/freeradius.pid
+EnvironmentFile=-/etc/default/freeradius
+ExecStartPre=/usr/sbin/freeradius $FREERADIUS_OPTIONS -Cxm -lstdout
+ExecStart=/usr/sbin/freeradius $FREERADIUS_OPTIONS
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+++ /dev/null
-diff --git a/scripts/logrotate/freeradius b/scripts/logrotate/freeradius
-index cbeeb5f..bfb8220 100644
---- a/scripts/logrotate/freeradius
-+++ b/scripts/logrotate/freeradius
-@@ -1,7 +1,7 @@
- #
- # Sample logrotate file for FreeRADIUS
- #
--# You can use this to rotate the /var/log/radius/* files, simply copy it to /etc/logrotate.d/radiusd
-+# You can use this to rotate the /var/log/freeradius/* files, simply copy it to /etc/logrotate.d/radiusd
- #
-
- #
-@@ -17,28 +17,28 @@ notifempty
- #
- # The main server log
- #
--/var/log/radius/radius.log {
-+/var/log/freeradius/radius.log {
- copytruncate
- }
-
- #
- # Session monitoring utilities
- #
--/var/log/radius/checkrad.log /var/log/radius/radwatch.log {
-+/var/log/freeradius/checkrad.log /var/log/freeradius/radwatch.log {
- nocreate
- }
-
- #
- # Session database modules
- #
--/var/log/radius/radutmp /var/log/radius/radwtmp {
-+/var/log/freeradius/radutmp /var/log/freeradius/radwtmp {
- nocreate
- }
-
- #
- # SQL log files
- #
--/var/log/radius/sqllog.sql {
-+/var/log/freeradius/sqllog.sql {
- nocreate
- }
-
-@@ -49,6 +49,6 @@ notifempty
- # (or similar) in radiusd.conf, without rotation. If you go with the
- # second technique, you will need another cron job that removes old
- # detail files. You do not need to comment out the below for method #2.
--/var/log/radius/radacct/*/detail {
-+/var/log/freeradius/radacct/*/detail {
- nocreate
- }
-Index: freeradius-server/Make.inc.in
-===================================================================
---- freeradius-server.orig/Make.inc.in
-+++ freeradius-server/Make.inc.in
-@@ -95,7 +95,7 @@ LDFLAGS = $(OPENSSL_LDFLAGS) $(TALLOC_L
+--- a/Make.inc.in
++++ b/Make.inc.in
+@@ -95,7 +95,7 @@
LOGDIR = ${logdir}
RADDBDIR = ${raddbdir}
SBINDIR = ${sbindir}
RADIR = ${radacctdir}
LIBRADIUS = $(top_builddir)/src/lib/$(LIBPREFIX)freeradius-radius.la $(TALLOC_LIBS)
-Index: freeradius-server/raddb/radiusd.conf.in
-===================================================================
---- freeradius-server.orig/raddb/radiusd.conf.in
-+++ freeradius-server/raddb/radiusd.conf.in
-@@ -61,7 +61,7 @@ radacctdir = @radacctdir@
+--- a/raddb/radiusd.conf.in
++++ b/raddb/radiusd.conf.in
+@@ -61,7 +61,7 @@
#
# name of the running server. See also the "-n" command-line option.
# Location of config and logfiles.
confdir = ${raddbdir}
-@@ -436,8 +436,8 @@ security {
+@@ -436,8 +436,8 @@
# member. This can allow for some finer-grained access
# controls.
#
# Core dumps are a bad thing. This should only be set to
# 'yes' if you're debugging a problem with the server.
-Index: freeradius-server/scripts/monit/freeradius.monitrc
-===================================================================
---- freeradius-server.orig/scripts/monit/freeradius.monitrc
-+++ freeradius-server/scripts/monit/freeradius.monitrc
+--- a/scripts/monit/freeradius.monitrc
++++ b/scripts/monit/freeradius.monitrc
@@ -8,9 +8,9 @@
# Totalmem limit should be lowered to 200.0 if none of the
# interpreted language modules or rlm_cache are being used.
if failed host 127.0.0.1 port 1812 type udp protocol radius secret testing123 then alert
if failed host 127.0.0.1 port 1813 type udp protocol radius secret testing123 then alert
if cpu > 95% for 2 cycles then alert
+--- a/raddb/sites-available/control-socket
++++ b/raddb/sites-available/control-socket
+@@ -72,12 +72,12 @@
+ #
+ # Name of user that is allowed to connect to the control socket.
+ #
+-# uid = radius
++# uid = freerad
+
+ #
+ # Name of group that is allowed to connect to the control socket.
+ #
+-# gid = radius
++# gid = freerad
+
+ #
+ # Access mode.
+diff --git a/src/main/radiusd.c b/src/main/radiusd.c
+index 1ae66ec..ee1a711 100644
+--- a/src/main/radiusd.c
++++ b/src/main/radiusd.c
+@@ -93,7 +93,6 @@ int main(int argc, char *argv[])
+ bool display_version = false;
+ int flag = 0;
+ int from_child[2] = {-1, -1};
+- char *p;
+ fr_state_t *state = NULL;
+
+ /*
+@@ -128,13 +127,7 @@ int main(int argc, char *argv[])
+ main_config.myip.af = AF_UNSPEC;
+ main_config.port = 0;
+ main_config.daemonize = true;
+-
+- p = strrchr(argv[0], FR_DIR_SEP);
+- if (!p) {
+- main_config.name = argv[0];
+- } else {
+- main_config.name = p + 1;
+- }
++ main_config.name = "radiusd";
+
+ /*
+ * Don't put output anywhere until we get told a little
radiusd-to-freeradius.diff
disable-dhcp-bydefault.diff
-logrotate-path.diff
mv config.sub.dist config.sub
#Architecture
-build: patch build-arch build-indep
+build: build-arch build-indep
-build-arch: build-arch-stamp patch
+build-arch: patch build-arch-stamp
build-arch-stamp: config.status
$(MAKE)
touch $@
-build-indep: build-indep-stamp
+build-indep: patch build-indep-stamp
build-indep-stamp: config.status
touch $@
--- /dev/null
+# The RFCs are included in the debian package for reference. This
+# might be a problem in the official Debian archive, but we don't
+# need lintian complaining about it here.
+
+freeradius source: license-problem-non-free-RFC-BCP78 doc/rfc/*
+freeradius source: license-problem-non-free-RFC doc/rfc/*
+FreeRADIUS 3.0.12 Thur 29 Sep 2016 13:00:00 EDT urgency=medium
+ Feature improvements
+ * Add support for =~ and !~ in update sections.
+ See "man unlang"
+ * Add dictionary.checkpoint.
+ * Simultaneous-Use prints out more information.
+ * Print WARNING in debug mode when packets may be
+ truncated.
+ * Added expansions %{home_server:state} and
+ %{home_server_pool:state}, which show the
+ state of the server / pool.
+ * Mark rlm_sql_freetds as stable.
+ * Make rlm_perl less fragile. Patch from
+ Herwin Weststrate.
+ * Allow extended attributes to have "encrypt=2"
+ * Update dictionary.aruba.
+ * Add support for EAP-FAST. This is an isolated
+ feature which does not affect anything else.
+ * Update OpenSSL vulnerability list. Use a version
+ of OpenSSL released after September 20, 2016.
+ * EAP certificate verification is now done when
+ "verify" is enabled and "ocsp" is disabled.
+ * New dhcpclient and rlm_rad_counter man pages.
+ * Minor abfab and moonshot additions.
+ * Pass CFLAGS through from environment in RPM builds.
+ Allows more custom builds.
+ * Build with Heimdal in addtion to libkrb5.
+
+ Bug fixes
+ * Use correct typedef for older versions of sqlite.
+ * Update mssql schema to add priority
+ * don't complain on /dev/urandom in ldap
+ * fix == operator in update sections
+ * Don't create DHCP strings with many trailing zeros.
+ Patch from Nicolas C. Fixes #1526.
+ * Allow MS-CHAP change passwords instead of complaining
+ on large buffer.
+ * Allow assignment or equality operator on SQL.
+ * Update aclocal tests for FreeBSD 10. Patches from
+ Mathieu Simon.
+ * Remove occasional hang in rlm_linelog.
+ * Copy VSAs to inner tunnel for TTLS and PEAP.
+ Fixes #1544
+ * A few minor bugfixes caught in v3.1.x cleanup, and
+ back-ported to v3.0.x.
+ * do_not_respond again works in post-proxy
+ * Allow realm "~^.*$" {} and User-Name with no realm.
+ * Fix leak when creating unknown attributes
+ * Fix Debian / logrotate.
+ * Make OpenSSL error functions thread-safe.
+ * Fix crash with rlm_sql and updating SQL-User-Name.
+ * Debian build updates.
+ * Allow regular expression comparisons in radclient
+ fixes #1574.
+ * Fix memory leak on unknown attributes in detail file
+ reader.
+ * Update example paths in "man" pages when installing
+ them
+ * Build fixes for rlm_mschap. Fixes #1489.
+ * BSD build fixes. Patch from issue #1583.
+ * Be more careful about /lib/ when building.
+ Fixes #1585.
+ * Correct ifdef placement error. Fixes #1572.
+ * Allow for more files in internal "exfile" API
+ So it will be possible to open more than 64
+ "detail" files at the same time.
+ * Remove support for statically built EAP modules.
+ Fixes #1591.
+ * Many fixes to rlm_python from Guillaume Pannatier.
+ * Use correct week adjustment in SQLcounter.
+ Fixes #1608
+ * Minor fixes to allow compilation without DHCP,
+ VMPS, or TCP.
+ * Fix checks for module / config file change on HUP.
+ * Compile regex comparisons when sent via
+ "debug condition". Fixes #1632.
+ * Update filenames in documentation and examples.
+ Patch from Alan Buxey, #1655.
+ * Don't crash if SQL connection becomes unavailable.
+ Fixes #1640.
+ * Disallow originate_coa when proxy_requests = no
+ Fixes #1684.
+ * Free rad_perlconf_hv in correct perl context.
+ Fixes #1675.
+ * Multiple fixes for Debian builds. #1510, among
+ others.
+ * Set OpenSSL FIPS compatibility flag when necessary.
+ * Pulled fixes for the build system over from other
+ branches.
+ * Fix OCSP for RADIUS over TLS.
+ * Fix skip_if_ocsp_ok behavior.
+ * Better fixes for systems without closefrom() but
+ which have /proc. Fixes #1757.
+ * Minor build fixes back-ported from v4.0.x.
+ * build --whout-ascend-binary. Fixes #1761.
+ * Be more aggressive about not opening new connections
+ in debug mode after CTRL-C. Address #1604.
+
+FreeRADIUS 3.0.11 Mon 25 Jan 2016 14:00:00 EST urgency=medium
+ Feature improvements
+ * "unlang" comparisons of IP addresses to IP prefixes
+ are now detected, and types automatically cast.
+ * Allow shorthand form of ipv4prefix values e.g. 127/8.
+ * Add "auto_chain" to raddb/mods-available/eap, tls
+ subsection. This allows the disabling of OpenSSL
+ auto-chaining of certificates. Which might be wrong.
+ * Added printing of coa and disconnect stats (radmin).
+ * radclient defaults to expecting Access-Accept responses
+ to Status-Server.
+ * Updated dictionary.lancom, dictionary.starent.
+ * Portability fixes for Solaris.
+ * More errors from ntlm_auth gets passed to MS-CHAP.
+ * Update abfab-tr-idp virtual server.
+ * Added "filter_password" in policy.d/filter. This
+ removes embedded zero bytes in User-Password, for
+ compatibility with broken clients.
+ * The server now issues a WARNING message if duplicate
+ configuration items are found.
+ * TLS can skip the "verify" section if OCSP returns OK.
+ See raddb/mods-available/eap, "skip_if_ocsp_ok".
+ * Set TLS-OCSP-Cert-Valid = yes / no / skipped, which
+ is the result from the OCSP check.
+ * Interoperate with AD and "LmCompatibiltyLevel = 5",
+ by always setting WBC_MSV1_0_ALLOW_MSVCHAPV2 for
+ native winbind in rlm_mschap.
+ * TTLS and PEAP now require "virtual_server" to be a real server.
+ * Print WARNING when TTLS or PEAP identities are spoofed
+ or not properly anonymized. See RFC 7542 for requirements.
+ * Various rlm_python fixes from Herwin Weststrate.
+ * Allow setting Response-Packet-Type in "Post-Proxy-Type Fail",
+ which is useful when the home server does not respond.
+ * elasticsearch updates from Matthew Newton
+
+ Bug fixes
+ * Fix issue where field nas_type would not be accessible via
+ the %{client:} xlat, for clients loaded from SQL.
+ * Fix compatiblity issues with OpenSSL 1.0.2. Ignore
+ calls to msg_callback with 'pseudo' content types.
+ * Data type "ipv4prefix" is parsed correctly.
+ * Use correct talloc context in rlm_exec. Fixes #1338.
+ * Complain in unlang if "else" is used with no previous
+ "if" or "elsif".
+ * Send accounting status packets to the accounting port.
+ Fixes #1364.
+ * Print out CFLAGS when doing "radiusd -Xxv"
+ * Fixed bug with coa/acct stats value #1339. Based on patch from
+ Jorge Pereira.
+ * Fixes for LEAP proxying. Don't use LEAP!
+ * Fix issue with "directory already exists" seen when doing
+ "make install".
+ * Fixed bug with radmin related to the option "stats detail <filename>"
+ * Complain if the detail file reader does not have permission
+ to read the "detail.work" file. Fixes #1398
+ * Fixed SoH. Attributes were not being copied to the virtual server.
+ * Used a wrong list to global statistics in "stats".
+ * Create EAP-PWD identity correctly. Prevents segfaults.
+ * Dynamically validate authentication types for PEAP and EAP-MSCHAPv2.
+ * Fix includes in installed headers.
+ * OpenSSL 1.0.1f and 1.0.1g do NOT calculate TLS 1.2 keys correctly.
+ See raddb/mods-available/eap, "disable_tlsv1_2"
+ * Allow password change to work for MS-CHAP. This requires 'r=0',
+ because password changes are not retries.
+ * Fix home server fail-over for home servers using TCP and/or RadSec.
+ * Special characters in expanded regexes are now escaped
+ e.g. User-Name containing '.', and comparing /%{User-Name}/,
+ the '.' will now be escaped. See src/tests/keywords/regex-escape.
+ * Use correct authentication vector when sending Access-Reject replies
+ for RadSec.
+ * Set FreeRADIUS-Proxied-To in TTLS again. You should use the
+ "inner-tunnel" virtual server, instead of relying on this attribute.
+ * Fix debugging constants in rlm_perl. Patch from Herwin Weststrate.
+ * Add samba-dev / samba4-dev to debian builds so that rlm_mschap can
+ automatically use the new winbind API.
+ * Automatically skip zero-length attributes when sending packets,
+ instead of erroring out.
+
FreeRADIUS 3.0.10 Mon 05 Oct 2015 15:00:00 EDT urgency=medium
Feature improvements
* Do more optimization of unlang policies. This makes
* Added EAP-PWD implementation from Dan Harkins
* Added connection pools for modules. This unifies connection
management which was previously different for different modules.
-l * SQL now uses the connection pool. See mods-available/sql
+ * SQL now uses the connection pool. See mods-available/sql
* SQL now supports arbitrary Acct-Status-Types.
These changes are not compatible with 2.x.
* SQL now has full support for SQLite. See raddb/sql/main/sqlite/
3d. HINTS
- Customize the /etc/raddb/hints file. This file is used to give users a
- different login type based on a prefix/suffix of their loginname. For
- example, logging in as "user" may result in a rlogin session to a Unix
- system, and logging in as "Puser" could start a PPP session.
+ Customize the /etc/raddb/mods-config/preprocess/hints file. This file is
+ used to give users different login type based on a prefix/suffix of their
+ loginname. For example, logging in as "user" may result in a rlogin session
+ to a Unix system, and logging in as "Puser" could start a PPP session.
3e. HUNTGROUPS
- This is the /etc/raddb/huntgroups file. Here you can define different
- huntgroups. These can be used to:
+ This is the /etc/raddb/mods-config/preprocess/huntgroups file. Here you can
+ define different huntgroups. These can be used to:
- restrict access to certain huntgroups to certain users/groups of
users (define this in the huntgroups file itself)
wish to read through them all before making and changes.
-edit radiusd.conf::
-
- ----Begin radiusd.conf----
- ##
- ## radiusd.conf -- FreeRADIUS server configuration file.
- ##
-
- prefix = /usr/local
- exec_prefix = ${prefix}
- sysconfdir = /usr/local/etc/raddb
- localstatedir = ${prefix}/var
- sbindir = ${exec_prefix}/sbin
- logdir = /var/log
- raddbdir = /usr/local/etc/raddb
- radacctdir = /var/log/radacct
-
- # Location of config and logfiles.
- confdir = ${raddbdir}
- run_dir = ${localstatedir}/run/radiusd
- log_file = ${logdir}/radius.log
- libdir = ${exec_prefix}/lib
- pidfile = ${run_dir}/radiusd.pid
-
- #user = nobody
- #group = nobody
-
- max_request_time = 30
- delete_blocked_requests = no
- cleanup_delay = 5
- max_requests = 0
- bind_address = *
- port = 0
- hostname_lookups = no
- allow_core_dumps = no
- log_stripped_names = no
- log_auth = no
- log_auth_badpass = no
- log_auth_goodpass = no
-
- # The program to execute to do concurrency checks.
- #checkrad = ${sbindir}/checkrad
-
- security {
- max_attributes = 200
- reject_delay = 0
- status_server = no
- }
-
- proxy_requests = yes
- $INCLUDE ${confdir}/proxy.conf
-
- $INCLUDE ${confdir}/clients.conf
-
- thread pool {
- start_servers = 5
- max_servers = 32
- min_spare_servers = 3
- max_spare_servers = 10
- max_requests_per_server = 0
- }
-
- modules {
-
- ldap {
- server = "localhost"
- identity = "uid=freeradius,ou=admins,ou=radius,dc=mydomain,dc=com"
- password = example
- basedn = "ou=users,ou=radius,dc=mydomain,dc=com"
- filter = "(&(uid=%{%{Stripped-User-Name}:-%{User-Name}})
- (objectclass=radiusprofile)"
- start_tls = no
- tls_mode = no
- #default_profile = "uid=dial,ou=profiles,ou=radius,dc=mydomain,dc=com"
- #profile_attribute = "radiusProfileDn"
- dictionary_mapping = ${raddbdir}/ldap.attrmap
- ldap_cache_timeout = 120
- ldap_cache_size = 0
- ldap_connections_number = 10
- #password_header = "{clear}"
- password_attribute = userPassword
- groupname_attribute = radiusGroupName
- groupmembership_filter = "(&(uid=%{%{Stripped-User-Name}:-%{User-Name}}))
- (objectclass=radiusProfile)"
- groupmembership_attribute = radiusGroupName
- timeout = 3
- timelimit = 5
- net_timeout = 1
- compare_check_items = no
- #access_attr_used_for_allow = yes
- }
-
- realm suffix {
- format = suffix
- delimiter = "@"
- }
-
- preprocess {
- huntgroups = ${confdir}/huntgroups
- #hints = ${confdir}/hints
- with_ascend_hack = no
- ascend_channels_per_line = 23
- with_ntdomain_hack = no
- with_specialix_jetstream_hack = no
- with_cisco_vsa_hack = no
- }
-
- files {
- usersfile = ${confdir}/users
- #acctusersfile = ${confdir}/acct_users
- compat = no
- #use old style users
- }
- # regular detail files
- detail detail1 {
- filename = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
- permissions = 0600
- dir_permissions = 0755
- }
- # temp detail file to replicate to accountrad
- detail detail2 {
- filename = ${radacctdir}/detail-combined
- permissions = 0600
- dir_permissions = 0755
- locking = yes
- }
-
- #radutmp {
- # filename = ${logdir}/radutmp
- # permissions = 0600
- # caller_id = "yes"
- #}
-
- #radutmp sradutmp {
- # filename = ${logdir}/sradutmp
- # permissions = 0644
- # caller_id = "no"
- #}
-
- #attr_filter {
- # attrsfile = ${confdir}/attrs
- #}
-
-
- # The "always" module is here for debugging purposes. Each
- # instance simply returns the same result, always, without
- # doing anything.
- always fail {
- rcode = fail
- }
- always reject {
- rcode = reject
- }
- always ok {
- rcode = ok
- simulcount = 0
- mpp = no
- }
-
- #
- # The 'expression' module current has no configuration.
- expr {
- }
-
- }
-
- instantiate {
- expr
- }
-
- authorize {
- preprocess
- suffix
- files
- ldap
- }
-
- authenticate {
- authtype LDAP {
- ldap
- }
- }
-
- preacct {
- preprocess
- suffix
- files
- }
-
- accounting {
- acct_unique
- detail1
- detail2
- #radutmp
- #sradutmp
- }
-
-
- #session {
- #radutmp
- #}
-
- #post-auth {
- # Get an address from the IP Pool.
- #main_pool
- #}
- ----End radiusd.conf----
-
-
edit huntgroups to specify a NAS to a huntgroup::
----Begin huntgroups----
================================================
So you've got all these RADIUS logs, but how do you analyse them? What is the
-easiest way to query the logs, find out when a client connected or
-disconnected, or view the top ten clients logging into the system over the last
-six hours?
+easiest way to query the logs, find out when a client connected or disconnected,
+or view the top ten clients logging into the system over the last six hours?
The logstash/elasticsearch/kibana stack is designed and built to do just that.
elasticsearch is a search engine; logstash is commonly used to feed data in,
logs in.
This directory contains the following files as a starting point for feeding
-RADIUS logs into elasticsearch via logstash.
+RADIUS logs into elasticsearch via logstash, then sample dashboards for Kibana
+to explore the data.
Files
-----
Please note that all files should be reviewed before use to determine if they
-are suitable for your configuration/system.
+are suitable for your configuration/system, especially if you are integrating
+this into an existing logstash/elasticsearch setup.
radius-mapping.sh
This shell script (which just runs curl) pushes a template mapping into the
elasticsearch cluster.
-
-radius.conf
+logstash-radius.conf
A sample configuration file for logstash that parses RADIUS 'detail' files.
It processes these by joining each record onto one line, then splitting the
- tab-delimited key-value pairs out.
+ tab-delimited key-value pairs out. Some additional data is then extracted
+ from certain key attributes.
The file will need to be edited at least to set the input method: for
experimentation the given input (stdin) may be used. If logstash is running on
input such as log-courier or logstash-forwarder may be better to get the data
over the network to the logstash server.
+ It would be best to use an input method that can join the multiple lines of
+ the detail file together and feed them to logstash as a single entry, rather
+ than using the logstash multiline filter.
+
+log-courier.conf
+
+ An example configuration for the log-courier feeder.
+
+kibana4-dashboard.json
+
+ Basic RADIUS dashboard for Kibana4.
+
+ To import the dashboard first create a new index called "radius-*" in
+ Settings/Indices. Then go to Kibana's Settings page, "Objects" and "Import".
+ Once imported open the "RADIUS detail" dashboard.
+
+kibana3-dashboard.json
+
+ Basic RADIUS dashboard for Kibana3. To import the dashboard go to Load,
+ Advanced and "Choose File".
+
Example usage
-------------
$ ./radius-mapping.sh
Feed a detail file in:
-$ /path/to/logstash -f radius.conf < acct-detail
+$ /path/to/logstash -f logstash-radius.conf < acct-detail
See also
elasticsearch web site: http://www.elastic.co/
+The configuration examples presented here have been tested with the
+following software versions (note that elasticsearch 2.x may not yet
+work with this config).
+ elasticsearch 1.7.4
+ logstash 1.4.5
+ kibana 4.1.2
+ kibana 3.1.0
Matthew Newton
-April 2015
+January 2016
--- /dev/null
+{
+ "title": "RADIUS detail",
+ "services": {
+ "query": {
+ "list": {
+ "0": {
+ "query": "*",
+ "alias": "",
+ "color": "#584477",
+ "id": 0,
+ "pin": false,
+ "type": "lucene",
+ "enable": true
+ },
+ "1": {
+ "id": 1,
+ "type": "lucene",
+ "query": "Acct-Status-Type:Start",
+ "alias": "Accounting Start",
+ "color": "#629E51",
+ "pin": false,
+ "enable": true
+ },
+ "2": {
+ "id": 2,
+ "color": "#6ED0E0",
+ "alias": "",
+ "pin": false,
+ "type": "lucene",
+ "enable": true,
+ "query": "Acct-Status-Type:Interim-Update"
+ },
+ "3": {
+ "id": 3,
+ "color": "#BF1B00",
+ "alias": "",
+ "pin": false,
+ "type": "lucene",
+ "enable": true,
+ "query": "Acct-Status-Type:Stop"
+ }
+ },
+ "ids": [
+ 0,
+ 1,
+ 2,
+ 3
+ ]
+ },
+ "filter": {
+ "list": {
+ "0": {
+ "type": "time",
+ "field": "@timestamp",
+ "from": "now-7d",
+ "to": "now",
+ "mandate": "must",
+ "active": true,
+ "alias": "",
+ "id": 0
+ }
+ },
+ "ids": [
+ 0
+ ]
+ }
+ },
+ "rows": [
+ {
+ "title": "Time series",
+ "height": "200px",
+ "editable": true,
+ "collapse": false,
+ "collapsable": true,
+ "panels": [
+ {
+ "span": 9,
+ "editable": true,
+ "type": "histogram",
+ "loadingEditor": false,
+ "mode": "count",
+ "time_field": "@timestamp",
+ "value_field": null,
+ "x-axis": true,
+ "y-axis": true,
+ "scale": 1,
+ "y_format": "none",
+ "grid": {
+ "max": null,
+ "min": 0
+ },
+ "queries": {
+ "mode": "selected",
+ "ids": [
+ 1,
+ 2,
+ 3
+ ]
+ },
+ "annotate": {
+ "enable": false,
+ "query": "*",
+ "size": 20,
+ "field": "_type",
+ "sort": [
+ "_score",
+ "desc"
+ ]
+ },
+ "auto_int": true,
+ "resolution": 100,
+ "interval": "1h",
+ "intervals": [
+ "auto",
+ "1s",
+ "1m",
+ "5m",
+ "10m",
+ "30m",
+ "1h",
+ "3h",
+ "12h",
+ "1d",
+ "1w",
+ "1y"
+ ],
+ "lines": false,
+ "fill": 0,
+ "linewidth": 3,
+ "points": false,
+ "pointradius": 5,
+ "bars": true,
+ "stack": true,
+ "spyable": true,
+ "zoomlinks": true,
+ "options": true,
+ "legend": true,
+ "show_query": true,
+ "interactive": true,
+ "legend_counts": true,
+ "timezone": "browser",
+ "percentage": false,
+ "zerofill": true,
+ "derivative": false,
+ "tooltip": {
+ "value_type": "cumulative",
+ "query_as_alias": true
+ },
+ "title": "RADIUS Accounting data"
+ },
+ {
+ "error": false,
+ "span": 3,
+ "editable": true,
+ "type": "terms",
+ "loadingEditor": false,
+ "field": "NAS-Identifier",
+ "exclude": [],
+ "missing": false,
+ "other": false,
+ "size": 20,
+ "order": "count",
+ "style": {
+ "font-size": "10pt"
+ },
+ "donut": false,
+ "tilt": false,
+ "labels": true,
+ "arrangement": "horizontal",
+ "chart": "pie",
+ "counter_pos": "above",
+ "spyable": true,
+ "queries": {
+ "mode": "selected",
+ "ids": [
+ 1
+ ]
+ },
+ "tmode": "terms",
+ "tstat": "total",
+ "valuefield": "",
+ "title": "Sessions by NAS"
+ }
+ ],
+ "notice": false
+ },
+ {
+ "title": "Graphs",
+ "height": "200px",
+ "editable": true,
+ "collapse": false,
+ "collapsable": true,
+ "panels": [
+ {
+ "error": false,
+ "span": 3,
+ "editable": true,
+ "type": "terms",
+ "loadingEditor": false,
+ "field": "Calling-Station-Id",
+ "exclude": [],
+ "missing": false,
+ "other": false,
+ "size": 10,
+ "order": "count",
+ "style": {
+ "font-size": "10pt"
+ },
+ "donut": false,
+ "tilt": false,
+ "labels": true,
+ "arrangement": "horizontal",
+ "chart": "table",
+ "counter_pos": "above",
+ "spyable": true,
+ "queries": {
+ "mode": "selected",
+ "ids": [
+ 1
+ ]
+ },
+ "tmode": "terms",
+ "tstat": "total",
+ "valuefield": "",
+ "title": "Top Calling-Station-Id"
+ },
+ {
+ "error": false,
+ "span": 3,
+ "editable": true,
+ "type": "terms",
+ "loadingEditor": false,
+ "field": "Called-Station-Id",
+ "exclude": [],
+ "missing": false,
+ "other": false,
+ "size": 10,
+ "order": "count",
+ "style": {
+ "font-size": "10pt"
+ },
+ "donut": false,
+ "tilt": false,
+ "labels": true,
+ "arrangement": "horizontal",
+ "chart": "table",
+ "counter_pos": "above",
+ "spyable": true,
+ "queries": {
+ "mode": "selected",
+ "ids": [
+ 1
+ ]
+ },
+ "tmode": "terms",
+ "tstat": "total",
+ "valuefield": "",
+ "title": "TopN Called-Station-Id"
+ },
+ {
+ "error": false,
+ "span": 3,
+ "editable": true,
+ "type": "terms",
+ "loadingEditor": false,
+ "field": "User-Name",
+ "exclude": [],
+ "missing": false,
+ "other": false,
+ "size": 10,
+ "order": "max",
+ "style": {
+ "font-size": "10pt"
+ },
+ "donut": false,
+ "tilt": false,
+ "labels": true,
+ "arrangement": "horizontal",
+ "chart": "table",
+ "counter_pos": "above",
+ "spyable": true,
+ "queries": {
+ "mode": "all",
+ "ids": [
+ 0,
+ 1,
+ 2,
+ 3
+ ]
+ },
+ "tmode": "terms_stats",
+ "tstat": "max",
+ "valuefield": "Acct-Output-Octets_long",
+ "title": "TopN data Output"
+ },
+ {
+ "error": false,
+ "span": 3,
+ "editable": true,
+ "type": "terms",
+ "loadingEditor": false,
+ "field": "User-Name",
+ "exclude": [],
+ "missing": false,
+ "other": false,
+ "size": 10,
+ "order": "max",
+ "style": {
+ "font-size": "10pt"
+ },
+ "donut": false,
+ "tilt": false,
+ "labels": true,
+ "arrangement": "horizontal",
+ "chart": "table",
+ "counter_pos": "above",
+ "spyable": true,
+ "queries": {
+ "mode": "all",
+ "ids": [
+ 0,
+ 1,
+ 2,
+ 3
+ ]
+ },
+ "tmode": "terms_stats",
+ "tstat": "max",
+ "valuefield": "Acct-Input-Octets_long",
+ "title": "TopN Data Input"
+ }
+ ],
+ "notice": false
+ },
+ {
+ "title": "Table",
+ "height": "150px",
+ "editable": true,
+ "collapse": false,
+ "collapsable": true,
+ "panels": [
+ {
+ "error": false,
+ "span": 12,
+ "editable": true,
+ "type": "table",
+ "loadingEditor": false,
+ "size": 100,
+ "pages": 5,
+ "offset": 0,
+ "sort": [
+ "@timestamp",
+ "asc"
+ ],
+ "overflow": "min-height",
+ "fields": [
+ "timestamp",
+ "User-Name",
+ "Calling-Station-Id",
+ "Called-Station-Id",
+ "Framed-IP-Address",
+ "NAS-Identifier"
+ ],
+ "highlight": [],
+ "sortable": true,
+ "header": true,
+ "paging": true,
+ "field_list": false,
+ "all_fields": false,
+ "trimFactor": 500,
+ "localTime": false,
+ "timeField": "@timestamp",
+ "spyable": true,
+ "queries": {
+ "mode": "all",
+ "ids": [
+ 0,
+ 1,
+ 2,
+ 3
+ ]
+ },
+ "style": {
+ "font-size": "9pt"
+ },
+ "normTimes": true,
+ "title": "RADIUS data"
+ }
+ ],
+ "notice": false
+ }
+ ],
+ "editable": true,
+ "failover": false,
+ "index": {
+ "interval": "day",
+ "pattern": "[radius-]YYYY.MM.DD",
+ "default": "[radius-]YYYY.MM.DD",
+ "warm_fields": false
+ },
+ "style": "dark",
+ "panel_hints": true,
+ "pulldowns": [
+ {
+ "type": "query",
+ "collapse": true,
+ "notice": false,
+ "enable": true,
+ "query": "*",
+ "pinned": true,
+ "history": [
+ "Acct-Status-Type:Stop",
+ "Acct-Status-Type:Interim-Update",
+ "Acct-Status-Type:Start",
+ "*"
+ ],
+ "remember": 10
+ },
+ {
+ "type": "filtering",
+ "collapse": true,
+ "notice": true,
+ "enable": true
+ }
+ ],
+ "nav": [
+ {
+ "type": "timepicker",
+ "collapse": false,
+ "notice": false,
+ "enable": true,
+ "status": "Stable",
+ "time_options": [
+ "5m",
+ "15m",
+ "1h",
+ "6h",
+ "12h",
+ "24h",
+ "2d",
+ "7d",
+ "30d"
+ ],
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ],
+ "timefield": "@timestamp",
+ "now": true,
+ "filter_id": 0
+ }
+ ],
+ "loader": {
+ "save_gist": false,
+ "save_elasticsearch": true,
+ "save_local": true,
+ "save_default": true,
+ "save_temp": true,
+ "save_temp_ttl_enable": true,
+ "save_temp_ttl": "30d",
+ "load_gist": false,
+ "load_elasticsearch": true,
+ "load_elasticsearch_size": 20,
+ "load_local": false,
+ "hide": false
+ },
+ "refresh": false
+}
--- /dev/null
+[
+ {
+ "_id": "RADIUS-detail",
+ "_type": "dashboard",
+ "_source": {
+ "title": "RADIUS detail",
+ "hits": 0,
+ "description": "",
+ "panelsJSON": "[{\"col\":5,\"id\":\"RADIUS-unique-User-Name-by-day\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"User-Name\",\"Calling-Station-Id\",\"Called-Station-Id\",\"Framed-IP-Address\",\"NAS-Identifier\"],\"id\":\"RADIUS-data\",\"row\":5,\"size_x\":8,\"size_y\":4,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"id\":\"RADIUS-accounting-packets-histogram\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"RADIUS-table-topN-data-transferred-by-User-Name\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"id\":\"RADIUS-Sessions-per-NAS\",\"type\":\"visualization\",\"size_x\":4,\"size_y\":4,\"col\":9,\"row\":5}]",
+ "version": 1,
+ "timeRestore": true,
+ "timeTo": "now",
+ "timeFrom": "now-7d",
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}"
+ }
+ }
+ },
+ {
+ "_id": "RADIUS-Accounting-Start-data",
+ "_type": "search",
+ "_source": {
+ "title": "RADIUS Accounting-Start data",
+ "description": "",
+ "hits": 0,
+ "columns": [
+ "User-Name",
+ "Calling-Station-Id",
+ "Called-Station-Id",
+ "Framed-IP-Address",
+ "NAS-Identifier"
+ ],
+ "sort": [
+ "@timestamp",
+ "desc"
+ ],
+ "version": 1,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"index\":\"radius-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"fragment_size\":2147483647},\"filter\":[{\"meta\":{\"negate\":false,\"index\":\"radius-*\",\"key\":\"Acct-Status-Type\",\"value\":\"Start\",\"disabled\":false},\"query\":{\"match\":{\"Acct-Status-Type\":{\"query\":\"Start\",\"type\":\"phrase\"}}}}]}"
+ }
+ }
+ },
+ {
+ "_id": "RADIUS-data",
+ "_type": "search",
+ "_source": {
+ "title": "RADIUS data",
+ "description": "",
+ "hits": 0,
+ "columns": [
+ "User-Name",
+ "Calling-Station-Id",
+ "Called-Station-Id",
+ "Framed-IP-Address",
+ "NAS-Identifier"
+ ],
+ "sort": [
+ "@timestamp",
+ "desc"
+ ],
+ "version": 1,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"index\":\"radius-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"fragment_size\":2147483647},\"filter\":[]}"
+ }
+ }
+ },
+ {
+ "_id": "RADIUS-unique-User-Name-by-day",
+ "_type": "visualization",
+ "_source": {
+ "title": "RADIUS unique User-Name by day",
+ "visState": "{\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"User-Name\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"d\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"User-Name\",\n \"size\": 50,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}",
+ "description": "",
+ "version": 1,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\n \"filter\": []\n}"
+ },
+ "savedSearchId": "RADIUS-data"
+ }
+ },
+ {
+ "_id": "RADIUS-accounting-packets-histogram",
+ "_type": "visualization",
+ "_source": {
+ "title": "RADIUS accounting packets histogram",
+ "visState": "{\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"Acct-Status-Type\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}",
+ "description": "",
+ "savedSearchId": "RADIUS-data",
+ "version": 1,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"filter\":[]}"
+ }
+ }
+ },
+ {
+ "_id": "RADIUS-table-topN-data-transferred-by-User-Name",
+ "_type": "visualization",
+ "_source": {
+ "title": "RADIUS table topN data transferred by User-Name",
+ "visState": "{\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false},\"aggs\":[{\"id\":\"1\",\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"Acct-Output-Octets_long\"}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"User-Name\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"Acct-Input-Octets_long\"}}],\"listeners\":{}}",
+ "description": "",
+ "savedSearchId": "RADIUS-data",
+ "version": 1,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"filter\":[]}"
+ }
+ }
+ },
+ {
+ "_id": "RADIUS-Sessions-per-NAS",
+ "_type": "visualization",
+ "_source": {
+ "title": "RADIUS Sessions per NAS",
+ "visState": "{\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"NAS-Identifier\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}",
+ "description": "",
+ "savedSearchId": "RADIUS-Accounting-Start-data",
+ "version": 1,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"filter\":[]}"
+ }
+ }
+ }
+]
--- /dev/null
+# Example log-courier configuration file for RADIUS detail files.
+#
+{
+ "general": {
+ "persist directory": "/var/lib/log-courier",
+ "log syslog": true,
+ "log stdout": false,
+ "admin listen address": "unix:/var/run/log-courier/admin.socket"
+ },
+
+ "network": {
+ "transport": "tcp",
+ "reconnect": 10,
+
+ # Servers to connect to.
+ #
+ "servers": [
+ "logstash1.example:5140",
+ "logstash2.example:5140"
+ ]
+ },
+
+ "files": [
+ {
+ # Match RADIUS detail files, but not anything that has
+ # been gzipped.
+ #
+ "paths": [ "/var/log/radius/radacct/*/detail-????????" ],
+
+ # Add a type:"radiusdetail" field to the data so that
+ # logstash can tell what type of data this is (in case
+ # log-courier is being used for other data as well).
+ #
+ "fields": {
+ "type": "radiusdetail"
+ },
+
+ # Stop watching a file if nothing has been written in 12h.
+ #
+ "dead time": "12h",
+
+ # Process multilines. If this is being used then the
+ # "multiline" section should be commented out from the
+ # logstash configuration. Logstash can then also be run
+ # with multiple workers (using -w).
+ #
+ "codec": {
+ "name": "multiline",
+ "pattern": "^[A-Z\t]",
+ "negate": false,
+ "what": "next"
+ }
+ }
+ ]
+}
+
--- /dev/null
+# logstash configuration to process RADIUS detail files
+#
+# Matthew Newton
+# January 2016
+#
+# RADIUS "detail" files are textual representations of the RADIUS
+# packets, and are written to disk by e.g. FreeRADIUS. They look
+# something like the following, with the timestamp on the first
+# line then all attributes/values tab-indented.
+#
+# Tue Mar 10 15:32:24 2015
+# Packet-Type = Access-Request
+# User-Name = "test@example.com"
+# Calling-Station-Id = "01-02-03-04-05-06"
+# Called-Station-Id = "aa-bb-cc-dd-ee-ff:myssid"
+# NAS-Port = 10
+# NAS-IP-Address = 10.9.0.4
+# NAS-Identifier = "Wireless-Controller-1"
+# Service-Type = Framed-User
+# NAS-Port-Type = Wireless-802.11
+#
+
+
+
+# Example input - read data from a file. This can be useful for
+# testing, but usually not so much for live service. For example,
+# to read in a detail file with this input you could use:
+#
+# /opt/logstash/bin/logstash -v -f logstash-radius.conf < detailfile
+
+input {
+ stdin {
+ type => radiusdetail
+ }
+}
+
+# Moving into production will likely need something more reliable.
+# There are many input methods, an example here using log-courier
+# (which supports client-site multiline processing and does not
+# lose log events if logstash is restarted).
+
+# input {
+# courier {
+# port => 5140
+# transport => "tcp"
+# }
+# }
+
+
+
+# Filter stage. Here we take the raw logs and process them into
+# something structured ready to index. Each attribute is stored as
+# a separate field in the output document.
+
+filter {
+
+ if [type] == "radiusdetail" {
+
+ # If you are using a log feeder that can join
+ # multiple lines together then that is preferrable
+ # to using multiline here, because this can not be
+ # used with threaded logstash (i.e. -w<n> at
+ # startup).
+
+ # In that case you should comment out the following
+ # section. For example, see the log-courier
+ # configuration configuration in this directory.
+
+ multiline {
+ pattern => "^[A-Z\t]"
+ negate => false
+ what => "next"
+ }
+
+ # Pull off the timestamp at the start of the
+ # detail record. Note there may be additional data
+ # after it that has been added by the local admin,
+ # so stop at a newline OR a tab.
+
+ grok {
+ match => [ "message", "^(?<timestamp>[^\n\t]+)[\n\t]" ]
+ }
+
+ # Create the @timestamp field.
+
+ date {
+ match => [ "timestamp", "EEE MMM dd HH:mm:ss yyyy",
+ "EEE MMM d HH:mm:ss yyyy" ]
+ }
+
+ # Split the attributes and values into fields.
+ # This is the bulk of processing that adds all of
+ # the RADIUS attributes as elasticsearch fields.
+
+ kv {
+ field_split => "\n"
+ source => "message"
+ trim => "\" "
+ trimkey => "\t "
+ }
+
+ # Now we try and add some useful additional
+ # information. If certain fields can be broken
+ # down into components then do that here and add
+ # the data as sub-fields. For example,
+ # Called-Station-Id might be able to be broken
+ # down to Called-Station-Id_mac and Called-Station-Id_ssid
+ # on some wireless systems, or to _ip and _port
+ # with a VPN.
+
+ # Multiple calls to grok otherwise it can stop
+ # processing once it has matched one field, but
+ # e.g. you want to pull both IP and port out of
+ # the same field in two different regex's.
+
+ # Pull out some IP addresses as field_ip:
+
+ grok {
+ break_on_match => false
+ tag_on_failure => []
+ match => [
+ "Framed-IP-Address", "^(?<Framed-IP-Address_ip>\d+\.\d+\.\d+\.\d+$)",
+ "NAS-IP-Address", "^(?<NAS-IP-Address_ip>\d+\.\d+\.\d+\.\d+$)",
+ "Calling-Station-Id", "^(?<Calling-Station-Id_ip>\d+\.\d+\.\d+\.\d+)",
+ "Called-Station-Id", "^(?<Called-Station-Id_ip>\d+\.\d+\.\d+\.\d+)"
+ ]
+ }
+
+ # Split User-Name, Operator-Name, and pull out
+ # some IP ports if they are there:
+
+ grok {
+ break_on_match => false
+ tag_on_failure => []
+ match => [
+ "User-Name", "^(?<User-Name_username>[^@]+)?(?:@(?<User-Name_realm>[^@]+))$",
+ "Operator-Name", "^(?<Operator-Name_id>.)(?<Operator-Name_value>.+)$",
+
+ "Calling-Station-Id", "\[(?<Calling-Station-Id_port>\d+)\]$",
+ "Called-Station-Id", "\[(?<Called-Station-Id_port>\d+)\]$"
+ ]
+ }
+
+ # Extract MAC addresses (and SSIDs if there).
+ # MAC address matching here is lazy, but should be
+ # good enough.
+
+ grok {
+ break_on_match => false
+ tag_on_failure => []
+ match => [
+ "Calling-Station-Id", "^(?<Calling-Station-Id_mac>[a-fA-F0-9:-]{17})$",
+ "Calling-Station-Id", "^(?<Calling-Station-Id_mac>[a-fA-F0-9\.]{14})$",
+ "Calling-Station-Id", "^(?<Calling-Station-Id_mac>[a-fA-F0-9]{12})$",
+
+ "Called-Station-Id", "^(?<Called-Station-Id_mac>[a-fA-F0-9:-]{17})(?::(?<Called-Station-Id_ssid>.*))?$",
+ "Called-Station-Id", "^(?<Called-Station-Id_mac>[a-fA-F0-9\.]{14})(?::(?<Called-Station-Id_ssid>.*))?$",
+ "Called-Station-Id", "^(?<Called-Station-Id_mac>[a-fA-F0-9]{12})(?::(?<Called-Station-Id_ssid>.*))?$"
+ ]
+ }
+
+ # With the optional sanitize_mac plugin, it's
+ # possible to make sure all MAC addresses look the
+ # same, which has obvious benefits.
+ #
+ # https://github.com/mcnewton/elk/blob/master/logstash-filters/sanitize_mac.rb
+
+ # sanitize_mac {
+ # match => {
+ # "Called-Station-Id_mac" => "Called-Station-Id_mac"
+ # "Calling-Station-Id_mac" => "Calling-Station-Id_mac"
+ # }
+ # separator => ":"
+ # fixcase => "lower"
+ # }
+
+
+ # Gigawords presents an issue because the 64-bit
+ # value is split across two attributes. Combine
+ # them both back into a single attribute so that
+ # the full value is available to use.
+
+ if ([Acct-Input-Octets]) {
+ ruby {
+ code => "event['Acct-Input-Octets_long'] =
+ event['Acct-Input-Octets'].to_i + ( event['Acct-Input-Gigawords'] ? (event['Acct-Input-Gigawords'].to_i * (2**32)) : 0)"
+ }
+ }
+
+ if ([Acct-Output-Octets]) {
+ ruby {
+ code => "event['Acct-Output-Octets_long'] =
+ event['Acct-Output-Octets'].to_i + ( event['Acct-Output-Gigawords'] ? (event['Acct-Output-Gigawords'].to_i * (2**32)) : 0)"
+ }
+ }
+
+ }
+}
+
+
+
+# Output data to the local elasticsearch cluster (called
+# "elasticsearch") using type "detail" in index "radius-DATE".
+
+output {
+ if [type] == "radiusdetail" {
+ elasticsearch {
+ host => localhost
+ protocol => http
+ cluster => elasticsearch
+ index_type => "detail"
+ index => "radius-%{+YYYY.MM.dd}"
+ flush_size => 1000
+ }
+ }
+}
+
# Matthew Newton
# April 2015
-# This should be run on an elasticsearch node. Alternatively, adjust
-# the curl URI below.
+# This should be run on an elasticsearch node. Alternatively,
+# adjust the curl URI below.
+
+# The template will be called "radius", and will apply to all
+# indices prefixed with "radius-" that contain data type "detail".
+# As not all RADIUS attributes are known to begin with it has the
+# following starting point that can be modified to suit the local
+# configuration:
+#
+# Acct-Input- or Acct-Output- attributes are numbers;
+# Acct-Session-Time is a number;
+# Everything else is a string.
+
+# Additionally, the supplied logstash config will try and extract
+# MAC addresses, IP addresses and ports from the data. These are
+# stored with suffixes on the respective attribute. For example,
+# an attribute
+#
+# Called-Station-Id := "10.0.4.6[4500]"
+#
+# will be broken down into the following fields in elasticsearch:
+#
+# Called-Station-Id = "10.0.4.6[4500]"
+# Called-Station-Id_ip = "10.0.4.6"
+# Called-Station-Id_port = "4500"
+#
+# This mapping ensures that these have an appropriate data type.
+
curl -XPUT '127.0.0.1:9200/_template/radius' -d '
{
"order":0,
"mappings":{
"detail":{
- "dynamic_templates":[
- { "keep_message":{
- "match":"message",
- "mapping":{
- "type":"string",
- "index":"analyzed"
+
+ "properties": {
+ "@timestamp": { "format": "dateOptionalTime", "type": "date" },
+ "@version": { "type" : "string" },
+ "message": { "type" : "string" },
+ "Acct-Session-Time": { "type" : "long", "doc_values": true },
+ "offset": { "type" : "long", "doc_values": true }
+ },
+
+ "dynamic_templates": [
+
+ { "acct_io_numbers": {
+ "match_pattern": "regex",
+ "match": "^Acct-(Input|Output)-.*$",
+ "mapping": {
+ "type": "long",
+ "doc_values": true
}
}
},
- { "no_analyze_strings":{
- "match":"*",
- "match_mapping_type":"string",
- "mapping":{
- "type":"string",
- "index":"not_analyzed"
+
+ { "ipv4_address": {
+ "path_match": "*_ip",
+ "mapping": {
+ "type": "ip",
+ "doc_values": true
+ }
+ }
+ },
+
+ { "network_port": {
+ "path_match": "*_port",
+ "mapping": {
+ "type": "integer",
+ "doc_values": true
+ }
+ }
+ },
+
+ { "long_number": {
+ "path_match": "*_long",
+ "mapping": {
+ "type": "integer",
+ "doc_values": true
+ }
+ }
+ },
+
+ { "no_analyze_strings": {
+ "match": "*",
+ "mapping": {
+ "type": "string",
+ "index": "not_analyzed",
+ "doc_values": true
}
}
}
+
]
}
}
}'
-
+++ /dev/null
-# logstash configuration to process RADIUS detail files
-#
-# Matthew Newton
-# February 2014
-#
-# RADIUS "detail" files are textual representations of the RADIUS
-# packets, and are written to disk by e.g. FreeRADIUS. They look
-# something like the following, with the timestamp on the first
-# line then all attributes/values tab-indented.
-#
-# Tue Mar 10 15:32:24 2015
-# Packet-Type = Access-Request
-# User-Name = "test@example.com"
-# Calling-Station-Id = "01-02-03-04-05-06"
-# Called-Station-Id = "aa-bb-cc-dd-ee-ff:myssid"
-# NAS-Port = 10
-# NAS-IP-Address = 10.9.0.4
-# NAS-Identifier = "Wireless-Controller-1"
-# Service-Type = Framed-User
-# NAS-Port-Type = Wireless-802.11
-#
-# This filter processes the detail file such that each attribute
-# is stored as a separate field in the output document.
-
-
-input {
- stdin {
- type => radiusdetail
- }
-}
-
-
-filter {
-
- if [type] == "radiusdetail" {
-
- # join all lines of a record together
- multiline {
- pattern => "^[^\t]"
- negate => true
- what => "previous"
- }
-
- # pull off the timestamp
- grok {
- match => [ "message", "^(?<timestamp>[^\n\t]+)[\n\t]" ]
- }
-
- # create the timestamp field
- date {
- match => [ "timestamp", "EEE MMM dd HH:mm:ss yyyy",
- "EEE MMM d HH:mm:ss yyyy" ]
- }
-
- # split the attributes and values into fields
- kv {
- field_split => "\n"
- source => "message"
- trim => "\" "
- trimkey => "\t "
- }
- }
-}
-
-output {
- if [type] == "radiusdetail" {
- elasticsearch {
- host => localhost
- protocol => http
- cluster => elasticsearch
- index_type => "detail"
- index => "radius-%{+YYYY.MM.dd}"
- flush_size => 1000
- }
- }
-}
-
if [ x"$dir_arg" != x ]
then
- $doit $instcmd $dst &&
+ ([ -d $dst ] || $doit $instcmd $dst) &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
--- /dev/null
+.TH DHCPCLIENT 1 "19 September 2016" "" "FreeRADIUS Daemon"
+.SH NAME
+dhcpclient - Send a DHCP request with provided RADIUS attributes and get the output response.
+.SH SYNOPSIS
+.B dhcpclient
+.RB [ \-d
+.IR raddb_directory ]
+.RB [ \-D
+.IR dictionary_directory ]
+.RB [ \-f
+.IR file ]
+.RB [ \-h ]
+.RB [ \-i
+.IR interface ]
+.RB [ \-t
+.IR timeout ]
+.RB [ \-v ]
+.RB [ \-x ]
+\fIserver[:port] {discover|request|decline|release|inform|auto}\fP
+.SH DESCRIPTION
+\fBdhcpclient\fP is a DHCP test client program. It can send arbitrary DHCP
+packets to the FreeRADIUS server running as DHCP server, then shows the reply.
+It can be used to test changes you made in the configuration of the radius server,
+or it can be used to monitor if a radius server is up.
+.PP
+\fBdhcpclient\fP reads radius attribute/value pairs from its standard
+input, or from a file specified on the command line. It then encodes
+these attribute/value pairs using the dictionary, and sends them
+to the local/remote server.
+.PP
+
+.SH OPTIONS
+
+.IP \-d\ \fIraddb_directory\fP
+The directory that contains the user dictionary file. Defaults to
+\fI/etc/raddb\fP.
+.IP \-D\ \fIdictionary_directory\fP
+The directory that contains the main dictionary file. Defaults to
+\fI/usr/share/freeradius\fP.
+.IP \-f\ \fIfile[:file]\fP
+File to read the attribute/value pairs from. If this is not specified,
+they are read from stdin. This option can be specified multiple
+times, in which case packets are sent in order by file, and within
+each file, by first packet to last packet. A blank line separates
+logical packets within a file.
+.IP \-h
+Print usage help information.
+.IP \-i\ \fIinterface\fP
+Select which interface to send/receive at packet level on a raw socket.
+.IP \-t\ \fItimeout\fP
+Wait \fItimeout\fP seconds before deciding that the NAS has not
+responded to a request, and re-sending the packet. This may be a floating
+point number, e.g. 2.2.
+.IP \-v
+Print out program version information.
+.IP \-x
+Print out debugging information.
+.IP server[:port]
+The hostname or IP address of the remote server. Optionally a UDP port
+can be specified. If no UDP port is specified, it is looked up in
+\fI/etc/services\fP. The service name looked for is \fBradacct\fP for
+accounting packets, and \fBradius\fP for all other requests. If a
+service is not found in \fI/etc/services\fP, 1813 and 1812 are used
+respectively.
+.IP discover\ |\ request\ |\ decline\ |\ release\ |\ inform\ |\ auto
+DHCP options - use the type relevant for testing
+
+.SH SEE ALSO
+radiusd(8)
+.SH AUTHORS
+Alan DeKok <aland@freeradius.org>
--- /dev/null
+.TH RAD_COUNTER 1 "19 September 2016" "" "FreeRADIUS Daemon"
+.SH NAME
+rad_counter - Query and maintain FreeRADIUS rlm_counter DB file.
+
+This tool is deprecated
+
+.SH SYNOPSIS
+.B rad_counter
+.RB [ \--file
+.IR counter_filename ]
+.RB [ \--user
+.IR username ]
+.RB [ \--match
+.IR <regex> ]
+.RB [ \--reset
+.IR number]
+.RB [ \--help ]
+.RB [ \--
+.IR(hours|minutes|seconds) ]
+
+.SH DESCRIPTION
+\fBrad_counter\fP is a tool that can query and maintain FreeRADIUS rlm_counter DB files.
+.PP
+
+.SH OPTIONS
+
+.IP \--file=
+Counter DB filename.
+.IP \--user=\ \fIusername\fP
+Information for specific user.
+.IP \--match=\ \fI<regex>\fP
+Information for matching users.
+.IP \--reset=\ \fInumber\fP
+Reset counter to <number>. If divisor is set use it, else <number> means seconds.
+.IP \--help
+Show the help screen.
+.IP \--(hours\ |\ minutes\ |\ seconds)
+Specify information divisor.
+
+.SH SEE ALSO
+radiusd(8)
+.SH AUTHORS
+Alan DeKok <aland@freeradius.org>
.RE
.sp
..
-.TH unlang 5 "24 November 2014" "" "FreeRADIUS Processing un-language"
+.TH unlang 5 "05 February 2016" "" "FreeRADIUS Processing un-language"
.SH NAME
unlang \- FreeRADIUS Processing un\-language
.SH DESCRIPTION
organized into lists. Processing of the language is line by line,
from the start of the list to the end. Actions are executed
per-keyword.
-.IP module-name
+.IP module-name[.section-name]
A reference to the named module. When processing reaches this point,
the pre-compiled module is called. The module may succeed or fail,
and will return a status to "unlang" if so. This status can be tested
in a condition. See the "Simple Conditions" text in the CONDITIONS
section, and MODULE RETURN CODES, below.
+If a section-name is provided, it will cause the module to execute
+as if it were listed in the named section.
.DS
chap # call the CHAP module
.PP
String lengths and arrays
.RS
-Similar to a Unix shell, there are ways to reference string lenths,
+Similar to a Unix shell, there are ways to reference string lengths,
and the second or more instance of an attribute in a list. If you
need more than this functionality, we suggest using a real language.
.IP %{strlen:string}
.IP !*
Delete all occurances of the named attribute, no matter what the
value.
+.IP =~
+Keep all attributes having values which match the given regular
+expression. If no attribute matches, nothing else is done.
+.IP !~
+Keep all attributes having values which fail to match the given
+regular expression. If no attribute matches, nothing else is done.
.RE
.IP Values
.br
FREERADIUS-NOTIFICATION-MIB DEFINITIONS ::= BEGIN
- IMPORTS freeRadius
+ IMPORTS
+ MODULE-IDENTITY, NOTIFICATION-TYPE
+ FROM SNMPv2-SMI
+ freeradiusObjects
+ FROM FREERADIUS-MGMT-MIB
+ freeRadius
FROM FREERADIUS-SMI
- radiusAuthServerAddress,radiusAuthClientServerPortNumber
+ radiusAuthServerAddress,radiusAuthClientServerPortNumber
FROM RADIUS-AUTH-CLIENT-MIB
- radiusAuthServIdent
+ radiusAuthServIdent
FROM RADIUS-AUTH-SERVER-MIB
- radiusd
+ radiusd
FROM FREERADIUS-PRODUCT-RADIUSD-MIB;
freeRadiusNotificationMib MODULE-IDENTITY
serverGlobal OBJECT IDENTIFIER ::= { freeRadiusNotificationMib 1 }
serverStart NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that the server has started"
::= { serverGlobal 1 }
serverStop NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that the server is stopping"
::= { serverGlobal 2 }
serverMaxRequests NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that the server has hit the max_requests limit"
::= { serverGlobal 3 }
serverSignal OBJECT IDENTIFIER ::= { serverGlobal 4 }
signalHup NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that the server has received a HUP signal"
::= { serverSignal 1 }
signalTerm NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that the server has received a TERM signal"
::= { serverSignal 2 }
serverThread OBJECT IDENTIFIER ::= { serverGlobal 5 }
threadStart NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that a thread has started"
::= { serverThread 1 }
threadStop NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that a thread has stopped"
::= { serverThread 2 }
threadUnresponsive NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that a child thread is unresponsive"
::= { serverThread 3 }
threadMaxThreads NOTIFICATION-TYPE
- OBJECTS { identity }
+ OBJECTS { radiusObject }
STATUS current
DESCRIPTION "Notification that the max_threads limit has been reached"
::= { serverThread 4 }
"The MIB module for entities implementing the statistics
side of the Remote Access Dialin User Service (RADIUS)
authentication protocol."
- REVISION "0001020000Z"
+ REVISION "0001020000Z"
DESCRIPTION "Experimental Version"
::= { radiusStatistics 1 }
::= { radiusStatMIB 7 }
radiusStatNASEntry OBJECT-TYPE
- SYNTAX RadiusNASStatEntry
+ SYNTAX RadiusStatNASEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"An entry (conceptual row) representing a Network
Access Server"
- INDEX { NASIndex }
+ INDEX { nasIndex }
::= { radiusStatNASTable 1 }
RadiusStatNASEntry ::= SEQUENCE {
- NASIndex Integer32,
- NASAddress IpAddress,
- NASID SnmpAdminString,
- NASLines Counter32,
- NASLinesInUse Counter32,
- NASLinesIdle Counter32,
+ nasIndex Integer32,
+ nasAddress IpAddress,
+ nasID SnmpAdminString,
+ nasLines Counter32,
+ nasLinesInUse Counter32,
+ nasLinesIdle Counter32,
}
-NASIndex OBJECT-TYPE
+nasIndex OBJECT-TYPE
SYNTAX Integer32 (1..2147483647)
MAX-ACCESS not-accessible
STATUS current
"A number uniquely identifying each NAS"
::= { radiusStatNASEntry 1 }
-NASAddress OBJECT-TYPE
+nasAddress OBJECT-TYPE
SYNTAX IpAddress
MAX-ACCESS read-only
STATUS current
"The NAS-IP-Address"
::= { radiusStatNASEntry 2 }
-NASID OBJECT-TYPE
+nasID OBJECT-TYPE
SYNTAX SnmpAdminString
MAX-ACCESS read-only
STATUS current
"The NAS-Identifier"
::= { radiusStatNASEntry 3 }
-NASLines OBJECT-TYPE
+nasLines OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
"The number of lines served by the NAS"
::= { radiusStatNASEntry 4 }
-NASLinesInUse OBJECT-TYPE
+nasLinesInUse OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
"The number of lines currently in use on this NAS"
::= { radiusStatNASEntry 5 }
-NASLinesIdle OBJECT-TYPE
+nasLinesIdle OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
radiusStatPortID Integer32,
radiusStatPortFramedAddress IpAddress,
radiusStatPortTotalLogins Counter32,
- radiusStatPortStatus Counter32,
+ radiusStatPortStatus INTEGER,
radiusStatPortStatusDate SnmpAdminString,
radiusStatPortUpTime TimeTicks,
- radiusStatPortLastLogin SnmpAdminString,
+ radiusStatPortLastLoginName SnmpAdminString,
radiusStatPortLastLoginDate SnmpAdminString,
radiusStatPortLastLogoutDate SnmpAdminString,
radiusStatPortIdleTotalTime TimeTicks,
``unix`` module. For those systems, we recommend putting users and
passwords into a database, instead of relying on ``/etc/passwd``.
+rlm_preprocess
+~~~~~~~~~~~~~~
+
+In 2.x.x ``huntroups`` and ``users`` files were loaded from default locations
+without being configured explicitly. Since 3.x.x you need to set
+``huntgroups`` and ``users`` configuration item(s) in module section in order
+to get them being processed.
+
New Modules
-----------
DEFAULT_SITES := default inner-tunnel
LOCAL_SITES := $(addprefix raddb/sites-enabled/,$(DEFAULT_SITES))
-DEFAULT_MODULES := always attr_filter cache_eap chap \
+DEFAULT_MODULES := always attr_filter cache_eap chap date \
detail detail.log digest dhcp dynamic_clients eap \
echo exec expiration expr files linelog logintime \
mschap ntlm_auth pap passwd preprocess radutmp realm \
.PHONY: server
server: server.pem server.vrfy
+.PHONY: verify
+verify: server.vrfy client.vrfy
+
passwords.mk: server.cnf ca.cnf client.cnf
@echo "PASSWORD_SERVER = '$(shell grep output_password server.cnf | sed 's/.*=//;s/^ *//')'" > $@
@echo "PASSWORD_CA = '$(shell grep output_password ca.cnf | sed 's/.*=//;s/^ *//')'" >> $@
# <list>:<attribute> <op> <value>
# Cache all instances of Reply-Message in the reply list
- reply:Reply-Message += &reply:Reply-Message
+ &reply:Reply-Message += &reply:Reply-Message
# Add our own to show when the cache was last updated
- reply:Reply-Message += "Cache last updated at %t"
+ &reply:Reply-Message += "Cache last updated at %t"
- reply:Class := "%{randstr:ssssssssssssssssssssssssssssssss}"
+ &reply:Class := "%{randstr:ssssssssssssssssssssssssssssssss}"
}
# This module supports a number of runtime configuration parameters
# common side effect of setting 'Auth-Type := EAP' is that the
# users then cannot use ANY other authentication method.
#
-# EAP types NOT listed here may be supported via the "eap2" module.
-# See experimental.conf for documentation.
-#
eap {
# Invoke the default supported EAP type when
# EAP-Identity response is received.
#
ca_file = ${cadir}/ca.pem
+ # OpenSSL will automatically create certificate chains,
+ # unless we tell it to not do that. The problem is that
+ # it sometimes gets the chains right from a certificate
+ # signature view, but wrong from the clients view.
+ #
+ # When setting "auto_chain = no", the server certificate
+ # file MUST include the full certificate chain.
+ # auto_chain = yes
+
#
# If OpenSSL supports TLS-PSK, then we can use
# a PSK identity and (hex) password. When the
# For DH cipher suites to work, you have to
# run OpenSSL to create the DH file first:
#
- # openssl dhparam -out certs/dh 1024
+ # openssl dhparam -out certs/dh 2048
#
dh_file = ${certdir}/dh
#
# include_length = yes
+
# Check the Certificate Revocation List
#
# 1) Copy CA certificates and CRLs to same directory.
# Set this option to specify the allowed
# TLS cipher suites. The format is listed
# in "man 1 ciphers".
+ #
+ # For EAP-FAST, use "ALL:!EXPORT:!eNULL:!SSLv2"
+ #
cipher_list = "DEFAULT"
+ # Work-arounds for OpenSSL nonsense
+ # OpenSSL 1.0.1f and 1.0.1g do not calculate
+ # the EAP keys correctly. The fix is to upgrade
+ # OpenSSL, or disable TLS 1.2 here.
+ #
+ # For EAP-FAST, this MUST be set to "yes".
+ #
+# disable_tlsv1_2 = no
+
#
#
enable = yes
#
- # Internal "name" of the session cache. Used to distinguish which
- # TLS context sessions belong to.
- #
- # The server will generate a random value if unset. This will change
- # across server restart so you MUST set the "name" if you want to
- # persist sessions (see below).
- #
- # name = "EAP module"
-
- #
# Lifetime of the cached entries, in hours. The sessions will be
# deleted/invalidated after this time.
#
max_entries = 255
#
- # Internal "name" of the session cache.
- # Used to distinguish which TLS context
- # sessions belong to.
+ # Internal "name" of the session cache. Used to
+ # distinguish which TLS context sessions belong to.
#
- # The server will generate a random value
- # if unset. This will change across server
- # restart so you MUST set the "name" if you
- # want to persist sessions (see below).
+ # The server will generate a random value if unset.
+ # This will change across server restart so you MUST
+ # set the "name" if you want to persist sessions (see
+ # below).
#
#name = "EAP module"
# default configuration. Uncomment it, and configure
# the correct paths below to enable it.
#
+ # If OCSP checking is enabled, and the OCSP checks fail,
+ # the verify section is not run.
+ #
+ # If OCSP checking is disabled, the verify section is
+ # run on successful certificate validation.
+ #
verify {
+ # If the OCSP checks succeed, the verify section
+ # is run to allow additional checks.
+ #
+ # If you want to skip verify on OCSP success,
+ # uncomment this configuration item, and set it
+ # to "yes".
+ # skip_if_ocsp_ok = no
+
# A temporary directory where the client
# certificates are stored. This directory
# MUST be owned by the UID of the server,
# identify it.
# identity = "FreeRADIUS"
}
+
+ ## EAP-FAST
+ #
+ # The FAST module implements the EAP-FAST protocol
+ #
+# fast {
+ # Point to the common TLS configuration
+ #
+ # cipher_list though must include "ADH" for anonymous provisioning.
+ # This is not as straight forward as appending "ADH" alongside
+ # "DEFAULT" as "DEFAULT" contains "!aNULL" so instead it is
+ # recommended "ALL:!EXPORT:!eNULL:!SSLv2" is used
+ #
+# tls = tls-common
+
+ # PAC lifetime in seconds (default: seven days)
+ #
+# pac_lifetime = 604800
+
+ # Authority ID of the server
+ #
+ # if you are running a cluster of RADIUS servers, you should make
+ # the value chosen here (and for "pac_opaque_key") the same on all
+ # your RADIUS servers. This value should be unique to your
+ # installation. We suggest using a domain name.
+ #
+# authority_identity = "1234"
+
+ # PAC Opaque encryption key (must be exactly 32 bytes in size)
+ #
+ # This value MUST be secret, and MUST be generated using
+ # a secure method, such as via 'openssl rand -hex 32'
+ #
+# pac_opaque_key = "0123456789abcdef0123456789ABCDEF"
+
+ # Same as for TTLS, PEAP, etc.
+ #
+# virtual_server = inner-tunnel
+# }
}
# Filter for user objects, should be specific enough
# to identify a single user object.
+ #
+ # For Active Directory, you should use
+ # "samaccountname=" instead of "uid="
+ #
filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
# SASL parameters to use for user binds
delete_stale_sessions = yes
# Write SQL queries to a logfile. This is potentially useful for tracing
- # issues with authorization queries.
+ # issues with authorization queries. See also "logfile" directives in
+ # mods-config/sql/main/*/queries.conf. You can enable per-section logging
+ # by enabling "logfile" there, or global logging by enabling "logfile" here.
+ #
+ # Per-section logging can be disabled by setting "logfile = ''"
# logfile = ${logdir}/sqllog.sql
# Set the maximum query duration and connection timeout
#nochap
# User-Name =* ANY,
# User-Password =* ANY,
-# NAS-Ip-Address =* ANY,
+# NAS-IP-Address =* ANY,
# NAS-Identifier =* ANY
# The entry for the 'brokenas' realm removes the attribute NAS-Port-Type
State =* ANY,
NAS-IP-Address =* ANY,
NAS-Identifier =* ANY,
+ Operator-Name =* ANY,
Proxy-State =* ANY
RLM_MODULE_NUMCODES => 9 # How many return codes there are
};
-# Same as src/include/radiusd.h
-use constant L_DBG=> 1;
-use constant L_AUTH=> 2;
-use constant L_INFO=> 3;
-use constant L_ERR=> 4;
-use constant L_PROXY=> 5;
-use constant L_ACCT=> 6;
+# Same as src/include/log.h
+use constant {
+ L_AUTH => 2, # Authentication message
+ L_INFO => 3, # Informational message
+ L_ERR => 4, # Error message
+ L_WARN => 5, # Warning
+ L_PROXY => 6, # Proxy messages
+ L_ACCT => 7, # Accounting messages
+ L_DBG => 16, # Only displayed when debugging is enabled
+ L_DBG_WARN => 17, # Warning only displayed when debugging is enabled
+ L_DBG_ERR => 18, # Error only displayed when debugging is enabled
+ L_DBG_WARN_REQ => 19, # Less severe warning only displayed when debugging is enabled
+ L_DBG_ERR_REQ => 20, # Less severe error only displayed when debugging is enabled
+};
# Global variables can persist across different calls to the module.
#
CREATE TABLE [radusergroup] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[UserName] [varchar] (64) NOT NULL ,
- [GroupName] [varchar] (64) NULL
+ [GroupName] [varchar] (64) NULL ,
+ [Priority] [int] NULL
) ON [PRIMARY]
GO
# - Note that the returned field order should not be changed.
#######################################################################
-#
-# Uncomment simul_count_query to enable simultaneous use checking
-#
-#simul_count_query = "\
-# SELECT COUNT(*) \
-# FROM ${acct_table1} \
-# WHERE username = '%{SQL-User-Name}' \
-# AND acctstoptime IS NULL"
+simul_count_query = "\
+ SELECT COUNT(*) \
+ FROM ${acct_table1} \
+ WHERE username = '%{SQL-User-Name}' \
+ AND acctstoptime IS NULL"
simul_verify_query = "\
SELECT \
username varchar(64) NOT NULL default '',
pass varchar(64) NOT NULL default '',
reply varchar(32) NOT NULL default '',
- authdate timestamp NOT NULL,
+ authdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) ENGINE = INNODB;
# - Note that the returned field order should not be changed.
#######################################################################
-#
-# Uncomment simul_count_query to enable simultaneous use checking
-#
-#simul_count_query = "\
-# SELECT COUNT(*) \
-# FROM ${acct_table1} \
-# WHERE UserName = '%{SQL-User-Name}' \
-# AND AcctStopTime IS NULL"
+simul_count_query = "\
+ SELECT COUNT(*) \
+ FROM ${acct_table1} \
+ WHERE UserName = '%{SQL-User-Name}' \
+ AND AcctStopTime IS NULL"
simul_verify_query = "\
SELECT \
# - Note that the returned field order should not be changed.
#######################################################################
-#
-# Uncomment simul_count_query to enable simultaneous use checking
-#
-#simul_count_query = "\
-# SELECT COUNT(*) \
-# FROM ${acct_table1} \
-# WHERE UserName='%{SQL-User-Name}' \
-# AND AcctStopTime IS NULL"
-
-#simul_verify_query = "\
-# SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, \
-# FramedProtocol \
-# FROM ${acct_table1} \
-# WHERE UserName='%{SQL-User-Name}' \
-# AND AcctStopTime IS NULL"
+simul_count_query = "\
+ SELECT COUNT(*) \
+ FROM ${acct_table1} \
+ WHERE UserName='%{SQL-User-Name}' \
+ AND AcctStopTime IS NULL"
+
+simul_verify_query = "\
+ SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, \
+ FramedProtocol \
+ FROM ${acct_table1} \
+ WHERE UserName='%{SQL-User-Name}' \
+ AND AcctStopTime IS NULL"
#######################################################################
# Group Membership Queries
# - Note that the returned field order should not be changed.
#######################################################################
-#
-# Uncomment simul_count_query to enable simultaneous use checking
-#
-#simul_count_query = "\
-# SELECT COUNT(*) \
-# FROM ${acct_table1} \
-# WHERE username = '%{SQL-User-Name}' \
-# AND acctstoptime IS NULL"
+simul_count_query = "\
+ SELECT COUNT(*) \
+ FROM ${acct_table1} \
+ WHERE username = '%{SQL-User-Name}' \
+ AND acctstoptime IS NULL"
simul_verify_query = "\
SELECT radacctid, acctsessionid, username, nasipaddress, nasportid, framedipaddress, \
# Verify rp parameters
#
psk_authorize {
- if (TLS-PSK-Identity) {
+ if (&TLS-PSK-Identity) {
# TODO: may need to check trust-router-apc as well
if ("%{psksql:select distinct keyid from authorizations_keys where keyid = '%{tls-psk-identity}' and '%{trust-router-coi}' like coi and '%{gss-acceptor-realm-name}' like acceptor_realm and '%{gss-acceptor-host-name}' like hostname;}") {
# do things here
# A policy which is used to validate channel-bindings.
#
abfab_channel_bindings {
- if (GSS-Acceptor-Service-Name && (outer.request:GSS-Acceptor-Service-Name != GSS-Acceptor-Service-Name)) {
+ if (&GSS-Acceptor-Service-Name && (&outer.request:GSS-Acceptor-Service-Name != &GSS-Acceptor-Service-Name)) {
reject
}
- if (GSS-Acceptor-Host-Name && outer.request:GSS-Acceptor-Host-Name != GSS-Acceptor-Host-Name ) {
+ if (&GSS-Acceptor-Host-Name && &outer.request:GSS-Acceptor-Host-Name != &GSS-Acceptor-Host-Name ) {
reject
}
- if (GSS-Acceptor-Realm-Name && outer.request:GSS-Acceptor-Realm-Name != GSS-Acceptor-Realm-Name ) {
+ if (&GSS-Acceptor-Realm-Name && &outer.request:GSS-Acceptor-Realm-Name != &GSS-Acceptor-Realm-Name ) {
reject
}
- if (GSS-Acceptor-Service-Name || GSS-Acceptor-Realm-Name || GSS-Acceptor-Host-Name) {
+ if (&GSS-Acceptor-Service-Name || &GSS-Acceptor-Realm-Name || &GSS-Acceptor-Host-Name) {
update control {
- Chbind-Response-Code := success
+ &Chbind-Response-Code := success
}
#
# then they won't be copied to the reply.
#
update reply {
- GSS-Acceptor-Service-Name = &GSS-Acceptor-Service-Name
- GSS-Acceptor-Host-Name = &GSS-Acceptor-Host-Name
- GSS-Acceptor-Realm-Name = &GSS-Acceptor-Realm-Name
+ &GSS-Acceptor-Service-Name = &GSS-Acceptor-Service-Name
+ &GSS-Acceptor-Host-Name = &GSS-Acceptor-Host-Name
+ &GSS-Acceptor-Realm-Name = &GSS-Acceptor-Realm-Name
}
}
# initial authentication session (Common in a
# wireless environment).
#
- if ("%{string:Class}" =~ /${policy.class_value_prefix}([0-9a-f]{32})/i) {
+ update request {
+ Tmp-String-9 := "${policy.class_value_prefix}"
+ }
+
+ if (("%{hex:&Class}" =~ /^%{hex:&Tmp-String-9}/) && \
+ ("%{string:&Class}" =~ /^${policy.class_value_prefix}([0-9a-f]{32})/i)) {
update request {
&Acct-Unique-Session-Id := "%{md5:%{1},%{Acct-Session-ID}}"
}
}
#
+# Outputs the contents of the proxy-request state list in debugging (-X) mode
+#
+debug_proxy_request {
+ if("%{debug_attr:proxy-request:}" == '') {
+ noop
+ }
+}
+
+#
# Outputs the contents of the main lists in debugging (-X) mode
#
debug_all {
# what constitutes a user name.
#
filter_username {
- if (!&User-Name) {
- noop
- }
+ if (&User-Name) {
+ #
+ # reject mixed case e.g. "UseRNaMe"
+ #
+ #if (&User-Name != "%{tolower:%{User-Name}}") {
+ # reject
+ #}
- #
- # reject mixed case e.g. "UseRNaMe"
- #
- #if (&User-Name != "%{tolower:%{User-Name}}") {
- # reject
- #}
+ #
+ # reject all whitespace
+ # e.g. "user@ site.com", or "us er", or " user", or "user "
+ #
+ if (&User-Name =~ / /) {
+ update request {
+ &Module-Failure-Message += 'Rejected: User-Name contains whitespace'
+ }
+ reject
+ }
- #
- # reject all whitespace
- # e.g. "user@ site.com", or "us er", or " user", or "user "
- #
- if (&User-Name =~ / /) {
- update reply {
- &Reply-Message += 'Rejected: Username contains whitespace'
+ #
+ # reject Multiple @'s
+ # e.g. "user@site.com@site.com"
+ #
+ if (&User-Name =~ /@[^@]*@/ ) {
+ update request {
+ &Module-Failure-Message += 'Rejected: Multiple @ in User-Name'
+ }
+ reject
}
- reject
- }
- #
- # reject Multiple @'s
- # e.g. "user@site.com@site.com"
- #
- if (&User-Name =~ /@.*@/ ) {
- update reply {
- &Reply-Message += 'Rejected: Multiple @ in username'
+ #
+ # reject double dots
+ # e.g. "user@site..com"
+ #
+ if (&User-Name =~ /\.\./ ) {
+ update request {
+ &Module-Failure-Message += 'Rejected: User-Name contains multiple ..s'
+ }
+ reject
}
- reject
- }
- #
- # reject double dots
- # e.g. "user@site..com"
- #
- if (&User-Name =~ /\.\./ ) {
- update reply {
- &Reply-Message += 'Rejected: Username contains ..s'
+ #
+ # must have at least 1 string-dot-string after @
+ # e.g. "user@site.com"
+ #
+ if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) {
+ update request {
+ &Module-Failure-Message += 'Rejected: Realm does not have at least one dot separator'
+ }
+ reject
}
- reject
- }
- #
- # must have at least 1 string-dot-string after @
- # e.g. "user@site.com"
- #
- if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) {
- update reply {
- &Reply-Message += 'Rejected: Realm does not have at least one dot separator'
+ #
+ # Realm ends with a dot
+ # e.g. "user@site.com."
+ #
+ if (&User-Name =~ /\.$/) {
+ update request {
+ &Module-Failure-Message += 'Rejected: Realm ends with a dot'
+ }
+ reject
+ }
+
+ #
+ # Realm begins with a dot
+ # e.g. "user@.site.com"
+ #
+ if (&User-Name =~ /@\./) {
+ update request {
+ &Module-Failure-Message += 'Rejected: Realm begins with a dot'
+ }
+ reject
}
- reject
}
+}
+
+#
+# Filter the User-Password
+#
+# Some equipment sends passwords with embedded zeros.
+# This policy filters them out.
+#
+filter_password {
+ if (&User-Password && \
+ (&User-Password != "%{string:User-Password}")) {
+ update request {
+ &Tmp-String-0 := "%{string:User-Password}"
+ &User-Password := "%{string:Tmp-String-0}"
+ }
+ }
+}
+filter_inner_identity {
#
- # Realm ends with a dot
- # e.g. "user@site.com."
+ # No names, reject.
#
- if (&User-Name =~ /\.$/) {
- update reply {
- &Reply-Message += 'Rejected: Realm ends with a dot'
+ if (!&outer.request:User-Name || !&User-Name) {
+ update request {
+ Module-Failure-Message = "User-Name is required for tunneled authentication"
}
reject
}
#
- # Realm begins with a dot
- # e.g. "user@.site.com"
+ # Do detailed checks only if the inner and outer
+ # NAIs are different.
+ #
+ # If the NAIs are the same, it violates user privacy,
+ # but is allowed.
#
- if (&User-Name =~ /@\./) {
- update reply {
- &Reply-Message += 'Rejected: Realm begins with a dot'
+ if (&outer.request:User-Name != &User-Name) {
+ #
+ # Get the outer realm.
+ #
+ if (&outer.request:User-Name =~ /@([^@]+)$/) {
+ update request {
+ Outer-Realm-Name = "%{1}"
+ }
+
+ #
+ # When we have an outer realm name, the user portion
+ # MUST either be empty, or begin with "anon".
+ #
+ # We don't check for the full "anonymous", because
+ # some vendors don't follow the standards.
+ #
+ if (&outer.request:User-Name !~ /^(anon|@)/) {
+ update request {
+ Module-Failure-Message = "User-Name is not anonymized"
+ }
+ reject
+ }
}
- reject
+
+ #
+ # There's no outer realm. The outer NAI is different from the
+ # inner NAI. The User-Name MUST be anonymized.
+ #
+ # Otherwise, you could log in as outer "bob", and inner "doug",
+ # and we'd have no idea which one was correct.
+ #
+ elsif (&outer.request:User-Name !~ /^anon/) {
+ update request {
+ Module-Failure-Message = "User-Name is not anonymized"
+ }
+ reject
+ }
+
+ #
+ # Get the inner realm.
+ #
+ if (&User-Name =~ /@([^@]+)$/) {
+ update request {
+ Inner-Realm-Name = "%{1}"
+ }
+
+ #
+ # Note that we do EQUALITY checks for realm names.
+ # There is no simple way to do case insensitive checks
+ # on internationalized domain names. There is no reason
+ # to allow outer "anonymous@EXAMPLE.COM" and inner
+ # "user@example.com". The user should enter the same
+ # realm for both identities.
+ #
+ # If the inner realm isn't the same as the outer realm,
+ # the inner realm MUST be a subdomain of the outer realm.
+ #
+ if (&Outer-Realm-Name && \
+ (&Inner-Realm-Name != &Outer-Realm-Name) && \
+ (&Inner-Realm-Name !~ /\.%{Outer-Realm-Name}$/)) {
+ update request {
+ Module-Failure-Message = "Inner realm '%{Inner-Realm-Name}' and outer realm '%{Outer-Realm-Name}' are not from the same domain."
+ }
+ reject
+ }
+
+ #
+ # It's OK to have an inner realm and no outer realm.
+ #
+ # That won't work for roaming, but the local RADIUS server
+ # can still authenticate the user.
+ #
+ }
+
+ #
+ # It's OK to have an outer realm and no inner realm.
+ #
+ # It will work for roaming, and the local RADIUS server
+ # can authenticate the user without the realm.
+ #
}
}
--- /dev/null
+#
+# The following policies generate targeted IDs for ABFAB (Moonshot)
+#
+# This policy requires that the UUID package is installed on your platform
+# and that this is called from the inner-tunnel
+#
+# The following string attributes need to exist in the UKERNA dictionary
+# Moonshot-Host-TargetedId (138)
+# Moonshot-Realm-TargetedId (139)
+# Moonshot-TR-COI-TargetedId (140)
+#
+# These attributes should also be listed in the attr_filter policies
+# post-proxy and pre-proxy when you use attribute filtering:
+# Moonshot-Host-TargetedId =* ANY,
+# Moonshot-Realm-TargetedId =* ANY,
+# Moonshot-TR-COI-TargetedId =* ANY,
+#
+
+#
+# targeted_id_salt definition
+# This salt serves the purpose of protecting targeted IDs against
+# dictionary attacks, therefore should be chosen as a "random"
+# string and kept secret.
+#
+targeted_id_salt = "changeme"
+#
+# Moonshot namespaces
+# These namespaces are used for UUID generation.
+# They should not be changed by implementors
+#
+moonshot_host_namespace = "a574a04e-b7ff-4850-aa24-a8599c7de1c6"
+moonshot_realm_namespace = "dea5f26d-a013-4444-977d-d09fc990d2e6"
+moonshot_coi_namespace = "145d7e7e-7d54-43ee-bbcb-3c6ad9428247"
+
+# This policy generates a host-specific targeted ID
+#
+moonshot_host_tid.post-auth {
+ # generate a UUID for Moonshot-Host-TargetedId
+ # targeted id = (uuid -v 5 [namespace] [username][salt][RP host name])@[IdP realm name]
+ if (&outer.request:GSS-Acceptor-Host-Name) {
+ if ("%{echo:/usr/bin/uuid -v 5 ${policy.moonshot_host_namespace} %{tolower:%{User-Name}}${policy.targeted_id_salt}%{tolower:%{outer.request:GSS-Acceptor-Host-Name}}}" =~ /^([^ ]+)([ ]*)$/) {
+ update outer.session-state {
+ Moonshot-Host-TargetedId := "%{1}@%{tolower:%{request:Realm}}"
+ }
+ }
+ }
+}
+# This policy generates a realm-specific targeted ID
+#
+moonshot_realm_tid.post-auth {
+ # generate a UUID for Moonshot-Realm-TargetedId
+ # targeted id = (uuid -v 5 [namespace] [username][salt][RP realm name])@[IdP realm name]
+ if (&outer.request:GSS-Acceptor-Realm-Name) {
+ if ("%{echo:/usr/bin/uuid -v 5 ${policy.moonshot_realm_namespace} %{tolower:%{User-Name}}${policy.targeted_id_salt}%{tolower:%{outer.request:GSS-Acceptor-Realm-Name}}}" =~ /^([^ ]+)([ ]*)$/) {
+ update outer.session-state {
+ Moonshot-Realm-TargetedId := "%{1}@%{tolower:%{request:Realm}}"
+ }
+ }
+ }
+}
+# This policy generates a COI-specific targeted ID
+#
+moonshot_coi_tid.post-auth {
+ # generate a UUID for Moonshot-TR-COI-TargetedId
+ # targeted id = (uuid -v 5 [namespace] [username][salt][RP COI name])@[IdP realm name]
+ if (&outer.request:Trust-Router-COI) {
+ if ("%{echo:/usr/bin/uuid -v 5 ${policy.moonshot_coi_namespace} %{tolower:%{User-Name}}${policy.targeted_id_salt}%{tolower:%{outer.request:Trust-Router-COI}}}" =~ /^([^ ]+)([ ]*)$/) {
+ update outer.session-state {
+ Moonshot-TR-COI-TargetedId := "%{1}@%{tolower:%{request:Realm}}"
+ }
+ }
+ }
+}
# Once we KNOW that the user has been authenticated, there are
# additional steps we can take.
post-auth {
+ #
+ # For EAP-TTLS and PEAP, add the cached attributes to the reply.
+ # The "session-state" attributes are automatically cached when
+ # an Access-Challenge is sent, and automatically retrieved
+ # when an Access-Request is received.
+ #
+ # The session-state attributes are automatically deleted after
+ # an Access-Reject or Access-Accept is sent.
+ #
+ update {
+ &reply: += &session-state:
+ }
+
# Create the CUI value and add the attribute to Access-Accept.
# Uncomment the line below if *returning* the CUI.
# cui
# authentication failure And already has an EAP message
# For non-ABFAB, we insert the failure all the time, but for ABFAB
# It's more desirable to preserve reply-message when we can
-if &reply:Eap-Message {
+ if (&reply:Eap-Message) {
eap
- }
+ }
# Remove reply message if the response contains an EAP-Message
remove_reply_message_if_eap
# This virtual server allows EAP-TLS to reject access requests
-# based on some certificate attributes.
+# based on some attributes of the certificates involved.
+#
+# To use this virtual server, you must enable it in the tls
+# section of mods-enabled/eap as well as adding a link to this
+# file in sites-enabled/.
+#
#
# Value-pairs that are available for checking include:
#
# passed in to this virtual server.
#
#
-# This virtual server is also useful when using EAP-TLS as it is only called
-# once, just before the final Accept is about to be returned from eap, whereas
-# the outer authorize section is called multiple times for each challenge /
-# response. For this reason, here may be a good location to put authentication
-# logging, and modules that check for further authorization, especially if they
+# This virtual server is also useful when using EAP-TLS as it is
+# only called once, just before the final Accept is about to be
+# returned from eap, whereas the outer authorize section is called
+# multiple times for each challenge / response. For this reason,
+# here may be a good location to put authentication logging, and
+# modules that check for further authorization, especially if they
# hit external services such as sql or ldap.
+
server check-eap-tls {
#
# Check the client certificate common name against the supplied User-Name
#
-# if ("host/%{TLS-Client-Cert-Common-Name}" == &User-Name) {
+# if (&User-Name == "host/%{TLS-Client-Cert-Common-Name}") {
# update config {
# &Auth-Type := Accept
# }
filter_username
#
+ # Some broken equipment sends passwords with embedded zeros.
+ # i.e. the debug output will show
+ #
+ # User-Password = "password\000\000"
+ #
+ # This policy will fix it to just be "password".
+ #
+# filter_password
+
+ #
# The preprocess module takes care of sanitizing some bizarre
# attributes in the request, and turning them into attributes
# which are more standard.
#
- # It takes care of processing the 'raddb/hints' and the
- # 'raddb/huntgroups' files.
+ # It takes care of processing the 'raddb/mods-config/preprocess/hints'
+ # and the 'raddb/mods-config/preprocess/huntgroups' files.
preprocess
# If you intend to use CUI and you require that the Operator-Name
}
#
+ # For old names, too.
+ #
+ mschap
+
+ #
# If you have a Cisco SIP server authenticating against
# FreeRADIUS, uncomment the following line, and the 'digest'
# line in the 'authorize' section.
# need to setup hints for the remote radius server
authorize {
#
+ # Take a User-Name, and perform some checks on it, for spaces and other
+ # invalid characters. If the User-Name appears invalid, reject the
+ # request.
+ #
+ # See policy.d/filter for the definition of the filter_username policy.
+ #
+ filter_username
+
+ #
+ # Do checks on outer / inner User-Name, so that users
+ # can't spoof us by using incompatible identities
+ #
+# filter_inner_identity
+
+ #
# The chap module will set 'Auth-Type := CHAP' if we are
# handling a CHAP request and Auth-Type has not already been set
chap
}
#
+ # For old names, too.
+ #
+ mschap
+
+ #
# Pluggable Authentication Modules.
# pam
#
+ # Un-comment the following if you want to generate Moonshot (ABFAB) TargetedIds
+ # IMPORTANT: This requires the UUID package to be installed!
+ #
+# moonshot_host_tid
+# moonshot_realm_tid
+# moonshot_coi_tid
+
+ #
# Instead of "use_tunneled_reply", uncomment the
# next two "update" blocks.
#
######################################################################
#
-# Sample contents: just do everything that the default configuration does.
-#
-# You WILL want to edit this to your local needs. We suggest copying
-# the "default" file here, and then editing it. That way, any
-# changes to the "default" file will not affect this virtual server,
-# and vice-versa.
+# You will want to edit this to your local needs. We suggest copying
+# the text from the "default" file here, and then editing the text.
+# That way, any changes to the "default" file will not affect this
+# virtual server, and vice-versa.
#
# When this virtual server receives the request, the original
# attributes can be accessed as "outer.request", "outer.control", etc.
# See "man unlang" for more details.
#
server virtual.example.com {
-$INCLUDE ${confdir}/sites-available/default
+authorize {
+ # insert policies here
+}
+
+authenticate {
+ # insert policies here
+}
+
+# etc.
}
# experimental modules
%bcond_with rlm_idn
%bcond_with rlm_ruby
-%bcond_with rlm_sql_freetds
%bcond_with rlm_sql_oracle
%{?_with_rlm_idn: %global _with_experimental_modules --with-experimental-modules}
%{?_with_rlm_opendirectory: %global _with_experimental_modules --with-experimental-modules}
%{?_with_rlm_ruby: %global _with_experimental_modules --with-experimental-modules}
%{?_with_rlm_securid: %global _with_experimental_modules --with-experimental-modules}
-%{?_with_rlm_sql_freetds: %global _with_experimental_modules --with-experimental-modules}
%{?_with_rlm_sql_oracle: %global _with_experimental_modules --with-experimental-modules}
%if %{?_with_experimental_modules:1}%{!?_with_experimental_modules:0}
%{!?_with_rlm_opendirectory: %global _without_rlm_opendirectory --without-rlm_opendirectory}
%{!?_with_rlm_ruby: %global _without_rlm_ruby --without-rlm_ruby}
%{!?_with_rlm_securid: %global _without_rlm_securid --without-rlm_securid}
-%{!?_with_rlm_sql_freetds: %global _without_rlm_sql_freetds --without-rlm_sql_freetds}
%{!?_with_rlm_sql_oracle: %global _without_rlm_sql_oracle --without-rlm_sql_oracle}
%endif
Summary: High-performance and highly configurable free RADIUS server
Name: freeradius
-Version: 3.0.10
+Version: 3.0.12
Release: 2%{?dist}
License: GPLv2+ and LGPLv2+
Group: System Environment/Daemons
%description unixODBC
This plugin provides unixODBC support for the FreeRADIUS server project.
-%if %{?_with_rlm_sql_freetds:1}%{!?_with_rlm_sql_freetds:0}
%package freetds
Summary: FreeTDS support for FreeRADIUS
Group: System Environment/Daemons
%description freetds
This plugin provides FreeTDS support for the FreeRADIUS server project.
-%endif
%if %{?_with_rlm_sql_oracle:1}%{!?_with_rlm_sql_oracle:0}
%package oracle
%build
-%ifarch s390 s390x
-export CFLAGS="$RPM_OPT_FLAGS -fPIC"
-%else
-export CFLAGS="$RPM_OPT_FLAGS -fpic"
+# Retain CFLAGS from the environment...
+%if %{?_with_developer:1}%{!?_with_developer:0}
+export CFLAGS="$CFLAGS -fpic"
+export CXXFLAGS="$CFLAGS"
%endif
+# Need to pass these explicitly for clang, else rpmbuilder bails when trying to extract debug info from
+# the libraries. Guessing GCC does this by default. Why use clang over gcc? The version of clang
+# which ships with RHEL 6 has basic C11 support, gcc doesn't.
+export LDFLAGS="-Wl,--build-id"
+
%configure \
--libdir=%{_libdir}/freeradius \
--with-system-libtool \
%{?_without_rlm_opendirectory} \
%{?_with_rlm_securid} \
%{?_without_rlm_securid} \
- %{?_with_rlm_sql_freetds} \
- %{?_without_rlm_sql_freetds} \
%{?_with_rlm_ruby} \
%{?_without_rlm_ruby} \
%{?_with_rlm_cache_memcached} \
%if %{?_with_rlm_ruby:0}%{!?_with_rlm_ruby:1}
rm -rf $RPM_BUILD_ROOT/%{_sysconfdir}/raddb/mods-config/ruby
%endif
-%if %{?_with_rlm_sql_freetds:0}%{!?_with_rlm_sql_freetds:1}
-rm -rf $RPM_BUILD_ROOT/%{_sysconfdir}/raddb/mods-config/sql/main/mssql
-%endif
%if %{?_with_rlm_sql_oracle:0}%{!?_with_rlm_sql_oracle:1}
rm -rf $RPM_BUILD_ROOT/%{_sysconfdir}/raddb/mods-config/sql/ippool/oracle
rm -rf $RPM_BUILD_ROOT/%{_sysconfdir}/raddb/mods-config/sql/ippool-dhcp/oracle
%{_libdir}/freeradius/rlm_digest.so
%{_libdir}/freeradius/rlm_dynamic_clients.so
%{_libdir}/freeradius/rlm_eap.so
+%{_libdir}/freeradius/rlm_eap_fast.so
%{_libdir}/freeradius/rlm_eap_gtc.so
%{_libdir}/freeradius/rlm_eap_leap.so
%{_libdir}/freeradius/rlm_eap_md5.so
%{_libdir}/freeradius/rlm_soh.so
%{_libdir}/freeradius/rlm_sometimes.so
%{_libdir}/freeradius/rlm_sql.so
-%{_libdir}/freeradius/rlm_sqlhpwippool.so
%{_libdir}/freeradius/rlm_sql_null.so
%{_libdir}/freeradius/rlm_sql_sqlite.so
%{_libdir}/freeradius/rlm_sqlcounter.so
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/ruby/*
%endif
# freetds
-%if %{?_with_rlm_sql_freetds:1}%{!?_with_rlm_sql_freetds:0}
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/main/mssql
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/main/mssql/*
-%endif
# oracle
%if %{?_with_rlm_sql_oracle:1}%{!?_with_rlm_sql_oracle:0}
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql
%defattr(-,root,root)
/usr/bin/*
# man-pages
+%doc %{_mandir}/man1/dhcpclient.1.gz
%doc %{_mandir}/man1/radclient.1.gz
+%doc %{_mandir}/man1/radcounter.1.gz
%doc %{_mandir}/man1/radeapclient.1.gz
%doc %{_mandir}/man1/radlast.1.gz
%doc %{_mandir}/man1/radtest.1.gz
%{_libdir}/freeradius/rlm_ruby.so
%endif
-%if %{?_with_rlm_sql_freetds:1}%{!?_with_rlm_sql_freetds:0}
%files freetds
%defattr(-,root,root)
%{_libdir}/freeradius/rlm_sql_freetds.so
-%endif
%if %{?_with_rlm_sql_oracle:1}%{!?_with_rlm_sql_oracle:0}
%files oracle
%changelog
-* Wed Sep 22 2013 Alan DeKok <aland@freeradius.org> - 3.0.0
+* Wed Sep 25 2013 Alan DeKok <aland@freeradius.org> - 3.0.0
- upgrade to latest upstream release
#
ifeq "${CPP_MAKEDEPEND}" "yes"
define ADD_OBJECT_RULE
-$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1} ${JLIBTOOL}
+$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1} | ${BOOTSTRAP_BUILD}
${2}
$${CPP} $${CPPFLAGS} $$(addprefix -I,$${SRC_INCDIRS}) $${SRC_DEFS} $$< | sed \
-n 's,^\# *[0-9][0-9]* *"\([^"]*\)".*,$$@: \1,p' > $${BUILD_DIR}/objs/$$*.d
else
define ADD_OBJECT_RULE
-$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1} ${JLIBTOOL}
+$${BUILD_DIR}/objs/%.${OBJ_EXT} $${BUILD_DIR}/objs/%.d: ${1} | ${BOOTSTRAP_BUILD}
${2}
${FILTER_DEPENDS}
endef
endif
define ADD_ANALYZE_RULE
-$${BUILD_DIR}/plist/%.plist: ${1} ${JLIBTOOL}
+$${BUILD_DIR}/plist/%.plist: ${1}
${2}
endef
BUILD_DIR := $(call CANONICAL_PATH,${BUILD_DIR})
endif
+.PHONY: $(BUILD_DIR)
+$(BUILD_DIR):
+ @mkdir -p $@
+
# Define compilers and linkers
#
+BOOTSTRAP_BUILD =
COMPILE.c = ${CC}
COMPILE.cxx = ${CXX}
CPP = cc -E
$(eval -include ${${TGT}_DEPS}))
endif
+# Build rules for installation subdirectories
+$(foreach D,$(patsubst %/,%,$(sort $(dir ${ALL_INSTALL}))),\
+ $(eval $(call ADD_INSTALL_RULE.dir,${D})))
+
+
scan: ${ALL_PLISTS}
.PHONY: clean.scan
--- /dev/null
+#
+# Collectd type definitions for radsniff probes
+#
+# $Id$
+#
+# Copyright 2013 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+#
+radius_count received:GAUGE:0:U, linked:GAUGE:0:U, unlinked:GAUGE:0:U, reused:GAUGE:0:U
+radius_latency smoothed:GAUGE:0:U, avg:GAUGE:0:U, high:GAUGE:0:U, low:GAUGE:0:U
+radius_rtx none:GAUGE:0:U, 1:GAUGE:0:U, 2:GAUGE:0:U, 3:GAUGE:0:U, 4:GAUGE:0:U, more:GAUGE:0:U, lost:GAUGE:0:U
install: $${${1}_INSTALLDIR}/$(notdir ${1})
# Install executable ${1}
- $${${1}_INSTALLDIR}/$(notdir ${1}): $${${1}_BUILD}/${1}
+ $${${1}_INSTALLDIR}/$(notdir ${1}): ${JLIBTOOL} $${${1}_BUILD}/${1} | $${${1}_INSTALLDIR}
@$(ECHO) INSTALL ${1}
- $(Q)$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
$(Q)$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/bin/${1} $${${1}_INSTALLDIR}/
$(Q)$${${1}_POSTINSTALL}
install: $${${1}_INSTALLDIR}/$(notdir ${1})
# Install static library ${1}
- $${${1}_INSTALLDIR}/$(notdir ${1}): ${1}
+ $${${1}_INSTALLDIR}/$(notdir ${1}): ${JLIBTOOL} ${1} | $${${1}_INSTALLDIR}
@$(ECHO) INSTALL ${1}
- $(Q)$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
$(Q)$${PROGRAM_INSTALL} -c -m 755 $${BUILD_DIR}/lib/${1} $${${1}_INSTALLDIR}/
$(Q)$${${1}_POSTINSTALL}
install: $${${1}_INSTALLDIR}/$(notdir ${1})
# Install libtool library ${1}
- $${${1}_INSTALLDIR}/$(notdir ${1}): $${${1}_BUILD}/${1}
+ $${${1}_INSTALLDIR}/$(notdir ${1}): ${JLIBTOOL} $${${1}_BUILD}/${1} | $${${1}_INSTALLDIR}
@$(ECHO) INSTALL ${1}
- $(Q)$${PROGRAM_INSTALL} -d -m 755 $${${1}_INSTALLDIR}
- $(Q)$${PROGRAM_INSTALL} -c -m 755 $${RELINK_FLAGS_MIN} $${BUILD_DIR}/lib/${1} $${${1}_INSTALLDIR}/
+ $(Q)$${PROGRAM_INSTALL} -c -m 755 $${LOCAL_FLAGS_MIN} $${BUILD_DIR}/lib/${1} $${${1}_INSTALLDIR}/
$(Q)$${${1}_POSTINSTALL}
endef
install: ${2}/$(notdir ${1})
# Install manual page ${1}
- ${2}/$(notdir ${1}): ${1}
+ ${2}/$(notdir ${1}): ${JLIBTOOL} ${1} | ${2}
@$(ECHO) INSTALL $(notdir ${1})
- $(Q)[ -d ${2} ] || $${PROGRAM_INSTALL} -d -m 755 ${2}
$(Q)$${PROGRAM_INSTALL} -c -m 644 ${1} ${2}/
endef
+# ADD_INSTALL_RULE.dir - Parameterized "function" that adds a new rule
+# and phony target for installing a directory
+#
+# USE WITH EVAL
+#
+define ADD_INSTALL_RULE.dir
+ # Install directory
+ .PHONY: ${1}
+ ${1}: ${JLIBTOOL}
+ @$(ECHO) INSTALL -d -m 755 ${1}
+ $(Q)$${PROGRAM_INSTALL} -d -m 755 ${1}
+endef
+
+
# ADD_INSTALL_TARGET - Parameterized "function" that adds a new rule
# which installs everything for the target.
#
# define LD_LIBRARY_PATH_LOCAL "DYLD_FALLBACK_LIBRARY_PATH"
#endif
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || (defined(__sun) && defined(__GNUC__))
# define SHELL_CMD "/bin/sh"
# define DYNAMIC_LIB_EXT "so"
# define MODULE_LIB_EXT "so"
# define SHARED_OPTS "-shared"
# define MODULE_OPTS "-shared"
# define LINKER_FLAG_PREFIX "-Wl,"
+#if !defined(__sun)
# define DYNAMIC_LINK_OPTS LINKER_FLAG_PREFIX "-export-dynamic"
+#else
+# define DYNAMIC_LINK_OPTS ""
+#endif
# define ADD_MINUS_L
# define LD_RUN_PATH "LD_RUN_PATH"
# define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
# define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
#endif
-#if defined(__sun)
+#if defined(__sun) && !defined(__GNUC__)
# define SHELL_CMD "/bin/sh"
# define DYNAMIC_LIB_EXT "so"
# define MODULE_LIB_EXT "so"
strcpy(libpath, cmd->arglist->vals[0]);
add_dotlibs(libpath);
- l = strrchr(libpath, '/');
- if (!l) l = strrchr(libpath, '\\');
- if (l) {
- *l = '\0';
- l = libpath;
- } else {
- l = ".libs/";
- }
+ l = strrchr(libpath, '/');
+ if (!l) l = strrchr(libpath, '\\');
+ if (l) {
+ *l = '\0';
+ l = libpath;
+ } else {
+ l = ".libs/";
+ }
- l = "./build/lib/.libs";
- setenv(LD_LIBRARY_PATH_LOCAL, l, 1);
- rv = run_command(cmd, cmd->arglist);
+ l = "./build/lib/.libs";
+ setenv(LD_LIBRARY_PATH_LOCAL, l, 1);
+#ifdef __APPLE__
+ setenv("DYLD_FALLBACK_LIBRARY_PATH", l, 1);
+#endif
+ setenv("FR_LIBRARY_PATH", "./build/lib/local/.libs", 1);
+ rv = run_command(cmd, cmd->arglist);
if (rv) goto finish;
}
- break;
+ break;
default:
break;
@$(ECHO) LINK $${${1}_BUILD}/${1}
$(Q)$${${1}_LINKER} -o $${${1}_BUILD}/${1} $${RPATH_FLAGS} $${LDFLAGS} \
$${${1}_LDFLAGS} $${${1}_OBJS} $${LDLIBS} $${${1}_LDLIBS} \
- $${${1}_PRLIBS}
+ $${${1}_PRLIBS}
$(Q)$${${1}_POSTMAKE}
ifneq "${ANALYZE.c}" ""
endif
endef
-# ADD_RELINK_RULE.exe - Parametric "function" that adds a rule to relink
-# the target before installation, so that the paths are correct.
+# ADD_LOCAL_RULE.exe - Parametric "function" that adds a rule to build
+# a local version of the target.
#
# USE WITH EVAL
#
-define ADD_RELINK_RULE.exe
- ${1}: $${${1}_BUILD}/$${RELINK}${1}
+define ADD_LOCAL_RULE.exe
+ ${1}: $${${1}_BUILD}/$${LOCAL}${1}
# used to fix up RPATH for ${1} on install.
- $${${1}_BUILD}/$${${1}_RELINK}: $${${1}_OBJS} $${${1}_PRBIN} $${${1}_R_PRLIBS}
- $(Q)$(strip mkdir -p $${${1}_BUILD}/${RELINK}/)
- $(Q)$${${1}_LINKER} -o $${${1}_BUILD}/$${RELINK}${1} $${RELINK_FLAGS} $${LDFLAGS} \
- $${${1}_LDFLAGS} $${${1}_OBJS} $${${1}_R_PRLIBS} \
+ $${${1}_BUILD}/$${${1}_LOCAL}: $${${1}_OBJS} $${${1}_PRBIN} $${${1}_LOCAL_PRLIBS}
+ $(Q)$(strip mkdir -p $${${1}_BUILD}/${LOCAL}/)
+ $(Q)$${${1}_LINKER} -o $${${1}_BUILD}/$${LOCAL}${1} $${LOCAL_FLAGS} $${LDFLAGS} \
+ $${${1}_LDFLAGS} $${${1}_OBJS} $${${1}_LOCAL_PRLIBS} \
$${LDLIBS} $${${1}_LDLIBS}
$(Q)$${${1}_POSTMAKE}
endef
-# ADD_RELINK_RULE.la - Parametric "function" that adds a rule to relink
-# the target before installation, so that the paths are correct.
+# ADD_LOCAL_RULE.la - Parametric "function" that adds a rule to build
+# a local version of the target.
#
# USE WITH EVAL
#
-define ADD_RELINK_RULE.la
- ${1}: $${${1}_BUILD}/$${RELINK}${1}
+define ADD_LOCAL_RULE.la
+ ${1}: $${${1}_BUILD}/$${LOCAL}${1}
# used to fix up RPATH for ${1} on install.
- $${${1}_BUILD}/$${${1}_RELINK}: $${${1}_OBJS} $${${1}_PRLIBS}
- $(Q)$(strip mkdir -p $${${1}_BUILD}/${RELINK}/)
- $(Q)$${${1}_LINKER} -o $${${1}_BUILD}/$${RELINK}${1} $${RELINK_FLAGS} $${LDFLAGS} \
- $${${1}_LDFLAGS} $${${1}_OBJS} $${LDLIBS} $${${1}_LDLIBS}
+ $${${1}_BUILD}/$${${1}_LOCAL}: $${${1}_OBJS} $${${1}_LOCAL_PRLIBS}
+ $(Q)$(strip mkdir -p $${${1}_BUILD}/${LOCAL}/)
+ $(Q)$${${1}_LINKER} -o $${${1}_BUILD}/$${LOCAL}${1} $${LOCAL_FLAGS} $${LDFLAGS} \
+ $${${1}_LDFLAGS} $${${1}_OBJS} $${LDLIBS} $${${1}_LDLIBS} \
+ $${${1}_LOCAL_PRLIBS}
$(Q)$${${1}_POSTMAKE}
endef
# Check if we build shared libraries.
ifeq "${bm_shared_libs}" "yes"
- RELINK := local/
+ LOCAL := local/
# RPATH : flags use to build executables that are installed,
# with no dependency on the source.
# RELINL : flags use to build executables that can be run
# from the build directory / source tree.
RPATH_FLAGS := -rpath ${libdir}
- RELINK_FLAGS := -rpath $(abspath ${BUILD_DIR})/lib/${RELINK}/.libs
+ LOCAL_FLAGS := -rpath $(abspath ${BUILD_DIR})/lib/${LOCAL}/.libs
- RELINK_FLAGS_MIN := -rpath ${libdir}
+ LOCAL_FLAGS_MIN := -rpath ${libdir}
ifneq "${bm_static_libs}" "yes"
RPATH_FLAGS += --shared
- RELINK_FLAGS += --shared
+ LOCAL_FLAGS += --shared
endif
else
ifneq "${bm_static_libs}" "yes"
$${TGT}_NOLIBTOOL := $${TGT_NOLIBTOOL}
endif
- ifneq "$${RELINK_FLAGS}" ""
- $${TGT}_RELINK := ${RELINK}$${TGT}
+ ifneq "$${LOCAL_FLAGS}" ""
+ $${TGT}_LOCAL := ${LOCAL}$${TGT}
endif
# re-write all of the dependencies to have the libtool endings.
endif
# If we need to relink, add the relink targets now.
- ifneq "$${$${TGT}_RELINK}" ""
+ ifneq "$${$${TGT}_LOCAL}" ""
# add rules to relink the target
- $${TGT}_R_PRLIBS := $$(subst /lib/,/lib/${RELINK},$${$${TGT}_PRLIBS})
+ $${TGT}_LOCAL_PRLIBS := $$(subst $${BUILD_DIR}/lib/,$${BUILD_DIR}/lib/${LOCAL},$${$${TGT}_PRLIBS})
- $$(eval $$(call ADD_RELINK_RULE$${$${TGT}_SUFFIX},$${TGT}))
+ $$(eval $$(call ADD_LOCAL_RULE$${$${TGT}_SUFFIX},$${TGT}))
- $$(eval $$(call ADD_CLEAN_RULE,$${$${TGT}_RELINK}_libtool))
+ $$(eval $$(call ADD_CLEAN_RULE,$${$${TGT}_LOCAL}_libtool))
ifneq "$${$${TGT}_NOLIBTOOL}" ""
$$(eval $$(call ADD_CLEAN_RULE,$${$${TGT}_NOLIBTOOL}_libtool))
#
#
-# Totalmem limit should be lowered to 200.0 if none of the
+# Totalmem limit should be lowered to 200.0 if none of the
# interpreted language modules or rlm_cache are being used.
#
check process radiusd with pidfile /var/run/radiusd/radiusd.pid
--- /dev/null
+#!/bin/sh
+: << =cut
+
+=head1 NAME
+
+radsniff - A plugin to consume statistics generated by radsniff via collectd RRD files
+
+=head1 APPLICABLE SYSTEMS
+
+radsniff 3.1.x or later
+
+=head1 CONFIGURATION
+
+This plugin uses the following configuration variables:
+
+ [radsniff]
+ env.host - The host collectd thinks the radsniff data
+ originated from (defaults to current host).
+ env.rrd_path - Path to the directory containing rrd files.
+ env.type - Either radius_rtx, radius_latency or radius_count
+ env.pkt_type - The type of packet to graph.
+ env.instance - radsniff instance name (passed to radsniff with -N).
+
+=head1 AUTHOR
+
+Copyright (C) 2014 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+
+=head1 LICENSE
+
+ 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
+
+=head1 MAGIC MARKERS
+
+ #%# family=manual
+
+=cut
+
+if [ -z "$type" ]; then
+ echo "env.type must be set" >&2
+ exit -1
+fi
+
+if [ -z "$pkt_type" ]; then
+ echo "env.pkt_type must be set" >&2
+ exit -1
+fi
+
+if [ "$1" = "config" ]; then
+ pretty_pkt_type=`echo "$pkt_type" | sed -e 's/_/ /g' | sed 's/^./\U&\E/'`
+
+ case "$type" in
+ radius_rtx)
+ echo "graph_title ${pretty_pkt_type} rtx"
+ echo 'graph_args --base 1000 -l 0 '
+ echo 'graph_period second'
+ echo 'graph_vlabel Exchanged / ${graph_period}'
+ echo 'graph_category RADIUS'
+
+ echo 'none.label no loss'
+ echo 'none.info Responses received after first request'
+ echo 'none.type GAUGE'
+ echo 'none.min 0'
+
+ echo 'one.label 1'
+ echo 'one.info Responses received after one retransmission'
+ echo 'one.type GAUGE'
+ echo 'one.min 0'
+
+ echo 'two.label 2'
+ echo 'two.info Responses received after two retransmissions'
+ echo 'two.type GAUGE'
+ echo 'two.min 0'
+
+ echo 'three.label 3'
+ echo 'three.info Responses received after three retransmissions'
+ echo 'three.type GAUGE'
+ echo 'three.min 0'
+
+ echo 'four.label 4'
+ echo 'four.info Responses received after four retransmissions'
+ echo 'four.type GAUGE'
+ echo 'four.min 0'
+
+ echo 'more.label more'
+ echo 'more.info Responses received after more than four retransmissions'
+ echo 'more.type GAUGE'
+ echo 'more.min 0'
+
+ echo 'lost.label lost'
+ echo 'lost.info Requests to which no response was seen'
+ echo 'lost.type GAUGE'
+ echo 'lost.min 0'
+ ;;
+
+ radius_latency)
+ echo "graph_title ${pretty_pkt_type} latency"
+ echo 'graph_args --base 1000 -l 0 '
+ echo 'graph_vlabel Latency (ms)'
+ echo 'graph_category RADIUS'
+
+ echo 'smoothed.label smoothed avg'
+ echo 'smoothed.info Smoothed average'
+ echo 'smoothed.type GAUGE'
+ echo 'smoothed.min 0'
+
+ echo 'avg.label avg'
+ echo 'avg.info Average latency over the stats interval'
+ echo 'avg.type GAUGE'
+ echo 'avg.min 0'
+
+ echo 'high.label high'
+ echo 'high.info Highest latency over the stats interval'
+ echo 'high.type GAUGE'
+ echo 'high.min 0'
+
+ echo 'low.label low'
+ echo 'low.info Lowest latency over the stats interval'
+ echo 'low.type GAUGE'
+ echo 'low.min 0'
+ ;;
+
+ radius_count)
+ echo "graph_title $pretty_pkt_type counters"
+ echo 'graph_args --base 1000 -l 0 '
+ echo 'graph_period second'
+ echo 'graph_vlabel Packets / ${graph_period}'
+ echo 'graph_category RADIUS'
+
+ echo 'received.label received'
+ echo 'received.info Packets of this type received'
+ echo 'received.type GAUGE'
+ echo 'received.min 0'
+
+ echo 'linked.label linked'
+ echo 'linked.info Packets linked to another request or response'
+ echo 'linked.type GAUGE'
+ echo 'linked.min 0'
+
+ echo 'unlinked.label unlinked'
+ echo 'unlinked.info Packets not linked to another request or response'
+ echo 'unlinked.type GAUGE'
+ echo 'unlinked.min 0'
+
+ echo 'reused.label reused'
+ echo 'reused.info Request which (prematurely) re-used the same ID as a previous request'
+ echo 'reused.type GAUGE'
+ echo 'reused.min 0'
+ ;;
+ *)
+ echo "env.type ($type) is invalid must be radius_rtx, radius_latency, or radius_count" >&2
+ exit -1
+ esac
+ exit 0
+fi
+
+HOST=${host:-`hostname -f`}
+INSTANCE=${instance:-'radsniff'}
+RRD_PATH=${rrd_path:-"/var/lib/collectd/rrd/${HOST}/${INSTANCE}-exchanged"}
+RRD_PATH="${RRD_PATH}/${type}-${pkt_type}.rrd"
+RRD_RES=${rrd_res:-300}
+
+if [ ! -e "$RRD_PATH" ]; then
+ echo "rrd file '$RRD_PATH' does not exist" >&2
+ exit -1
+fi
+
+fetch_data()
+{
+ # RRD tool doesn't always select the correct period (seems
+ # to round up and give us -nan results) in the interest of
+ # gap free graphing, we attempt to get the last two periods
+ # worth of data, and then use the newest non -nan one.
+ # It's not perfect and should be fixed at some point...
+ rrd_last=`rrdtool fetch "$RRD_PATH" $1 -r $RRD_RES -e $(expr $(date +%s) / $RRD_RES \* $RRD_RES) -s end-$(expr $RRD_RES \* 2)`; ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "$rrd_last" >&2
+ exit $ret
+ fi
+ echo "$rrd_last" | head -1
+ echo "$rrd_last" | grep '^[0-9]*:' | grep -v -E '^[0-9]*:( -nan)*$' | tail -1
+}
+
+fetch_data_column()
+{
+ echo "$(fetch_data $1)" | tail -1 | cut -d ' ' -f $(expr $2 + 2)
+}
+
+case "$type" in
+ radius_rtx)
+ col=2
+ rrd_data=$(fetch_data 'AVERAGE')
+ for var in `echo "$rrd_data" | head -1`; do
+ case "$var" in
+ 1) printf "one.value ";;
+ 2) printf "two.value ";;
+ 3) printf "three.value ";;
+ 4) printf "four.value ";;
+ *) printf "$var.value ";;
+ esac
+ echo "$rrd_data" | tail -1 | cut -d ' ' -f $col
+ col=`expr $col + 1`
+ done
+ ;;
+
+ radius_count)
+ col=2
+ rrd_data=$(fetch_data 'AVERAGE')
+ for var in `echo "$rrd_data" | head -1`; do
+ printf "$var.value "
+ echo "$rrd_data" | tail -1 | cut -d ' ' -f $col
+ col=`expr $col + 1`
+ done
+ ;;
+
+ radius_latency)
+ printf "smoothed.value "
+ fetch_data_column 'AVERAGE' 0
+
+ printf "avg.value "
+ fetch_data_column 'AVERAGE' 1
+
+ # Averages here are unacceptable because we use this to detect
+ # abnormally long delays in responses, and if we average all the highs
+ # over a five minute period, transient spikes in latency may be lost.
+ printf "high.value "
+ fetch_data_column 'MAX' 2
+
+ # Again we need the lowest value of the set here, as an abnormally
+ # quick response may indicate something is wrong.
+ printf "low.value "
+ fetch_data_column 'MIN' 3
+ ;;
+esac
+exit 0
#
usage() {
- printf "Usage: %s: [-c condition] [-d directory] [-i client-ip-address] [-I client-ipv6-address] [-f socket_file] [-t timeout] [-u user]\n" $(basename $0) >&2
+ printf "Usage: %s: [-c condition] [-d directory] [-D dictdir] [-i client-ip-address] [-I client-ipv6-address] [-f socket_file] [-t timeout] [-u user]\n" $(basename $0) >&2
exit 2
}
extra=
condition=1
timeout=60
-while getopts 'd:c:i:I:f:t:u:' OPTION
+while getopts 'd:D:c:i:I:f:t:u:' OPTION
do
case $OPTION in
c) condition="$OPTARG"
;;
- d) [ "$extra" = "" ] || usage
- extra="-d $OPTARG"
+ d) extra="$extra -d $OPTARG"
;;
- i) condition="(Packet-Src-IP-Address == $OPTARG)"
+ D) extra="$extra -D $OPTARG"
;;
- I) condition="(Packet-Src-IPv6-Address == $OPTARG)"
+ i) x="(Packet-Src-IP-Address == $OPTARG)"
+ if [ "$condition" = "" ]; then
+ condition="$x"
+ else
+ condition="$condition && $x"
+ fi
;;
- f) [ "$extra" = "" ] || usage
- extra="-f $OPTARG"
+ I) x="(Packet-Src-IPv6-Address == $OPTARG)"
+ if [ "$condition" = "" ]; then
+ condition="$x"
+ else
+ condition="$condition && $x"
+ fi
+ ;;
+ f) extra="$extra -f $OPTARG"
;;
t) timeout="$OPTARG"
[ "$timeout" = "0" ] && timeout=1000000
;;
- u) condition="(User-Name == '$OPTARG')"
+ u) x="(User-Name == '$OPTARG')"
+ if [ "$condition" = "" ]; then
+ condition="$x"
+ else
+ condition="$condition && $x"
+ fi
;;
?) usage
;;
-f file Read password from file, instead of command line.
-h host Connect to host.
-P port Port number to use for connection.
- -p passord Password to use when connecting to server.
+ -p password Password to use when connecting to server.
-u user User for login.
-x Turn on debugging.
HERE
$INCLUDE dictionary.acc
$INCLUDE dictionary.acme
$INCLUDE dictionary.actelis
+$INCLUDE dictionary.adtran
$INCLUDE dictionary.airespace
$INCLUDE dictionary.alcatel
$INCLUDE dictionary.alcatel.sr
$INCLUDE dictionary.cablelabs
$INCLUDE dictionary.cabletron
$INCLUDE dictionary.camiant
+$INCLUDE dictionary.checkpoint
$INCLUDE dictionary.chillispot
$INCLUDE dictionary.cisco
$INCLUDE dictionary.cisco.asa
$INCLUDE dictionary.gandalf
$INCLUDE dictionary.gemtek
$INCLUDE dictionary.h3c
+$INCLUDE dictionary.hillstone
$INCLUDE dictionary.hp
$INCLUDE dictionary.huawei
$INCLUDE dictionary.iea
$INCLUDE dictionary.karlnet
$INCLUDE dictionary.kineto
$INCLUDE dictionary.lancom
+$INCLUDE dictionary.lantronix
$INCLUDE dictionary.livingston
$INCLUDE dictionary.localweb
$INCLUDE dictionary.lucent
$INCLUDE dictionary.manzara
$INCLUDE dictionary.meinberg
+$INCLUDE dictionary.meraki
$INCLUDE dictionary.merit
$INCLUDE dictionary.meru
$INCLUDE dictionary.microsoft
$INCLUDE dictionary.roaringpenguin
$INCLUDE dictionary.ruggedcom
$INCLUDE dictionary.ruckus
+$INCLUDE dictionary.sangoma
$INCLUDE dictionary.shasta
$INCLUDE dictionary.sg
$INCLUDE dictionary.shiva
ATTRIBUTE 3GPP-Teardown-Indicator 19 byte
ATTRIBUTE 3GPP-IMEISV 20 string
ATTRIBUTE 3GPP-RAT-Type 21 byte
+
+#
+# See http://www.3gpp.org/DynaReport/29061.htm
+# http://www.3gpp.org/DynaReport/29274.htm
+#
ATTRIBUTE 3GPP-Location-Info 22 octets
ATTRIBUTE 3GPP-MS-Time-Zone 23 octets[2]
ATTRIBUTE 3GPP-Camel-Charging-Info 24 octets
--- /dev/null
+# -*- text -*-
+# Copyright (C) 2015 The FreeRADIUS Server project and contributors
+#
+
+VENDOR Adtran 664
+
+BEGIN-VENDOR Adtran
+
+# Managed WiFi attributes
+
+ATTRIBUTE Adtran-AP-Name 100 string
+ATTRIBUTE Adtran-AP-IP 101 ipaddr
+ATTRIBUTE Adtran-AP-Template 102 string
+ATTRIBUTE Adtran-SSID 103 string
+ATTRIBUTE Adtran-Role 104 string
+
+END-VENDOR Adtran
BEGIN-VENDOR Arista
ATTRIBUTE Arista-AVPair 1 string
+ATTRIBUTE Arista-User-Priv-Level 2 integer
+ATTRIBUTE Arista-User-Role 3 string
+ATTRIBUTE Arista-CVP-Role 4 string
END-VENDOR Arista
ATTRIBUTE Aruba-Port-Bounce-Host 40 integer
+ATTRIBUTE Aruba-Calea-Server-Ip 41 ipaddr
+
+ATTRIBUTE Aruba-Admin-Path 42 string
+
VALUE Aruba-AirGroup-Device-Type Personal-Device 1
VALUE Aruba-AirGroup-Device-Type Shared-Device 2
--- /dev/null
+#
+# Copyright (C) 2016 The FreeRADIUS Server project and contributors
+#
+# Check Point dictionary file for freeradius AAA server
+#
+VENDOR CheckPoint 2620
+
+BEGIN-VENDOR CheckPoint
+
+ATTRIBUTE CP-Gaia-User-Role 229 string
+ATTRIBUTE CP-Gaia-SuperUser-Access 230 integer
+
+END-VENDOR CheckPoint
ATTRIBUTE FreeRADIUS-Stats-Last-Packet-Recv 184 date
ATTRIBUTE FreeRADIUS-Stats-Last-Packet-Sent 185 date
+#
+# EAP-FAST TLVs
+#
+ATTRIBUTE FreeRADIUS-EAP-FAST-TLV 186 tlv
+ATTRIBUTE FreeRADIUS-EAP-FAST-Result 186.3 short
+ATTRIBUTE FreeRADIUS-EAP-FAST-NAK 186.4 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-Error 186.5 integer
+ATTRIBUTE FreeRADIUS-EAP-FAST-Vendor-Specific 186.7 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-EAP-Payload 186.9 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-Intermediate-Result 186.10 octets
+
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC 186.11 tlv
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Key 186.11.1 octets
+
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Opaque-TLV 186.11.2 tlv
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Opaque-PAC-Key 186.11.2.1 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Opaque-PAC-Lifetime 186.11.2.3 integer
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Opaque-I-ID 186.11.2.5 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Opaque-PAC-Type 186.11.2.10 short
+
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Lifetime 186.11.3 integer
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-A-ID 186.11.4 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-I-ID 186.11.5 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-A-ID-Info 186.11.7 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Acknowledge 186.11.8 short
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Info-TLV 186.11.9 tlv
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Info-PAC-Lifetime 186.11.9.3 integer
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Info-A-ID 186.11.9.4 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Info-I-ID 186.11.9.5 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Info-A-ID-Info 186.11.9.7 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Info-PAC-Type 186.11.9.10 short
+
+ATTRIBUTE FreeRADIUS-EAP-FAST-PAC-Type 186.11.10 short
+
+ATTRIBUTE FreeRADIUS-EAP-FAST-Crypto-Binding 186.12 octets
+
+ATTRIBUTE FreeRADIUS-EAP-FAST-Trusted-Root 186.18 octets
+ATTRIBUTE FreeRADIUS-EAP-FAST-Request-Action 186.19 short
+ATTRIBUTE FreeRADIUS-EAP-FAST-PKCS 186.20 octets
+
END-VENDOR FreeRADIUS
ATTRIBUTE EAP-Session-Id 1146 octets
ATTRIBUTE Chbind-Response-Code 1147 integer
-ATTRIBUTE Chbind-Response-Code 1147 integer
-
VALUE Chbind-Response-Code success 2
VALUE Chbind-Response-Code failure 3
ATTRIBUTE SSHA2-384-Password 1179 octets
ATTRIBUTE SSHA2-512-Password 1180 octets
+ATTRIBUTE MS-CHAP-Peer-Challenge 1192 octets
+
#
# Range: 1200-1279
# EAP-SIM (and other EAP type) weirdness.
ATTRIBUTE EAP-Sim-Ki 1215 octets
ATTRIBUTE EAP-Sim-Algo-Version 1216 integer
+ATTRIBUTE Outer-Realm-Name 1218 string
+ATTRIBUTE Inner-Realm-Name 1219 string
+
#
# Range: 1280 - 1535
# EAP-type specific attributes
# 1934 - 1939: reserved for future cert attributes
+# 1940 - 1949: reserved for TLS session caching, mostly in 3.1
+
+# Set by EAP-TLS code
+ATTRIBUTE TLS-OCSP-Cert-Valid 1943 integer
+VALUE TLS-OCSP-Cert-Valid unknown 3
+VALUE TLS-OCSP-Cert-Valid skipped 2
+VALUE TLS-OCSP-Cert-Valid yes 1
+VALUE TLS-OCSP-Cert-Valid no 0
+
#
# Range: 1940-2099
# Free
#
VALUE Auth-Type Local 1
-VALUE Auth-Type System 2
-VALUE Auth-Type SecurID 3
VALUE Auth-Type Reject 4
-VALUE Auth-Type ActivCard 5
-VALUE Auth-Type EAP 6
#
# FreeRADIUS extensions (most originally from Cistron)
#
VALUE Auth-Type Accept 254
-VALUE Auth-Type PAP 1024
-VALUE Auth-Type CHAP 1025
-# 1026 was LDAP, but we deleted it. Adding it back will break the
-# ldap module.
-VALUE Auth-Type PAM 1027
-VALUE Auth-Type MS-CHAP 1028
-VALUE Auth-Type MSCHAP 1028
-VALUE Auth-Type Kerberos 1029
-VALUE Auth-Type CRAM 1030
-VALUE Auth-Type NS-MTA-MD5 1031
-# 1032 is unused (was a duplicate of CRAM)
-VALUE Auth-Type SMB 1033
-VALUE Auth-Type MS-CHAP-V2 1034
-
#
# Authorization type, too.
#
VALUE EAP-Type AKA2 50
VALUE EAP-Type GPSK 51
VALUE EAP-Type PWD 52
-VALUE EAP-Type EVEv1 53
+VALUE EAP-Type EKEv1 53
#
# And this is what most people mean by MS-CHAPv2
--- /dev/null
+# -*- text -*-
+# Copyright (C) 2015 The FreeRADIUS Server project and contributors
+##############################################################################
+#
+# From yqsi@hillstonenet.com 2015/11/2
+#
+# $Id$
+#
+##############################################################################
+
+VENDOR Hillstone 28557
+
+BEGIN-VENDOR Hillstone
+
+ATTRIBUTE Hillstone-User-vsys-id 1 integer
+ATTRIBUTE Hillstone-User-Type 2 integer
+ATTRIBUTE Hillstone-User-Admin-Privilege 3 integer
+ATTRIBUTE Hillstone-User-Login-Type 4 integer
+ATTRIBUTE Hillstone-User-Mobile-Number 5 string
+ATTRIBUTE Hillstone-User-Mobile-Operator 6 integer
+ATTRIBUTE Hillstone-User-Policy-dst-ip-begin 7 ipaddr
+ATTRIBUTE Hillstone-User-Policy-dst-ip-end 8 ipaddr
+ATTRIBUTE Hillstone-User-Role-Bame 9 string
+ATTRIBUTE Hillstone-VPN-DHCP-Gateway 100 string
+ATTRIBUTE Hillstone-VPN-DHCP-Mask 101 string
+ATTRIBUTE Hillstone-VPN-DHCP-Pool 102 string
+ATTRIBUTE Hillstone-VPN-WINS 103 string
+ATTRIBUTE Hillstone-VPN-DNS 104 string
+ATTRIBUTE Hillstone-VPN-Split-Route 105 string
+ATTRIBUTE Hillstone-VPN-Tunnel-IP 106 string
+ATTRIBUTE Hillstone-VPN-SNAT 107 integer
+
+VALUE Hillstone-User-Type HS-User-l2tp 1
+VALUE Hillstone-User-Type HS-User-8021x 2
+VALUE Hillstone-User-Type HS-User-smartvpn 4
+VALUE Hillstone-User-Type HS-User-normal 8
+VALUE Hillstone-User-Type HS-User-Admin 16
+
+VALUE Hillstone-User-Login-Type HS-Admin-Console 1
+VALUE Hillstone-User-Login-Type HS-Admin-Telnet 2
+VALUE Hillstone-User-Login-Type HS-Admin-SSH 4
+VALUE Hillstone-User-Login-Type HS-Admin-HTTP 8
+VALUE Hillstone-User-Login-Type HS-Admin-HTTPS 16
+
+VALUE Hillstone-User-Mobile-Operator HS-Mobile-ChinaMobile 1
+VALUE Hillstone-User-Mobile-Operator HS-Mobile-ChinaUnicom 2
+VALUE Hillstone-User-Mobile-Operator HS-Mobile-ChinaTelecom 3
+
+END-VENDOR Hillstone
ATTRIBUTE HP-Port-Client-Limit-MA 11 integer
ATTRIBUTE HP-Port-Client-Limit-WA 12 integer
ATTRIBUTE HP-Port-Auth-Mode-Dot1x 13 integer
+ATTRIBUTE HP-Port-Bounce-Host 23 integer
+ATTRIBUTE HP-Captive-Portal-URL 24 string
# Client QoS attributes
ATTRIBUTE HP-Port-Priority-Regeneration-Table 40 string
ATTRIBUTE Huawei-NAT-Port-Range-Update 165 integer
ATTRIBUTE Huawei-DS-Lite-Tunnel-Name 166 string
ATTRIBUTE Huawei-PCP-Server-Name 167 string # manual says text?
-ATTRIBUTE Huawei-Public-IP-Addr-State 168 Integer
+ATTRIBUTE Huawei-Public-IP-Addr-State 168 integer
VALUE Huawei-Public-IP-Addr-State Safe 0
VALUE Huawei-Public-IP-Addr-State Warning 1
ATTRIBUTE Huawei-IPv6-Prefix-Lease 192 octets
ATTRIBUTE Huawei-IPv6-Address-Lease 193 octets
ATTRIBUTE Huawei-IPv6-Policy-Route 194 ipv6prefix # manual says string?
-ATTRIBUTE Huawei-MNG-IPv6 196 Integer
+ATTRIBUTE Huawei-MNG-IPv6 196 integer
VALUE Huawei-MNG-IPv6 Unsupported 0
VALUE Huawei-MNG-IPv6 Supported 1
ATTRIBUTE LCS-PbSpotUserName 7 string
ATTRIBUTE LCS-TxRateLimit 8 integer
ATTRIBUTE LCS-RxRateLimit 9 integer
+ATTRIBUTE LCS-Access-Rights 11 integer
+ATTRIBUTE LCS-Function-Rights 12 integer
+ATTRIBUTE LCS-Advertisement-URL 13 string
+ATTRIBUTE LCS-Advertisement-Interval 14 integer
+ATTRIBUTE LCS-Traffic-Limit-Gigawords 15 integer
+ATTRIBUTE LCS-Orig-NAS-Identifier 16 string
+ATTRIBUTE LCS-Orig-NAS-IP-Address 17 ipaddr
+ATTRIBUTE LCS-Orig-NAS-IPv6-Address 18 ipv6addr
+ATTRIBUTE LCS-IKEv2-Local-Password 19 string has_tag,encrypt=2
+ATTRIBUTE LCS-IKEv2-Remote-Password 20 string has_tag,encrypt=2
+ATTRIBUTE LCS-DNS-Server-IPv4-Address 21 ipaddr
+ATTRIBUTE LCS-VPN-IPv4-Rule 22 string
+ATTRIBUTE LCS-VPN-IPv6-Rule 23 string
+ATTRIBUTE LCS-Routing-Tag 24 integer
+ATTRIBUTE LCS-IKEv2-IPv4-Route 25 string
+ATTRIBUTE LCS-IKEv2-IPv6-Route 26 string
END-VENDOR Lancom
--- /dev/null
+# dictionary.lantronix
+#
+# Lantronix SLC Secure Lantronix Console Manager
+# Provides SLC-specific user attributes
+#
+VENDOR Lantronix 244
+
+BEGIN-VENDOR Lantronix
+
+ATTRIBUTE Lantronix-User-Attributes 1 string
+
+END-VENDOR Lantronix
--- /dev/null
+# -*- text -*-
+# Copyright (C) 2015 The FreeRADIUS Server project and contributors
+#
+# For Meraki.
+#
+
+VENDOR Meraki 29671
+BEGIN-VENDOR Meraki
+
+ATTRIBUTE Meraki-Device-Name 1 string
+
+END-VENDOR Meraki
# Copyright (C) 2015 The FreeRADIUS Server project and contributors
#
# Attributes and values defined in RFC 4072
-# http://www.ietf.org/rfc/4072.txt
+# http://www.ietf.org/rfc/rfc4072.txt
#
# $Id$
#
# Copyright (C) 2015 The FreeRADIUS Server project and contributors
#
# Attributes and values defined in RFC 4372.
-# http://www.ietf.org/rfc/4372.txt
+# http://www.ietf.org/rfc/rfc4372.txt
#
# $Id$
#
# Copyright (C) 2015 The FreeRADIUS Server project and contributors
#
# Attributes and values defined in RFC 4675.
-# http://www.ietf.org/rfc/4675.txt
+# http://www.ietf.org/rfc/rfc4675.txt
#
# $Id$
#
# Copyright (C) 2015 The FreeRADIUS Server project and contributors
#
# Attributes and values defined in RFC 4679.
-# http://www.ietf.org/rfc/4679.txt
+# http://www.ietf.org/rfc/rfc4679.txt
#
# $Id$
#
#
#
-VENDOR Ruckus 25053
+VENDOR Ruckus 25053
-BEGIN-VENDOR Ruckus
+BEGIN-VENDOR Ruckus
-ATTRIBUTE Ruckus-User-Groups 1 string
-# Value Format: group_attr1,group_attr2,...
+# Value Format: group_attr1,group_attr2,...
+ATTRIBUTE Ruckus-User-Groups 1 string
+ATTRIBUTE Ruckus-Sta-RSSI 2 integer
+ATTRIBUTE Ruckus-SSID 3 string
+ATTRIBUTE Ruckus-Wlan-Id 4 integer
+ATTRIBUTE Ruckus-Location 5 string
+ATTRIBUTE Ruckus-Grace-Period 6 integer
+ATTRIBUTE Ruckus-SCG-CBlade-IP 7 integer
+ATTRIBUTE Ruckus-SCG-DBlade-IP 8 integer
+ATTRIBUTE Ruckus-VLAN-ID 9 integer
+ATTRIBUTE Ruckus-Sta-Expiration 10 integer # not used by AP anymore. Please check SCG-33602
+ATTRIBUTE Ruckus-Sta-UUID 11 string
+ATTRIBUTE Ruckus-Accept-Enhancement-Reason 12 integer
+ATTRIBUTE Ruckus-Sta-Inner-Id 13 string
+ATTRIBUTE Ruckus-BSSID 14 octets
-ATTRIBUTE Ruckus-Sta-RSSI 2 integer
-ATTRIBUTE Ruckus-SSID 3 string
-ATTRIBUTE Ruckus-WlanID 4 integer
-ATTRIBUTE Ruckus-Location 5 string
-ATTRIBUTE Ruckus-Grace-Period 6 integer
-# Sent to the server, range: 1 to 14400 [minutes]
+ATTRIBUTE Ruckus-WSG-User 10 string
-ATTRIBUTE Ruckus-SCG-CBlade-IP 7 integer
-ATTRIBUTE Ruckus-SCG-DBlade-IP 8 integer
-ATTRIBUTE Ruckus-Session-Type 125 integer
-ATTRIBUTE Ruckus-Acct-Status 126 integer
+ATTRIBUTE Ruckus-Triplets 101 octets
+ATTRIBUTE Ruckus-IMSI 102 octets
+ATTRIBUTE Ruckus-MSISDN 103 octets
+ATTRIBUTE Ruckus-APN-NI 104 string
+ATTRIBUTE Ruckus-QoS 105 octets
+ATTRIBUTE Ruckus-Selection-Mode 106 integer
+ATTRIBUTE Ruckus-APN-Resolution-Req 107 integer
+ATTRIBUTE Ruckus-Start-Time 108 octets
+ATTRIBUTE Ruckus-NAS-Type 109 integer
+ATTRIBUTE Ruckus-Status 110 integer
+ATTRIBUTE Ruckus-APN-OI 111 string
+ATTRIBUTE Ruckus-Auth-Type 112 integer
+ATTRIBUTE Ruckus-Gn-User-Name 113 string
+ATTRIBUTE Ruckus-Brand-Code 114 string
+ATTRIBUTE Ruckus-Policy-Name 115 string
+ATTRIBUTE Ruckus-Client-Local-IP 116 ipaddr
+ATTRIBUTE Ruckus-SGSN-IP 117 ipaddr
+ATTRIBUTE Ruckus-Charging-Charac 118 octets
+ATTRIBUTE Ruckus-PDP-Type 119 octets
+ATTRIBUTE Ruckus-Dynamic-Address-Flag 120 octets
+ATTRIBUTE Ruckus-ChCh-Selection-Mode 121 octets
+ATTRIBUTE Ruckus-AAA-IP 122 ipaddr
+ATTRIBUTE Ruckus-CDR-TYPE 123 integer
+ATTRIBUTE Ruckus-SGSN-Number 124 octets
+ATTRIBUTE Ruckus-Session-Type 125 integer
+ATTRIBUTE Ruckus-Accounting-Status 126 integer
+ATTRIBUTE Ruckus-Zone-Id 127 string
+ATTRIBUTE Ruckus-Auth-Server-Id 128 string
+ATTRIBUTE Ruckus-Utp-Id 129 string
+ATTRIBUTE Ruckus-Area-Code 130 octets
+ATTRIBUTE Ruckus-Cell-Identifier 131 octets
+ATTRIBUTE Ruckus-Wispr-Redirect-Policy 132 string
+ATTRIBUTE Ruckus-Eth-Profile-Id 133 integer
+ATTRIBUTE Ruckus-Zone-Name 134 string
+ATTRIBUTE Ruckus-Wlan-Name 135 string
-END-VENDOR Ruckus
+#
+# Integer Translations
+#
+
+# Ruckus-Selection-Mode Values
+
+VALUE Ruckus-Selection-Mode Subscribed 0
+VALUE Ruckus-Selection-Mode SentByMS 1
+VALUE Ruckus-Selection-Mode ChosenBySGSN 2
+
+# Ruckus-APN-Resolution-Req Values
+
+VALUE Ruckus-APN-Resolution-Req NotRequired 0
+VALUE Ruckus-APN-Resolution-Req Required 1
+
+# Ruckus-Status Values
+
+VALUE Ruckus-Status Success 0
+VALUE Ruckus-Status Failure 1
+
+# Ruckus-Auth-Type Values
+
+VALUE Ruckus-Auth-Type PPP-SIM 1
+VALUE Ruckus-Auth-Type DummyIMSI 2
+VALUE Ruckus-Auth-Type SoftSIM 3
+VALUE Ruckus-Auth-Type RadiusSIM 4
+VALUE Ruckus-Auth-Type Postpaid 5
+VALUE Ruckus-Auth-Type Prepaid 6
+VALUE Ruckus-Auth-Type LocalRadius 7
+VALUE Ruckus-Auth-Type ProxyRadius 8
+VALUE Ruckus-Auth-Type Voucher 9
+VALUE Ruckus-Auth-Type EAP-SIM 10
+
+# Ruckus-Session-Type Values
+# Updated as per SCG2.1
+#Value (1) No more valid for SCG2.1
+VALUE Ruckus-Session-Type TTG 2
+VALUE Ruckus-Session-Type Local-Breakout 3
+VALUE Ruckus-Session-Type Local-Breakout-AP 4
+VALUE Ruckus-Session-Type L3GRE 5
+VALUE Ruckus-Session-Type L2GRE 6
+VALUE Ruckus-Session-Type QinQL3 7
+VALUE Ruckus-Session-Type PMIP 8
+
+
+#RUCKUS-NAS_Type
+
+VALUE Ruckus-NAS-Type SCG 1
+VALUE Ruckus-NAS-Type Others 2
+
+#Ruckus-Accounting-Status
+VALUE Ruckus-Accounting-Status Accounting-On 1
+VALUE Ruckus-Accounting-Status Accounting-Off 0
+
+END-VENDOR Ruckus
--- /dev/null
+# -*- text -*-
+#
+# dictionary.sangoma
+#
+# jma@sangoma.com
+#
+# Version: $Id: dictionary.sangoma
+#
+
+VENDOR NetBorder 35987
+
+#
+# Standard attribute
+#
+BEGIN-VENDOR NetBorder
+
+ATTRIBUTE NetBorder-AVPair 1 string
+ATTRIBUTE NetBorder-CLID 2 string
+ATTRIBUTE NetBorder-Dialplan 3 string
+ATTRIBUTE NetBorder-Src 4 string
+ATTRIBUTE NetBorder-Dst 5 string
+ATTRIBUTE NetBorder-Src-Channel 6 string
+ATTRIBUTE NetBorder-Dst-Channel 7 string
+ATTRIBUTE NetBorder-Ani 8 string
+ATTRIBUTE NetBorder-Aniii 9 string
+ATTRIBUTE NetBorder-Lastapp 10 string
+ATTRIBUTE NetBorder-Lastdata 11 string
+ATTRIBUTE NetBorder-Disposition 12 string
+ATTRIBUTE NetBorder-Hangupcause 13 integer
+ATTRIBUTE NetBorder-Billusec 15 integer
+ATTRIBUTE NetBorder-AMAFlags 16 integer
+ATTRIBUTE NetBorder-RDNIS 17 string
+ATTRIBUTE NetBorder-Context 18 string
+ATTRIBUTE NetBorder-Source 19 string
+ATTRIBUTE NetBorder-Callstartdate 20 string
+ATTRIBUTE NetBorder-Callanswerdate 21 string
+ATTRIBUTE NetBorder-Calltransferdate 22 string
+ATTRIBUTE NetBorder-Callenddate 23 string
+ATTRIBUTE NetBorder-Signalbond 24 string
+
+#
+# NetBorder-Hangupcause
+#
+VALUE NetBorder-Hangupcause None 0
+VALUE NetBorder-Hangupcause Unallocated-Number 1
+VALUE NetBorder-Hangupcause No-Route-Transit-Net 2
+VALUE NetBorder-Hangupcause No-Route-Destination 3
+VALUE NetBorder-Hangupcause Channel-Unacceptable 6
+VALUE NetBorder-Hangupcause Call-Awarded-Delivery 7
+VALUE NetBorder-Hangupcause Normal-Clearing 16
+VALUE NetBorder-Hangupcause User-Busy 17
+VALUE NetBorder-Hangupcause No-User-Response 18
+VALUE NetBorder-Hangupcause No-Answer 19
+VALUE NetBorder-Hangupcause Subscriber-Absent 20
+VALUE NetBorder-Hangupcause Call-Rejected 21
+VALUE NetBorder-Hangupcause Number-Changed 22
+VALUE NetBorder-Hangupcause Redirecto-To-New-Destination 23
+VALUE NetBorder-Hangupcause Exchange-Routing-Error 25
+VALUE NetBorder-Hangupcause Destination-Out-Of-Order 27
+VALUE NetBorder-Hangupcause Invalid-Number-Format 28
+VALUE NetBorder-Hangupcause Facility-Rejected 29
+VALUE NetBorder-Hangupcause Response-To-Status-Enquiry 30
+VALUE NetBorder-Hangupcause Normal-Unspecified 31
+VALUE NetBorder-Hangupcause Normal-Circuit-Congestion 34
+VALUE NetBorder-Hangupcause Network-Out-Of-Order 38
+VALUE NetBorder-Hangupcause Normal-Temporary-Failure 41
+VALUE NetBorder-Hangupcause Switch-Congestion 42
+VALUE NetBorder-Hangupcause Access-Info-Discarded 43
+VALUE NetBorder-Hangupcause Requested-Chan-Unavail 44
+VALUE NetBorder-Hangupcause Pre-Empted 45
+VALUE NetBorder-Hangupcause Facility-Not-Subscribed 50
+VALUE NetBorder-Hangupcause Outgoing-Call-Barred 52
+VALUE NetBorder-Hangupcause Incoming-Call-Barred 54
+VALUE NetBorder-Hangupcause Bearercapability-Notauth 57
+VALUE NetBorder-Hangupcause Bearercapability-Notavail 58
+VALUE NetBorder-Hangupcause Service-Unavailable 63
+VALUE NetBorder-Hangupcause Bearercapability-Notimpl 65
+VALUE NetBorder-Hangupcause Chan-Not-Implemented 66
+VALUE NetBorder-Hangupcause Facility-Not-Implemented 69
+VALUE NetBorder-Hangupcause Service-Not-Implemented 79
+VALUE NetBorder-Hangupcause Invalid-Call-Reference 81
+VALUE NetBorder-Hangupcause Incompatible-Destination 88
+VALUE NetBorder-Hangupcause Invalid-Msg-Unspecified 95
+VALUE NetBorder-Hangupcause Mandatory-IE-Missing 96
+VALUE NetBorder-Hangupcause Message-Type-Nonexist 97
+VALUE NetBorder-Hangupcause Wrong-Message 98
+VALUE NetBorder-Hangupcause IE-Nonexist 99
+VALUE NetBorder-Hangupcause Invalid-IE-Contents 100
+VALUE NetBorder-Hangupcause Wrong-Call-State 101
+VALUE NetBorder-Hangupcause Recovery-On-Timer-Expire 102
+VALUE NetBorder-Hangupcause Mandatory-IE-Length-Error 103
+VALUE NetBorder-Hangupcause Protocol-Error 111
+VALUE NetBorder-Hangupcause Interworking 127
+VALUE NetBorder-Hangupcause Success 142
+VALUE NetBorder-Hangupcause Originator-Cancel 487
+VALUE NetBorder-Hangupcause Crash 500
+VALUE NetBorder-Hangupcause System-Shutdown 501
+VALUE NetBorder-Hangupcause Lose-Race 502
+VALUE NetBorder-Hangupcause Manager-Request 503
+VALUE NetBorder-Hangupcause Blind-Transfer 600
+VALUE NetBorder-Hangupcause Attended-Transfer 601
+VALUE NetBorder-Hangupcause Allotted-Timeout 602
+VALUE NetBorder-Hangupcause User-Challenge 603
+VALUE NetBorder-Hangupcause Media-Timeout 604
+VALUE NetBorder-Hangupcause Picked-Off 605
+VALUE NetBorder-Hangupcause User-Not-Registered 606
+
+#
+#
+#
+
+END-VENDOR NetBorder
ATTRIBUTE SN-Transparent-Data 247 octets
ATTRIBUTE SN-MS-ISDN 248 octets
ATTRIBUTE SN-Routing-Area-Id 249 string
-#ATTRIBUTE SN-Rulebase 249 string
+ATTRIBUTE SN-Rulebase 250 string
ATTRIBUTE SN-Call-Id 251 integer
ATTRIBUTE SN-IMSI 252 octets
ATTRIBUTE SN-Long-Duration-Notification 253 integer
ATTRIBUTE SN-QOS-HLR-Profile 303 octets
ATTRIBUTE SN-Fast-Reauth-Username 304 octets
ATTRIBUTE SN-Pseudonym-Username 305 octets
-ATTRIBUTE SN-WiMAX-Auth-Only 206 integer
+ATTRIBUTE SN-WiMAX-Auth-Only 306 integer
ATTRIBUTE SN-TrafficSelector-Class 307 integer
ATTRIBUTE SN-DHCP-Options 309 octets
ATTRIBUTE SN-Handoff-Indicator 310 integer
ATTRIBUTE Wichorus-Policy-Name 1 string
ATTRIBUTE Wichorus-User-Privilege 2 string
+#
+# Some versions of the Wichorus equipment use the following attribute.
+# instead of Wichorus-User-Privilege. This is considered to be
+# bad practice.
+#
+
+#ATTRIBUTE Wichorus-Host-IP 2 ipaddr
+
END-VENDOR Wichorus
# add this dependency BEFORE including the other submakefiles.
all:
-#
-# This nonsense is here because pattern rules don't work if you have
-# multiple of them. If you try to run the shell script by assigning
-# it to a variable, GNU Make notices that the variable isn't used...
-# and doesn't run the shell script. This crap below seems to bypass
-# Make's optimization.
-#
-ifeq "$(shell [ -e src/freeradius-devel ] || ln -s include src/freeradius-devel)" ""
-# do nothing
-endif
-
SUBMAKEFILES := include/all.mk lib/all.mk modules/all.mk main/all.mk tests/all.mk
features.h
radpaths.h
vqp.h
+freeradius.h
+
+# Headers from v3.1.x
+freeradius.snmp.h
# Build scripts
build-radpaths-h
# Version: $Id$
#
+#
+# Build dynamic headers by substituting various values from autoconf.h, these
+# get installed with the library files, so external programs can tell what
+# the server library was built with.
+#
+# The RFC headers are dynamic, too.
+#
+# The rest of the headers are static.
+#
+
+HEADERS_DY = attributes.h features.h missing.h radpaths.h tls.h
+
HEADERS = \
- attributes.h \
build.h \
conf.h \
conffile.h \
detail.h \
event.h \
- features.h \
hash.h \
heap.h \
libradius.h \
md4.h \
md5.h \
- missing.h \
modcall.h \
modules.h \
packet.h \
rad_assert.h \
radius.h \
radiusd.h \
- radpaths.h \
radutmp.h \
realms.h \
sha1.h \
token.h \
udpfromto.h \
base64.h \
- map.h
-
-#
-# Build dynamic headers by substituting various values from autoconf.h, these
-# get installed with the library files, so external programs can tell what
-# the server library was built with.
-#
-
-HEADERS_DY = src/include/features.h src/include/missing.h src/include/tls.h \
- src/include/radpaths.h src/include/attributes.h
+ map.h \
+ $(HEADERS_DY)
#
# Solaris awk doesn't recognise [[:blank:]] hence [\t ]
# Create the header files from the dictionaries.
#
-RFC_DICTS := $(filter-out %~,$(wildcard share/dictionary.rfc*))
-RFC_HEADERS := $(patsubst share/dictionary.%,src/include/%.h,$(RFC_DICTS))
+RFC_DICTS := $(filter-out %~,$(wildcard share/dictionary.rfc*)) share/dictionary.vqp share/dictionary.freeradius
+HEADERS_RFC := $(patsubst share/dictionary.%,src/include/%.h,$(RFC_DICTS))
+HEADERS += $(notdir ${HEADERS_RFC})
+
+.PRECIOUS: $(HEADERS_RFC)
src/include/attributes.h: share/dictionary.freeradius.internal
@$(ECHO) HEADER $@
- @grep ^ATTRIBUTE $< | awk '{print "PW_"$$2 " " $$3 " //!< AUTOGENERATED ATTRIBUTE DEFINITION"}' | tr '[:lower:]' '[:upper:]' | tr -- - _ | sed 's/^/#define /' > $@
+ @echo "/* AUTO-GENERATED HEADER FILE. DO NOT EDIT. */" > $@
+ @grep ^ATTRIBUTE $< | awk '{print "PW_"$$2 " " $$3 }' | tr '[:lower:]' '[:upper:]' | tr -- - _ | sed 's/^/#define /' >> $@
@echo " " >> $@
- @grep -- 'Auth-Type' $< | grep ^VALUE | awk '{print "PW_"$$2 "_" $$3 " " $$4 " //!< AUTOGENERATED VALUE DEFINITION"}' | tr '[:lower:]' '[:upper:]' | tr -- - _ | sed 's/^/#define /' >> $@
+ @grep -- 'Auth-Type' $< | grep ^VALUE | awk '{print "PW_"$$2 "_" $$3 " " $$4 }' | tr '[:lower:]' '[:upper:]' | tr -- - _ | sed 's/^/#define /' >> $@
src/include/%.h: share/dictionary.% share/dictionary.vqp
@$(ECHO) HEADER $@
- @grep ^ATTRIBUTE $< | awk '{print "PW_"$$2 " " $$3 " //!< AUTOGENERATED ATTRIBUTE DEFINITION"}' | tr '[:lower:]' '[:upper:]' | tr -- - _ | sed 's/^/#define /' > $@
-
-src/include/radius.h: | src/include/attributes.h $(RFC_HEADERS) src/include/vqp.h
-
-#
-# So the headers are created before we compile anything
-#
-$(JLIBTOOL): src/include/radius.h
-
-src/freeradius-devel/features.h: src/include/features.h src/freeradius-devel
+ @echo "/* AUTO-GENERATED HEADER FILE. DO NOT EDIT. */" > $@
+ @grep ^ATTRIBUTE $< | awk '{print "PW_"$$2 " " $$3 } ' | tr '[:lower:]' '[:upper:]' | tr -- - _ | sed 's/^/#define /' >> $@
#
# Build features.h by copying over WITH_* and RADIUSD_VERSION_*
@grep "^#define[ ]*WITH_" src/include/autoconf.h >> $@
@grep "^#define[ ]*RADIUSD_VERSION" src/include/autoconf.h >> $@
-src/freeradius-devel/missing.h: src/include/missing.h src/freeradius-devel
-
#
# Use the SED script we built earlier to make permanent substitutions
# of definitions in missing-h to build missing.h
@$(ECHO) HEADER $@
@sed -f src/include/autoconf.sed < $< > $@
-src/freeradius-devel/tls.h: src/include/tls.h src/freeradius-devel
-
src/include/tls.h: src/include/tls-h src/include/autoconf.sed
@$(ECHO) HEADER $@
@sed -f src/include/autoconf.sed < $< > $@
-src/freeradius-devel/radpaths.h: src/include/radpaths.h src/freeradius-devel
-
src/include/radpaths.h: src/include/build-radpaths-h
@$(ECHO) HEADER $@
@cd src/include && /bin/sh build-radpaths-h
-${BUILD_DIR}/make/jlibtool: $(HEADERS_DY)
+#
+# Create the soft link for the fake include file path.
+#
+src/freeradius-devel:
+ @[ -e $@ ] || ln -s include $@
+
+#
+# Ensure we set up the build environment
+#
+BOOTSTRAP_BUILD += src/freeradius-devel $(addprefix src/include/,$(HEADERS_DY)) $(HEADERS_RFC)
+scan: $(BOOTSTRAP_BUILD)
######################################################################
#
# if there's a trailing slash, tries to create a directory
# it already created, and fails...
#
-${SRC_INCLUDE_DIR}/%.h: ${top_srcdir}/src/include/%.h | $(SRC_INCLUDE_DIR)
+${SRC_INCLUDE_DIR}/%.h: src/include/%.h | $(SRC_INCLUDE_DIR)
@echo INSTALL $(notdir $<)
@$(INSTALL) -d -m 755 `echo $(dir $@) | sed 's/\/$$//'`
- @sed 's/^#include <freeradius-devel/#include <freeradius/' < $< > $@
+# Expression must deal with indentation after the hash and copy it to the substitution string.
+# Hash not anchored to allow substitution in function documentation.
+ @sed -e 's/#\([\\t ]*\)include <freeradius-devel\/\([^>]*\)>/#\1include <freeradius\/\2>/g' < $< > $@
@chmod 644 $@
install.src.include: $(addprefix ${SRC_INCLUDE_DIR}/,${HEADERS})
#
.PHONY: clean.src.include distclean.src.include
clean.src.include:
- @rm -f $(HEADERS_DY)
+ @rm -f $(addprefix src/include/,$(HEADERS_DY)) $(HEADERS_RFC)
clean: clean.src.include
/* Define to 1 if you have the <sys/capability.h> header file. */
#undef HAVE_CAPABILITY_H
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
/* Define to 1 if you have the `closefrom' function. */
#undef HAVE_CLOSEFROM
/* Define to 1 if you have the <fnmatch.h> header file. */
#undef HAVE_FNMATCH_H
+/* Define to 1 if you have the `fopencookie' function. */
+#undef HAVE_FOPENCOOKIE
+
+/* Define to 1 if you have the `funopen' function. */
+#undef HAVE_FUNOPEN
+
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
/* Define if the function (or macro) htonlll exists. */
#undef HAVE_HTONLLL
+/* Define to 1 if you have the `if_indextoname' function. */
+#undef HAVE_IF_INDEXTONAME
+
/* define if you have IN6_PKTINFO (Linux) */
#undef HAVE_IN6_PKTINFO
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
+/* Define to 1 if you have the `SSL_get_client_random' function. */
+#undef HAVE_SSL_GET_CLIENT_RANDOM
+
/* Define to 1 if you have the <stdbool.h> header file. */
#undef HAVE_STDBOOL_H
/* Define to 1 if you have the <utmp.h> header file. */
#undef HAVE_UTMP_H
+/* Define to 1 if you have the `vdprintf' function. */
+#undef HAVE_VDPRINTF
+
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
#ifdef __cplusplus
extern "C" {
#endif
-#include <freeradius-devel/autoconf.h> /* Needed for endian macros */
+#include <freeradius-devel/autoconf.h> /* Needed for endian macros */
/*
* The ubiquitous stringify macros
#define PW_TYPE_MULTI (1 << 18) //!< CONF_PAIR can have multiple copies.
#define PW_TYPE_NOT_EMPTY (1 << 19) //!< CONF_PAIR is required to have a non zero length value.
+#define PW_TYPE_FILE_EXISTS ((1 << 20) | PW_TYPE_STRING) //!< File matching value must exist
/* @} **/
#define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
extern const size_t dict_attr_sizes[PW_TYPE_MAX][2];
extern const int fr_attr_max_tlv;
extern const int fr_attr_shift[];
-extern const int fr_attr_mask[];
+extern const unsigned int fr_attr_mask[];
/** dictionary attribute
*
PW_TYPE type);
DICT_ATTR const *dict_attrbyparent(DICT_ATTR const *parent, unsigned int attr,
unsigned int vendor);
+DICT_ATTR const *dict_parent(unsigned int attr, unsigned int vendor);
int dict_attr_child(DICT_ATTR const *parent,
unsigned int *pattr, unsigned int *pvendor);
DICT_VALUE *dict_valbyattr(unsigned int attr, unsigned int vendor, int val);
uint8_t const *vector);
#define FR_TUNNEL_PW_ENC_LENGTH(_x) (2 + 1 + _x + PAD(_x + 1, 16))
-int rad_tunnel_pwencode(char *encpw, size_t *len, char const *secret,
+ssize_t rad_tunnel_pwencode(char *encpw, size_t *len, char const *secret,
uint8_t const *vector);
-int rad_tunnel_pwdecode(uint8_t *encpw, size_t *len,
+ssize_t rad_tunnel_pwdecode(uint8_t *encpw, size_t *len,
char const *secret, uint8_t const *vector);
int rad_chap_encode(RADIUS_PACKET *packet, uint8_t *output,
int id, VALUE_PAIR *password);
extern char const *fr_packet_codes[FR_MAX_PACKET_CODE];
#define is_radius_code(_x) ((_x > 0) && (_x < FR_MAX_PACKET_CODE))
extern FILE *fr_log_fp;
-void rad_print_hex(RADIUS_PACKET *packet);
+void rad_print_hex(RADIUS_PACKET const *packet);
void fr_printf_log(char const *, ...) CC_HINT(format (printf, 1, 2));
/*
* Several handy miscellaneous functions.
*/
int fr_set_signal(int sig, sig_t func);
+int fr_unset_signal(int sig);
int fr_link_talloc_ctx_free(TALLOC_CTX *parent, TALLOC_CTX *child);
char const *fr_inet_ntop(int af, void const *src);
char const *ip_ntoa(char *, uint32_t);
struct tm *gmtime_r(time_t const *l_clock, struct tm *result);
#endif
+#ifndef HAVE_VDPRINTF
+int vdprintf (int fd, char const *format, va_list args);
+#endif
+
#ifndef HAVE_GETTIMEOFDAY
int gettimeofday (struct timeval *tv, void *tz);
#endif
void modcall_debug(modcallable *mc, int depth);
+int modcall_pass2_condition(fr_cond_t *c);
+
#ifdef __cplusplus
}
#endif
#define PW_RADIUS_TLS_PORT 2083
#define PW_COA_UDP_PORT 3799
+/*
+ * The RFC says 4096 octets max, and most packets are less than 256.
+ */
+#define MAX_PACKET_LEN 4096
+
#include <freeradius-devel/rfc2865.h>
#include <freeradius-devel/rfc2866.h>
#include <freeradius-devel/rfc2867.h>
*/
#include <freeradius-devel/attributes.h>
+#include <freeradius-devel/freeradius.h>
+
#include <freeradius-devel/vqp.h>
#define PW_DIGEST_RESPONSE 206
#define VENDORPEC_UKERNA 25622
/*
- * Vendor specific attributes
- */
-#define PW_FREERADIUS_PROXIED_TO 1
-
-/*
* Microsoft has vendor code 311.
*/
-#define PW_MSCHAP_RESPONSE 1
-#define PW_MSCHAP_ERROR 2
-#define PW_MSCHAP_CPW_1 3
-#define PW_MSCHAP_CPW_2 4
-#define PW_MSCHAP_NT_ENC_PW 6
-#define PW_MSCHAP_CHALLENGE 11
-#define PW_MSCHAP2_RESPONSE 25
-#define PW_MSCHAP2_SUCCESS 26
-#define PW_MSCHAP2_CPW 27
+#define PW_MSCHAP_RESPONSE 1
+#define PW_MSCHAP_ERROR 2
+#define PW_MSCHAP_CPW_1 3
+#define PW_MSCHAP_CPW_2 4
+#define PW_MSCHAP_NT_ENC_PW 6
+#define PW_MSCHAP_MPPE_ENCRYPTION_POLICY 7
+#define PW_MSCHAP_MPPE_ENCRYPTION_TYPES 8
+#define PW_MSCHAP_CHALLENGE 11
+#define PW_MSCHAP_MPPE_SEND_KEY 16
+#define PW_MSCHAP_MPPE_RECV_KEY 17
+#define PW_MSCHAP2_RESPONSE 25
+#define PW_MSCHAP2_SUCCESS 26
+#define PW_MSCHAP2_CPW 27
+#define PW_MS_QUARANTINE_SOH 55
/*
* JANET's code for transporting eap channel binding data over ttls
bool write_pid; //!< write the PID file
+ bool exiting; //!< are we exiting?
+
#ifdef ENABLE_OPENSSL_VERSION_CHECK
char const *allow_vulnerable_openssl; //!< The CVE number of the last security issue acknowledged.
VALUE_PAIR *config; //!< #VALUE_PAIR (s) used to set per request parameters
//!< for modules and the server core at runtime.
+
+ TALLOC_CTX *state_ctx; //!< for request->state
VALUE_PAIR *state; //!< #VALUE_PAIR (s) available over the lifetime of the authentication
//!< attempt. Useful where the attempt involves a sequence of
//!< many request/challenge packets, like OTP, and EAP.
#ifdef WITH_PROXY
bool in_proxy_hash;
- struct timeval proxy_retransmit;
-
uint32_t num_proxied_requests; //!< How many times this request was proxied.
//!< Retransmissions are driven by requests from the NAS.
uint32_t num_proxied_responses;
*
* We really shouldn't have this many.
*/
-extern char const *progname;
extern log_lvl_t rad_debug_lvl;
extern char const *radacct_dir;
extern char const *radlog_dir;
static pthread_key_t __fr_thread_local_key_##_n;\
static pthread_once_t __fr_thread_local_once_##_n = PTHREAD_ONCE_INIT;\
static pthread_destructor_t __fr_thread_local_destructor_##_n = NULL;\
-static inline void __fr_thread_local_key_init_##_n(void)\
+static void __fr_thread_local_destroy_##_n(UNUSED void *unused)\
{\
- (void) pthread_key_create(&__fr_thread_local_key_##_n, __fr_thread_local_destructor_##_n);\
+ __fr_thread_local_destructor_##_n(_n);\
}\
-static inline _t __fr_thread_local_init_##_n(pthread_destructor_t func)\
+static void __fr_thread_local_key_init_##_n(void)\
+{\
+ (void) pthread_key_create(&__fr_thread_local_key_##_n, __fr_thread_local_destroy_##_n);\
+}\
+static _t __fr_thread_local_init_##_n(pthread_destructor_t func)\
{\
__fr_thread_local_destructor_##_n = func;\
+ if (_n) return _n; \
(void) pthread_once(&__fr_thread_local_once_##_n, __fr_thread_local_key_init_##_n);\
+ (void) pthread_setspecific(__fr_thread_local_key_##_n, &(_n));\
return _n;\
}
# define fr_thread_local_init(_n, _f) __fr_thread_local_init_##_n(_f)
# define fr_thread_local_setup(_t, _n) \
static pthread_key_t __fr_thread_local_key_##_n;\
static pthread_once_t __fr_thread_local_once_##_n = PTHREAD_ONCE_INIT;\
-static pthread_destructor_t __fr_thread_local_destructor_##_n = NULL; \
-static inline void __fr_thread_local_key_init_##_n(void)\
-{\
- (void) pthread_key_create(&__fr_thread_local_key_##_n, __fr_thread_local_destructor_##_n);\
-}\
-static inline _t __fr_thread_local_init_##_n(pthread_destructor_t func)\
+static pthread_destructor_t __fr_thread_local_destructor_##_n = NULL;\
+static void __fr_thread_local_destroy_##_n(UNUSED void *unused)\
{\
- __fr_thread_local_destructor_##_n = func;\
- (void) pthread_once(&__fr_thread_local_once_##_n, __fr_thread_local_key_init_##_n);\
- return pthread_getspecific(__fr_thread_local_key_##_n);\
+ __fr_thread_local_destructor_##_n(_n);\
}\
-DIAG_OFF(unused-function)\
-static inline _t __fr_thread_local_get_##_n(void)\
+static void __fr_thread_local_key_init_##_n(void)\
{\
- return pthread_getspecific(__fr_thread_local_key_##_n);\
+ (void) pthread_key_create(&__fr_thread_local_key_##_n, __fr_thread_local_destroy_##_n);\
+ (void) pthread_setspecific(__fr_thread_local_key_##_n, &(_n));\
}\
-DIAG_ON(unused-function)\
-static inline int __fr_thread_local_set_##_n(_t val)\
+static _t __fr_thread_local_init_##_n(pthread_destructor_t func)\
{\
- return pthread_setspecific(__fr_thread_local_key_##_n, val);\
+ __fr_thread_local_destructor_##_n = func;\
+ if (_n) return _n; \
+ (void) pthread_once(&__fr_thread_local_once_##_n, __fr_thread_local_key_init_##_n);\
+ return _n;\
}
# define fr_thread_local_init(_n, _f) __fr_thread_local_init_##_n(_f)
# define fr_thread_local_set(_n, _v) __fr_thread_local_set_##_n(_v)
int version;
} tls_info_t;
+#if OPENSSL_VERSION_NUMBER < 0x10001000L
+#define ssl_session ssl->session
+#else
+#define ssl_session session
+#endif
+
/** Contains EAP-REQUEST specific data (ie FR_TLS_DATA(fragment), EAPTLS-ALERT, EAPTLS-REQUEST ...)
*
* The tls_session_t Structure gets stored as opaque in eap_handler_t
typedef struct _tls_session_t {
SSL_CTX *ctx;
SSL *ssl;
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ SSL_SESSION *session;
+#endif
tls_info_t info;
BIO *into_ssl;
#ifdef ENABLE_OPENSSL_VERSION_CHECK
int tls_global_version_check(char const *acknowledged);
#endif
+
+int tls_error_log(REQUEST *request, char const *msg, ...) CC_HINT(format (printf, 2, 3));
+int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char const *msg, ...)
+ CC_HINT(format (printf, 4, 5));
+
void tls_global_cleanup(void);
tls_session_t *tls_new_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, REQUEST *request, bool client_cert);
tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, int fd);
int tls_handshake_recv(REQUEST *, tls_session_t *ssn);
int tls_handshake_send(REQUEST *, tls_session_t *ssn);
void tls_session_information(tls_session_t *ssn);
+void tls_session_id(SSL_SESSION *ssn, char *buffer, size_t bufsize);
/*
* Low-level TLS stuff
char const *ca_file;
char const *dh_file;
char const *rsa_file;
- bool rsa_key;
- bool dh_key;
- uint32_t rsa_key_length;
- uint32_t dh_key_length;
uint32_t verify_depth;
bool file_type;
bool include_length;
+ bool auto_chain;
+ bool disable_single_dh_use;
bool disable_tlsv1;
bool disable_tlsv1_1;
bool disable_tlsv1_2;
/*
- * Always < 4096 (due to radius limit), 0 by default = 2048
+ * Always < 4096 (due to radius limit), 0 by default = 1024
*/
uint32_t fragment_size;
bool check_crl;
char session_context_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
time_t session_last_flushed;
+ bool verify_skip_if_ocsp_ok;
char const *verify_tmp_dir;
char const *verify_client_cert_cmd;
bool require_client_cert;
*(cursor->first) = vp->next;
cursor->current = vp->next;
cursor->next = vp->next ? vp->next->next : NULL;
+ before = NULL;
goto fixup;
}
vp->next = NULL; /* limit scope of fr_pair_list_free() */
/*
- * Fixup cursor->found if we removed the VP it was referring to
+ * Fixup cursor->found if we removed the VP it was referring to,
+ * and point to the previous one.
*/
- if (vp == cursor->found) cursor->found = cursor->current;
+ if (vp == cursor->found) cursor->found = before;
/*
* Fixup cursor->last if we removed the VP it was referring to
if (strlen(p) >= left) goto oob;
strlcpy(out, p, left);
- FR_FAULT_LOG("Calling: %s", cmd);
-
{
bool disable = false;
+ FR_FAULT_LOG("Calling: %s", cmd);
+
/*
* Here we temporarily enable the dumpable flag so if GBD or LLDB
* is called in the panic_action, they can pattach to the running
fr_exit_now(1);
}
}
+
+ FR_FAULT_LOG("Panic action exited with %i", code);
+
+ fr_exit_now(code);
}
- FR_FAULT_LOG("Panic action exited with %i", code);
finish:
- fr_exit_now(1);
+ /*
+ * (Re-)Raise the signal, so that if we're running under
+ * a debugger, the debugger can break when it receives
+ * the signal.
+ */
+ fr_unset_signal(sig); /* Make sure we don't get into a loop */
+
+ raise(sig);
+
+ fr_exit_now(1); /* Function marked as noreturn */
}
/** Callback executed on fatal talloc error
env = getenv("DEBUG");
if (!env || (strcmp(env, "no") == 0)) {
debug_state = DEBUG_STATE_NOT_ATTACHED;
- } else if (strcmp(env, "auto") == 0) {
+ } else if (!strcmp(env, "auto") || !strcmp(env, "yes")) {
/*
* Figure out if we were started under a debugger
*/
int const fr_attr_max_tlv = MAX_TLV_NEST;
int const fr_attr_shift[MAX_TLV_NEST + 1] = { 0, 8, 16, 24, 29 };
-int const fr_attr_mask[MAX_TLV_NEST + 1] = { 0xff, 0xff, 0xff, 0x1f, 0x07 };
+unsigned const fr_attr_mask[MAX_TLV_NEST + 1] = { 0xff, 0xff, 0xff, 0x1f, 0x07 };
/*
* attr & fr_attr_parent_mask[i] == Nth parent of attr
/*
- * Bamboo skewers under the fingernails in 5, 4, 3, 2, ...
+ * Find the parent of the attr/vendor.
*/
-static DICT_ATTR const *dict_parent(unsigned int attr, unsigned int vendor)
+DICT_ATTR const *dict_parent(unsigned int attr, unsigned int vendor)
{
int i;
unsigned int base_vendor;
/*
- * RFC attributes can't be of type "tlv".
+ * RFC attributes can't be of type "tlv", except for dictionary.rfc6930
*/
- if (!vendor) return NULL;
+ if (!vendor) {
+#ifdef PW_IPV6_6RD_CONFIGURATION
+ if (attr == PW_IPV6_6RD_CONFIGURATION) return NULL;
+
+ if (((attr & 0xff) == PW_IPV6_6RD_CONFIGURATION) &&
+ (attr >> 8) < 4) {
+ return dict_attrbyvalue(PW_IPV6_6RD_CONFIGURATION, 0);
+ }
+#endif
+ return NULL;
+ }
base_vendor = vendor & (FR_MAX_VENDOR - 1);
#ifdef WITH_DHCP
|| flags.array
#endif
- || (flags.encrypt != FLAG_ENCRYPT_NONE)) {
+ || ((flags.encrypt != FLAG_ENCRYPT_NONE) && (flags.encrypt != FLAG_ENCRYPT_TUNNEL_PASSWORD))) {
fr_strerror_printf("dict_addattr: The \"extended\" attributes MUST NOT have any flags set");
return -1;
}
*
* Remember, the packing format is weird.
*
+ * Vendor Attribute
+ * ------ ---------
* 00VID 000000AA normal VSA for vendor VID
* 00VID AABBCCDD normal VSAs with TLVs
* EE000 000000AA extended attr (241.1)
int tlv_depth)
{
char const *p;
- unsigned int value;
- DICT_ATTR const *da = NULL;
+ unsigned int attr;
+
+#ifdef WITH_DICT_OID_DEBUG
+ fprintf(stderr, "PARSING %s tlv_depth %d pvalue %08x pvendor %08x\n", ptr,
+ tlv_depth, *pvalue, *pvendor);
+#endif
if (tlv_depth > fr_attr_max_tlv) {
fr_strerror_printf("Too many sub-attributes");
}
/*
- * If *pvalue is set, check if the attribute exists.
- * Otherwise, check that the vendor exists.
+ * No vendor, try to do basic parsing.
*/
- if (*pvalue) {
- da = dict_attrbyvalue(*pvalue, *pvendor);
- if (!da) {
- fr_strerror_printf("Parent attribute is undefined");
+ if (!*pvendor && !*pvalue) {
+ /*
+ * Can't call us with a pre-parsed value and no vendor.
+ */
+ if (tlv_depth != 0) {
+ fr_strerror_printf("Invalid call with wrong TLV depth %d", tlv_depth);
return -1;
}
- if (!da->flags.has_tlv && !da->flags.extended) {
- fr_strerror_printf("Parent attribute %s cannot have sub-attributes",
- da->name);
+ p = strchr(ptr, '.');
+ if (!sscanf_i(ptr, &attr)) {
+ fr_strerror_printf("Invalid data '%s' in attribute identifier", ptr);
return -1;
}
- } else if ((*pvendor & (FR_MAX_VENDOR - 1)) != 0) {
- if (!dict_vendorbyvalue(*pvendor & (FR_MAX_VENDOR - 1))) {
- fr_strerror_printf("Unknown vendor %u",
- *pvendor & (FR_MAX_VENDOR - 1));
- return -1;
+ /*
+ * Normal attribute with no OID. Return it.
+ */
+ if (!p) {
+ *pvalue = attr;
+ goto done;
}
- }
-
- p = strchr(ptr, '.');
- /*
- * Look for 26.VID.x.y
- *
- * If we find it, re-write the parameters, and recurse.
- */
- if (!*pvendor && (tlv_depth == 0) && (*pvalue == PW_VENDOR_SPECIFIC)) {
- DICT_VENDOR const *dv;
+ /*
+ * We have an OID, look up the attribute to see what it is.
+ */
+ if (attr != PW_VENDOR_SPECIFIC) {
+ DICT_ATTR const *da;
- if (!p) {
- fr_strerror_printf("VSA needs to have sub-attribute");
- return -1;
- }
+ da = dict_attrbyvalue(attr, 0);
+ if (!da) {
+ *pvalue = attr;
+ goto done;
+ }
- if (!sscanf_i(ptr, pvendor)) {
- fr_strerror_printf("Invalid number in attribute");
- return -1;
- }
+ /*
+ * Standard attributes (including internal
+ * ones) can have TLVs, but only for some
+ * of them.
+ */
+ if (!da->flags.extended) {
+#ifdef PW_IPV6_6RD_CONFIGURATION
+ if (attr == PW_IPV6_6RD_CONFIGURATION) {
+ *pvalue = attr;
+ ptr = p + 1;
+ tlv_depth = 1;
+ goto keep_parsing;
+ }
+#endif
+ fr_strerror_printf("Standard attributes cannot use OIDs");
+ return -1;
+ }
- if (*pvendor >= FR_MAX_VENDOR) {
- fr_strerror_printf("Cannot handle vendor ID larger than 2^24");
+ *pvendor = attr * FR_MAX_VENDOR;
+ ptr = p + 1;
+ } /* and fall through to re-parsing the VSA */
+ /*
+ * Look for the attribute number.
+ */
+ if (!sscanf_i(ptr, &attr)) {
+ fr_strerror_printf("Invalid data '%s' in attribute identifier", ptr);
return -1;
}
- dv = dict_vendorbyvalue(*pvendor & (FR_MAX_VENDOR - 1));
- if (!dv) {
- fr_strerror_printf("Unknown vendor \"%u\" ",
- *pvendor & (FR_MAX_VENDOR - 1));
- return -1;
- }
+ p = strchr(ptr, '.');
/*
- * Start off with (attr=0, vendor=VID), and
- * recurse. This causes the various checks above
- * to be done.
+ * Handle VSAs. Either in the normal space, or in the extended space.
*/
- *pvalue = 0;
- return dict_str2oid(p + 1, pvalue, pvendor, 0);
- }
+ if (attr == PW_VENDOR_SPECIFIC) {
+ if (!p) {
+ *pvalue = attr;
+ goto done;
+ }
+ ptr = p + 1;
- if (!sscanf_i(ptr, &value)) {
- fr_strerror_printf("Invalid number in attribute");
- return -1;
- }
+ if (!sscanf_i(ptr, &attr)) {
+ fr_strerror_printf("Invalid data '%s' in vendor identifier", ptr);
+ return -1;
+ }
+
+ p = strchr(ptr, '.');
+ if (!p) {
+ fr_strerror_printf("Cannot define VENDOR in an ATTRIBUTE");
+ return -1;
+ }
+ ptr = p + 1;
+
+ *pvendor |= attr;
+ } else {
+ *pvalue = attr;
+ }
+ } /* fall through to processing an OID with pre-defined *pvendor and *pvalue */
+
+keep_parsing:
+#ifdef WITH_DICT_OID_DEBUG
+ fprintf(stderr, "KEEP PARSING %s tlv_depth %d pvalue %08x pvendor %08x\n", ptr,
+ tlv_depth, *pvalue, *pvendor);
+#endif
+
+ /*
+ * Check the vendor. Only RFC format attributes can have TLVs.
+ */
+ if (*pvendor) {
+ DICT_VENDOR const *dv = NULL;
- if (!*pvendor && (tlv_depth == 1) && da &&
- (da->flags.has_tlv || da->flags.extended)) {
+ dv = dict_vendorbyvalue(*pvendor);
+ if (dv && (dv->type != 1)) {
+ if (*pvalue || (tlv_depth != 0)) {
+ fr_strerror_printf("Attribute cannot have TLVs");
+ return -1;
+ }
+ if (!sscanf_i(ptr, &attr)) {
+ fr_strerror_printf("Invalid data '%s' in attribute identifier", ptr);
+ return -1;
+ }
- *pvendor = *pvalue * FR_MAX_VENDOR;
- *pvalue = value;
+ if ((dv->type < 3) && (attr > (unsigned int) (1 << (8 * dv->type)))) {
+ fr_strerror_printf("Number '%s' out of allowed range in attribute identifier", ptr);
+ return -1;
+ }
+
+ *pvalue = attr;
- if (!p) return 0;
- return dict_str2oid(p + 1, pvalue, pvendor, 1);
+#ifdef WITH_DHCP
+ /*
+ * DHCP attributes can have TLVs. <sigh>
+ */
+ if (*pvendor == 54) goto dhcp_skip;
+#endif
+ goto done;
+ }
}
/*
- * And pack the data according to the scheme described in
- * the comments at the start of this function.
+ * Parse the rest of the TLVs.
*/
- if (*pvalue) {
- *pvalue |= (value & fr_attr_mask[tlv_depth]) << fr_attr_shift[tlv_depth];
- } else {
- *pvalue = value;
- }
+ while (tlv_depth <= fr_attr_max_tlv) {
+#ifdef WITH_DICT_OID_DEBUG
+ fprintf(stderr, "TLV PARSING %s tlv_depth %d pvalue %08x pvendor %08x\n", ptr,
+ tlv_depth, *pvalue, *pvendor);
+#endif
- if (p) {
- return dict_str2oid(p + 1, pvalue, pvendor, tlv_depth + 1);
+ if (!sscanf_i(ptr, &attr)) {
+ fr_strerror_printf("Invalid data '%s' in attribute identifier", ptr);
+ return -1;
+ }
+
+ if (attr > fr_attr_mask[tlv_depth]) {
+ fr_strerror_printf("Number '%s' out of allowed range in attribute identifier", ptr);
+ return -1;
+ }
+
+ attr <<= fr_attr_shift[tlv_depth];
+
+#ifdef WITH_DICT_OID_DEBUG
+ if (*pvendor) {
+ DICT_ATTR const *da;
+
+ da = dict_parent(*pvalue | attr, *pvendor);
+ if (!da) {
+ fprintf(stderr, "STR2OID FAILED PARENT %08x | %08x, %08x\n",
+ *pvalue, attr, *pvendor);
+ } else if ((da->attr != *pvalue) || (da->vendor != *pvendor)) {
+ fprintf(stderr, "STR2OID DISAGREEMENT WITH PARENT %08x, %08x\t%08x, %08x\n",
+ *pvalue, *pvendor, da->attr, da->vendor);
+ }
+ }
+#endif
+
+ *pvalue |= attr;
+
+#ifdef WITH_DHCP
+ dhcp_skip:
+#endif
+ p = strchr(ptr, '.');
+ if (!p) break;
+
+ ptr = p + 1;
+ tlv_depth++;
}
- return tlv_depth;
+done:
+#ifdef WITH_DICT_OID_DEBUG
+ fprintf(stderr, "RETURNING %08x %08x\n", *pvalue, *pvendor);
+#endif
+ return 0;
}
/*
* Dictionaries need to have real names, not shitty ones.
*/
- if (strncmp(argv[1], "Attr-", 5) == 0) {
+ if (strncmp(argv[0], "Attr-", 5) == 0) {
fr_strerror_printf("dict_init: %s[%d]: Invalid attribute name",
fn, line);
return -1;
/*
* Look for OIDs before doing anything else.
*/
- p = strchr(argv[1], '.');
- if (p) oid = 1;
-
- /*
- * Validate all entries
- */
- if (!sscanf_i(argv[1], &value)) {
- fr_strerror_printf("dict_init: %s[%d]: invalid value", fn, line);
- return -1;
- }
+ if (strchr(argv[1], '.') != NULL) oid = 1;
- if (oid) {
+ {
DICT_ATTR const *da;
vendor = block_vendor;
+ if (!block_tlv) {
+ value = 0;
+ } else {
+ value = block_tlv->attr;
+ }
+
/*
- * Parse the rest of the OID.
+ * Parse OID.
*/
- if (dict_str2oid(p + 1, &value, &vendor, tlv_depth + 1) < 0) {
+ if (dict_str2oid(argv[1], &value, &vendor, tlv_depth) < 0) {
char buffer[256];
strlcpy(buffer, fr_strerror(), sizeof(buffer));
}
block_vendor = vendor;
- /*
- * Set the flags based on the parents flags.
- */
- da = dict_parent(value, vendor);
- if (!da) {
- fr_strerror_printf("dict_init: %s[%d]: Parent attribute is undefined.", fn, line);
- return -1;
- }
+ if (oid) {
+ /*
+ * Set the flags based on the parents flags.
+ */
+ da = dict_parent(value, vendor);
+ if (!da) {
+ fr_strerror_printf("dict_init: %s[%d]: Parent attribute for %08x,%08x is undefined.", fn, line, value, vendor);
+ return -1;
+ }
- flags.extended = da->flags.extended;
- flags.long_extended = da->flags.long_extended;
- flags.evs = da->flags.evs;
- if (da->flags.has_tlv) flags.is_tlv = 1;
+ flags.extended = da->flags.extended;
+ flags.long_extended = da->flags.long_extended;
+ flags.evs = da->flags.evs;
+ if (da->flags.has_tlv) flags.is_tlv = 1;
+ }
}
if (strncmp(argv[2], "octets[", 7) != 0) {
*p = 0;
- if (!sscanf_i(argv[1], &length)) {
+ if (!sscanf_i(argv[2] + 7, &length)) {
fr_strerror_printf("dict_init: %s[%d]: invalid length", fn, line);
return -1;
}
*/
int dict_unknown_from_str(DICT_ATTR *da, char const *name)
{
- unsigned int attr, vendor = 0;
- unsigned int dv_type = 1; /* The type of vendor field */
+ unsigned int attr = 0, vendor = 0;
char const *p = name;
char *q;
- DICT_VENDOR *dv;
- DICT_ATTR const *found;
-
if (dict_valid_name(name) < 0) return -1;
/*
return -1;
}
- attr = strtol(p + 5, &q, 10);
-
- /*
- * Invalid name.
- */
- if (attr == 0) {
- fr_strerror_printf("Invalid value in attribute name \"%s\"", name);
-
- return -1;
- }
-
- p = q;
-
- /*
- * Vendor-%d-Attr-%d
- * VendorName-Attr-%d
- * Attr-%d
- * Attr-%d.
- *
- * Anything else is invalid.
- */
- if (((vendor != 0) && (*p != '\0')) ||
- ((vendor == 0) && *p && (*p != '.'))) {
- invalid:
- fr_strerror_printf("Invalid OID");
- return -1;
- }
-
/*
- * Look for OIDs. Require the "Attr-26.Vendor-Id.type"
- * format, and disallow "Vendor-%d-Attr-%d" and
- * "VendorName-Attr-%d"
- *
- * This section parses the Vendor-Id portion of
- * Attr-%d.%d. where the first number is 26, *or* an
- * extended name of the "evs" foundta type.
+ * Parse the OID, with a (possibly) pre-defined vendor.
*/
- if (*p == '.') {
- found = dict_attrbyvalue(attr, 0);
- if (!found) {
- fr_strerror_printf("Cannot parse names without dictionaries");
-
- return -1;
- }
-
- if ((attr != PW_VENDOR_SPECIFIC) &&
- !(found->flags.extended || found->flags.long_extended)) {
- fr_strerror_printf("Standard attributes cannot use OIDs");
-
- return -1;
- }
-
- if ((attr == PW_VENDOR_SPECIFIC) || found->flags.evs) {
- vendor = strtol(p + 1, &q, 10);
- if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
- fr_strerror_printf("Invalid vendor");
-
- return -1;
- }
-
- if (*q != '.') goto invalid;
-
- p = q;
-
- if (found->flags.evs) vendor |= attr * FR_MAX_VENDOR;
- attr = 0;
- } /* else the second number is a TLV number */
- }
-
- /*
- * Get the expected maximum size of the name.
- */
- if (vendor) {
- dv = dict_vendorbyvalue(vendor & (FR_MAX_VENDOR - 1));
- if (dv) {
- dv_type = dv->type;
- if (dv_type > 3) dv_type = 3; /* hack */
- }
- }
-
- /*
- * Parse the next number. It could be a Vendor-Type
- * of 1..2^24, or it could be a TLV.
- */
- if (*p == '.') {
- attr = strtol(p + 1, &q, 10);
- if (attr == 0) {
- fr_strerror_printf("Invalid name number");
- return -1;
- }
-
- if (*q) {
- if (*q != '.') {
- goto invalid;
- }
-
- if (dv_type != 1) {
- goto invalid;
- }
- }
-
- p = q;
- }
-
- /*
- * Enforce a maximum value on the attribute number.
- */
- if ((vendor > 0) && (attr >= (unsigned) (1 << (dv_type << 3)))) goto invalid;
-
- if (*p == '.') {
- if (dict_str2oid(p + 1, &attr, &vendor, 1) < 0) {
- return -1;
- }
- }
-
- /*
- * If the caller doesn't provide a DICT_ATTR
- * we can't call dict_unknown_from_fields.
- */
- if (!da) {
- fr_strerror_printf("Unknown attributes disallowed");
+ if (dict_str2oid(p + 5, &attr, &vendor, 0) < 0) {
return -1;
}
fr_thread_local_setup(char *, fr_strerror_buffer) /* macro */
fr_thread_local_setup(char *, fr_syserror_buffer) /* macro */
+#ifndef NDEBUG
+/** POSIX-2008 errno macros
+ *
+ * Non-POSIX macros may be added, but you must check they're defined.
+ */
+char const *fr_errno_macro_names[] = {
+ [E2BIG] = "E2BIG",
+ [EACCES] = "EACCES",
+ [EADDRINUSE] = "EADDRINUSE",
+ [EADDRNOTAVAIL] = "EADDRNOTAVAIL",
+ [EAFNOSUPPORT] = "EAFNOSUPPORT",
+#if EWOULDBLOCK == EAGAIN
+ [EWOULDBLOCK] = "EWOULDBLOCK or EAGAIN",
+#else
+ [EAGAIN] = "EAGAIN",
+ [EWOULDBLOCK] = "EWOULDBLOCK",
+#endif
+ [EALREADY] = "EALREADY",
+ [EBADF] = "EBADF",
+ [EBADMSG] = "EBADMSG",
+ [EBUSY] = "EBUSY",
+ [ECANCELED] = "ECANCELED",
+ [ECHILD] = "ECHILD",
+ [ECONNABORTED] = "ECONNABORTED",
+ [ECONNREFUSED] = "ECONNREFUSED",
+ [ECONNRESET] = "ECONNRESET",
+ [EDEADLK] = "EDEADLK",
+ [EDESTADDRREQ] = "EDESTADDRREQ",
+ [EDOM] = "EDOM",
+ [EDQUOT] = "EDQUOT",
+ [EEXIST] = "EEXIST",
+ [EFAULT] = "EFAULT",
+ [EFBIG] = "EFBIG",
+ [EHOSTUNREACH] = "EHOSTUNREACH",
+ [EIDRM] = "EIDRM",
+ [EILSEQ] = "EILSEQ",
+ [EINPROGRESS] = "EINPROGRESS",
+ [EINTR] = "EINTR",
+ [EINVAL] = "EINVAL",
+ [EIO] = "EIO",
+ [EISCONN] = "EISCONN",
+ [EISDIR] = "EISDIR",
+ [ELOOP] = "ELOOP",
+ [EMFILE] = "EMFILE",
+ [EMLINK] = "EMLINK",
+ [EMSGSIZE] = "EMSGSIZE",
+ [EMULTIHOP] = "EMULTIHOP",
+ [ENAMETOOLONG] = "ENAMETOOLONG",
+ [ENETDOWN] = "ENETDOWN",
+ [ENETRESET] = "ENETRESET",
+ [ENETUNREACH] = "ENETUNREACH",
+ [ENFILE] = "ENFILE",
+ [ENOBUFS] = "ENOBUFS",
+#ifdef ENODATA
+ [ENODATA] = "ENODATA",
+#endif
+ [ENODEV] = "ENODEV",
+ [ENOENT] = "ENOENT",
+ [ENOEXEC] = "ENOEXEC",
+ [ENOLCK] = "ENOLCK",
+ [ENOLINK] = "ENOLINK",
+ [ENOMEM] = "ENOMEM",
+ [ENOMSG] = "ENOMSG",
+ [ENOPROTOOPT] = "ENOPROTOOPT",
+ [ENOSPC] = "ENOSPC",
+#ifdef ENOSR
+ [ENOSR] = "ENOSR",
+#endif
+#ifdef ENOSTR
+ [ENOSTR] = "ENOSTR",
+#endif
+ [ENOSYS] = "ENOSYS",
+ [ENOTCONN] = "ENOTCONN",
+ [ENOTDIR] = "ENOTDIR",
+ [ENOTEMPTY] = "ENOTEMPTY",
+#ifdef ENOTRECOVERABLE
+ [ENOTRECOVERABLE] = "ENOTRECOVERABLE",
+#endif
+ [ENOTSOCK] = "ENOTSOCK",
+ [ENOTSUP] = "ENOTSUP",
+#if ENOTSUP != EOPNOTSUPP
+ [EOPNOTSUPP] = "EOPNOTSUPP",
+#endif
+ [ENOTTY] = "ENOTTY",
+ [ENXIO] = "ENXIO",
+ [EOVERFLOW] = "EOVERFLOW",
+#ifdef EOWNERDEAD
+ [EOWNERDEAD] = "EOWNERDEAD",
+#endif
+ [EPERM] = "EPERM",
+ [EPIPE] = "EPIPE",
+ [EPROTO] = "EPROTO",
+ [EPROTONOSUPPORT] = "EPROTONOSUPPORT",
+ [EPROTOTYPE] = "EPROTOTYPE",
+ [ERANGE] = "ERANGE",
+ [EROFS] = "EROFS",
+ [ESPIPE] = "ESPIPE",
+ [ESRCH] = "ESRCH",
+ [ESTALE] = "ESTALE",
+#ifdef ETIME
+ [ETIME] = "ETIME",
+#endif
+ [ETIMEDOUT] = "ETIMEDOUT",
+ [ETXTBSY] = "ETXTBSY",
+ [EXDEV] = "EXDEV"
+};
+#endif
/*
* Explicitly cleanup the memory allocated to the error buffer,
*/
char const *fr_syserror(int num)
{
- char *buffer;
+ char *buffer, *p, *end;
int ret;
buffer = fr_thread_local_init(fr_syserror_buffer, _fr_logging_free);
}
}
- if (!num) {
- return "No error";
+ if (!num) return "No error";
+
+ p = buffer;
+ end = p + FR_STRERROR_BUFSIZE;
+
+#ifndef NDEBUG
+ /*
+ * Prefix system errors with the macro name and number
+ * if we're debugging.
+ */
+ if (num < (int)(sizeof(fr_errno_macro_names) / sizeof(*fr_errno_macro_names))) {
+ p += snprintf(p, end - p, "%s: ", fr_errno_macro_names[num]);
+ } else {
+ p += snprintf(p, end - p, "errno %i: ", num);
}
+ if (p >= end) return p;
+#endif
/*
* XSI-Compliant version
*/
#if !defined(HAVE_FEATURES_H) || !defined(__GLIBC__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 500) && ! _GNU_SOURCE)
- if ((ret = strerror_r(num, buffer, (size_t)FR_STRERROR_BUFSIZE) != 0)) {
+ ret = strerror_r(num, p, end - p);
+ if (ret != 0) {
# ifndef NDEBUG
fprintf(stderr, "strerror_r() failed to write error for errno %i to buffer %p (%zu bytes), "
"returned %i: %s\n", num, buffer, (size_t) FR_STRERROR_BUFSIZE, ret, strerror(ret));
*/
#else
{
- char const *p;
- p = strerror_r(num, buffer, (size_t)FR_STRERROR_BUFSIZE);
+ p = strerror_r(num, p, end - p);
if (!p) {
# ifndef NDEBUG
fprintf(stderr, "strerror_r() failed to write error for errno %i to buffer %p "
buffer[0] = '\0';
return buffer;
}
+
return p;
}
#endif
#include <pwd.h>
#include <sys/uio.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+
+/*
+ * Some versions of Linux don't have closefrom(), but they will
+ * have /proc.
+ *
+ * BSD systems will generally have closefrom(), but not proc.
+ *
+ * OSX doesn't have closefrom() or /proc/self/fd, but it does
+ * have /dev/fd
+ */
+#ifdef __linux__
+#define CLOSEFROM_DIR "/proc/self/fd"
+#elif defined(__APPLE__)
+#define CLOSEFROM_DIR "/dev/fd"
+#else
+#undef HAVE_DIRENT_H
+#endif
+
+#endif
+
#define FR_PUT_LE16(a, val)\
do {\
a[1] = ((uint16_t) (val)) >> 8;\
return 0;
}
+/** Uninstall a signal for a specific handler
+ *
+ * man sigaction says these are fine to call from a signal handler.
+ *
+ * @param sig SIGNAL
+ */
+int fr_unset_signal(int sig)
+{
+#ifdef HAVE_SIGACTION
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+
+ return sigaction(sig, &act, NULL);
+#else
+ return signal(sig, SIG_DFL);
+#endif
+}
+
static int _fr_trigger_talloc_ctx_free(fr_talloc_link_t *trigger)
{
if (trigger->armed) talloc_free(trigger->child);
return buffer;
}
+/*
+ * Parse decimal digits until we run out of decimal digits.
+ */
+static int ip_octet_from_str(char const *str, uint32_t *poctet)
+{
+ uint32_t octet;
+ char const *p = str;
+
+ if ((*p < '0') || (*p > '9')) {
+ return -1;
+ }
+
+ octet = 0;
+
+ while ((*p >= '0') && (*p <= '9')) {
+ octet *= 10;
+ octet += *p - '0';
+ p++;
+
+ if (octet > 255) return -1;
+ }
+
+
+ *poctet = octet;
+ return p - str;
+}
+
+static int ip_prefix_from_str(char const *str, uint32_t *paddr)
+{
+ int shift, length;
+ uint32_t octet;
+ uint32_t addr;
+ char const *p = str;
+
+ addr = 0;
+
+ for (shift = 24; shift >= 0; shift -= 8) {
+ length = ip_octet_from_str(p, &octet);
+ if (length <= 0) return -1;
+
+ addr |= octet << shift;
+ p += length;
+
+ /*
+ * EOS or / means we're done.
+ */
+ if (!*p || (*p == '/')) break;
+
+ /*
+ * We require dots between octets.
+ */
+ if (*p != '.') return -1;
+ p++;
+ }
+
+ *paddr = htonl(addr);
+ return p - str;
+}
+
+
/** Parse an IPv4 address or IPv4 prefix in presentation format (and others)
*
* @param out Where to write the ip address value.
int fr_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback)
{
char *p;
- unsigned int prefix;
+ unsigned int mask;
char *eptr;
/* Dotted quad + / + [0-9]{1,2} */
}
p = strchr(value, '/');
+
/*
* 192.0.2.2 is parsed as if it was /32
*/
*/
if ((value[0] == '*') && (value[1] == '\0')) {
out->ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
+
/*
* Convert things which are obviously integers to IP addresses
*
*/
} else if (is_integer(value) || ((value[0] == '0') && (value[1] == 'x'))) {
out->ipaddr.ip4addr.s_addr = htonl(strtoul(value, NULL, 0));
+
} else if (!resolve) {
if (inet_pton(AF_INET, value, &out->ipaddr.ip4addr.s_addr) <= 0) {
- fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
+ fr_strerror_printf("Failed to parse IPv4 addreess string \"%s\"", value);
return -1;
}
} else if (ip_hton(out, AF_INET, value, fallback) < 0) return -1;
}
/*
- * Otherwise parse the prefix
- */
- if ((size_t)(p - value) >= INET_ADDRSTRLEN) {
- fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
- return -1;
- }
-
- /*
* Copy the IP portion into a temporary buffer if we haven't already.
*/
if (inlen < 0) memcpy(buffer, value, p - value);
buffer[p - value] = '\0';
- if (!resolve) {
- if (inet_pton(AF_INET, buffer, &out->ipaddr.ip4addr.s_addr) <= 0) {
- fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
- return -1;
- }
- } else if (ip_hton(out, AF_INET, buffer, fallback) < 0) return -1;
+ if (ip_prefix_from_str(buffer, &out->ipaddr.ip4addr.s_addr) <= 0) {
+ fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
+ return -1;
+ }
- prefix = strtoul(p + 1, &eptr, 10);
- if (prefix > 32) {
+ mask = strtoul(p + 1, &eptr, 10);
+ if (mask > 32) {
fr_strerror_printf("Invalid IPv4 mask length \"%s\". Should be between 0-32", p);
return -1;
}
+
if (eptr[0] != '\0') {
fr_strerror_printf("Failed to parse IPv4 address string \"%s\", "
"got garbage after mask length \"%s\"", value, eptr);
return -1;
}
- if (prefix < 32) {
- out->ipaddr.ip4addr = fr_inaddr_mask(&out->ipaddr.ip4addr, prefix);
+ if (mask < 32) {
+ out->ipaddr.ip4addr = fr_inaddr_mask(&out->ipaddr.ip4addr, mask);
}
- out->prefix = (uint8_t) prefix;
+ out->prefix = (uint8_t) mask;
out->af = AF_INET;
return 0;
* Host, IPv4 or IPv6 with no port
*/
q = memchr(p, ':', len);
- if (!q || !memchr(p, '.', len)) return fr_pton(out, p, len, af, resolve);
+ if (!q) return fr_pton(out, p, len, af, resolve);
/*
* IPv4 or host, with port
*/
if (fr_pton(out, p, (q - p), af, resolve) < 0) return -1;
+
do_port:
/*
* Valid ports are a maximum of 5 digits, so if the
{
int i;
int maxfd = 256;
+#ifdef HAVE_DIRENT_H
+ DIR *dir;
+#endif
+
+#ifdef F_CLOSEM
+ if (fcntl(fd, F_CLOSEM) == 0) {
+ return 0;
+ }
+#endif
+
+#ifdef F_MAXFD
+ maxfd = fcntl(fd, F_F_MAXFD);
+ if (maxfd >= 0) goto do_close;
+#endif
#ifdef _SC_OPEN_MAX
maxfd = sysconf(_SC_OPEN_MAX);
if (maxfd < 0) {
- maxfd = 256;
+ maxfd = 256;
}
#endif
+#ifdef HAVE_DIRENT_H
+ /*
+ * Use /proc/self/fd directory if it exists.
+ */
+ dir = opendir(CLOSEFROM_DIR);
+ if (dir != NULL) {
+ long my_fd;
+ char *endp;
+ struct dirent *dp;
+
+ while ((dp = readdir(dir)) != NULL) {
+ my_fd = strtol(dp->d_name, &endp, 10);
+ if (my_fd <= 0) continue;
+
+ if (*endp) continue;
+
+ if (my_fd == dirfd(dir)) continue;
+
+ if ((my_fd >= fd) && (my_fd <= maxfd)) {
+ (void) close((int) my_fd);
+ }
+ }
+ (void) closedir(dir);
+ return 0;
+ }
+#endif
+
+#ifdef F_MAXFD
+do_close:
+#endif
+
if (fd > maxfd) return 0;
/*
* FIXME: return EINTR?
- *
- * Use F_CLOSEM?
*/
for (i = fd; i < maxfd; i++) {
close(i);
}
#endif
+#ifndef HAVE_VDPRINTF
+int vdprintf (int fd, char const *format, va_list args)
+{
+ int ret;
+ FILE *fp;
+ int dup_fd;
+
+ dup_fd = dup(fd);
+ if (dup_fd < 0) return -1;
+
+ fp = fdopen(fd, "w");
+ if (!fp) {
+ close(dup_fd);
+ return -1;
+ }
+
+ ret = vfprintf(fp, format, args);
+ fclose(fp); /* Also closes dup_fd */
+
+ return ret;
+}
+#endif
+
#ifndef HAVE_GETTIMEOFDAY
#ifdef WIN32
/*
* TCP sockets are always bound to the correct src/dst IP/port
*/
if (ps->proto == IPPROTO_TCP) {
- my_request.src_ipaddr = reply->dst_ipaddr;
- my_request.src_port = reply->dst_port;
+ reply->dst_ipaddr = ps->src_ipaddr;
+ reply->dst_port = ps->src_port;
+ reply->src_ipaddr = ps->dst_ipaddr;
+ reply->src_port = ps->dst_port;
+
+ my_request.src_ipaddr = ps->src_ipaddr;
+ my_request.src_port = ps->src_port;
+ my_request.dst_ipaddr = ps->dst_ipaddr;
+ my_request.dst_port = ps->dst_port;
+
} else
#endif
{
my_request.src_ipaddr = reply->dst_ipaddr;
}
my_request.src_port = ps->src_port;
- }
- my_request.dst_ipaddr = reply->src_ipaddr;
- my_request.dst_port = reply->src_port;
+ my_request.dst_ipaddr = reply->src_ipaddr;
+ my_request.dst_port = reply->src_port;
+ }
#ifdef WITH_TCP
my_request.proto = reply->proto;
return 0;
}
+static VALUE_PAIR *fr_pair_alloc(TALLOC_CTX *ctx)
+{
+ VALUE_PAIR *vp;
+
+ vp = talloc_zero(ctx, VALUE_PAIR);
+ if (!vp) {
+ fr_strerror_printf("Out of memory");
+ return NULL;
+ }
+
+ vp->op = T_OP_EQ;
+ vp->tag = TAG_ANY;
+ vp->type = VT_NONE;
+
+ talloc_set_destructor(vp, _fr_pair_free);
+
+ return vp;
+}
+
+
/** Dynamically allocate a new attribute
*
* Allocates a new attribute and a new dictionary attr if no DA is provided.
return NULL;
}
- vp = talloc_zero(ctx, VALUE_PAIR);
+ vp = fr_pair_alloc(ctx);
if (!vp) {
fr_strerror_printf("Out of memory");
return NULL;
}
+ /*
+ * Use the 'da' to initialize more fields.
+ */
vp->da = da;
- vp->op = T_OP_EQ;
- vp->tag = TAG_ANY;
- vp->type = VT_NONE;
-
vp->vp_length = da->flags.length;
- talloc_set_destructor(vp, _fr_pair_free);
-
return vp;
}
da = dict_attrbyvalue(attr, vendor);
if (!da) {
- da = dict_unknown_afrom_fields(ctx, attr, vendor);
+ VALUE_PAIR *vp;
+
+ vp = fr_pair_alloc(ctx);
+ if (!vp) return NULL;
+
+ /*
+ * Ensure that the DA is parented by the VP.
+ */
+ da = dict_unknown_afrom_fields(vp, attr, vendor);
if (!da) {
+ talloc_free(vp);
return NULL;
}
+
+ vp->da = da;
+ return vp;
}
return fr_pair_afrom_da(ctx, da);
*
* @param[in] ctx for talloc
* @param[in] from whence to copy VALUE_PAIRs.
- * @param[in] attr to match, if 0 input list will not be filtered by attr.
+ * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
+ * will match (and therefore copy) only VSAs.
+ * If attribute 0 and vendor 0 will match (and therefore copy) all
+ * attributes.
* @param[in] vendor to match.
* @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
* @return the head of the new VALUE_PAIR list or NULL on error.
vp = fr_cursor_next(&src)) {
VERIFY_VP(vp);
- if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
+ if (vp->da->flags.has_tag && !TAG_EQ(tag, vp->tag)) {
continue;
}
- if (vp->da->flags.has_tag && !TAG_EQ(tag, vp->tag)) {
+ /*
+ * Attr/vendor of 0 means "move them all".
+ * It's better than "fr_pair_copy(foo,bar);bar=NULL"
+ */
+ if ((attr == 0) && (vendor == 0)) {
+ goto do_copy;
+ }
+
+ /*
+ * vendor=0, attr = PW_VENDOR_SPECIFIC means
+ * "match any vendor attribute".
+ */
+ if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
+ /*
+ * It's a VSA: copy it over.
+ */
+ if (vp->da->vendor != 0) goto do_copy;
+
+ /*
+ * It's Vendor-Specific: copy it over.
+ */
+ if (vp->da->attr == attr) goto do_copy;
+
+ /*
+ * It's not a VSA: ignore it.
+ */
+ continue;
+ }
+
+ if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
continue;
}
+ do_copy:
vp = fr_pair_copy(ctx, vp);
if (!vp) {
fr_pair_list_free(&out);
}
-static VALUE_PAIR *fr_pair_from_unkown(VALUE_PAIR *vp, DICT_ATTR const *da)
-{
- ssize_t len;
- VALUE_PAIR *vp2;
-
- len = data2vp(NULL, NULL, NULL, NULL, da,
- vp->vp_octets, vp->vp_length, vp->vp_length,
- &vp2);
- if (len < 0) return vp; /* it's really unknown */
-
- if (vp2->da->flags.is_unknown) {
- fr_pair_list_free(&vp2);
- return vp;
- }
-
- /*
- * Didn't parse all of it. Return the "unknown" one.
- *
- * FIXME: it COULD have parsed 2 attributes and
- * then not the third, so returning 2 "knowns"
- * and 1 "unknown" is likely preferable.
- */
- if ((size_t) len < vp->vp_length) {
- fr_pair_list_free(&vp2);
- return vp;
- }
-
- fr_pair_steal(talloc_parent(vp), vp2);
- fr_pair_list_free(&vp);
- return vp2;
-}
-
/** Create a valuepair from an ASCII attribute and value
*
* Where the attribute name is in the form:
char const *attribute, char const *value,
FR_TOKEN op)
{
- VALUE_PAIR *vp;
+ VALUE_PAIR *vp, *vp2;
DICT_ATTR const *da;
uint8_t *data;
size_t size;
+ ssize_t len;
+
+ vp = fr_pair_alloc(ctx);
+ if (!vp) return NULL;
- da = dict_unknown_afrom_str(ctx, attribute);
- if (!da) return NULL;
+ vp->da = dict_unknown_afrom_str(vp, attribute);
+ if (!vp->da) {
+ talloc_free(vp);
+ return NULL;
+ }
+
+ /*
+ * No value. Nothing more to do.
+ */
+ if (!value) return vp;
/*
* Unknown attributes MUST be of type 'octets'
*/
- if (value && (strncasecmp(value, "0x", 2) != 0)) {
+ if (strncasecmp(value, "0x", 2) != 0) {
fr_strerror_printf("Unknown attribute \"%s\" requires a hex "
"string, not \"%s\"", attribute, value);
-
- dict_attr_free(&da);
+ talloc_free(vp);
return NULL;
}
/*
- * We've now parsed the attribute properly, Let's create
- * it. This next stop also looks the attribute up in the
- * dictionary, and creates the appropriate type for it.
+ * Convert the hex data to binary.
*/
- vp = fr_pair_afrom_da(ctx, da);
- if (!vp) {
- dict_attr_free(&da);
- return NULL;
- }
-
- vp->op = (op == 0) ? T_OP_EQ : op;
-
- if (!value) return vp;
-
size = strlen(value + 2);
+
vp->vp_length = size >> 1;
- data = talloc_array(vp, uint8_t, vp->vp_length);
+ vp->vp_octets = data = talloc_array(vp, uint8_t, vp->vp_length);
+ vp->type = VT_DATA;
+ vp->op = (op == 0) ? T_OP_EQ : op;
if (fr_hex2bin(data, vp->vp_length, value + 2, size) != vp->vp_length) {
fr_strerror_printf("Invalid hex string");
return NULL;
}
- vp->vp_octets = data;
- vp->type = VT_DATA;
-
/*
- * Convert unknowns to knowns
+ * It's still unknown, return it as-is.
*/
da = dict_attrbyvalue(vp->da->attr, vp->da->vendor);
- if (da) {
- return fr_pair_from_unkown(vp, da);
+ if (!da) return vp;
+
+ /*
+ * It MIGHT be known. See if we can decode the raw data
+ * into a valid attribute.
+ */
+ len = data2vp(ctx, NULL, NULL, NULL, da,
+ vp->vp_octets, vp->vp_length, vp->vp_length,
+ &vp2);
+ if (len <= 0) return vp;
+
+ /*
+ * It's still unknown. Return the original VP.
+ */
+ if (vp2->da->flags.is_unknown) {
+ fr_pair_list_free(&vp2);
+ return vp;
}
- return vp;
+ /*
+ * Didn't parse all of it. Return the "unknown" one.
+ *
+ * FIXME: it COULD have parsed 2 attributes and
+ * then not the third, so returning 2 "knowns"
+ * and 1 "unknown" is likely preferable.
+ */
+ if ((size_t) len < vp->vp_length) {
+ fr_pair_list_free(&vp2);
+ return vp;
+ }
+
+ fr_pair_list_free(&vp);
+ return vp2;
}
* valuepair should not already have a value.
*/
if (vp->type != VT_NONE) {
+ fr_strerror_printf("Pair already has a value");
return -1;
}
raw = talloc_typed_strdup(vp, value);
if (!raw) {
+ fr_strerror_printf("Out of memory");
return -1;
}
if (!fr_assert(a->da->type == PW_TYPE_STRING)) return -1;
- slen = regex_compile(NULL, &preg, a->vp_strvalue, a->vp_length, false, false, false, true);
+ slen = regex_compile(NULL, &preg, a->value.xlat, talloc_array_length(a->value.xlat) - 1, false, false, false, true);
if (slen <= 0) {
fr_strerror_printf("Error at offset %zu compiling regex for %s: %s",
-slen, a->da->name, fr_strerror());
{
VERIFY_VP(vp);
+ if (vp->type == VT_XLAT) {
+ return fr_aprints(ctx, vp->value.xlat, talloc_array_length(vp->value.xlat) - 1, quote);
+ }
+
return value_data_aprints(ctx, vp->da->type, vp->da, &vp->data, vp->vp_length, quote);
}
* JSON value to.
*
* @param out Where to write the string.
- * @param outlen Lenth of output buffer.
+ * @param outlen Length of output buffer.
* @param vp to print.
* @return the length of data written to out, or a value >= outlen on truncation.
*/
* to a string.
*
* @param out Where to write the string.
- * @param outlen Lenth of output buffer.
+ * @param outlen Length of output buffer.
* @param vp to print.
* @return the length of data written to out, or a value >= outlen on truncation.
*/
/*
- * The RFC says 4096 octets max, and most packets are less than 256.
- */
-#define MAX_PACKET_LEN 4096
-
-/*
* The maximum number of attributes which we allow in an incoming
* request. If there are more attributes than this, the request
* is rejected.
}
-void rad_print_hex(RADIUS_PACKET *packet)
+void rad_print_hex(RADIUS_PACKET const *packet)
{
int i;
case PW_TYPE_STRING:
case PW_TYPE_OCTETS:
data = vp->data.ptr;
- if (!data) {
- fr_strerror_printf("ERROR: Cannot encode NULL data");
- return -1;
- }
+ if (!data) return 0;
break;
case PW_TYPE_IFID:
ptr[0] = attribute & 0xff;
ptr[1] = 2;
- if (room > ((unsigned) 255 - ptr[1])) room = 255 - ptr[1];
+ if (room > 255) room = 255;
- len = vp2data_any(packet, original, secret, 0, pvp, ptr + ptr[1], room);
+ len = vp2data_any(packet, original, secret, 0, pvp, ptr + ptr[1], room - ptr[1]);
if (len <= 0) return len;
ptr[1] += len;
}
- if (room > ((unsigned) 255 - (dv->type + dv->length))) {
- room = 255 - (dv->type + dv->length);
- }
+ if (room > 255) room = 255;
len = vp2data_any(packet, original, secret, 0, pvp,
- ptr + dv->type + dv->length, room);
+ ptr + dv->type + dv->length, room - (dv->type + dv->length));
if (len <= 0) return len;
if (dv->length) ptr[dv->type + dv->length - 1] += len;
lvalue = htonl(vp->da->vendor);
memcpy(ptr + 2, &lvalue, 4);
- if (room > ((unsigned) 255 - ptr[1])) room = 255 - ptr[1];
+ if (room > 255) room = 255;
len = vp2attr_vsa(packet, original, secret, pvp,
vp->da->attr, vp->da->vendor,
- ptr + ptr[1], room);
+ ptr + ptr[1], room - ptr[1]);
if (len < 0) return len;
#ifndef NDEBUG
* RFC format attributes take the fast path.
*/
if (!vp->da->vendor) {
- if (vp->da->attr > 255) return 0;
+ if (vp->da->attr > 255) {
+ *pvp = vp->next;
+ return 0;
+ }
return rad_vp2rfc(packet, original, secret, pvp,
start, room);
*/
reply = packet->vps;
while (reply) {
- size_t last_len;
+ size_t last_len, room;
char const *last_name = NULL;
VERIFY_VP(reply);
}
/*
+ * We allow zero-length strings in "unlang", but
+ * skip them (except for CUI, thanks WiMAX!) on
+ * all other attributes.
+ */
+ if (reply->vp_length == 0) {
+ if ((reply->da->vendor != 0) ||
+ ((reply->da->attr != PW_CHARGEABLE_USER_IDENTITY) &&
+ (reply->da->attr != PW_MESSAGE_AUTHENTICATOR))) {
+ reply = reply->next;
+ continue;
+ }
+ }
+
+ /*
* Set the Message-Authenticator to the correct
* length and initial value.
*/
}
last_name = reply->da->name;
- len = rad_vp2attr(packet, original, secret, &reply, ptr,
- ((uint8_t *) data) + sizeof(data) - ptr);
+ room = ((uint8_t *) data) + sizeof(data) - ptr;
+
+ if (room <= 2) break;
+
+ len = rad_vp2attr(packet, original, secret, &reply, ptr, room);
if (len < 0) return -1;
/*
}
/*
+ * Set up the authentication vector with zero, or with
+ * the original vector, prior to signing.
+ */
+ switch (packet->code) {
+ case PW_CODE_ACCOUNTING_REQUEST:
+ case PW_CODE_DISCONNECT_REQUEST:
+ case PW_CODE_COA_REQUEST:
+ memset(packet->vector, 0, AUTH_VECTOR_LEN);
+ break;
+
+ case PW_CODE_ACCESS_ACCEPT:
+ case PW_CODE_ACCESS_REJECT:
+ case PW_CODE_ACCESS_CHALLENGE:
+ case PW_CODE_ACCOUNTING_RESPONSE:
+ case PW_CODE_DISCONNECT_ACK:
+ case PW_CODE_DISCONNECT_NAK:
+ case PW_CODE_COA_ACK:
+ case PW_CODE_COA_NAK:
+ if (!original) {
+ fr_strerror_printf("ERROR: Cannot sign response packet without a request packet");
+ return -1;
+ }
+ memcpy(packet->vector, original->vector, AUTH_VECTOR_LEN);
+ break;
+
+ case PW_CODE_ACCESS_REQUEST:
+ case PW_CODE_STATUS_SERVER:
+ default:
+ break; /* packet->vector is already random bytes */
+ }
+
+#ifndef NDEBUG
+ if ((fr_debug_lvl > 3) && fr_log_fp) rad_print_hex(packet);
+#endif
+
+ /*
* If there's a Message-Authenticator, update it
- * now, BEFORE updating the authentication vector.
+ * now.
*/
if (packet->offset > 0) {
uint8_t calc_auth_vector[AUTH_VECTOR_LEN];
case PW_CODE_DISCONNECT_NAK:
case PW_CODE_COA_REQUEST:
case PW_CODE_COA_ACK:
+ case PW_CODE_COA_NAK:
memset(hdr->vector, 0, AUTH_VECTOR_LEN);
break;
case PW_CODE_ACCESS_ACCEPT:
case PW_CODE_ACCESS_REJECT:
case PW_CODE_ACCESS_CHALLENGE:
- if (!original) {
- fr_strerror_printf("ERROR: Cannot sign response packet without a request packet");
- return -1;
- }
- memcpy(hdr->vector, original->vector,
- AUTH_VECTOR_LEN);
+ memcpy(hdr->vector, original->vector, AUTH_VECTOR_LEN);
break;
- default: /* others have vector already set to zero */
+ default:
break;
-
}
/*
(uint8_t const *) secret, strlen(secret));
memcpy(packet->data + packet->offset + 2,
calc_auth_vector, AUTH_VECTOR_LEN);
-
- /*
- * Copy the original request vector back
- * to the raw packet.
- */
- memcpy(hdr->vector, packet->vector, AUTH_VECTOR_LEN);
}
/*
+ * Copy the request authenticator over to the packet.
+ */
+ memcpy(hdr->vector, packet->vector, AUTH_VECTOR_LEN);
+
+ /*
* Switch over the packet code, deciding how to
* sign the packet.
*/
switch (packet->code) {
/*
- * Request packets are not signed, bur
+ * Request packets are not signed, but
* have a random authentication vector.
*/
case PW_CODE_ACCESS_REQUEST:
* This is per RFC-2868 which adds a two char SALT to the initial intermediate
* value MD5 hash.
*/
-int rad_tunnel_pwencode(char *passwd, size_t *pwlen, char const *secret,
- uint8_t const *vector)
+ssize_t rad_tunnel_pwencode(char *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
{
uint8_t buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 3];
unsigned char digest[AUTH_VECTOR_LEN];
* initial intermediate value, to differentiate it from the
* above.
*/
-int rad_tunnel_pwdecode(uint8_t *passwd, size_t *pwlen, char const *secret,
- uint8_t const *vector)
+ssize_t rad_tunnel_pwdecode(uint8_t *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
{
FR_MD5_CTX context, old;
uint8_t digest[AUTH_VECTOR_LEN];
#ifdef WITH_TCP
-/* FIXME: into common RADIUS header? */
-#define MAX_PACKET_LEN 4096
-
RADIUS_PACKET *fr_tcp_recv(int sockfd, int flags)
{
RADIUS_PACKET *packet = rad_alloc(NULL, false);
packet->sockfd);
}
-
- if (is_radius_code(packet->code)) {
- DEBUG("Received %s packet from %s",
- fr_packet_codes[packet->code], buffer);
- } else {
- DEBUG("Received packet from %s code %d",
- buffer, packet->code);
- }
- DEBUG(", id=%d, length=%zu\n", packet->id, packet->data_len);
}
return 1; /* done reading the packet */
/* Skip whitespace */
p = *ptr;
- while (*p && isspace((int) *p))
- p++;
- if (*p == 0) {
+ while (*p && isspace((int) *p)) p++;
+
+ if (!*p) {
*ptr = p;
return T_EOL;
}
if (TOKEN_MATCH(p, t->name)) {
strcpy(buf, t->name);
p += strlen(t->name);
- while (isspace((int) *p))
- p++;
- *ptr = p;
- return (FR_TOKEN) t->number;
+
+ rcode = t->number;
+ goto done;
}
}
/* Read word. */
quote = '\0';
- if ((*p == '"') ||
- (*p == '\'') ||
- (*p == '`')) {
+ switch (*p) {
+ default:
+ rcode = T_BARE_WORD;
+ break;
+
+ case '\'':
+ rcode = T_SINGLE_QUOTED_STRING;
+ break;
+
+ case '"':
+ rcode = T_DOUBLE_QUOTED_STRING;
+ break;
+
+ case '`':
+ rcode = T_BACK_QUOTED_STRING;
+ break;
+ }
+
+ if (rcode != T_BARE_WORD) {
quote = *p;
end = false;
p++;
s = buf;
while (*p && buflen-- > 1) {
- if (unescape && quote && (*p == '\\')) {
+ /*
+ * We're looking for strings. Stop on spaces, or
+ * (if given a token list), on a token, or on a
+ * comma.
+ */
+ if (!quote) {
+ if (isspace((int) *p)) {
+ break;
+ }
+
+ if (tok) {
+ for (t = tokenlist; t->name; t++) {
+ if (TOKEN_MATCH(p, t->name)) {
+ *s++ = 0;
+ goto done;
+ }
+ }
+ }
+ if (*p == ',') break;
+
+ /*
+ * Copy the character over.
+ */
+ *s++ = *p++;
+ continue;
+ } /* else there was a quotation character */
+
+ /*
+ * Un-escaped quote character. We're done.
+ */
+ if (*p == quote) {
+ end = true;
+ p++;
+ break;
+ }
+
+ /*
+ * Everything but backslash gets copied over.
+ */
+ if (*p != '\\') {
+ *s++ = *p++;
+ continue;
+ }
+
+ /*
+ * There's nothing after the backslash, it's an error.
+ */
+ if (!p[1]) {
+ fr_strerror_printf("Unterminated string");
+ return T_INVALID;
+ }
+
+ if (unescape) {
p++;
switch (*p) {
case 't':
*s++ = '\t';
break;
- case '\0':
- *s++ = '\\';
- p--; /* force EOS */
- break;
+
default:
if (*p >= '0' && *p <= '9' &&
sscanf(p, "%3o", &x) == 1) {
break;
}
p++;
- continue;
- }
-
- /*
- * Deal with quotes and escapes, but don't mash
- * escaped characters into their non-escaped
- * equivalent.
- */
- if (!unescape && quote && (*p == '\\')) {
- if (!p[1]) continue; /* force end of string */
+ } else {
+ /*
+ * Convert backslash-quote to quote, but
+ * leave everything else alone.
+ */
if (p[1] == quote) { /* convert '\'' --> ' */
p++;
} else {
+ if (buflen < 2) {
+ fr_strerror_printf("Truncated input");
+ return T_INVALID;
+ }
+
*(s++) = *(p++);
}
*(s++) = *(p++);
- continue;
- }
-
- if (quote && (*p == quote)) {
- end = true;
- p++;
- break;
- }
- if (!quote) {
- if (isspace((int) *p))
- break;
- if (tok) {
- for (t = tokenlist; t->name; t++)
- if (TOKEN_MATCH(p, t->name))
- break;
- if (t->name != NULL)
- break;
- }
- if (*p == ',') break; /* hack */
}
- *s++ = *p++;
}
+
*s++ = 0;
if (quote && !end) {
return T_INVALID;
}
+done:
/* Skip whitespace again. */
- while (*p && isspace((int) *p))
- p++;
- *ptr = p;
-
- /* we got SOME form of output string, even if it is empty */
- switch (quote) {
- default:
- rcode = T_BARE_WORD;
- break;
-
- case '\'':
- rcode = T_SINGLE_QUOTED_STRING;
- break;
-
- case '"':
- rcode = T_DOUBLE_QUOTED_STRING;
- break;
+ while (*p && isspace((int) *p)) p++;
- case '`':
- rcode = T_BACK_QUOTED_STRING;
- break;
- }
+ *ptr = p;
return rcode;
}
return gettoken(ptr, buf, buflen, unescape);
}
- return getthing(ptr, buf, buflen, 0, fr_tokens, unescape);
+ return getthing(ptr, buf, buflen, false, fr_tokens, unescape);
}
/*
{
size_t length;
- if (a_len > b_len) {
+ if (a_len < b_len) {
length = a_len;
} else {
length = b_len;
return -1;
/* raw octets: 0x01020304... */
+#ifndef WITH_ASCEND_BINARY
+ do_octets:
+#endif
case PW_TYPE_OCTETS:
{
uint8_t *p;
#ifdef WITH_ASCEND_BINARY
p = talloc_array(ctx, char, 128);
if (!p) return NULL;
- print_abinary(p, 128, (uint8_t *) &data->filter, inlen, 0);
+ print_abinary(p, 128, (uint8_t const *) &data->filter, inlen, 0);
break;
#else
/* FALL THROUGH */
radmin
radconf2xml
dhclient
+*_ext
/*
* We WERE going to have a nice reply, but
* something went wrong. So we've got to run
- * Post-Auth-Type Reject, which is defined in the
- * dictionaries as having value "1".
+ * Post-Auth-Type Reject.
*/
if (request->reply->code != PW_CODE_ACCESS_REJECT) {
RDEBUG("Using Post-Auth-Type Reject");
- process_post_auth(1, request);
+ process_post_auth(PW_POST_AUTH_TYPE_REJECT, request);
}
fr_state_discard(request, request->packet);
RDEBUG("Virtual server %s received request", request->server);
rdebug_pair_list(L_DBG_LVL_1, request, request->packet->vps, NULL);
+ if (!request->username) {
+ request->username = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ }
+
+ /*
+ * Complain about possible issues related to tunnels.
+ */
+ if (request->parent && request->parent->username && request->username) {
+ /*
+ * Look at the full User-Name with realm.
+ */
+ if (request->parent->username->da->attr == PW_STRIPPED_USER_NAME) {
+ vp = fr_pair_find_by_num(request->parent->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+ rad_assert(vp != NULL);
+ } else {
+ vp = request->parent->username;
+ }
+
+ /*
+ * If the names aren't identical, we do some detailed checks.
+ */
+ if (strcmp(vp->vp_strvalue, request->username->vp_strvalue) != 0) {
+ char const *outer, *inner;
+
+ outer = strchr(vp->vp_strvalue, '@');
+
+ /*
+ * If there's no realm, or there's a user identifier before
+ * the realm name, check the user identifier.
+ *
+ * It SHOULD be "anonymous", or "anonymous@realm"
+ */
+ if (outer) {
+ if ((outer != vp->vp_strvalue) &&
+ ((vp->vp_length < 10) || (memcmp(vp->vp_strvalue, "anonymous@", 10) != 0))) {
+ RWDEBUG("Outer User-Name is not anonymized. User privacy is compromised.");
+ } /* else it is anonymized */
+
+ /*
+ * Check when there's no realm, and without the trailing '@'
+ */
+ } else if ((vp->vp_length < 9) || (memcmp(vp->vp_strvalue, "anonymous", 9) != 0)) {
+ RWDEBUG("Outer User-Name is not anonymized. User privacy is compromised.");
+
+ } /* else the user identifier is anonymized */
+
+ /*
+ * Look for an inner realm, which may or may not exist.
+ */
+ inner = strchr(request->username->vp_strvalue, '@');
+ if (outer && inner) {
+ outer++;
+ inner++;
+
+ /*
+ * The realms are different, do
+ * more detailed checks.
+ */
+ if (strcmp(outer, inner) != 0) {
+ size_t outer_len, inner_len;
+
+ outer_len = vp->vp_length;
+ outer_len -= (outer - vp->vp_strvalue);
+
+ inner_len = request->username->vp_length;
+ inner_len -= (inner - request->username->vp_strvalue);
+
+ /*
+ * Inner: secure.example.org
+ * Outer: example.org
+ */
+ if (inner_len > outer_len) {
+ char const *suffix;
+
+ suffix = inner + (inner_len - outer_len) - 1;
+
+ if ((*suffix != '.') ||
+ (strcmp(suffix + 1, outer) != 0)) {
+ RWDEBUG("Possible spoofing: Inner realm '%s' is not a subdomain of the outer realm '%s'", inner, outer);
+ }
+
+ } else {
+ RWDEBUG("Possible spoofing: Inner realm and outer realms are different");
+ }
+ }
+ }
+
+ } else {
+ RWDEBUG("Outer and inner identities are the same. User privacy is compromised.");
+ }
+ }
+
RDEBUG("server %s {", request->server);
RINDENT();
tls_session_t *state = (tls_session_t *)arg;
/*
+ * OpenSSL 1.0.2 calls this function with 'pseudo'
+ * content types. Which breaks our tracking of
+ * the SSL Session state.
+ */
+ if ((msg_version == 0) && (content_type > UINT8_MAX)) {
+ DEBUG4("Ignoring cbtls_msg call with pseudo content type %i, version %i",
+ content_type, msg_version);
+ return;
+ }
+
+ if ((write_p != 0) && (write_p != 1)) {
+ DEBUG4("Ignoring cbtls_msg call with invalid write_p %d", write_p);
+ return;
+ }
+
+ /*
* Work around bug #298, where we may be called with a NULL
* argument. We should really log a serious error
*/
if (!state) return;
+ /*
+ * 0 - received (from peer)
+ * 1 - sending (to peer)
+ */
state->info.origin = write_p;
state->info.content_type = content_type;
state->info.record_len = len;
-install: install.sbindir $(R)$(sbindir)/checkrad
+install: $(R)$(sbindir)/checkrad
-$(R)$(sbindir)/checkrad: src/main/checkrad
+$(R)$(sbindir)/checkrad: src/main/checkrad | $(R)$(sbindir)
@echo INSTALL $(notdir $<)
@$(INSTALL) -m 755 $< $(R)$(sbindir)
static fr_ipaddr_t cl_ipaddr;
static uint32_t cl_netmask;
static char const *cl_srcipaddr = NULL;
-#ifdef WITH_TCP
static char const *hs_proto = NULL;
-#endif
#ifdef WITH_TCP
static CONF_PARSER limit_config[] = {
#ifdef WITH_COMMAND_SOCKET
#include <freeradius-devel/parser.h>
+#include <freeradius-devel/modcall.h>
#include <freeradius-devel/md5.h>
#include <freeradius-devel/channel.h>
{ NULL, 0 }
};
-#ifndef HAVE_GETPEEREID
+#if !defined(HAVE_GETPEEREID) && defined(SO_PEERCRED)
static int getpeereid(int s, uid_t *euid, gid_t *egid)
{
-#ifndef SO_PEERCRED
- return -1;
-#else
struct ucred cr;
socklen_t cl = sizeof(cr);
*euid = cr.uid;
*egid = cr.gid;
return 0;
-#endif /* SO_PEERCRED */
}
+
+/* we now have getpeereid() in this file */
+#define HAVE_GETPEEREID (1)
+
#endif /* HAVE_GETPEEREID */
/** Initialise a socket for use with peercred authentication
return CMD_FAIL;
}
+ (void) modcall_pass2_condition(new_condition);
+
/*
* Delete old condition.
*
static int command_stats_detail(rad_listen_t *listener, int argc, char *argv[])
{
rad_listen_t *this;
- listen_detail_t *data;
+ listen_detail_t *data, *needle;
struct stat buf;
if (argc == 0) {
for (this = main_config.listen; this != NULL; this = this->next) {
if (this->type != RAD_LISTEN_DETAIL) continue;
- data = this->data;
- if (strcmp(argv[1], data->filename) != 0) continue;
-
- break;
+ needle = this->data;
+ if (!strcmp(argv[0], needle->filename)) {
+ data = needle;
+ break;
+ }
}
if (!data) {
home_server_t *home;
if (argc == 0) {
- cprintf_error(listener, "Must specify [auth/acct] OR <ipaddr> <port>\n");
+ cprintf_error(listener, "Must specify [auth|acct|coa|disconnect] OR <ipaddr> <port>\n");
return 0;
}
if (argc == 1) {
+ if (strcmp(argv[0], "auth") == 0) {
+ return command_print_stats(listener,
+ &proxy_auth_stats, 1, 1);
+ }
+
#ifdef WITH_ACCOUNTING
if (strcmp(argv[0], "acct") == 0) {
return command_print_stats(listener,
&proxy_acct_stats, 0, 1);
}
#endif
- if (strcmp(argv[0], "auth") == 0) {
+
+#ifdef WITH_ACCOUNTING
+ if (strcmp(argv[0], "coa") == 0) {
return command_print_stats(listener,
- &proxy_auth_stats, 1, 1);
+ &proxy_coa_stats, 0, 1);
}
+#endif
+
+#ifdef WITH_ACCOUNTING
+ if (strcmp(argv[0], "disconnect") == 0) {
+ return command_print_stats(listener,
+ &proxy_dsc_stats, 0, 1);
+ }
+#endif
- cprintf_error(listener, "Should specify [auth/acct]\n");
+ cprintf_error(listener, "Should specify [auth|acct|coa|disconnect]\n");
return 0;
}
*/
fake.auth = radius_auth_stats;
#ifdef WITH_ACCOUNTING
- fake.auth = radius_acct_stats;
+ fake.acct = radius_acct_stats;
#endif
#ifdef WITH_COA
fake.coa = radius_coa_stats;
#ifdef WITH_PROXY
{ "home_server", FR_READ,
- "stats home_server [<ipaddr>/auth/acct] <port> [udp|tcp] - show statistics for given home server (ipaddr and port), or for all home servers (auth or acct)",
+ "stats home_server [<ipaddr>|auth|acct|coa|disconnect] <port> [udp|tcp] - show statistics for given home server (ipaddr and port), or for all home servers (auth or acct)",
command_stats_home_server, NULL },
#endif
* Can't get uid or gid of connecting user, so can't do
* peercred authentication.
*/
-#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED)
+#ifndef HAVE_GETPEEREID
if (sock->peercred && (sock->uid_name || sock->gid_name)) {
ERROR("System does not support uid or gid authentication for sockets");
return -1;
/*
* Write 32-bit magic number && version information.
*/
-static int command_write_magic(int newfd, listen_socket_t *sock)
+static int command_write_magic(int newfd,
+#ifndef WITH_TCP
+ UNUSED
+#endif
+ listen_socket_t *sock
+ )
{
ssize_t r;
uint32_t magic;
r = fr_channel_write(newfd, FR_CHANNEL_INIT_ACK, buffer, 8);
if (r <= 0) goto do_close;
+#ifdef WITH_TCP
/*
* Write an initial challenge
*/
r = fr_channel_write(newfd, FR_CHANNEL_AUTH_CHALLENGE, co->buffer, 16);
if (r <= 0) goto do_close;
}
+#endif
return 0;
}
-
+#ifdef WITH_TCP
static int command_tcp_recv(rad_listen_t *this)
{
ssize_t r;
fr_cs_buffer_t *co = (void *) sock->packet;
fr_channel_type_t channel;
- rad_assert(co != NULL);
+ if (!co) {
+ do_close:
+ command_close_socket(this);
+ return 0;
+ }
if (!co->auth) {
uint8_t expected[16];
r = fr_channel_read(this->fd, &channel, co->buffer, 16);
if ((r != 16) || (channel != FR_CHANNEL_AUTH_RESPONSE)) {
- do_close:
- command_close_socket(this);
- return 0;
+ goto do_close;
}
fr_hmac_md5(expected, (void const *) sock->client->secret,
return command_domain_recv_co(this, co);
}
+
/*
* Should never be called. The functions should just call write().
*/
{
return 0;
}
+#endif
static int command_domain_recv(rad_listen_t *listener)
{
return 0;
}
-#if defined(HAVE_GETPEEREID) || defined (SO_PEERCRED)
+#ifdef HAVE_GETPEEREID
/*
* Perform user authentication.
*/
typedef struct cf_file_t {
char const *filename;
CONF_SECTION *cs;
- bool input;
struct stat buf;
} cf_file_t;
file->filename = filename;
file->cs = cs;
- file->input = true;
if (fstat(fd, &file->buf) == 0) {
#ifdef S_IWOTH
}
/*
- * Do some checks on the file as an "input" file. i.e. one read
- * by a module.
+ * Do some checks on the file
*/
-static bool cf_file_input(CONF_SECTION *cs, char const *filename)
+static bool cf_file_check(CONF_SECTION *cs, char const *filename, bool check_perms)
{
cf_file_t *file;
CONF_DATA *cd;
file->filename = filename;
file->cs = cs;
- file->input = true;
if (stat(filename, &file->buf) < 0) {
- ERROR("Unable to open file \"%s\": %s", filename, fr_syserror(errno));
+ ERROR("Unable to check file \"%s\": %s", filename, fr_syserror(errno));
talloc_free(file);
return false;
}
+ if (!check_perms) {
+ talloc_free(file);
+ return true;
+ }
+
#ifdef S_IWOTH
if ((file->buf.st_mode & S_IWOTH) != 0) {
ERROR("Configuration file %s is globally writable. "
* The file changed, we'll need to re-read it.
*/
if (buf.st_mtime != file->buf.st_mtime) {
- if (!file->input) {
- cb->rcode |= CF_FILE_CONFIG;
- } else {
- (void) cb->callback(cb->modules, file->cs);
+
+ if (cb->callback(cb->modules, file->cs)) {
cb->rcode |= CF_FILE_MODULE;
+ DEBUG3("HUP: Changed module file %s", file->filename);
+ } else {
+ DEBUG3("HUP: Changed config file %s", file->filename);
+ cb->rcode |= CF_FILE_CONFIG;
}
}
/*
* Avoid mallocs if possible.
*/
- if (!cp->item.filename || (strcmp(parent->item.filename, cp->item.filename) == 0)) {
+ if (!cp->item.filename || (parent->item.filename && !strcmp(parent->item.filename, cp->item.filename))) {
new->item.filename = parent->item.filename;
} else {
new->item.filename = talloc_strdup(new, cp->item.filename);
int cf_item_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt)
{
int rcode;
- bool deprecated, required, attribute, secret, file_input, cant_be_empty, tmpl, multi;
+ bool deprecated, required, attribute, secret, file_input, cant_be_empty, tmpl, multi, file_exists;
char **q;
char const *value;
CONF_PAIR *cp = NULL;
attribute = (type & PW_TYPE_ATTRIBUTE);
secret = (type & PW_TYPE_SECRET);
file_input = (type == PW_TYPE_FILE_INPUT); /* check, not and */
+ file_exists = (type == PW_TYPE_FILE_EXISTS); /* check, not and */
cant_be_empty = (type & PW_TYPE_NOT_EMPTY);
tmpl = (type & PW_TYPE_TMPL);
multi = (type & PW_TYPE_MULTI);
*/
} else {
CONF_PAIR *next = cp;
+
value = cp->value;
cp->parsed = true;
c_item = &cp->item;
- /*
- * @fixme We should actually validate
- * the value of the pairs too
- */
- if (multi) while ((next = cf_pair_find_next(cs, next, name))) {
- next->parsed = true;
- }
-
if (deprecated) {
cf_log_err(c_item, "Configuration item \"%s\" is deprecated", name);
-
return -2;
}
+
+ /*
+ * A quick check to see if the next item is the same.
+ */
+ if (!multi && cp->item.next && (cp->item.next->type == CONF_ITEM_PAIR)) {
+ next = cf_item_to_pair(cp->item.next);
+
+ if (strcmp(next->attr, name) == 0) {
+ WARN("%s[%d]: Ignoring duplicate configuration item '%s'",
+ next->item.filename ? next->item.filename : "unknown",
+ next->item.lineno, name);
+ }
+ }
+
+ if (multi) {
+ while ((next = cf_pair_find_next(cs, next, name)) != NULL) {
+ /*
+ * @fixme We should actually validate
+ * the value of the pairs too
+ */
+ next->parsed = true;
+ };
+ }
}
if (!value) {
* to be caught as early as possible, during
* server startup.
*/
- if (*q && file_input && !cf_file_input(cs, *q)) {
+ if (*q && file_input && !cf_file_check(cs, *q, true)) {
+ return -1;
+ }
+
+ if (*q && file_exists && !cf_file_check(cs, *q, false)) {
return -1;
}
break;
if (!pool) return NULL;
+ /*
+ * Allow CTRL-C to kill the server in debugging mode.
+ */
+ if (main_config.exiting) return NULL;
+
#ifdef HAVE_PTHREAD_H
if (spawn) pthread_mutex_lock(&pool->mutex);
#endif
if (!pool || !conn) return NULL;
/*
+ * Don't allow opening of new connections if we're trying
+ * to exit.
+ */
+ if (main_config.exiting) {
+ fr_connection_release(pool, conn);
+ return NULL;
+ }
+
+ /*
* If fr_connection_find is successful the pool is now locked
*/
this = fr_connection_find(pool, conn);
*/
data->fp = NULL;
data->work_fd = open(data->filename_work, O_RDWR);
+
+ /*
+ * Couldn't open it for a reason OTHER than "it doesn't
+ * exist". Complain and tell the admin.
+ */
+ if ((data->work_fd < 0) && (errno != ENOENT)) {
+ ERROR("Failed opening detail file %s: %s",
+ data->filename_work, fr_syserror(errno));
+ return 0;
+ }
+
+ /*
+ * The file doesn't exist. Poll for it again.
+ */
if (data->work_fd < 0) {
#ifndef HAVE_GLOB_H
return 0;
* And try to open the filename.
*/
data->work_fd = open(data->filename_work, O_RDWR);
- if (data->work_fd < 0) return 0;
+ if (data->work_fd < 0) {
+ ERROR("Failed opening detail file %s: %s",
+ data->filename_work, fr_syserror(errno));
+ return 0;
+ }
#endif
} /* else detail.work existed, and we opened it */
}
+static size_t regex_escape(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
+{
+ char *p = out;
+
+ while (*in && (outlen > 2)) {
+ switch (*in) {
+ case '\\':
+ case '.':
+ case '*':
+ case '+':
+ case '?':
+ case '|':
+ case '^':
+ case '$':
+ case '[': /* we don't list close braces */
+ case '{':
+ case '(':
+ if (outlen < 3) goto done;
+
+ *(p++) = '\\';
+ outlen--;
+ /* FALL-THROUGH */
+
+ default:
+ *(p++) = *(in++);
+ outlen--;
+ break;
+ }
+ }
+
+done:
+ *(p++) = '\0';
+ return p - out;
+}
+
/** Convert both operands to the same type
*
value_data_t lhs_cast, rhs_cast;
void *lhs_cast_buff = NULL, *rhs_cast_buff = NULL;
+ xlat_escape_t escape = NULL;
+
/*
* Cast operand to correct type.
*
* Regular expressions need both operands to be strings
*/
#ifdef HAVE_REGEX
- if (map->op == T_OP_REG_EQ) cast_type = PW_TYPE_STRING;
+ if (map->op == T_OP_REG_EQ) {
+ cast_type = PW_TYPE_STRING;
+
+ if (map->rhs->type == TMPL_TYPE_XLAT_STRUCT) escape = regex_escape;
+ }
else
#endif
/*
if (map->rhs->type != TMPL_TYPE_LITERAL) {
char *p;
- ret = tmpl_aexpand(request, &p, request, map->rhs, NULL, NULL);
+ ret = tmpl_aexpand(request, &p, request, map->rhs, escape, NULL);
if (ret < 0) {
EVAL_DEBUG("FAIL [%i]", __LINE__);
rcode = -1;
return rcode;
}
+
/** Evaluate a map
*
* @param[in] request the REQUEST
rcode = select(fd + 1, &fds, NULL, NULL, &wake);
if (rcode == 0) {
too_long:
- DEBUG("Child PID %u is taking too much time: forcing failure and killing child.", pid);
+ DEBUG("Child PID %u is taking too much time: forcing failure and killing child.", (unsigned int) pid);
kill(pid, SIGTERM);
close(fd); /* should give SIGPIPE to child, too */
struct exfile_t {
uint32_t max_entries; //!< How many file descriptors we keep track of.
uint32_t max_idle; //!< Maximum idle time for a descriptor.
+ time_t last_cleaned;
#ifdef HAVE_PTHREAD_H
pthread_mutex_t mutex;
return ef;
}
+
+static void exfile_cleanup_entry(exfile_entry_t *entry)
+{
+ TALLOC_FREE(entry->filename);
+
+ close(entry->fd);
+ entry->hash = 0;
+ entry->fd = -1;
+ entry->dup = -1;
+}
+
/** Open a new log file, or maybe an existing one.
*
* When multithreaded, the FD is locked via a mutex. This way we're
*/
int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, bool append)
{
- uint32_t i, tries;
+ int i, tries, unused, oldest;
uint32_t hash;
time_t now = time(NULL);
struct stat st;
if (!ef || !filename) return -1;
hash = fr_hash_string(filename);
+ unused = -1;
PTHREAD_MUTEX_LOCK(&ef->mutex);
/*
- * Clean up old entries.
+ * Clean up idle entries.
*/
- for (i = 0; i < ef->max_entries; i++) {
- if (!ef->entries[i].filename) continue;
- if ((ef->entries[i].last_used + ef->max_idle) < now) {
+ if (now > (ef->last_cleaned + 1)) {
+ ef->last_cleaned = now;
+
+ for (i = 0; i < (int) ef->max_entries; i++) {
+ if (!ef->entries[i].filename) continue;
+
+ if ((ef->entries[i].last_used + ef->max_idle) >= now) continue;
+
/*
* This will block forever if a thread is
* doing something stupid.
*/
- TALLOC_FREE(ef->entries[i].filename);
- close(ef->entries[i].fd);
+ exfile_cleanup_entry(&ef->entries[i]);
}
}
/*
- * Find the matching entry.
+ * Find the matching entry, or an unused one.
+ *
+ * Also track which entry is the oldest, in case there
+ * are no unused entries.
*/
- for (i = 0; i < ef->max_entries; i++) {
- if (!ef->entries[i].filename) continue;
+ oldest = -1;
+ for (i = 0; i < (int) ef->max_entries; i++) {
+ if (!ef->entries[i].filename) {
+ if (unused < 0) unused = i;
+ continue;
+ }
- if (ef->entries[i].hash == hash) {
- /*
- * Same hash but different filename. Give up.
- */
- if (strcmp(ef->entries[i].filename, filename) != 0) {
- PTHREAD_MUTEX_UNLOCK(&ef->mutex);
- return -1;
- }
- /*
- * Someone else failed to create the entry.
- */
- if (!ef->entries[i].filename) {
- PTHREAD_MUTEX_UNLOCK(&ef->mutex);
- return -1;
- }
- goto do_return;
+ if ((oldest < 0) ||
+ (ef->entries[i].last_used < ef->entries[oldest].last_used)) {
+ oldest = i;
}
+
+ /*
+ * Hash comparisons are fast. String comparisons are slow.
+ */
+ if (ef->entries[i].hash != hash) continue;
+
+ /*
+ * But we still need to do string comparisons if
+ * the hash matches, because 1/2^16 filenames
+ * will result in a hash collision. And that's
+ * enough filenames in a long-running server to
+ * ensure that it happens.
+ */
+ if (strcmp(ef->entries[i].filename, filename) != 0) continue;
+
+ goto do_return;
}
/*
- * Find an unused entry
+ * There are no unused entries, free the oldest one.
*/
- for (i = 0; i < ef->max_entries; i++) {
- if (!ef->entries[i].filename) break;
- }
-
- if (i >= ef->max_entries) {
- fr_strerror_printf("Too many different filenames");
- PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
- return -1;
+ if (unused < 0) {
+ exfile_cleanup_entry(&ef->entries[oldest]);
+ unused = oldest;
}
/*
* Create a new entry.
*/
+ i = unused;
ef->entries[i].hash = hash;
ef->entries[i].filename = talloc_strdup(ef->entries, filename);
ef->entries[i].fd = -1;
+ ef->entries[i].dup = -1;
ef->entries[i].fd = open(filename, O_RDWR | O_APPEND | O_CREAT, permissions);
if (ef->entries[i].fd < 0) {
fr_strerror_printf("Failed to seek in file %s: %s", filename, strerror(errno));
error:
- ef->entries[i].hash = 0;
- TALLOC_FREE(ef->entries[i].filename);
- close(ef->entries[i].fd);
- ef->entries[i].fd = -1;
+ exfile_cleanup_entry(&ef->entries[i]);
PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
return -1;
PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
- fr_strerror_printf("Attempt to unlock file which does not exist");
+ fr_strerror_printf("Attempt to unlock file which is not tracked");
return -1;
}
# This lets the linker determine which version of the SSLeay functions to use.
TGT_LDLIBS := $(OPENSSL_LIBS)
+
+ifneq ($(MAKECMDGOALS),scan)
+SRC_CFLAGS += -DBUILT_WITH_CPPFLAGS=\"$(CPPFLAGS)\" -DBUILT_WITH_CFLAGS=\"$(CFLAGS)\" -DBUILT_WITH_LDFLAGS=\"$(LDFLAGS)\" -DBUILT_WITH_LIBS=\"$(LIBS)\"
+endif
static rad_listen_t *listen_alloc(TALLOC_CTX *ctx, RAD_LISTEN_TYPE type);
#ifdef WITH_COMMAND_SOCKET
+#ifdef WITH_TCP
static int command_tcp_recv(rad_listen_t *listener);
static int command_tcp_send(rad_listen_t *listener, REQUEST *request);
static int command_write_magic(int newfd, listen_socket_t *sock);
#endif
+#endif
static fr_protocol_t master_listen[];
ADDSTRING(name);
+#ifdef WITH_TCP
if (this->dual) {
ADDSTRING("+acct");
}
+#endif
if (sock->interface) {
ADDSTRING(" interface ");
return -1;
}
+ if (request->reply->data_len > (MAX_PACKET_LEN - 100)) {
+ RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+ request->reply->data_len, MAX_PACKET_LEN);
+ }
+
return 0;
}
return -1;
}
+ if (request->reply->data_len > (MAX_PACKET_LEN - 100)) {
+ RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+ request->reply->data_len, MAX_PACKET_LEN);
+ }
+
return 0;
}
#endif
return -1;
}
+ if (request->proxy->data_len > (MAX_PACKET_LEN - 100)) {
+ RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+ request->proxy->data_len, MAX_PACKET_LEN);
+ }
+
return 0;
}
#endif
return -1;
}
+ if (request->reply->data_len > (MAX_PACKET_LEN - 100)) {
+ RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+ request->reply->data_len, MAX_PACKET_LEN);
+ }
+
if (rad_sign(request->reply, request->packet, request->client->secret) < 0) {
RERROR("Failed signing packet: %s", fr_strerror());
return -1;
}
+ if (request->proxy->data_len > (MAX_PACKET_LEN - 100)) {
+ RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+ request->proxy->data_len, MAX_PACKET_LEN);
+ }
+
if (rad_sign(request->proxy, NULL, request->home_server->secret) < 0) {
RERROR("Failed signing proxied packet: %s", fr_strerror());
common_socket_parse, common_socket_free,
proxy_socket_recv, proxy_socket_send,
common_socket_print, proxy_socket_encode, proxy_socket_decode },
+#else
+ { 0, "proxy", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
#endif
/* authentication */
common_socket_parse, common_socket_free,
acct_socket_recv, acct_socket_send,
common_socket_print, client_socket_encode, client_socket_decode},
+#else
+ { 0, "acct", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
#endif
#ifdef WITH_DETAIL
detail_print, detail_encode, detail_decode },
#endif
-#ifdef WITH_VMPS
/* vlan query protocol */
{ 0, "vmps", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
-#endif
-#ifdef WITH_DHCP
/* dhcp query protocol */
{ 0, "dhcp", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
-#endif
#ifdef WITH_COMMAND_SOCKET
/* TCP command socket */
command_socket_parse, command_socket_free,
command_domain_accept, command_domain_send,
command_socket_print, command_socket_encode, command_socket_decode },
+#else
+ { 0, "command", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
#endif
#ifdef WITH_COA
common_socket_parse, NULL,
coa_socket_recv, auth_socket_send, /* CoA packets are same as auth */
common_socket_print, client_socket_encode, client_socket_decode },
+#else
+ { 0, "coa", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
#endif
};
override = true;
#ifdef WITH_VMPS
- if (strcmp(progname, "vmpsd") == 0) {
+ if (strcmp(main_config.name, "vmpsd") == 0) {
this = listen_alloc(config, RAD_LISTEN_VQP);
if (!auth_port) auth_port = 1589;
} else
/*
* No acct for vmpsd
*/
- if (strcmp(progname, "vmpsd") == 0) goto add_sockets;
+ if (strcmp(main_config.name, "vmpsd") == 0) goto add_sockets;
#endif
#ifdef WITH_ACCOUNTING
if (!check_config && !spawn_flag && this->tls) {
cf_log_err_cs(this->cs, "Threading must be enabled for TLS sockets to function properly");
cf_log_err_cs(this->cs, "You probably need to do '%s -fxx -l stdout' for debugging",
- progname);
+ main_config.name);
return -1;
}
#endif
cp = cf_pair_find(request->client->cs, fmt);
if (!cp || !(value = cf_pair_value(cp))) {
- if (strcmp(fmt, "shortname") == 0) {
- strlcpy(out, request->client->shortname, outlen);
- return strlen(out);
+ if (strcmp(fmt, "shortname") == 0 && request->client->shortname) {
+ value = request->client->shortname;
+ }
+ else if (strcmp(fmt, "nas_type") == 0 && request->client->nas_type) {
+ value = request->client->nas_type;
+ } else {
+ *out = '\0';
+ return 0;
}
- *out = '\0';
- return 0;
}
strlcpy(out, value, outlen);
* initialized.
*/
if (fr_set_dumpable_init() < 0) {
- fr_perror("radiusd");
+ fr_perror("%s", main_config.name);
return 0;
}
if (rad_debug_lvl && (getuid() != 0)) return 1;
if (cf_section_parse(cs, NULL, bootstrap_config) < 0) {
- fprintf(stderr, "radiusd: Error: Failed to parse user/group information.\n");
+ fprintf(stderr, "%s: Error: Failed to parse user/group information.\n",
+ main_config.name);
return 0;
}
gr = getgrnam(gid_name);
if (!gr) {
fprintf(stderr, "%s: Cannot get ID for group %s: %s\n",
- progname, gid_name, fr_syserror(errno));
+ main_config.name, gid_name, fr_syserror(errno));
return 0;
}
if (rad_getpwnam(cs, &user, uid_name) < 0) {
fprintf(stderr, "%s: Cannot get passwd entry for user %s: %s\n",
- progname, uid_name, fr_strerror());
+ main_config.name, uid_name, fr_strerror());
return 0;
}
#ifdef HAVE_INITGROUPS
if (initgroups(uid_name, server_gid) < 0) {
fprintf(stderr, "%s: Cannot initialize supplementary group list for user %s: %s\n",
- progname, uid_name, fr_syserror(errno));
+ main_config.name, uid_name, fr_syserror(errno));
talloc_free(user);
return 0;
}
if (chroot_dir) {
if (chroot(chroot_dir) < 0) {
fprintf(stderr, "%s: Failed to perform chroot %s: %s",
- progname, chroot_dir, fr_syserror(errno));
+ main_config.name, chroot_dir, fr_syserror(errno));
return 0;
}
if (do_sgid) {
if (setgid(server_gid) < 0){
fprintf(stderr, "%s: Failed setting group to %s: %s",
- progname, gid_name, fr_syserror(errno));
+ main_config.name, gid_name, fr_syserror(errno));
return 0;
}
}
default_log.fd = open(main_config.log_file,
O_WRONLY | O_APPEND | O_CREAT, 0640);
if (default_log.fd < 0) {
- fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", main_config.log_file, fr_syserror(errno));
+ fprintf(stderr, "%s: Failed to open log file %s: %s\n",
+ main_config.name, main_config.log_file, fr_syserror(errno));
return 0;
}
}
(default_log.dst == L_DST_FILES)) {
if (fchown(default_log.fd, server_uid, server_gid) < 0) {
fprintf(stderr, "%s: Cannot change ownership of log file %s: %s\n",
- progname, main_config.log_file, fr_syserror(errno));
+ main_config.name, main_config.log_file, fr_syserror(errno));
return 0;
}
}
*/
if (default_log.dst == L_DST_NULL) {
if (cf_section_parse(cs, NULL, startup_server_config) < 0) {
- fprintf(stderr, "radiusd: Error: Failed to parse log{} section.\n");
+ fprintf(stderr, "%s: Error: Failed to parse log{} section.\n",
+ main_config.name);
cf_file_free(cs);
return -1;
}
if (!radlog_dest) {
- fprintf(stderr, "radiusd: Error: No log destination specified.\n");
+ fprintf(stderr, "%s: Error: No log destination specified.\n",
+ main_config.name);
cf_file_free(cs);
return -1;
}
default_log.dst = fr_str2int(log_str2dst, radlog_dest,
L_DST_NUM_DEST);
if (default_log.dst == L_DST_NUM_DEST) {
- fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
- radlog_dest);
+ fprintf(stderr, "%s: Error: Unknown log_destination %s\n",
+ main_config.name, radlog_dest);
cf_file_free(cs);
return -1;
}
* before using it
*/
if (!syslog_facility) {
- fprintf(stderr, "radiusd: Error: Syslog chosen but no facility was specified\n");
+ fprintf(stderr, "%s: Error: Syslog chosen but no facility was specified\n",
+ main_config.name);
cf_file_free(cs);
return -1;
}
main_config.syslog_facility = fr_str2int(syslog_facility_table, syslog_facility, -1);
if (main_config.syslog_facility < 0) {
- fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
- syslog_facility);
+ fprintf(stderr, "%s: Error: Unknown syslog_facility %s\n",
+ main_config.name, syslog_facility);
cf_file_free(cs);
return -1;
}
* Call openlog only once, when the
* program starts.
*/
- openlog(progname, LOG_PID, main_config.syslog_facility);
+ openlog(main_config.name, LOG_PID, main_config.syslog_facility);
#endif
} else if (default_log.dst == L_DST_FILES) {
if (!main_config.log_file) {
- fprintf(stderr, "radiusd: Error: Specified \"files\" as a log destination, but no log filename was given!\n");
+ fprintf(stderr, "%s: Error: Specified \"files\" as a log destination, but no log filename was given!\n",
+ main_config.name);
cf_file_free(cs);
return -1;
}
if (!module_hup_module(mi->cs, mi, time(NULL))) return 0;
- return 0;
+ return 1;
}
void main_config_hup(void)
#include <ctype.h>
-#if 0
+#ifdef DEBUG_MAP
static void map_dump(REQUEST *request, vp_map_t const *map)
{
RDEBUG(">>> MAP TYPES LHS: %s, RHS: %s",
break;
/*
- * Filtering operators
+ * Filter operators
*/
- default:
- /*
- * If the dst doesn't exist, the filters will add
- * it with the given value.
- */
- if (!dst) {
- RDEBUG3("No existing attribute to filter, adding instead");
- fr_cursor_merge(&dst_list, head);
- head = NULL;
- goto finish;
- }
+ case T_OP_REG_NE:
+ case T_OP_NE:
+ case T_OP_REG_EQ:
+ case T_OP_CMP_EQ:
+ case T_OP_GE:
+ case T_OP_GT:
+ case T_OP_LE:
+ case T_OP_LT:
+ {
+ VALUE_PAIR *a, *b;
- /*
- * The LHS exists. We need to limit it's value based on
- * the operator, and the value of the RHS.
- */
- found = false;
- for (vp = fr_cursor_first(&src_list);
- vp;
- vp = fr_cursor_next(&src_list)) {
- vp->op = map->op;
- rcode = radius_compare_vps(request, vp, dst);
- vp->op = T_OP_SET;
-
- switch (map->op) {
- case T_OP_CMP_EQ:
- if (rcode == 0) continue;
- replace:
- dst = fr_cursor_remove(&dst_list);
- DEBUG_OVERWRITE(dst, fr_cursor_current(&src_list));
- fr_pair_list_free(&dst);
- fr_cursor_insert(&dst_list, fr_cursor_remove(&src_list));
- found = true;
- continue;
+ fr_pair_list_sort(&head, fr_pair_cmp_by_da_tag);
+ fr_pair_list_sort(list, fr_pair_cmp_by_da_tag);
- case T_OP_LE:
- if (rcode <= 0) continue;
- goto replace;
+ fr_cursor_first(&dst_list);
- case T_OP_GE:
- if (rcode >= 0) continue;
- goto replace;
+ for (b = fr_cursor_first(&src_list);
+ b;
+ b = fr_cursor_next(&src_list)) {
+ for (a = fr_cursor_current(&dst_list);
+ a;
+ a = fr_cursor_next(&dst_list)) {
+ int8_t cmp;
- default:
- fr_pair_list_free(&head);
- return -1;
+ cmp = fr_pair_cmp_by_da_tag(a, b); /* attribute and tag match */
+ if (cmp > 0) break;
+ else if (cmp < 0) continue;
+
+ cmp = (value_data_cmp_op(map->op, a->da->type, &a->data, a->vp_length, b->da->type, &b->data, b->vp_length) == 0);
+ if (cmp != 0) {
+ a = fr_cursor_remove(&dst_list);
+ talloc_free(a);
+ }
}
+ if (!a) break; /* end of the list */
}
fr_pair_list_free(&head);
- if (!found) return 0;
-
+ }
break;
+
+ default:
+ rad_assert(0); /* Should have been caught be the caller */
+ return -1;
}
finish:
blocked = (request->master_state == REQUEST_STOP_PROCESSING);
if (blocked) return RLM_MODULE_NOOP;
- RDEBUG3("modsingle[%s]: calling %s (%s) for request %d",
+ RDEBUG3("modsingle[%s]: calling %s (%s)",
comp2str[component], sp->modinst->name,
- sp->modinst->entry->name, request->number);
+ sp->modinst->entry->name);
request->log.indent = 0;
if (sp->modinst->force) {
*/
blocked = (request->master_state == REQUEST_STOP_PROCESSING);
if (blocked) {
- RWARN("Module %s became unblocked for request %u", sp->modinst->entry->name, request->number);
+ RWARN("Module %s became unblocked", sp->modinst->entry->name);
}
fail:
request->log.indent = indent;
- RDEBUG3("modsingle[%s]: returned from %s (%s) for request %d",
+ RDEBUG3("modsingle[%s]: returned from %s (%s)",
comp2str[component], sp->modinst->name,
- sp->modinst->entry->name, request->number);
+ sp->modinst->entry->name);
return request->rcode;
}
*/
if (!c) goto finish;
+ if (fr_debug_lvl >= 3) {
+ VERIFY_REQUEST(request);
+ }
+
rad_assert(c->debug_name != NULL); /* if this happens, all bets are off. */
/*
* Like MOD_ELSE, but allow for a later "else"
*/
if (if_taken) {
- RDEBUG2("... skipping %s for request %d: Preceding \"if\" was taken",
- unlang_keyword[c->type], request->number);
+ RDEBUG2("... skipping %s: Preceding \"if\" was taken",
+ unlang_keyword[c->type]);
was_if = true;
if_taken = true;
goto next_sibling;
if (c->type == MOD_ELSE) {
if (!was_if) { /* error */
elsif_error:
- RDEBUG2("... skipping %s for request %d: No preceding \"if\"",
- unlang_keyword[c->type], request->number);
+ RDEBUG2("... skipping %s: No preceding \"if\"",
+ unlang_keyword[c->type]);
goto next_sibling;
}
if (if_taken) {
- RDEBUG2("... skipping %s for request %d: Preceding \"if\" was taken",
- unlang_keyword[c->type], request->number);
+ RDEBUG2("... skipping %s: Preceding \"if\" was taken",
+ unlang_keyword[c->type]);
was_if = false;
if_taken = false;
goto next_sibling;
rad_assert(parent != NULL);
p = mod_callabletogroup(parent);
- rad_assert(p->tail != NULL);
+ if (!p->tail) goto elsif_fail;
/*
* We're in the process of compiling the
f = mod_callabletogroup(p->tail);
if ((f->mc.type != MOD_IF) &&
(f->mc.type != MOD_ELSIF)) {
+ elsif_fail:
cf_log_err_cs(g->cs, "Invalid location for 'elsif'. There is no preceding 'if' statement");
talloc_free(g);
return NULL;
rad_assert(parent != NULL);
p = mod_callabletogroup(parent);
- rad_assert(p->tail != NULL);
+ if (!p->tail) goto else_fail;
f = mod_callabletogroup(p->tail);
if ((f->mc.type != MOD_IF) &&
(f->mc.type != MOD_ELSIF)) {
+ else_fail:
cf_log_err_cs(g->cs, "Invalid location for 'else'. There is no preceding 'if' statement");
talloc_free(g);
return NULL;
goto do_children;
}
+ if (g->vpt->type == TMPL_TYPE_ATTR_UNDEFINED) {
+ if (!pass2_fixup_undefined(cf_section_to_item(g->cs), g->vpt)) {
+ return false;
+ }
+ }
+
/*
* Compile and sanity check xlat
* expansions.
char const *name1 = cf_section_name1(g->cs);
if (strcmp(name1, unlang_keyword[c->type]) != 0) {
- c->debug_name = talloc_asprintf(c, "%s %s", name1, cf_section_name2(g->cs));
+ name2 = cf_section_name2(g->cs);
+
+ if (!name2) {
+ c->debug_name = name1;
+ } else {
+ c->debug_name = talloc_asprintf(c, "%s %s", name1, name2);
+ }
}
}
}
}
}
+
+int modcall_pass2_condition(fr_cond_t *c)
+{
+ if (!fr_condition_walk(c, pass2_callback, NULL)) return -1;
+
+ return 0;
+}
#include <freeradius-devel/parser.h>
#include <freeradius-devel/rad_assert.h>
+/** Path to search for modules in
+ *
+ */
+char const *radlib_dir = NULL;
+
typedef struct indexed_modcallable {
rlm_components_t comp;
int idx;
lt_dlhandle lt_dlopenext(char const *name)
{
- int flags = RTLD_NOW;
- void *handle;
- char buffer[2048];
- char *env;
-
+ int flags = RTLD_NOW;
+ void *handle;
+ char buffer[2048];
+ char *env;
+ char const *search_path;
#ifdef RTLD_GLOBAL
if (strcmp(name, "rlm_perl") == 0) {
flags |= RTLD_GLOBAL;
*/
flags |= RTLD_NOW;
#endif
+
+ /*
+ * Apple removed support for DYLD_LIBRARY_PATH in rootless mode.
+ */
+ env = getenv("FR_LIBRARY_PATH");
+ if (env) {
+ DEBUG3("Ignoring libdir as FR_LIBRARY_PATH set. Module search path will be: %s", env);
+ search_path = env;
+ } else {
+ search_path = radlib_dir;
+ }
+
/*
* Prefer loading our libraries by absolute path.
*/
- if (radlib_dir) {
+ if (search_path) {
char *error;
+ char *ctx, *paths, *path;
+ char *p;
- snprintf(buffer, sizeof(buffer), "%s/%s%s", radlib_dir, name, LT_SHREXT);
+ fr_strerror();
- DEBUG4("Loading library using absolute path \"%s\"", buffer);
+ ctx = paths = talloc_strdup(NULL, search_path);
+ while ((path = strsep(&paths, ":")) != NULL) {
+ /*
+ * Trim the trailing slash
+ */
+ p = strrchr(path, '/');
+ if (p && ((p[1] == '\0') || (p[1] == ':'))) *p = '\0';
- handle = dlopen(buffer, flags);
- if (handle) return handle;
- error = dlerror();
+ path = talloc_asprintf(ctx, "%s/%s%s", path, name, LT_SHREXT);
- fr_strerror_printf("%s", error);
- DEBUG4("Failed with error: %s", error);
+ DEBUG4("Loading %s with path: %s", name, path);
- /*
- * Because dlopen (on OSX at least) produces really
- * shitty and inaccurate error messages
- */
- if (access(buffer, R_OK) < 0) {
- switch (errno) {
- case EACCES:
- WARN("Library file found, but we don't have permission to read it");
- break;
-
- case ENOENT:
- DEBUG4("Library file not found");
- break;
-
- default:
- DEBUG4("Issue accessing library file: %s", fr_syserror(errno));
- break;
+ handle = dlopen(path, flags);
+ if (handle) {
+ talloc_free(ctx);
+ return handle;
}
+ error = dlerror();
+
+ fr_strerror_printf("%s%s\n", fr_strerror(), error);
+ DEBUG4("Loading %s failed: %s - %s", name, error,
+ (access(path, R_OK) < 0) ? fr_syserror(errno) : "No access errors");
+ talloc_free(path);
}
+ talloc_free(ctx);
}
DEBUG4("Loading library using linker search path(s)");
}
#endif
- /*
- * Remove any registered paircompares.
- */
- paircompare_unregister_instance(module->insthandle);
-
xlat_unregister(module->name, NULL, module->insthandle);
+
/*
* Remove all xlat's registered to module instance.
*/
- if (module->insthandle) xlat_unregister_module(module->insthandle);
+ if (module->insthandle) {
+ /*
+ * Remove any registered paircompares.
+ */
+ paircompare_unregister_instance(module->insthandle);
+
+ xlat_unregister_module(module->insthandle);
+ }
talloc_free(module);
}
* section. If the CS is free'd the instance will be
* free'd, too.
*/
- node = talloc_zero(cs, module_instance_t);
+ node = talloc_zero(instance_tree, module_instance_t);
node->cs = cs;
strlcpy(node->name, name2, sizeof(node->name));
* Loop over all of the components
*/
for (comp = 0; comp < MOD_COUNT; ++comp) {
- CONF_SECTION *subcs;
- CONF_ITEM *modref;
+ CONF_SECTION *subcs, *type_cs;
DICT_ATTR const *da;
subcs = cf_section_sub_find(cs,
/*
* Define dynamic types, so that others can reference
* them.
+ *
+ * First, bare modules for 'authenticate'.
+ * Second, Auth-Type, etc.
*/
- for (modref = cf_item_find_next(subcs, NULL);
- modref != NULL;
- modref = cf_item_find_next(subcs, modref)) {
- char const *name1;
- CONF_SECTION *subsubcs;
+ if (section_type_value[comp].attr == PW_AUTH_TYPE) {
+ CONF_ITEM *modref;
- /*
- * Create types for simple references
- * only when parsing the authenticate
- * section.
- */
- if ((section_type_value[comp].attr == PW_AUTH_TYPE) &&
- cf_item_is_pair(modref)) {
- CONF_PAIR *cp = cf_item_to_pair(modref);
+ for (modref = cf_item_find_next(subcs, NULL);
+ modref != NULL;
+ modref = cf_item_find_next(subcs, modref)) {
+ CONF_PAIR *cp;
+
+ if (!cf_item_is_pair(modref)) continue;
+
+ cp = cf_item_to_pair(modref);
if (!define_type(cs, da, cf_pair_attr(cp))) {
return false;
}
- continue;
+ /*
+ * Check for duplicates
+ */
+ if (rad_debug_lvl) {
+ CONF_PAIR *cp2;
+ CONF_SECTION *cs2;
+
+ cp2 = cf_pair_find(subcs, cf_pair_attr(cp));
+ rad_assert(cp2 != NULL);
+ if (cp2 != cp) {
+ WARN("%s[%d]: Duplicate module '%s'",
+ cf_pair_filename(cp2),
+ cf_pair_lineno(cp2),
+ cf_pair_attr(cp));
+ }
+
+ cs2 = cf_section_sub_find_name2(subcs, section_type_value[comp].typename, cf_pair_attr(cp));
+ if (cs2) {
+ WARN("%s[%d]: Duplicate Auth-Type '%s'",
+ cf_section_filename(cs2),
+ cf_section_lineno(cs2),
+ cf_pair_attr(cp));
+ }
+ }
+
}
+ }
- if (!cf_item_is_section(modref)) continue;
+ /*
+ * And loop over the type names
+ */
+ for (type_cs = cf_subsection_find_next(subcs, NULL, section_type_value[comp].typename);
+ type_cs != NULL;
+ type_cs = cf_subsection_find_next(subcs, type_cs, section_type_value[comp].typename)) {
+ if (!define_type(cs, da, cf_section_name2(type_cs))) {
+ return false;
+ }
- subsubcs = cf_item_to_section(modref);
- name1 = cf_section_name1(subsubcs);
+ if (rad_debug_lvl) {
+ CONF_SECTION *cs2;
- if (strcmp(name1, section_type_value[comp].typename) == 0) {
- if (!define_type(cs, da,
- cf_section_name2(subsubcs))) {
- return false;
- }
+ cs2 = cf_section_sub_find_name2(subcs, section_type_value[comp].typename, cf_section_name2(type_cs));
+ rad_assert(cs2 != NULL);
+ if (cs2 != type_cs) {
+ WARN("%s[%d]: Duplicate Auth-Type '%s'",
+ cf_section_filename(cs2),
+ cf_section_lineno(cs2),
+ cf_section_name2(cs2));
+ }
}
}
} /* loop over components */
for (cs = cf_subsection_find_next(config, NULL, "server");
cs != NULL;
cs = cf_subsection_find_next(config, cs, "server")) {
+#if defined(WITH_DHCP) || defined(WITH_VMPS)
CONF_SECTION *subcs;
DICT_ATTR const *da;
+#endif
#ifdef WITH_VMPS
/*
DEBUG2("%s: #### Instantiating modules ####", main_config.name);
+ cf_log_info(config, " modules {");
+
/*
* Loop over module definitions, looking for duplicates.
*
module_instance_t *module;
char const *name;
- cf_log_info(cs, " instantiate {");
+ cf_log_info(cs, " instantiate {");
/*
* Loop over the items in the 'instantiate' section.
} /* handle subsections */
} /* loop over the "instantiate" section */
- cf_log_info(cs, " }");
+ cf_log_info(cs, " }");
} /* if there's an 'instantiate' section. */
/*
* because we've now split up the modules into
* mods-enabled.
*/
- cf_log_info(cs, " modules {");
for (ci=cf_item_find_next(modules, NULL);
ci != NULL;
ci=next) {
module = module_instantiate(modules, name);
if (!module) return -1;
}
- cf_log_info(cs, " } # modules");
+ cf_log_info(config, " } # modules");
if (virtual_servers_load(config) < 0) return -1;
{
vp_cursor_t cursor;
VALUE_PAIR *check_item;
- VALUE_PAIR *auth_item;
+ VALUE_PAIR *auth_item = NULL;
DICT_ATTR const *from;
int result = 0;
try_again:
if (!first_only) {
while (auth_item != NULL) {
+ VERIFY_VP(auth_item);
if ((auth_item->da == from) || (!from)) {
break;
}
* another of the same attribute, which DOES match.
*/
if ((result != 0) && (!first_only)) {
+ fr_assert(auth_item != NULL);
auth_item = auth_item->next;
result = 0;
goto try_again;
return true;
}
+ /*
+ * Same checks as above, but with the types swapped, and
+ * with explicit cast for the interpretor.
+ */
+ if ((lhs_type == PW_TYPE_IPV4_ADDR) &&
+ (c->data.map->rhs->tmpl_da->type == PW_TYPE_IPV4_PREFIX)) {
+ c->cast = c->data.map->rhs->tmpl_da;
+ return true;
+ }
+
+ if ((lhs_type == PW_TYPE_IPV6_ADDR) &&
+ (c->data.map->rhs->tmpl_da->type == PW_TYPE_IPV6_PREFIX)) {
+ c->cast = c->data.map->rhs->tmpl_da;
+ return true;
+ }
+
return false;
}
*/
if ((c->data.map->lhs->type == TMPL_TYPE_ATTR) &&
(c->data.map->rhs->type == TMPL_TYPE_LITERAL)) {
- PW_TYPE type;
+ PW_TYPE type = c->data.map->lhs->tmpl_da->type;
switch (c->data.map->lhs->tmpl_da->type) {
case PW_TYPE_IPV4_ADDR:
- type = PW_TYPE_IPV4_PREFIX;
+ if (strchr(c->data.map->rhs->name, '/') != NULL) {
+ type = PW_TYPE_IPV4_PREFIX;
+ c->cast = dict_attrbyvalue(PW_CAST_BASE + type, 0);
+ }
break;
case PW_TYPE_IPV6_ADDR:
- type = PW_TYPE_IPV6_PREFIX;
+ if (strchr(c->data.map->rhs->name, '/') != NULL) {
+ type = PW_TYPE_IPV6_PREFIX;
+ c->cast = dict_attrbyvalue(PW_CAST_BASE + type, 0);
+ }
break;
default:
- type = c->data.map->lhs->tmpl_da->type;
break;
}
} /* attr to literal comparison */
/*
+ * The RHS will turn into... something. Allow for prefixes
+ * there, too.
+ */
+ if ((c->data.map->lhs->type == TMPL_TYPE_ATTR) &&
+ ((c->data.map->rhs->type == TMPL_TYPE_XLAT) ||
+ (c->data.map->rhs->type == TMPL_TYPE_XLAT_STRUCT) ||
+ (c->data.map->rhs->type == TMPL_TYPE_EXEC))) {
+ if (c->data.map->lhs->tmpl_da->type == PW_TYPE_IPV4_ADDR) {
+ c->cast = dict_attrbyvalue(PW_CAST_BASE + PW_TYPE_IPV4_PREFIX, 0);
+ }
+
+ if (c->data.map->lhs->tmpl_da->type == PW_TYPE_IPV6_ADDR) {
+ c->cast = dict_attrbyvalue(PW_CAST_BASE + PW_TYPE_IPV6_PREFIX, 0);
+ }
+ }
+
+ /*
* If the LHS is a bare word, AND it looks like
* an attribute, try to parse it as such.
*
static int request_num_counter = 1;
#ifdef WITH_PROXY
static int request_will_proxy(REQUEST *request) CC_HINT(nonnull);
-static int request_proxy(REQUEST *request, int retransmit) CC_HINT(nonnull);
+static int request_proxy(REQUEST *request) CC_HINT(nonnull);
STATE_MACHINE_DECL(request_ping) CC_HINT(nonnull);
STATE_MACHINE_DECL(request_response_delay) CC_HINT(nonnull);
return;
} /* else it's time to clean up */
- request_done(request, REQUEST_DONE);
+ request_done(request, FR_ACTION_DONE);
break;
default:
switch (action) {
case FR_ACTION_DUP:
- ERROR("(%u) Discarding duplicate request from "
+ RDEBUG("(%u) Discarding duplicate request from "
"client %s port %d - ID: %u due to delayed response",
request->number, request->client->shortname,
request->packet->src_port,request->packet->id);
* up the post proxy fail
* handler.
*/
- if (request_proxy(request, 0) < 0) goto req_finished;
+ if (request_proxy(request) < 0) goto req_finished;
} else
#endif
{
#ifdef WITH_ACCOUNTING
if (listener->type != RAD_LISTEN_DETAIL)
#endif
+
+#ifdef WITH_TCP
{
sock = listener->data;
sock->last_packet = now.tv_sec;
-#ifdef WITH_TCP
packet->proto = sock->proto;
-#endif
}
+#endif
/*
* Skip everything if required.
ERROR("No memory");
return NULL;
}
- request->reply = rad_alloc(request, false);
+ request->reply = rad_alloc_reply(request, packet);
if (!request->reply) {
ERROR("No memory");
talloc_free(request);
#ifdef WITH_PROXY
/*
- * Add +/- 2s of jitter, as suggested in RFC 3539
- * and in RFC 5080.
- */
-static void add_jitter(struct timeval *when)
-{
- uint32_t jitter;
-
- when->tv_sec -= 2;
-
- jitter = fr_rand();
- jitter ^= (jitter >> 10);
- jitter &= ((1 << 22) - 1); /* 22 bits of 1 */
-
- /*
- * Add in ~ (4 * USEC) of jitter.
- */
- tv_add(when, jitter);
-}
-
-/*
* Called by socket_del to remove requests with this socket
*/
static int eol_proxy_listener(void *ctx, void *data)
}
#ifdef WITH_COA
- if (request->packet->code == request->proxy->code)
+ if (request->packet->code == request->proxy->code) {
/*
* Don't run the next bit if we originated a CoA
* packet, after receiving an Access-Request or
*/
#endif
- /*
- * There may NOT be a proxy reply, as we may be
- * running Post-Proxy-Type = Fail.
- */
- if (reply) {
- fr_pair_add(&request->reply->vps, fr_pair_list_copy(request->reply, reply->vps));
-
/*
- * Delete the Proxy-State Attributes from
- * the reply. These include Proxy-State
- * attributes from us and remote server.
+ * There may NOT be a proxy reply, as we may be
+ * running Post-Proxy-Type = Fail.
*/
- fr_pair_delete_by_num(&request->reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
- }
+ if (reply) {
+ fr_pair_add(&request->reply->vps, fr_pair_list_copy(request->reply, reply->vps));
+ /*
+ * Delete the Proxy-State Attributes from
+ * the reply. These include Proxy-State
+ * attributes from us and remote server.
+ */
+ fr_pair_delete_by_num(&request->reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
+
+ } else {
+ vp = fr_pair_find_by_num(request->config, PW_RESPONSE_PACKET_TYPE, 0, TAG_ANY);
+ if (vp && (vp->vp_integer != 256)) {
+ request->proxy_reply = rad_alloc_reply(request, request->proxy);
+ request->proxy_reply->code = vp->vp_integer;
+ }
+ }
+#ifdef WITH_COA
+ }
+#endif
switch (rcode) {
default: /* Don't do anything */
break;
}
request = fr_packet2myptr(REQUEST, proxy, proxy_p);
- request->num_proxied_responses++; /* needs to be protected by lock */
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
* Status-Server packets don't count as real packets.
*/
if (request->proxy->code != PW_CODE_STATUS_SERVER) {
+#ifdef WITH_TCP
listen_socket_t *sock = request->proxy_listener->data;
- request->home_server->last_packet_recv = now.tv_sec;
sock->last_packet = now.tv_sec;
+#endif
+ request->home_server->last_packet_recv = now.tv_sec;
}
+ request->num_proxied_responses++;
+
/*
* If we have previously seen a reply, ignore the
* duplicate.
#ifdef WITH_ACCOUNTING
case PW_CODE_ACCOUNTING_REQUEST:
+ proxy_acct_stats.last_packet = packet->timestamp.tv_sec;
+
request->proxy_listener->stats.total_responses++;
proxy_acct_stats.last_packet = packet->timestamp.tv_sec;
break;
request->server = old_server;
} else {
+ char buffer[128];
+
+ RDEBUG2("Starting proxy to home server %s port %d",
+ inet_ntop(request->proxy->dst_ipaddr.af,
+ &request->proxy->dst_ipaddr.ipaddr,
+ buffer, sizeof(buffer)),
+ request->proxy->dst_port);
+
rcode = process_pre_proxy(pre_proxy_type, request);
}
}
-static int request_proxy(REQUEST *request, int retransmit)
+static int request_proxy(REQUEST *request)
{
char buffer[128];
}
- gettimeofday(&request->proxy_retransmit, NULL);
- if (!retransmit) {
- request->proxy->timestamp = request->proxy_retransmit;
- }
- request->home_server->last_packet_sent = request->proxy_retransmit.tv_sec;
+ gettimeofday(&request->proxy->timestamp, NULL);
+ request->home_server->last_packet_sent = request->proxy->timestamp.tv_sec;
/*
* Encode the packet before we do anything else.
#ifdef WITH_ACCOUNTING
/*
- * Update the Acct-Delay-Time attribute.
+ * Update the Acct-Delay-Time attribute, since the LAST
+ * time we tried to retransmit this packet.
*/
if (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) {
VALUE_PAIR *vp;
struct timeval now;
gettimeofday(&now, NULL);
- vp->vp_integer += now.tv_sec - request->proxy_retransmit.tv_sec;
+ vp->vp_integer += now.tv_sec - request->proxy->timestamp.tv_sec;
}
}
#endif
request->proxy->data = NULL;
request->proxy->data_len = 0;
- if (request_proxy(request, 1) != 1) goto post_proxy_fail;
+ if (request_proxy(request) != 1) goto post_proxy_fail;
return 1;
}
&request->proxy->dst_ipaddr.ipaddr,
buffer, sizeof(buffer)),
request->proxy->dst_port);
+ remove_from_proxy_hash(request);
break;
case FR_ACTION_PROXY_REPLY:
}
rad_assert(!request->in_request_hash);
+ rad_assert(!request->in_proxy_hash);
rad_assert(request->ev == NULL);
NO_CHILD_THREAD;
request_done(request, FR_ACTION_DONE);
}
/*
+ * Add +/- 2s of jitter, as suggested in RFC 3539
+ * and in RFC 5080.
+ */
+static void add_jitter(struct timeval *when)
+{
+ uint32_t jitter;
+
+ when->tv_sec -= 2;
+
+ jitter = fr_rand();
+ jitter ^= (jitter >> 10);
+ jitter &= ((1 << 22) - 1); /* 22 bits of 1 */
+
+ /*
+ * Add in ~ (4 * USEC) of jitter.
+ */
+ tv_add(when, jitter);
+}
+
+/*
* Called from start of zombie period, OR after control socket
* marks the home server dead.
*/
struct timeval when, now;
if ((home->state == HOME_STATE_ALIVE) ||
-#ifdef WITH_TCP
- (home->proto == IPPROTO_TCP) ||
-#endif
(home->ev != NULL)) {
return;
}
fr_pair_make(request->proxy, &request->proxy->vps,
"Message-Authenticator", "0x00", T_OP_SET);
- } else if (home->type == HOME_TYPE_AUTH) {
+ } else if ((home->type == HOME_TYPE_AUTH) ||
+ (home->type == HOME_TYPE_AUTH_ACCT)) {
request->proxy->code = PW_CODE_ACCESS_REQUEST;
fr_pair_make(request->proxy, &request->proxy->vps,
fr_pair_make(request->proxy, &request->proxy->vps,
"Message-Authenticator", "0x00", T_OP_SET);
- } else {
#ifdef WITH_ACCOUNTING
+ } else if (home->type == HOME_TYPE_ACCT) {
request->proxy->code = PW_CODE_ACCOUNTING_REQUEST;
fr_pair_make(request->proxy, &request->proxy->vps,
vp = fr_pair_make(request->proxy, &request->proxy->vps,
"Event-Timestamp", "0", T_OP_SET);
vp->vp_date = now.tv_sec;
-#else
- rad_assert("Internal sanity check failed");
#endif
+
+ } else {
+ /*
+ * Unkown home server type.
+ */
+ talloc_free(request);
+ return;
}
vp = fr_pair_make(request->proxy, &request->proxy->vps,
rad_assert((home->state == HOME_STATE_ALIVE) ||
(home->state == HOME_STATE_UNKNOWN));
-#ifdef WITH_TCP
- if (home->proto == IPPROTO_TCP) {
- WARN("Not marking TCP server %s zombie", home->log_name);
- return;
- }
-#endif
-
/*
* We've received a real packet recently. Don't mark the
* server as zombie until we've received NO packets for a
home_server_t *home = talloc_get_type_abort(ctx, home_server_t);
char buffer[128];
-#ifdef WITH_TCP
- rad_assert(home->proto != IPPROTO_TCP);
-#endif
-
home->state = HOME_STATE_ALIVE;
home->response_timeouts = 0;
home_trigger(home, "home_server.alive");
int previous_state = home->state;
char buffer[128];
-#ifdef WITH_TCP
- if (home->proto == IPPROTO_TCP) {
- WARN("Not marking TCP server dead");
- return;
- }
-#endif
-
PROXY( "Marking home server %s port %d as dead.",
inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
buffer, sizeof(buffer)),
* More than one retransmit a second is stupid,
* and should be suppressed by the proxy.
*/
- when = request->proxy_retransmit;
+ when = request->proxy->timestamp;
when.tv_sec++;
if (timercmp(&now, &when, <)) {
rad_assert(request->proxy_listener != NULL);
FR_STATS_TYPE_INC(home->stats.total_requests);
home->last_packet_sent = now.tv_sec;
- request->proxy_retransmit = now;
+ request->proxy->timestamp = now;
debug_packet(request, request->proxy, false);
request->proxy_listener->send(request->proxy_listener, request);
break;
* "response_window", then mark the home server
* as zombie.
*
- * If the connection is TCP, then another
- * "watchdog timer" function takes care of pings,
- * etc. So we don't need to do it here.
- *
* This check should really be part of a home
* server state machine.
*/
if (((home->state == HOME_STATE_ALIVE) ||
(home->state == HOME_STATE_UNKNOWN))
-#ifdef WITH_TCP
- && (home->proto != IPPROTO_TCP)
-#endif
) {
home->response_timeouts++;
if (home->response_timeouts >= home->max_response_timeouts)
FR_STATS_TYPE_INC(proxy_acct_stats.total_timeouts);
}
#endif
+#ifdef WITH_COA
+ else if (home->type == HOME_TYPE_COA) {
+ if (request->proxy_listener) FR_STATS_TYPE_INC(request->proxy_listener->stats.total_timeouts);
+
+ if (request->packet->code == PW_CODE_COA_REQUEST) {
+ FR_STATS_TYPE_INC(proxy_coa_stats.total_timeouts);
+ } else {
+ FR_STATS_TYPE_INC(proxy_dsc_stats.total_timeouts);
+ }
+ }
+#endif
/*
* There was no response within the window. Stop
}
}
+ if (!main_config.proxy_requests) {
+ RWDEBUG("Cannot originate CoA packets unless 'proxy_requests = yes'");
+ TALLOC_FREE(request->coa);
+ return;
+ }
+
coa = request->coa;
/*
case FR_ACTION_TIMER:
if (request_max_time(request)) break;
+ /*
+ * Don't do fail-over. This is a 3.1 feature.
+ */
+ if (!request->home_server ||
+ (request->home_server->state == HOME_STATE_IS_DEAD) ||
+ !request->proxy_listener ||
+ (request->proxy_listener->status >= RAD_LISTEN_STATUS_EOL)) {
+ request_done(request, FR_ACTION_DONE);
+ break;
+ }
+
coa_retransmit(request);
break;
rad_assert(this->next == NULL);
talloc_free(this);
}
-#endif
#ifdef WITH_PROXY
static int proxy_eol_cb(void *ctx, void *data)
*/
return 0;
}
-#endif
+#endif /* WITH_PROXY */
+#endif /* WITH_TCP */
static int event_new_fd(rad_listen_t *this)
{
rad_panic("Failed to insert event");
}
}
-#endif
+#endif /* WITH_TCP */
break;
#endif /* WITH_PROXY */
fr_exit(1);
}
}
-#endif
+#endif /* WITH_TCP */
break;
} /* switch over listener types */
}
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
}
-#endif
+#endif /* WITH_PROXY */
/*
* Requests are still using the socket. Wait for
*/
this->status = RAD_LISTEN_STATUS_REMOVE_NOW;
} /* socket is at EOL */
-#endif
+#endif /* WITH_TCP */
/*
* Nuke the socket.
int devnull;
#ifdef WITH_TCP
listen_socket_t *sock = this->data;
-#endif
struct timeval when;
+#endif
/*
* Re-open the socket, pointing it to /dev/null.
}
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
} else
-#endif
+#endif /* WITH_PROXY */
{
INFO(" ... shutting down socket %s", buffer);
&(sock->ev))) {
rad_panic("Failed to insert event");
}
- }
#endif /* WITH_TCP */
+ }
return 1;
}
#ifndef HAVE_PTHREAD_H
void radius_signal_self(int flag)
{
+ if (flag == RADIUS_SIGNAL_SELF_TERM) {
+ main_config.exiting = true;
+ }
+
return handle_signal_self(flag);
}
ssize_t rcode;
uint8_t buffer[16];
+ if (flag == RADIUS_SIGNAL_SELF_TERM) {
+ main_config.exiting = true;
+ }
+
/*
* The read MUST be non-blocking for this to work.
*/
break;
default:
- REDEBUG("Can't determine expected response to Status-Server request, specify "
- "a well known RADIUS port, or add a Response-Packet-Type attribute "
- "to the request of filter");
- goto error;
+ request->filter_code = PW_CODE_UNDEFINED;
+ break;
}
break;
* If we had an expected response code, check to see if the
* packet matched that.
*/
- if (request->reply->code != request->filter_code) {
+ if ((request->filter_code != PW_CODE_UNDEFINED) && (request->reply->code != request->filter_code)) {
if (is_radius_code(request->reply->code)) {
REDEBUG("%s: Expected %s got %s", request->name, fr_packet_codes[request->filter_code],
fr_packet_codes[request->reply->code]);
/*
* Global variables.
*/
-char const *progname = NULL;
char const *radacct_dir = NULL;
char const *radlog_dir = NULL;
-char const *radlib_dir = NULL;
+
bool log_stripped_names;
char const *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION_STRING
bool display_version = false;
int flag = 0;
int from_child[2] = {-1, -1};
+ char *p;
fr_state_t *state = NULL;
/*
set_auth_parameters(argc, argv);
#endif
- if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
- progname = argv[0];
- else
- progname++;
-
#ifdef WIN32
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
- fprintf(stderr, "%s: Unable to initialize socket library.\n", progname);
+ fprintf(stderr, "%s: Unable to initialize socket library.\n",
+ main_config.name);
exit(EXIT_FAILURE);
}
}
memset(&main_config, 0, sizeof(main_config));
main_config.myip.af = AF_UNSPEC;
main_config.port = 0;
- main_config.name = "radiusd";
main_config.daemonize = true;
+ p = strrchr(argv[0], FR_DIR_SEP);
+ if (!p) {
+ main_config.name = argv[0];
+ } else {
+ main_config.name = p + 1;
+ }
+
/*
* Don't put output anywhere until we get told a little
* more.
default_log.fd = open(main_config.log_file,
O_WRONLY | O_APPEND | O_CREAT, 0640);
if (default_log.fd < 0) {
- fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", main_config.log_file, fr_syserror(errno));
+ fprintf(stderr, "%s: Failed to open log file %s: %s\n",
+ main_config.name, main_config.log_file, fr_syserror(errno));
exit(EXIT_FAILURE);
}
fr_log_fp = fdopen(default_log.fd, "a");
case 'i':
if (ip_hton(&main_config.myip, AF_UNSPEC, optarg, false) < 0) {
- fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
+ fprintf(stderr, "%s: Invalid IP Address or hostname \"%s\"\n",
+ main_config.name, optarg);
exit(EXIT_FAILURE);
}
flag |= 1;
port = strtoul(optarg, 0, 10);
if ((port == 0) || (port > UINT16_MAX)) {
- fprintf(stderr, "radiusd: Invalid port number \"%s\"\n", optarg);
+ fprintf(stderr, "%s: Invalid port number \"%s\"\n",
+ main_config.name, optarg);
exit(EXIT_FAILURE);
}
* Mismatch between the binary and the libraries it depends on.
*/
if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
- fr_perror("radiusd");
+ fr_perror("%s", main_config.name);
exit(EXIT_FAILURE);
}
#endif
if (flag && (flag != 0x03)) {
- fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
+ fprintf(stderr, "%s: The options -i and -p cannot be used individually.\n",
+ main_config.name);
exit(EXIT_FAILURE);
}
*/
if (main_config.memory_report) {
if (spawn_flag) {
- fprintf(stderr, "radiusd: The server cannot produce memory reports (-M) in threaded mode\n");
+ fprintf(stderr, "%s: The server cannot produce memory reports (-M) in threaded mode\n",
+ main_config.name);
exit(EXIT_FAILURE);
}
talloc_enable_null_tracking();
* Better here, so it doesn't matter whether we get passed -xv or -vx.
*/
if (display_version) {
- /* Don't print timestamps */
- rad_debug_lvl += 2;
+ if (rad_debug_lvl == 0) rad_debug_lvl = 1;
fr_log_fp = stdout;
default_log.dst = L_DST_STDOUT;
default_log.fd = STDOUT_FILENO;
- INFO("%s: %s", progname, radiusd_version);
+ INFO("%s: %s", main_config.name, radiusd_version);
version_print();
exit(EXIT_SUCCESS);
}
if (!panic_action) panic_action = main_config.panic_action;
if (panic_action && (fr_fault_setup(panic_action, argv[0]) < 0)) {
- fr_perror("radiusd");
+ fr_perror("%s", main_config.name);
exit(EXIT_FAILURE);
}
}
{
FILE *output = status?stderr:stdout;
- fprintf(output, "Usage: %s [options]\n", progname);
+ fprintf(output, "Usage: %s [options]\n", main_config.name);
fprintf(output, "Options:\n");
fprintf(output, " -C Check configuration and exit.\n");
fprintf(stderr, " -d <raddb> Set configuration directory (defaults to " RADDBDIR ").\n");
endif
SRC_CFLAGS := -DHOSTINFO=\"${HOSTINFO}\"
-ifneq ($(MAKECMDGOALS),scan)
-SRC_CFLAGS += -DBUILT_WITH_CPPFLAGS=\"$(CPPFLAGS)\" -DBUILT_WITH_CFLAGS=\"$(CFLAGS)\" -DBUILT_WITH_LDFLAGS=\"$(LDFLAGS)\" -DBUILT_WITH_LIBS=\"$(LIBS)\"
-endif
TGT_INSTALLDIR := ${sbindir}
TGT_LDLIBS := $(LIBS) $(OPENSSL_LIBS) $(LCRYPT)
-install: install.bindir $(R)$(bindir)/radlast
+install: $(R)$(bindir)/radlast
-$(R)$(bindir)/radlast: src/main/radlast
+$(R)$(bindir)/radlast: src/main/radlast | $(R)$(bindir)
@echo INSTALL $(notdir $<)
@$(INSTALL) -m 755 $< $(R)$(bindir)
/*
* For configuration file stuff.
*/
-char const *progname = "radmin";
+static char const *progname = "radmin";
static char const *radmin_version = "radmin version " RADIUSD_VERSION_STRING
#ifdef RADIUSD_VERSION_COMMIT
" (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")"
if (!quiet) {
printf("%s - FreeRADIUS Server administration tool.\n", radmin_version);
- printf("Copyright (C) 2008-2015 The FreeRADIUS server project and contributors.\n");
+ printf("Copyright (C) 2008-2016 The FreeRADIUS server project and contributors.\n");
printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
printf("PARTICULAR PURPOSE.\n");
printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
diff, udp_len);
return;
}
- /* Trailing data */
+
+#if 0
+ /*
+ * It seems many probes add trailing garbage to the end
+ * of each capture frame. This has been observed with
+ * the F5 and Netscout.
+ *
+ * Leaving the code here in case it's ever needed for
+ * debugging.
+ */
else if (diff < 0) {
REDEBUG("Packet too big by %zi bytes, UDP header + Payload should be %hu bytes",
diff * -1, udp_len);
return;
}
+#endif
}
if ((version == 4) && conf->verify_udp_checksum) {
uint16_t expected;
-install: install.bindir $(R)$(bindir)/radtest
+install: $(R)$(bindir)/radtest
-$(R)$(bindir)/radtest: src/main/radtest
+$(R)$(bindir)/radtest: src/main/radtest | $(R)$(bindir)
@echo INSTALL $(notdir $<)
@$(INSTALL) -m 755 $< $(R)$(bindir)
static int showname = -1;
static int showptype = 0;
static int showcid = 0;
-char const *progname = "radwho";
+static char const *progname = "radwho";
char const *radlog_dir = NULL;
static char const *radutmp_file = NULL;
static char const *dict_dir = DICTDIR;
char const *radacct_dir = NULL;
-char const *radlib_dir = NULL;
bool log_stripped_names;
-install: install.bindir $(R)$(bindir)/radzap
+install: $(R)$(bindir)/radzap
-$(R)$(bindir)/radzap: src/main/radzap
+$(R)$(bindir)/radzap: src/main/radzap | $(R)$(bindir)
@echo INSTALL $(notdir $<)
@$(INSTALL) -m 755 $< $(R)$(bindir)
return 0;
}
+ if (strcmp(fmt, "state") == 0) {
+ char const *state;
+
+ switch (request->home_server->state) {
+ case HOME_STATE_ALIVE:
+ state = "alive";
+ break;
+
+ case HOME_STATE_ZOMBIE:
+ state = "zombie";
+ break;
+
+ case HOME_STATE_IS_DEAD:
+ state = "dead";
+ break;
+
+ default:
+ state = "unknown";
+ break;
+ }
+
+ strlcpy(out, state, outlen);
+ return strlen(out);
+ }
+
return xlat_cs(request->home_server->cs, fmt, out, outlen);
}
return 0;
}
+ if (strcmp(fmt, "state") == 0) {
+ char const *state;
+
+ if (request->home_pool->in_fallback) {
+ state = "fallback";
+
+ } else {
+ state = "alive";
+ }
+
+ strlcpy(out, state, outlen);
+ return strlen(out);
+ }
+
return xlat_cs(request->home_pool->cs, fmt, out, outlen);
}
#endif
goto error;
}
- if ((home->type == HOME_TYPE_AUTH) && !home->ping_user_password) {
+ if (((home->type == HOME_TYPE_AUTH) ||
+ (home->type == HOME_TYPE_AUTH_ACCT)) && !home->ping_user_password) {
cf_log_err_cs(cs, "You must supply a 'password' to enable status_check=request");
goto error;
}
if (cs) {
server = cf_section_dup(client, cs, "home_server", NULL, true);
} else {
- server = cf_section_alloc(client, "home_server", NULL);
+ server = cf_section_alloc(client, "home_server", cf_section_name2(client));
}
if (!cs || (!cf_pair_find(cs, "ipaddr") && !cf_pair_find(cs, "ipv4addr") && !cf_pair_find(cs, "ipv6addr"))) {
}
-home_server_t *home_server_find(fr_ipaddr_t *ipaddr, uint16_t port, int proto)
+home_server_t *home_server_find(fr_ipaddr_t *ipaddr, uint16_t port,
+#ifndef WITH_TCP
+ UNUSED
+#endif
+ int proto)
{
home_server_t myhome;
int session_time)
{
REQUEST *stopreq;
- VALUE_PAIR *vp, *userpair;
+ VALUE_PAIR *vp;
int ret;
stopreq = request_alloc_fake(request);
if(!(vp = fr_pair_afrom_num(stopreq->packet,n, 0))) { \
talloc_free(stopreq); \
ERROR("no memory"); \
- fr_pair_list_free(&(stopreq->packet->vps)); \
return 0; \
} \
vp->e = v; \
if(!(vp = fr_pair_afrom_num(stopreq->packet,n, 0))) { \
talloc_free(stopreq); \
ERROR("no memory"); \
- fr_pair_list_free(&(stopreq->packet->vps)); \
return 0; \
} \
fr_pair_value_strcpy(vp, v); \
INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
+
+ INTPAIR(PW_EVENT_TIMESTAMP, 0);
+ vp->vp_date = time(NULL);
INTPAIR(PW_ACCT_DELAY_TIME, 0);
+
STRINGPAIR(PW_USER_NAME, user);
- userpair = vp;
+ stopreq->username = vp;
+
INTPAIR(PW_NAS_PORT, nas_port);
STRINGPAIR(PW_ACCT_SESSION_ID, sessionid);
if(proto == 'P') {
INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
- stopreq->username = userpair;
stopreq->password = NULL;
+ RDEBUG("Running Accounting section for automatically created accounting 'stop'");
+ rdebug_pair_list(L_DBG_LVL_1, request, request->packet->vps, NULL);
ret = rad_accounting(stopreq);
/*
VALUE_PAIR *vp;
uint8_t c;
int t;
- char *q;
while (data_len > 0) {
c = *p++;
vp = pair_make_request("SoH-MS-Machine-Name", NULL, T_OP_EQ);
if (!vp) return 0;
- vp->vp_strvalue = q = talloc_array(vp, char, t);
- vp->type = VT_DATA;
-
- memcpy(q, p, t);
- q[t] = 0;
+ fr_pair_value_bstrncpy(vp, p, t);
p += t;
data_len -= 2 + t;
int tries;
- VALUE_PAIR *vps;
+ TALLOC_CTX *ctx;
+ VALUE_PAIR *vps;
void *opaque;
void (*free_opaque)(void *opaque);
(void) talloc_get_type_abort(entry, state_entry_t);
#endif
rbtree_deletebydata(state->tree, entry);
+
+ if (entry->ctx) talloc_free(entry->ctx);
+
talloc_free(entry);
}
/*
* Create a new entry. Called with the mutex held.
*/
-static state_entry_t *fr_state_create(fr_state_t *state, RADIUS_PACKET *packet, state_entry_t *old)
+static state_entry_t *fr_state_create(fr_state_t *state, const char *server, RADIUS_PACKET *packet, state_entry_t *old)
{
size_t i;
uint32_t x;
* Unused. We can delete it, even if now isn't
* the time to clean it up.
*/
- if (!entry->vps && !entry->opaque) {
+ if (!entry->ctx && !entry->opaque) {
state_entry_free(state, entry);
continue;
}
if (old) {
entry->tries = old->tries + 1;
- rad_assert(old->vps == NULL);
-
/*
* Track State
*/
fr_pair_add(&packet->vps, vp);
}
+ /* Make unique for different virtual servers handling same request
+ */
+ if (server) *((uint32_t *)(&entry->state[4])) ^= fr_hash_string(server);
+
if (!rbtree_insert(state->tree, entry)) {
talloc_free(entry);
return NULL;
/*
* Find the entry, based on the State attribute.
*/
-static state_entry_t *fr_state_find(fr_state_t *state, RADIUS_PACKET *packet)
+static state_entry_t *fr_state_find(fr_state_t *state, const char *server, RADIUS_PACKET *packet)
{
VALUE_PAIR *vp;
state_entry_t *entry, my_entry;
memcpy(my_entry.state, vp->vp_octets, sizeof(my_entry.state));
+ /* Make unique for different virtual servers handling same request
+ */
+ if (server) *((uint32_t *)(&my_entry.state[4])) ^= fr_hash_string(server);
+
entry = rbtree_finddata(state->tree, &my_entry);
#ifdef WITH_VERIFY_PTR
request->state = NULL;
PTHREAD_MUTEX_LOCK(&state->mutex);
- entry = fr_state_find(state, original);
+ entry = fr_state_find(state, request->server, original);
if (!entry) {
PTHREAD_MUTEX_UNLOCK(&state->mutex);
return;
{
state_entry_t *entry;
fr_state_t *state = &global_state;
+ TALLOC_CTX *old_ctx = NULL;
rad_assert(request->state == NULL);
}
PTHREAD_MUTEX_LOCK(&state->mutex);
- entry = fr_state_find(state, packet);
+ entry = fr_state_find(state, request->server, packet);
/*
* This has to be done in a mutex lock, because talloc
* isn't thread-safe.
*/
if (entry) {
- fr_pair_list_mcopy_by_num(request, &request->state, &entry->vps, 0, 0, TAG_ANY);
- RDEBUG2("session-state: Found cached attributes");
- rdebug_pair_list(L_DBG_LVL_1, request, request->state, NULL);
+ RDEBUG2("Restoring &session-state");
+
+ if (request->state_ctx) old_ctx = request->state_ctx;
+
+ request->state_ctx = entry->ctx;
+ request->state = entry->vps;
+
+ entry->ctx = NULL;
+ entry->vps = NULL;
+
+ rdebug_pair_list(L_DBG_LVL_2, request, request->state, "&session-state:");
} else {
RDEBUG2("session-state: No cached attributes");
PTHREAD_MUTEX_UNLOCK(&state->mutex);
+ /*
+ * Free this outside of the mutex for less contention.
+ */
+ if (old_ctx) talloc_free(old_ctx);
+
VERIFY_REQUEST(request);
return;
}
PTHREAD_MUTEX_LOCK(&state->mutex);
if (original) {
- old = fr_state_find(state, original);
+ old = fr_state_find(state, request->server, original);
} else {
old = NULL;
}
- entry = fr_state_create(state, packet, old);
+ entry = fr_state_create(state, request->server, packet, old);
if (!entry) {
PTHREAD_MUTEX_UNLOCK(&state->mutex);
return false;
}
- /*
- * This has to be done in a mutex lock, because talloc
- * isn't thread-safe.
- */
- fr_pair_list_mcopy_by_num(entry, &entry->vps, &request->state, 0, 0, TAG_ANY);
+ rad_assert(entry->ctx == NULL);
+ entry->ctx = request->state_ctx;
+ entry->vps = request->state;
+
+ request->state_ctx = NULL;
+ request->state = NULL;
+
PTHREAD_MUTEX_UNLOCK(&state->mutex);
rad_assert(request->state == NULL);
* Find the opaque data associated with a State attribute.
* Leave the data in the entry.
*/
-void *fr_state_find_data(fr_state_t *state, UNUSED REQUEST *request, RADIUS_PACKET *packet)
+void *fr_state_find_data(fr_state_t *state, REQUEST *request, RADIUS_PACKET *packet)
{
void *data;
state_entry_t *entry;
if (!state) return false;
PTHREAD_MUTEX_LOCK(&state->mutex);
- entry = fr_state_find(state, packet);
+ entry = fr_state_find(state, request->server, packet);
if (!entry) {
PTHREAD_MUTEX_UNLOCK(&state->mutex);
return NULL;
* Get the opaque data associated with a State attribute.
* and remove the data from the entry.
*/
-void *fr_state_get_data(fr_state_t *state, UNUSED REQUEST *request, RADIUS_PACKET *packet)
+void *fr_state_get_data(fr_state_t *state, REQUEST *request, RADIUS_PACKET *packet)
{
void *data;
state_entry_t *entry;
if (!state) return NULL;
PTHREAD_MUTEX_LOCK(&state->mutex);
- entry = fr_state_find(state, packet);
+ entry = fr_state_find(state, request->server, packet);
if (!entry) {
PTHREAD_MUTEX_UNLOCK(&state->mutex);
return NULL;
* Get the opaque data associated with a State attribute.
* and remove the data from the entry.
*/
-bool fr_state_put_data(fr_state_t *state, UNUSED REQUEST *request, RADIUS_PACKET *original, RADIUS_PACKET *packet,
+bool fr_state_put_data(fr_state_t *state, REQUEST *request, RADIUS_PACKET *original, RADIUS_PACKET *packet,
void *data, void (*free_data)(void *))
{
state_entry_t *entry, *old;
PTHREAD_MUTEX_LOCK(&state->mutex);
if (original) {
- old = fr_state_find(state, original);
+ old = fr_state_find(state, request->server, original);
} else {
old = NULL;
}
- entry = fr_state_create(state, packet, old);
+ entry = fr_state_create(state, request->server, packet, old);
if (!entry) {
PTHREAD_MUTEX_UNLOCK(&state->mutex);
return false;
#endif
#endif
-
static void tv_sub(struct timeval *end, struct timeval *start,
struct timeval *elapsed)
{
#undef INC_AUTH
#define INC_AUTH(_x) radius_auth_stats._x++;request->listener->stats._x++;request->client->auth._x++;
-
#undef INC_ACCT
#ifdef WITH_ACCOUNTING
#define INC_ACCT(_x) radius_acct_stats._x++;request->listener->stats._x++;request->client->acct._x++
#ifdef WITH_ACCOUNTING
case PW_CODE_ACCOUNTING_REQUEST:
- proxy_acct_stats.total_requests++;
+ proxy_acct_stats.total_requests += request->num_proxied_requests;
request->home_server->stats.total_requests += request->num_proxied_requests;
break;
#endif
#ifdef WITH_COA
case PW_CODE_COA_REQUEST:
- proxy_coa_stats.total_requests++;
+ proxy_coa_stats.total_requests += request->num_proxied_requests;
request->home_server->stats.total_requests += request->num_proxied_requests;
break;
case PW_CODE_DISCONNECT_REQUEST:
- proxy_dsc_stats.total_requests++;
+ proxy_dsc_stats.total_requests += request->num_proxied_requests;
request->home_server->stats.total_requests += request->num_proxied_requests;
break;
#endif
case PW_CODE_COA_NAK:
proxy_coa_stats.total_responses++;
request->home_server->stats.total_responses++;
- stats_time(&proxy_acct_stats,
+ stats_time(&proxy_coa_stats,
&request->proxy->timestamp,
&request->proxy_reply->timestamp);
stats_time(&request->home_server->stats,
case PW_CODE_DISCONNECT_ACK:
case PW_CODE_DISCONNECT_NAK:
- proxy_coa_stats.total_responses++;
+ proxy_dsc_stats.total_responses++;
request->home_server->stats.total_responses++;
- stats_time(&proxy_acct_stats,
+ stats_time(&proxy_dsc_stats,
&request->proxy->timestamp,
&request->proxy_reply->timestamp);
stats_time(&request->home_server->stats,
* Authentication
*/
static fr_stats2vp authvp[] = {
- { 128, offsetof(fr_stats_t, total_requests) },
- { 129, offsetof(fr_stats_t, total_access_accepts) },
- { 130, offsetof(fr_stats_t, total_access_rejects) },
- { 131, offsetof(fr_stats_t, total_access_challenges) },
- { 132, offsetof(fr_stats_t, total_responses) },
- { 133, offsetof(fr_stats_t, total_dup_requests) },
- { 134, offsetof(fr_stats_t, total_malformed_requests) },
- { 135, offsetof(fr_stats_t, total_bad_authenticators) },
- { 136, offsetof(fr_stats_t, total_packets_dropped) },
- { 137, offsetof(fr_stats_t, total_unknown_types) },
+ { PW_FREERADIUS_TOTAL_ACCESS_REQUESTS, offsetof(fr_stats_t, total_requests) },
+ { PW_FREERADIUS_TOTAL_ACCESS_ACCEPTS, offsetof(fr_stats_t, total_access_accepts) },
+ { PW_FREERADIUS_TOTAL_ACCESS_REJECTS, offsetof(fr_stats_t, total_access_rejects) },
+ { PW_FREERADIUS_TOTAL_ACCESS_CHALLENGES, offsetof(fr_stats_t, total_access_challenges) },
+ { PW_FREERADIUS_TOTAL_AUTH_RESPONSES, offsetof(fr_stats_t, total_responses) },
+ { PW_FREERADIUS_TOTAL_AUTH_DUPLICATE_REQUESTS, offsetof(fr_stats_t, total_dup_requests) },
+ { PW_FREERADIUS_TOTAL_AUTH_MALFORMED_REQUESTS, offsetof(fr_stats_t, total_malformed_requests) },
+ { PW_FREERADIUS_TOTAL_AUTH_INVALID_REQUESTS, offsetof(fr_stats_t, total_bad_authenticators) },
+ { PW_FREERADIUS_TOTAL_AUTH_DROPPED_REQUESTS, offsetof(fr_stats_t, total_packets_dropped) },
+ { PW_FREERADIUS_TOTAL_AUTH_UNKNOWN_TYPES, offsetof(fr_stats_t, total_unknown_types) },
{ 0, 0 }
};
* Proxied authentication requests.
*/
static fr_stats2vp proxy_authvp[] = {
- { 138, offsetof(fr_stats_t, total_requests) },
- { 139, offsetof(fr_stats_t, total_access_accepts) },
- { 140, offsetof(fr_stats_t, total_access_rejects) },
- { 141, offsetof(fr_stats_t, total_access_challenges) },
- { 142, offsetof(fr_stats_t, total_responses) },
- { 143, offsetof(fr_stats_t, total_dup_requests) },
- { 144, offsetof(fr_stats_t, total_malformed_requests) },
- { 145, offsetof(fr_stats_t, total_bad_authenticators) },
- { 146, offsetof(fr_stats_t, total_packets_dropped) },
- { 147, offsetof(fr_stats_t, total_unknown_types) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCESS_REQUESTS, offsetof(fr_stats_t, total_requests) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCESS_ACCEPTS, offsetof(fr_stats_t, total_access_accepts) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCESS_REJECTS, offsetof(fr_stats_t, total_access_rejects) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCESS_CHALLENGES, offsetof(fr_stats_t, total_access_challenges) },
+ { PW_FREERADIUS_TOTAL_PROXY_AUTH_RESPONSES, offsetof(fr_stats_t, total_responses) },
+ { PW_FREERADIUS_TOTAL_PROXY_AUTH_DUPLICATE_REQUESTS, offsetof(fr_stats_t, total_dup_requests) },
+ { PW_FREERADIUS_TOTAL_PROXY_AUTH_MALFORMED_REQUESTS, offsetof(fr_stats_t, total_malformed_requests) },
+ { PW_FREERADIUS_TOTAL_PROXY_AUTH_INVALID_REQUESTS, offsetof(fr_stats_t, total_bad_authenticators) },
+ { PW_FREERADIUS_TOTAL_PROXY_AUTH_DROPPED_REQUESTS, offsetof(fr_stats_t, total_packets_dropped) },
+ { PW_FREERADIUS_TOTAL_PROXY_AUTH_UNKNOWN_TYPES, offsetof(fr_stats_t, total_unknown_types) },
{ 0, 0 }
};
#endif
* Accounting
*/
static fr_stats2vp acctvp[] = {
- { 148, offsetof(fr_stats_t, total_requests) },
- { 149, offsetof(fr_stats_t, total_responses) },
- { 150, offsetof(fr_stats_t, total_dup_requests) },
- { 151, offsetof(fr_stats_t, total_malformed_requests) },
- { 152, offsetof(fr_stats_t, total_bad_authenticators) },
- { 153, offsetof(fr_stats_t, total_packets_dropped) },
- { 154, offsetof(fr_stats_t, total_unknown_types) },
+ { PW_FREERADIUS_TOTAL_ACCOUNTING_REQUESTS, offsetof(fr_stats_t, total_requests) },
+ { PW_FREERADIUS_TOTAL_ACCOUNTING_RESPONSES, offsetof(fr_stats_t, total_responses) },
+ { PW_FREERADIUS_TOTAL_ACCT_DUPLICATE_REQUESTS, offsetof(fr_stats_t, total_dup_requests) },
+ { PW_FREERADIUS_TOTAL_ACCT_MALFORMED_REQUESTS, offsetof(fr_stats_t, total_malformed_requests) },
+ { PW_FREERADIUS_TOTAL_ACCT_INVALID_REQUESTS, offsetof(fr_stats_t, total_bad_authenticators) },
+ { PW_FREERADIUS_TOTAL_ACCT_DROPPED_REQUESTS, offsetof(fr_stats_t, total_packets_dropped) },
+ { PW_FREERADIUS_TOTAL_ACCT_UNKNOWN_TYPES, offsetof(fr_stats_t, total_unknown_types) },
{ 0, 0 }
};
#ifdef WITH_PROXY
static fr_stats2vp proxy_acctvp[] = {
- { 155, offsetof(fr_stats_t, total_requests) },
- { 156, offsetof(fr_stats_t, total_responses) },
- { 157, offsetof(fr_stats_t, total_dup_requests) },
- { 158, offsetof(fr_stats_t, total_malformed_requests) },
- { 159, offsetof(fr_stats_t, total_bad_authenticators) },
- { 160, offsetof(fr_stats_t, total_packets_dropped) },
- { 161, offsetof(fr_stats_t, total_unknown_types) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCOUNTING_REQUESTS, offsetof(fr_stats_t, total_requests) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCOUNTING_RESPONSES, offsetof(fr_stats_t, total_responses) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCT_DUPLICATE_REQUESTS, offsetof(fr_stats_t, total_dup_requests) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCT_MALFORMED_REQUESTS, offsetof(fr_stats_t, total_malformed_requests) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCT_INVALID_REQUESTS, offsetof(fr_stats_t, total_bad_authenticators) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCT_DROPPED_REQUESTS, offsetof(fr_stats_t, total_packets_dropped) },
+ { PW_FREERADIUS_TOTAL_PROXY_ACCT_UNKNOWN_TYPES, offsetof(fr_stats_t, total_unknown_types) },
{ 0, 0 }
};
#endif
#endif
static fr_stats2vp client_authvp[] = {
- { 128, offsetof(fr_stats_t, total_requests) },
- { 129, offsetof(fr_stats_t, total_access_accepts) },
- { 130, offsetof(fr_stats_t, total_access_rejects) },
- { 131, offsetof(fr_stats_t, total_access_challenges) },
- { 132, offsetof(fr_stats_t, total_responses) },
- { 133, offsetof(fr_stats_t, total_dup_requests) },
- { 134, offsetof(fr_stats_t, total_malformed_requests) },
- { 135, offsetof(fr_stats_t, total_bad_authenticators) },
- { 136, offsetof(fr_stats_t, total_packets_dropped) },
- { 137, offsetof(fr_stats_t, total_unknown_types) },
+ { PW_FREERADIUS_TOTAL_ACCESS_REQUESTS, offsetof(fr_stats_t, total_requests) },
+ { PW_FREERADIUS_TOTAL_ACCESS_ACCEPTS, offsetof(fr_stats_t, total_access_accepts) },
+ { PW_FREERADIUS_TOTAL_ACCESS_REJECTS, offsetof(fr_stats_t, total_access_rejects) },
+ { PW_FREERADIUS_TOTAL_ACCESS_CHALLENGES, offsetof(fr_stats_t, total_access_challenges) },
+ { PW_FREERADIUS_TOTAL_AUTH_RESPONSES, offsetof(fr_stats_t, total_responses) },
+ { PW_FREERADIUS_TOTAL_AUTH_DUPLICATE_REQUESTS, offsetof(fr_stats_t, total_dup_requests) },
+ { PW_FREERADIUS_TOTAL_AUTH_MALFORMED_REQUESTS, offsetof(fr_stats_t, total_malformed_requests) },
+ { PW_FREERADIUS_TOTAL_AUTH_INVALID_REQUESTS, offsetof(fr_stats_t, total_bad_authenticators) },
+ { PW_FREERADIUS_TOTAL_AUTH_DROPPED_REQUESTS, offsetof(fr_stats_t, total_packets_dropped) },
+ { PW_FREERADIUS_TOTAL_AUTH_UNKNOWN_TYPES, offsetof(fr_stats_t, total_unknown_types) },
{ 0, 0 }
};
#ifdef WITH_ACCOUNTING
static fr_stats2vp client_acctvp[] = {
- { 148, offsetof(fr_stats_t, total_requests) },
- { 149, offsetof(fr_stats_t, total_responses) },
- { 150, offsetof(fr_stats_t, total_dup_requests) },
- { 151, offsetof(fr_stats_t, total_malformed_requests) },
- { 152, offsetof(fr_stats_t, total_bad_authenticators) },
- { 153, offsetof(fr_stats_t, total_packets_dropped) },
- { 154, offsetof(fr_stats_t, total_unknown_types) },
+ { PW_FREERADIUS_TOTAL_ACCOUNTING_REQUESTS, offsetof(fr_stats_t, total_requests) },
+ { PW_FREERADIUS_TOTAL_ACCOUNTING_RESPONSES, offsetof(fr_stats_t, total_responses) },
+ { PW_FREERADIUS_TOTAL_ACCT_DUPLICATE_REQUESTS, offsetof(fr_stats_t, total_dup_requests) },
+ { PW_FREERADIUS_TOTAL_ACCT_MALFORMED_REQUESTS, offsetof(fr_stats_t, total_malformed_requests) },
+ { PW_FREERADIUS_TOTAL_ACCT_INVALID_REQUESTS, offsetof(fr_stats_t, total_bad_authenticators) },
+ { PW_FREERADIUS_TOTAL_ACCT_DROPPED_REQUESTS, offsetof(fr_stats_t, total_packets_dropped) },
+ { PW_FREERADIUS_TOTAL_ACCT_UNKNOWN_TYPES, offsetof(fr_stats_t, total_unknown_types) },
{ 0, 0 }
};
#endif
rad_assert(request->packet->code == PW_CODE_STATUS_SERVER);
rad_assert(request->listener->type == RAD_LISTEN_NONE);
- flag = fr_pair_find_by_num(request->packet->vps, 127, VENDORPEC_FREERADIUS, TAG_ANY);
+ flag = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATISTICS_TYPE, VENDORPEC_FREERADIUS, TAG_ANY);
if (!flag || (flag->vp_integer == 0)) return;
/*
*/
if ((flag->vp_integer & 0x10) != 0) {
vp = radius_pair_create(request->reply, &request->reply->vps,
- 176, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_START_TIME, VENDORPEC_FREERADIUS);
if (vp) vp->vp_date = start_time.tv_sec;
vp = radius_pair_create(request->reply, &request->reply->vps,
- 177, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_HUP_TIME, VENDORPEC_FREERADIUS);
if (vp) vp->vp_date = hup_time.tv_sec;
#ifdef HAVE_PTHREAD_H
for (i = 0; i <= 4; i++) {
vp = radius_pair_create(request->reply, &request->reply->vps,
- 162 + i, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_QUEUE_LEN_INTERNAL + i, VENDORPEC_FREERADIUS);
if (!vp) continue;
vp->vp_integer = array[i];
for (i = 0; i < 2; i++) {
vp = radius_pair_create(request->reply, &request->reply->vps,
- 181 + i, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_QUEUE_PPS_IN + i, VENDORPEC_FREERADIUS);
if (!vp) continue;
vp->vp_integer = pps[i];
* See if we need to look up the client by server
* socket.
*/
- server_ip = fr_pair_find_by_num(request->packet->vps, 170, VENDORPEC_FREERADIUS, TAG_ANY);
+ server_ip = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_IP_ADDRESS, VENDORPEC_FREERADIUS, TAG_ANY);
if (server_ip) {
- server_port = fr_pair_find_by_num(request->packet->vps, 171, VENDORPEC_FREERADIUS, TAG_ANY);
+ server_port = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_PORT, VENDORPEC_FREERADIUS, TAG_ANY);
if (server_port) {
ipaddr.af = AF_INET;
}
- vp = fr_pair_find_by_num(request->packet->vps, 167, VENDORPEC_FREERADIUS, TAG_ANY);
+ vp = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_CLIENT_IP_ADDRESS, VENDORPEC_FREERADIUS, TAG_ANY);
if (vp) {
memset(&ipaddr, 0, sizeof(ipaddr));
ipaddr.af = AF_INET;
/*
* Else look it up by number.
*/
- } else if ((vp = fr_pair_find_by_num(request->packet->vps, 168, VENDORPEC_FREERADIUS, TAG_ANY)) != NULL) {
+ } else if ((vp = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_CLIENT_NUMBER, VENDORPEC_FREERADIUS, TAG_ANY)) != NULL) {
client = client_findbynumber(cl, vp->vp_integer);
}
(client->ipaddr.af == AF_INET)) {
vp = radius_pair_create(request->reply,
&request->reply->vps,
- 167, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_CLIENT_IP_ADDRESS, VENDORPEC_FREERADIUS);
if (vp) {
vp->vp_ipaddr = client->ipaddr.ipaddr.ip4addr.s_addr;
}
if (client->ipaddr.prefix != 32) {
vp = radius_pair_create(request->reply,
&request->reply->vps,
- 169, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_CLIENT_NETMASK, VENDORPEC_FREERADIUS);
if (vp) {
vp->vp_integer = client->ipaddr.prefix;
}
&client->auth);
}
#ifdef WITH_ACCOUNTING
- if ((flag->vp_integer & 0x01) != 0) {
+ if ((flag->vp_integer & 0x02) != 0) {
request_stats_addvp(request, client_acctvp,
&client->acct);
}
* See if we need to look up the server by socket
* socket.
*/
- server_ip = fr_pair_find_by_num(request->packet->vps, 170, VENDORPEC_FREERADIUS, TAG_ANY);
+ server_ip = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_IP_ADDRESS, VENDORPEC_FREERADIUS, TAG_ANY);
if (!server_ip) return;
- server_port = fr_pair_find_by_num(request->packet->vps, 171, VENDORPEC_FREERADIUS, TAG_ANY);
+ server_port = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_PORT, VENDORPEC_FREERADIUS, TAG_ANY);
if (!server_port) return;
ipaddr.af = AF_INET;
* See if we need to look up the server by socket
* socket.
*/
- server_ip = fr_pair_find_by_num(request->packet->vps, 170, VENDORPEC_FREERADIUS, TAG_ANY);
+ server_ip = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_IP_ADDRESS, VENDORPEC_FREERADIUS, TAG_ANY);
if (!server_ip) return;
- server_port = fr_pair_find_by_num(request->packet->vps, 171, VENDORPEC_FREERADIUS, TAG_ANY);
+ server_port = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_PORT, VENDORPEC_FREERADIUS, TAG_ANY);
if (!server_port) return;
#ifndef NDEBUG
fr_pair_copy(request->reply, server_port));
vp = radius_pair_create(request->reply, &request->reply->vps,
- 172, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_SERVER_OUTSTANDING_REQUESTS, VENDORPEC_FREERADIUS);
if (vp) vp->vp_integer = home->currently_outstanding;
vp = radius_pair_create(request->reply, &request->reply->vps,
- 173, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_SERVER_STATE, VENDORPEC_FREERADIUS);
if (vp) vp->vp_integer = home->state;
if ((home->state == HOME_STATE_ALIVE) &&
(home->revive_time.tv_sec != 0)) {
vp = radius_pair_create(request->reply, &request->reply->vps,
- 175, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_SERVER_TIME_OF_LIFE, VENDORPEC_FREERADIUS);
if (vp) vp->vp_date = home->revive_time.tv_sec;
}
(home->ema.window > 0)) {
vp = radius_pair_create(request->reply,
&request->reply->vps,
- 178, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_SERVER_EMA_WINDOW, VENDORPEC_FREERADIUS);
if (vp) vp->vp_integer = home->ema.window;
vp = radius_pair_create(request->reply,
&request->reply->vps,
- 179, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_SERVER_EMA_USEC_WINDOW_1, VENDORPEC_FREERADIUS);
if (vp) vp->vp_integer = home->ema.ema1 / EMA_SCALE;
vp = radius_pair_create(request->reply,
&request->reply->vps,
- 180, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_SERVER_EMA_USEC_WINDOW_10, VENDORPEC_FREERADIUS);
if (vp) vp->vp_integer = home->ema.ema10 / EMA_SCALE;
}
if (home->state == HOME_STATE_IS_DEAD) {
vp = radius_pair_create(request->reply, &request->reply->vps,
- 174, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_SERVER_TIME_OF_DEATH, VENDORPEC_FREERADIUS);
if (vp) vp->vp_date = home->zombie_period_start.tv_sec + home->zombie_period;
}
* FIXME: do this for clients, too!
*/
vp = radius_pair_create(request->reply, &request->reply->vps,
- 184, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_LAST_PACKET_RECV, VENDORPEC_FREERADIUS);
if (vp) vp->vp_date = home->last_packet_recv;
vp = radius_pair_create(request->reply, &request->reply->vps,
- 185, VENDORPEC_FREERADIUS);
+ PW_FREERADIUS_STATS_LAST_PACKET_SENT, VENDORPEC_FREERADIUS);
if (vp) vp->vp_date = home->last_packet_sent;
if (((flag->vp_integer & 0x01) != 0) &&
rad_assert(request->magic == REQUEST_MAGIC);
request->component = "<core>";
- request->module = "<running>";
+ request->module = "";
request->child_state = REQUEST_RUNNING;
/*
char const *comment;
} libssl_defect_t;
-/* Record critical defects in libssl here (newest first)*/
+/* Record critical defects in libssl here, new versions of OpenSSL to older versions of OpenSSL. */
static libssl_defect_t libssl_defects[] =
{
{
+ .low = 0x01010101f, /* 1.1.0a */
+ .high = 0x01010101f, /* 1.1.0a */
+ .id = "CVE-2016-6309",
+ .name = "OCSP status request extension",
+ .comment = "For more information see https://www.openssl.org/news/secadv/20160926.txt"
+ },
+ {
+ .low = 0x01010100f, /* 1.1.0 */
+ .high = 0x01010100f, /* 1.1.0 */
+ .id = "CVE-2016-6304",
+ .name = "OCSP status request extension",
+ .comment = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
+ },
+ {
+ .low = 0x01000209f, /* 1.0.2i */
+ .high = 0x01000209f, /* 1.0.2i */
+ .id = "CVE-2016-7052",
+ .name = "OCSP status request extension",
+ .comment = "For more information see https://www.openssl.org/news/secadv/20160926.txt"
+ },
+ {
+ .low = 0x01000200f, /* 1.0.2 */
+ .high = 0x01000208f, /* 1.0.2h */
+ .id = "CVE-2016-6304",
+ .name = "OCSP status request extension",
+ .comment = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
+ },
+ {
+ .low = 0x01000100f, /* 1.0.1 */
+ .high = 0x01000114f, /* 1.0.1t */
+ .id = "CVE-2016-6304",
+ .name = "OCSP status request extension",
+ .comment = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
+ },
+ {
.low = 0x010001000, /* 1.0.1 */
.high = 0x01000106f, /* 1.0.1f */
.id = "CVE-2014-0160",
.name = "Heartbleed",
.comment = "For more information see http://heartbleed.com"
- }
+ },
};
#endif /* ENABLE_OPENSSL_VERSION_CHECK */
static unsigned int record_minus(record_t *buf, void *ptr,
unsigned int size);
+DIAG_OFF(format-nonliteral)
+/** Print errors in the TLS thread local error stack
+ *
+ * Drains the thread local OpenSSL error queue, and prints out errors.
+ *
+ * @param[in] request The current request (may be NULL).
+ * @param[in] msg Error message describing the operation being attempted.
+ * @param[in] ap Arguments for msg.
+ * @return the number of errors drained from the stack.
+ */
+static int tls_verror_log(REQUEST *request, char const *msg, va_list ap)
+{
+ unsigned long error;
+ char *p;
+ int in_stack = 0;
+ char buffer[256];
+
+ int line;
+ char const *file;
+
+ /*
+ * Pop the first error, so ERR_peek_error()
+ * can be used to determine if there are
+ * multiple errors.
+ */
+ error = ERR_get_error_line(&file, &line);
+
+ if (msg) {
+ p = talloc_vasprintf(request, msg, ap);
+
+ /*
+ * Single line mode (there's only one error)
+ */
+ if (error && !ERR_peek_error()) {
+ ERR_error_string_n(error, buffer, sizeof(buffer));
+
+ /* Extra verbose */
+ if ((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) {
+ ROPTIONAL(REDEBUG, ERROR, "%s: %s[%i]:%s", p, file, line, buffer);
+ } else {
+ ROPTIONAL(REDEBUG, ERROR, "%s: %s", p, buffer);
+ }
+
+ talloc_free(p);
+
+ return 1;
+ }
+
+ /*
+ * Print the error we were given, irrespective
+ * of whether there were any OpenSSL errors.
+ */
+ ROPTIONAL(RERROR, ERROR, "%s", p);
+ talloc_free(p);
+ }
+
+ /*
+ * Stack mode (there are multiple errors)
+ */
+ if (!error) return 0;
+ do {
+ ERR_error_string_n(error, buffer, sizeof(buffer));
+ /* Extra verbose */
+ if ((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) {
+ ROPTIONAL(REDEBUG, ERROR, "%s[%i]:%s", file, line, buffer);
+ } else {
+ ROPTIONAL(REDEBUG, ERROR, "%s", buffer);
+ }
+ in_stack++;
+ } while ((error = ERR_get_error_line(&file, &line)));
+
+ return in_stack;
+}
+DIAG_ON(format-nonliteral)
+
+/** Print errors in the TLS thread local error stack
+ *
+ * Drains the thread local OpenSSL error queue, and prints out errors.
+ *
+ * @param[in] request The current request (may be NULL).
+ * @param[in] msg Error message describing the operation being attempted.
+ * @param[in] ... Arguments for msg.
+ * @return the number of errors drained from the stack.
+ */
+int tls_error_log(REQUEST *request, char const *msg, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, msg);
+ ret = tls_verror_log(request, msg, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+/** Print errors raised by OpenSSL I/O functions
+ *
+ * Drains the thread local OpenSSL error queue, and prints out errors
+ * based on the SSL handle and the return code of the I/O function.
+ *
+ * OpenSSL lists I/O functions to be:
+ * - SSL_connect
+ * - SSL_accept
+ * - SSL_do_handshake
+ * - SSL_read
+ * - SSL_peek
+ * - SSL_write
+ *
+ * @param request The current request (may be NULL).
+ * @param session The current tls_session.
+ * @param ret from the I/O operation.
+ * @param msg Error message describing the operation being attempted.
+ * @param ... Arguments for msg.
+ * @return
+ * - 0 TLS session cannot continue.
+ * - 1 TLS session may still be viable.
+ */
+int tls_error_io_log(REQUEST *request, tls_session_t *session, int ret, char const *msg, ...)
+{
+ int error;
+ va_list ap;
+
+ if (ERR_peek_error()) {
+ va_start(ap, msg);
+ tls_verror_log(request, msg, ap);
+ va_end(ap);
+ }
+
+ error = SSL_get_error(session->ssl, ret);
+ switch (error) {
+ /*
+ * These seem to be harmless and already "dealt
+ * with" by our non-blocking environment. NB:
+ * "ZERO_RETURN" is the clean "error"
+ * indicating a successfully closed SSL
+ * tunnel. We let this happen because our IO
+ * loop should not appear to have broken on
+ * this condition - and outside the IO loop, the
+ * "shutdown" state is checked.
+ *
+ * Don't print anything if we ignore the error.
+ */
+ case SSL_ERROR_NONE:
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ case SSL_ERROR_ZERO_RETURN:
+ break;
+
+ /*
+ * These seem to be indications of a genuine
+ * error that should result in the SSL tunnel
+ * being regarded as "dead".
+ */
+ case SSL_ERROR_SYSCALL:
+ ROPTIONAL(REDEBUG, ERROR, "System call (I/O) error (%i)", ret);
+ return 0;
+
+ case SSL_ERROR_SSL:
+ ROPTIONAL(REDEBUG, ERROR, "TLS protocol error (%i)", ret);
+ return 0;
+
+ /*
+ * For any other errors that (a) exist, and (b)
+ * crop up - we need to interpret what to do with
+ * them - so "politely inform" the caller that
+ * the code needs updating here.
+ */
+ default:
+ ROPTIONAL(REDEBUG, ERROR, "TLS session error %i (%i)", error, ret);
+ return 0;
+ }
+
+ return 1;
+}
+
#ifdef PSK_MAX_IDENTITY_LEN
static bool identity_is_safe(const char *identity)
{
return true;
}
-
/*
* When a client uses TLS-PSK to talk to a server, this callback
* is used by the server to determine the PSK to use.
#endif
+#define MAX_SESSION_SIZE (256)
+
+
+void tls_session_id(SSL_SESSION *ssn, char *buffer, size_t bufsize)
+{
+#if OPENSSL_VERSION_NUMBER < 0x10001000L
+ size_t size;
+
+ size = ssn->session_id_length;
+ if (size > bufsize) size = bufsize;
+
+ fr_bin2hex(buffer, ssn->session_id, size);
+#else
+ unsigned int size;
+ uint8_t const *p;
+
+ p = SSL_SESSION_get_id(ssn, &size);
+ if (size > bufsize) size = bufsize;
+
+ fr_bin2hex(buffer, p, size);
+
+#endif
+}
+
+
+
static int _tls_session_free(tls_session_t *ssn)
{
/*
tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, int fd)
{
+ int ret;
int verify_mode;
tls_session_t *ssn = NULL;
REQUEST *request;
SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_SSN, (void *)ssn);
SSL_set_fd(ssn->ssl, fd);
- if (SSL_connect(ssn->ssl) <= 0) {
- int err;
- while ((err = ERR_get_error())) {
- ERROR("tls: %s", ERR_error_string(err, NULL));
- }
+ ret = SSL_connect(ssn->ssl);
+ if (ret <= 0) {
+ tls_error_io_log(NULL, ssn, ret, "Failed in " STRINGIFY(__FUNCTION__) " (SSL_connect)");
talloc_free(ssn);
return NULL;
conf->session_last_flushed = request->timestamp;
}
- if ((new_tls = SSL_new(conf->ctx)) == NULL) {
- RERROR("Error creating new SSL session: %s", ERR_error_string(ERR_get_error(), NULL));
+ new_tls = SSL_new(conf->ctx);
+ if (new_tls == NULL) {
+ tls_error_log(request, "Error creating new TLS session");
return NULL;
}
}
/*
- * Print out some text describing the error.
- */
-static int int_ssl_check(REQUEST *request, SSL *s, int ret, char const *text)
-{
- int e;
- unsigned long l;
-
- if ((l = ERR_get_error()) != 0) {
- char const *p = ERR_error_string(l, NULL);
-
- if (p) ROPTIONAL(REDEBUG, ERROR, "SSL says: %s", p);
- }
-
- e = SSL_get_error(s, ret);
- switch (e) {
- /*
- * These seem to be harmless and already "dealt
- * with" by our non-blocking environment. NB:
- * "ZERO_RETURN" is the clean "error"
- * indicating a successfully closed SSL
- * tunnel. We let this happen because our IO
- * loop should not appear to have broken on
- * this condition - and outside the IO loop, the
- * "shutdown" state is checked.
- *
- * Don't print anything if we ignore the error.
- */
- case SSL_ERROR_NONE:
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_X509_LOOKUP:
- case SSL_ERROR_ZERO_RETURN:
- break;
-
- /*
- * These seem to be indications of a genuine
- * error that should result in the SSL tunnel
- * being regarded as "dead".
- */
- case SSL_ERROR_SYSCALL:
- ROPTIONAL(REDEBUG, ERROR, "%s failed in a system call (%d), TLS session failed", text, ret);
- return 0;
-
- case SSL_ERROR_SSL:
- ROPTIONAL(REDEBUG, ERROR, "%s failed inside of TLS (%d), TLS session failed", text, ret);
- return 0;
-
- /*
- * For any other errors that (a) exist, and (b)
- * crop up - we need to interpret what to do with
- * them - so "politely inform" the caller that
- * the code needs updating here.
- */
- default:
- ROPTIONAL(REDEBUG, ERROR, "FATAL SSL error: %d", e);
- return 0;
- }
-
- return 1;
-}
-
-/*
* We are the server, we always get the dirty data
* (Handshake data is also considered as dirty data)
* During handshake, since SSL API handles itself,
return 1;
}
- if (!int_ssl_check(request, ssn->ssl, err, "SSL_read")) return 0;
+ if (!tls_error_io_log(request, ssn, err, "Failed in " STRINGIFY(__FUNCTION__) " (SSL_read)")) return 0;
/* Some Extra STATE information for easy debugging */
if (SSL_is_init_finished(ssn->ssl)) RDEBUG2("SSL Connection Established");
if (SSL_in_accept_init(ssn->ssl)) RDEBUG2("In SSL Accept mode");
if (SSL_in_connect_init(ssn->ssl)) RDEBUG2("In SSL Connect mode");
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ /*
+ * Cache the SSL_SESSION pointer.
+ */
+ if (!ssn->ssl_session && SSL_is_init_finished(ssn->ssl)) {
+ ssn->ssl_session = SSL_get_session(ssn->ssl);
+ if (!ssn->ssl_session) {
+ RDEBUG("Failed getting SSL session");
+ return 0;
+ }
+ }
+#endif
+
err = BIO_ctrl_pending(ssn->from_ssl);
if (err > 0) {
err = BIO_read(ssn->from_ssl, ssn->dirty_out.data,
return 1;
} else {
- int_ssl_check(request, ssn->ssl, err, "BIO_read");
+ tls_error_log(NULL, NULL);
record_init(&ssn->dirty_in);
return 0;
}
if (err > 0) {
ssn->dirty_out.used = err;
} else {
- int_ssl_check(request, ssn->ssl, err, "handshake_send");
+ if (!tls_error_io_log(request, ssn, err,
+ "Failed in " STRINGIFY(__FUNCTION__) " (SSL_write)")) {
+ return 0;
+ }
}
}
/*
* This is pretty bad...
*/
- if(rec->used > 0)
- memmove(rec->data, rec->data + taken, rec->used);
+ if (rec->used > 0) memmove(rec->data, rec->data + taken, rec->used);
+
return taken;
}
* Don't print this out in the normal course of
* operations.
*/
- if (rad_debug_lvl == 0) {
- return;
- }
+ if (rad_debug_lvl == 0) return;
- str_write_p = tls_session->info.origin ? ">>>" : "<<<";
+ str_write_p = tls_session->info.origin ? ">>> send" : "<<< recv";
switch (tls_session->info.version) {
case SSL2_VERSION:
str_details1, str_details2);
request = SSL_get_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST);
- if (request) {
- RDEBUG2("%s", tls_session->info.info_description);
- } else {
- DEBUG2("%s", tls_session->info.info_description);
- }
+ ROPTIONAL(RDEBUG2, DEBUG2, "%s", tls_session->info.info_description);
}
static CONF_PARSER cache_config[] = {
};
static CONF_PARSER verify_config[] = {
+ { "skip_if_ocsp_ok", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, verify_skip_if_ocsp_ok), "no" },
{ "tmpdir", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, verify_tmp_dir), NULL },
{ "client", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, verify_client_cert_cmd), NULL },
CONF_PARSER_TERMINATOR
#endif
static CONF_PARSER tls_server_config[] = {
- { "rsa_key_exchange", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, rsa_key), "no" },
- { "dh_key_exchange", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, dh_key), "yes" },
- { "rsa_key_length", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_tls_server_conf_t, rsa_key_length), "512" },
- { "dh_key_length", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_tls_server_conf_t, dh_key_length), "512" },
{ "verify_depth", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_tls_server_conf_t, verify_depth), "0" },
{ "CA_path", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT | PW_TYPE_DEPRECATED, fr_tls_server_conf_t, ca_path), NULL },
{ "ca_path", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT, fr_tls_server_conf_t, ca_path), NULL },
{ "psk_hexphrase", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, fr_tls_server_conf_t, psk_password), NULL },
{ "psk_query", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, psk_query), NULL },
#endif
- { "dh_file", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, dh_file), NULL },
- { "random_file", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, random_file), NULL },
+ { "dh_file", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT, fr_tls_server_conf_t, dh_file), NULL },
+ { "random_file", FR_CONF_OFFSET(PW_TYPE_FILE_EXISTS, fr_tls_server_conf_t, random_file), NULL },
{ "fragment_size", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_tls_server_conf_t, fragment_size), "1024" },
{ "include_length", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, include_length), "yes" },
+ { "auto_chain", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, auto_chain), "yes" },
+ { "disable_single_dh_use", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, disable_single_dh_use), NULL },
{ "check_crl", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, check_crl), "no" },
#ifdef X509_V_FLAG_CRL_CHECK_ALL
{ "check_all_crl", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, check_all_crl), "no" },
static CONF_PARSER tls_client_config[] = {
- { "rsa_key_exchange", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, rsa_key), "no" },
- { "dh_key_exchange", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, dh_key), "yes" },
- { "rsa_key_length", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_tls_server_conf_t, rsa_key_length), "512" },
- { "dh_key_length", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_tls_server_conf_t, dh_key_length), "512" },
{ "verify_depth", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_tls_server_conf_t, verify_depth), "0" },
{ "ca_path", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT, fr_tls_server_conf_t, ca_path), NULL },
{ "pem_file_type", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, file_type), "yes" },
/*
* Print debugging messages, and free data.
*/
-#define MAX_SESSION_SIZE (256)
-
static void cbtls_remove_session(SSL_CTX *ctx, SSL_SESSION *sess)
{
- size_t size;
char buffer[2 * MAX_SESSION_SIZE + 1];
fr_tls_server_conf_t *conf;
- size = sess->session_id_length;
- if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
-
- fr_bin2hex(buffer, sess->session_id, size);
+ tls_session_id(sess, buffer, MAX_SESSION_SIZE);
conf = (fr_tls_server_conf_t *)SSL_CTX_get_app_data(ctx);
if (!conf) {
static int cbtls_new_session(SSL *ssl, SSL_SESSION *sess)
{
- size_t size;
char buffer[2 * MAX_SESSION_SIZE + 1];
fr_tls_server_conf_t *conf;
unsigned char *sess_blob = NULL;
return 0;
}
- size = sess->session_id_length;
- if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
-
- fr_bin2hex(buffer, sess->session_id, size);
+ tls_session_id(sess, buffer, MAX_SESSION_SIZE);
{
int fd, rv, todo, blob_len;
{
int rv, fd, todo;
char filename[256];
- unsigned char *p;
+
+ unsigned char const **o;
+ unsigned char **p;
+ uint8_t *q;
+
struct stat st;
VALUE_PAIR *vps = NULL;
goto err;
}
- p = sess_data;
+ q = sess_data;
todo = st.st_size;
while (todo > 0) {
- rv = read(fd, p, todo);
+ rv = read(fd, q, todo);
if (rv < 1) {
RWDEBUG("Failed reading persisted session: %s", fr_syserror(errno));
close(fd);
goto err;
}
todo -= rv;
- p += rv;
+ q += rv;
}
close(fd);
- /* openssl mutates &p */
- p = sess_data;
- sess = d2i_SSL_SESSION(NULL, (unsigned char const **)(void **) &p, st.st_size);
-
+ /*
+ * OpenSSL mutates what's passed in, so we assign sess_data to q,
+ * so the value of q gets mutated, and not the value of sess_data.
+ *
+ * We then need a pointer to hold &q, but it can't be const, because
+ * clang complains about lack of consting in nested pointer types.
+ *
+ * So we memcpy the value of that pointer, to one that
+ * does have a const, which we then pass into d2i_SSL_SESSION *sigh*.
+ */
+ q = sess_data;
+ p = &q;
+ memcpy(&o, &p, sizeof(o));
+ sess = d2i_SSL_SESSION(NULL, o, st.st_size);
if (!sess) {
RWDEBUG("Failed loading persisted session: %s", ERR_error_string(ERR_get_error(), NULL));
goto err;
/* Maximum leeway in validity period: default 5 minutes */
#define MAX_VALIDITY_PERIOD (5 * 60)
-static int ocsp_check(REQUEST *request, X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
- fr_tls_server_conf_t *conf)
+typedef enum {
+ OCSP_STATUS_FAILED = 0,
+ OCSP_STATUS_OK = 1,
+ OCSP_STATUS_SKIPPED = 2,
+} ocsp_status_t;
+
+static ocsp_status_t ocsp_check(REQUEST *request, X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
+ fr_tls_server_conf_t *conf)
{
OCSP_CERTID *certid;
OCSP_REQUEST *req;
int use_ssl = -1;
long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
BIO *cbio, *bio_out;
- int ocsp_ok = 0;
+ ocsp_status_t ocsp_status = OCSP_STATUS_FAILED;
int status;
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
int reason;
struct timeval now;
struct timeval when;
#endif
+ VALUE_PAIR *vp;
/*
* Create OCSP Request
OCSP_parse_url(url, &host, &port, &path, &use_ssl);
if (!host || !port || !path) {
RWDEBUG("ocsp: Host or port or path missing from configured URL \"%s\". Not doing OCSP", url);
- ocsp_ok = 2;
- goto ocsp_skip;
+ goto skipped;
}
} else {
int ret;
goto use_ocsp_url;
}
RWDEBUG("ocsp: No OCSP URL in certificate. Not doing OCSP");
- ocsp_ok = 2;
- goto ocsp_skip;
+ goto skipped;
case 1:
break;
/* Check host and port length are sane, then create Host: HTTP header */
if ((strlen(host) + strlen(port) + 2) > sizeof(hostheader)) {
RWDEBUG("ocsp: Host and port too long");
- goto ocsp_skip;
+ goto skipped;
}
snprintf(hostheader, sizeof(hostheader), "%s:%s", host, port);
resp = OCSP_sendreq_bio(cbio, path, req);
if (!resp) {
REDEBUG("ocsp: Couldn't get OCSP response");
- ocsp_ok = 2;
+ ocsp_status = OCSP_STATUS_SKIPPED;
goto ocsp_end;
}
#else
rc = BIO_do_connect(cbio);
if ((rc <= 0) && ((!conf->ocsp_timeout) || !BIO_should_retry(cbio))) {
REDEBUG("ocsp: Couldn't connect to OCSP responder");
- ocsp_ok = 2;
+ ocsp_status = OCSP_STATUS_SKIPPED;
goto ocsp_end;
}
ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
if (!ctx) {
REDEBUG("ocsp: Couldn't create OCSP request");
- ocsp_ok = 2;
+ ocsp_status = OCSP_STATUS_SKIPPED;
goto ocsp_end;
}
if (!OCSP_REQ_CTX_add1_header(ctx, "Host", hostheader)) {
REDEBUG("ocsp: Couldn't set Host header");
- ocsp_ok = 2;
+ ocsp_status = OCSP_STATUS_SKIPPED;
goto ocsp_end;
}
if (!OCSP_REQ_CTX_set1_req(ctx, req)) {
REDEBUG("ocsp: Couldn't add data to OCSP request");
- ocsp_ok = 2;
+ ocsp_status = OCSP_STATUS_SKIPPED;
goto ocsp_end;
}
if (conf->ocsp_timeout && (rc == -1) && BIO_should_retry(cbio)) {
REDEBUG("ocsp: Response timed out");
- ocsp_ok = 2;
+ ocsp_status = OCSP_STATUS_SKIPPED;
goto ocsp_end;
}
if (rc == 0) {
REDEBUG("ocsp: Couldn't get OCSP response");
- ocsp_ok = 2;
+ ocsp_status = OCSP_STATUS_SKIPPED;
goto ocsp_end;
}
#endif
switch (status) {
case V_OCSP_CERTSTATUS_GOOD:
RDEBUG2("ocsp: Cert status: good");
- ocsp_ok = 1;
+ vp = pair_make_request("TLS-OCSP-Cert-Valid", NULL, T_OP_SET);
+ vp->vp_integer = 1; /* yes */
+ ocsp_status = OCSP_STATUS_OK;
break;
default:
if (bio_out) BIO_free(bio_out);
OCSP_BASICRESP_free(bresp);
- ocsp_skip:
- switch (ocsp_ok) {
- case 1:
+ switch (ocsp_status) {
+ case OCSP_STATUS_OK:
RDEBUG2("ocsp: Certificate is valid");
break;
- case 2:
+ case OCSP_STATUS_SKIPPED:
+ skipped:
+ vp = pair_make_request("TLS-OCSP-Cert-Valid", NULL, T_OP_SET);
+ vp->vp_integer = 2; /* skipped */
if (conf->ocsp_softfail) {
RWDEBUG("ocsp: Unable to check certificate, assuming it's valid");
RWDEBUG("ocsp: This may be insecure");
- ocsp_ok = 1;
+
+ /* Remove OpenSSL errors from queue or handshake will fail */
+ while (ERR_get_error());
+
+ ocsp_status = OCSP_STATUS_SKIPPED;
} else {
REDEBUG("ocsp: Unable to check certificate, failing");
- ocsp_ok = 0;
+ ocsp_status = OCSP_STATUS_FAILED;
}
break;
default:
+ vp = pair_make_request("TLS-OCSP-Cert-Valid", NULL, T_OP_SET);
+ vp->vp_integer = 0; /* no */
REDEBUG("ocsp: Certificate has been expired/revoked");
break;
}
- return ocsp_ok;
+ return ocsp_status;
}
#endif /* HAVE_OPENSSL_OCSP_H */
#ifdef HAVE_OPENSSL_OCSP_H
X509_STORE *ocsp_store = NULL;
X509 *issuer_cert;
+ bool do_verify = false;
#endif
VALUE_PAIR *vp;
TALLOC_CTX *talloc_ctx;
identity = (char **)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_IDENTITY);
#ifdef HAVE_OPENSSL_OCSP_H
- ocsp_store = (X509_STORE *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_STORE);
+ ocsp_store = conf->ocsp_store;
#endif
talloc_ctx = SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_TALLOC);
} /* check_cert_cn */
#ifdef HAVE_OPENSSL_OCSP_H
- if (my_ok && conf->ocsp_enable){
- RDEBUG2("Starting OCSP Request");
- if (X509_STORE_CTX_get1_issuer(&issuer_cert, ctx, client_cert) != 1) {
- RERROR("Couldn't get issuer_cert for %s", common_name);
+ if (my_ok) {
+ /*
+ * No OCSP, allow external verification.
+ */
+ if (!conf->ocsp_enable) {
+ do_verify = true;
+
} else {
- my_ok = ocsp_check(request, ocsp_store, issuer_cert, client_cert, conf);
+ RDEBUG2("Starting OCSP Request");
+ if ((X509_STORE_CTX_get1_issuer(&issuer_cert, ctx, client_cert) != 1) ||
+ !issuer_cert) {
+ /*
+ * Allow for external verify.
+ */
+ RERROR("Couldn't get issuer_cert for %s", common_name);
+ do_verify = true;
+
+ } else {
+ /*
+ * Do the full OCSP checks.
+ *
+ * If they fail, don't run the external verify. We don't want
+ * to allow admins to force authentication success for bad
+ * certificates.
+ *
+ * If the OCSP checks succeed, check whether we still want to
+ * run the external verification routine. If it's marked as
+ * "skip verify on OK", then we don't do verify.
+ */
+ my_ok = ocsp_check(request, ocsp_store, issuer_cert, client_cert, conf);
+ if (my_ok != OCSP_STATUS_FAILED) {
+ do_verify = !conf->verify_skip_if_ocsp_ok;
+ }
+ }
}
}
#endif
- while (conf->verify_client_cert_cmd) {
+ if ((my_ok != OCSP_STATUS_FAILED)
+#ifdef HAVE_OPENSSL_OCSP_H
+ && do_verify
+#endif
+ ) while (conf->verify_client_cert_cmd) {
char filename[256];
int fd;
FILE *fp;
snprintf(filename, sizeof(filename), "%s/%s.client.XXXXXXXX",
- conf->verify_tmp_dir, progname);
+ conf->verify_tmp_dir, main_config.name);
fd = mkstemp(filename);
if (fd < 0) {
RDEBUG("Failed creating file in %s: %s",
unlink(filename);
break;
}
-
-
} /* depth == 0 */
+ if (certs && request && !my_ok) {
+ fr_pair_add(&request->packet->vps, fr_pair_list_copy(request->packet, *certs));
+ }
+
if (RDEBUG_ENABLED3) {
RDEBUG3("chain-depth : %d", depth);
RDEBUG3("error : %d", err);
RDEBUG3("issuer : %s", issuer);
RDEBUG3("verify return : %d", my_ok);
}
- return my_ok;
+
+ return (my_ok != 0);
}
/* Load the CAs we trust */
if (conf->ca_file || conf->ca_path)
- if(!X509_STORE_load_locations(store, conf->ca_file, conf->ca_path)) {
- ERROR(LOG_PREFIX ": X509_STORE error %s", ERR_error_string(ERR_get_error(), NULL));
- ERROR(LOG_PREFIX ": Error reading Trusted root CA list %s",conf->ca_file );
+ if (!X509_STORE_load_locations(store, conf->ca_file, conf->ca_path)) {
+ tls_error_log(NULL, "Error reading Trusted root CA list \"%s\"", conf->ca_file);
return NULL;
}
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
-static int set_ecdh_curve(SSL_CTX *ctx, char const *ecdh_curve)
+static int set_ecdh_curve(SSL_CTX *ctx, char const *ecdh_curve, bool disable_single_dh_use)
{
int nid;
EC_KEY *ecdh;
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
- SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
+ if (!disable_single_dh_use) {
+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
+ }
EC_KEY_free(ecdh);
int tls_global_version_check(char const *acknowledged)
{
uint64_t v;
+ bool bad = false;
+ size_t i;
+
+ if (strcmp(acknowledged, "yes") == 0) return 0;
- if ((strcmp(acknowledged, libssl_defects[0].id) != 0) && (strcmp(acknowledged, "yes") != 0)) {
- bool bad = false;
- size_t i;
+ /* Check for bad versions */
+ v = (uint64_t) SSLeay();
- /* Check for bad versions */
- v = (uint64_t) SSLeay();
+ for (i = 0; i < (sizeof(libssl_defects) / sizeof(*libssl_defects)); i++) {
+ libssl_defect_t *defect = &libssl_defects[i];
- for (i = 0; i < (sizeof(libssl_defects) / sizeof(*libssl_defects)); i++) {
- libssl_defect_t *defect = &libssl_defects[i];
+ if ((v >= defect->low) && (v <= defect->high)) {
+ /*
+ * If the CVE is acknowledged, allow it.
+ */
+ if (!bad && (strcmp(acknowledged, defect->id) == 0)) return 0;
- if ((v >= defect->low) && (v <= defect->high)) {
- ERROR("Refusing to start with libssl version %s (in range %s)",
- ssl_version(), ssl_version_range(defect->low, defect->high));
- ERROR("Security advisory %s (%s)", defect->id, defect->name);
- ERROR("%s", defect->comment);
+ ERROR("Refusing to start with libssl version %s (in range %s)",
+ ssl_version(), ssl_version_range(defect->low, defect->high));
+ ERROR("Security advisory %s (%s)", defect->id, defect->name);
+ ERROR("%s", defect->comment);
+
+ /*
+ * Only warn about the first one...
+ */
+ if (!bad) {
+ INFO("Once you have verified libssl has been correctly patched, "
+ "set security.allow_vulnerable_openssl = '%s'", defect->id);
bad = true;
}
}
-
- if (bad) {
- INFO("Once you have verified libssl has been correctly patched, "
- "set security.allow_vulnerable_openssl = '%s'", libssl_defects[0].id);
- return -1;
- }
}
+ if (bad) return -1;
+
return 0;
}
#endif
ctx = SSL_CTX_new(SSLv23_method()); /* which is really "all known SSL / TLS methods". Idiots. */
if (!ctx) {
- int err;
- while ((err = ERR_get_error())) {
- ERROR(LOG_PREFIX ": Failed creating SSL context: %s", ERR_error_string(err, NULL));
- return NULL;
- }
+ tls_error_log(NULL, "Failed creating TLS context");
+ return NULL;
}
/*
if (type == SSL_FILETYPE_PEM) {
if (!(SSL_CTX_use_certificate_chain_file(ctx, conf->certificate_file))) {
- ERROR(LOG_PREFIX ": Error reading certificate file %s:%s", conf->certificate_file,
- ERR_error_string(ERR_get_error(), NULL));
+ tls_error_log(NULL, "Failed reading certificate file \"%s\"",
+ conf->certificate_file);
return NULL;
}
} else if (!(SSL_CTX_use_certificate_file(ctx, conf->certificate_file, type))) {
- ERROR(LOG_PREFIX ": Error reading certificate file %s:%s",
- conf->certificate_file,
- ERR_error_string(ERR_get_error(), NULL));
+ tls_error_log(NULL, "Failed reading certificate file \"%s\"",
+ conf->certificate_file);
return NULL;
}
load_ca:
if (conf->ca_file || conf->ca_path) {
if (!SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) {
- ERROR(LOG_PREFIX ": SSL error %s", ERR_error_string(ERR_get_error(), NULL));
- ERROR(LOG_PREFIX ": Error reading Trusted root CA list %s",conf->ca_file );
+ tls_error_log(NULL, "Failed reading Trusted root CA list \"%s\"",
+ conf->ca_file);
return NULL;
}
}
if (conf->private_key_file) {
if (!(SSL_CTX_use_PrivateKey_file(ctx, conf->private_key_file, type))) {
- ERROR(LOG_PREFIX ": Failed reading private key file %s:%s",
- conf->private_key_file,
- ERR_error_string(ERR_get_error(), NULL));
+ tls_error_log(NULL, "Failed reading private key file \"%s\"",
+ conf->private_key_file);
return NULL;
}
ctx_tls_versions |= SSL_OP_NO_TLSv1_1;
#endif
#ifdef SSL_OP_NO_TLSv1_2
+
if (conf->disable_tlsv1_2) ctx_options |= SSL_OP_NO_TLSv1_2;
ctx_tls_versions |= SSL_OP_NO_TLSv1_2;
+
#endif
if ((ctx_options & ctx_tls_versions) == ctx_tls_versions) {
ctx_options |= SSL_OP_NO_TICKET;
#endif
- /*
- * SSL_OP_SINGLE_DH_USE must be used in order to prevent
- * small subgroup attacks and forward secrecy. Always
- * using
- *
- * SSL_OP_SINGLE_DH_USE has an impact on the computer
- * time needed during negotiation, but it is not very
- * large.
- */
- ctx_options |= SSL_OP_SINGLE_DH_USE;
+ if (!conf->disable_single_dh_use) {
+ /*
+ * SSL_OP_SINGLE_DH_USE must be used in order to prevent
+ * small subgroup attacks and forward secrecy. Always
+ * using SSL_OP_SINGLE_DH_USE has an impact on the
+ * computer time needed during negotiation, but it is not
+ * very large.
+ */
+ ctx_options |= SSL_OP_SINGLE_DH_USE;
+ }
/*
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS to work around issues
*/
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
- if (set_ecdh_curve(ctx, conf->ecdh_curve) < 0) {
+ if (set_ecdh_curve(ctx, conf->ecdh_curve, conf->disable_single_dh_use) < 0) {
return NULL;
}
#endif
#endif
+ /*
+ * OpenSSL will automatically create certificate chains,
+ * unless we tell it to not do that. The problem is that
+ * it sometimes gets the chains right from a certificate
+ * signature view, but wrong from the clients view.
+ */
+ if (!conf->auto_chain) {
+ SSL_CTX_set_mode(ctx, SSL_MODE_NO_AUTO_CHAIN);
+ }
+
/* Set Info callback */
SSL_CTX_set_info_callback(ctx, cbtls_info);
if (conf->check_crl) {
certstore = SSL_CTX_get_cert_store(ctx);
if (certstore == NULL) {
- ERROR(LOG_PREFIX ": SSL error %s", ERR_error_string(ERR_get_error(), NULL));
- ERROR(LOG_PREFIX ": Error reading Certificate Store");
+ tls_error_log(NULL, "Error reading Certificate Store");
return NULL;
}
X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
/* Load randomness */
if (conf->random_file) {
if (!(RAND_load_file(conf->random_file, 1024*10))) {
- ERROR(LOG_PREFIX ": SSL error %s", ERR_error_string(ERR_get_error(), NULL));
- ERROR(LOG_PREFIX ": Error loading randomness");
+ tls_error_log(NULL, "Failed loading randomness");
return NULL;
}
}
*/
if (conf->cipher_list) {
if (!SSL_CTX_set_cipher_list(ctx, conf->cipher_list)) {
- ERROR(LOG_PREFIX ": Error setting cipher list");
+ tls_error_log(NULL, "Failed setting cipher list");
return NULL;
}
}
goto error;
}
+#ifdef SSL_OP_NO_TLSv1_2
+ /*
+ * OpenSSL 1.0.1f and 1.0.1g get the MS-MPPE keys wrong.
+ */
+#if (OPENSSL_VERSION_NUMBER >= 0x10010060L) && (OPENSSL_VERSION_NUMBER < 0x10010060L)
+ conf->disable_tlsv1_2 = true;
+ WARN(LOG_PREFIX ": Disabling TLSv1.2 due to OpenSSL bugs");
+#endif
+#endif
+
/*
* Cache conf in cs in case we're asked to parse this again.
*/
(((vp = fr_pair_find_by_num(request->config, PW_ALLOW_SESSION_RESUMPTION, 0, TAG_ANY)) != NULL) &&
(vp->vp_integer == 0))) {
SSL_CTX_remove_session(ssn->ctx,
- ssn->ssl->session);
+ ssn->ssl_session);
ssn->allow_session_resumption = false;
/*
* user data in the cache.
*/
} else if (!SSL_session_reused(ssn->ssl)) {
- size_t size;
VALUE_PAIR **certs;
char buffer[2 * MAX_SESSION_SIZE + 1];
- size = ssn->ssl->session->session_id_length;
- if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
-
- fr_bin2hex(buffer, ssn->ssl->session->session_id, size);
+ tls_session_id(ssn->ssl_session, buffer, MAX_SESSION_SIZE);
vp = fr_pair_list_copy_by_num(talloc_ctx, request->reply->vps, PW_USER_NAME, 0, TAG_ANY);
if (vp) fr_pair_add(&vps, vp);
}
if (vps) {
- SSL_SESSION_set_ex_data(ssn->ssl->session, fr_tls_ex_index_vps, vps);
+ SSL_SESSION_set_ex_data(ssn->ssl_session, fr_tls_ex_index_vps, vps);
rdebug_pair_list(L_DBG_LVL_2, request, vps, " caching ");
if (conf->session_cache_path) {
}
} else {
RDEBUG2("No information to cache: session caching will be disabled for session %s", buffer);
- SSL_CTX_remove_session(ssn->ctx, ssn->ssl->session);
+ SSL_CTX_remove_session(ssn->ctx, ssn->ssl_session);
}
/*
* Else the session WAS allowed. Copy the cached reply.
*/
} else {
- size_t size;
char buffer[2 * MAX_SESSION_SIZE + 1];
- size = ssn->ssl->session->session_id_length;
- if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
-
- fr_bin2hex(buffer, ssn->ssl->session->session_id, size);
+ tls_session_id(ssn->ssl_session, buffer, MAX_SESSION_SIZE);
/*
* The "restore VPs from OpenSSL cache" code is
/*
* Force the session to NOT be cached.
*/
- SSL_CTX_remove_session(ssn->ctx, ssn->ssl->session);
+ SSL_CTX_remove_session(ssn->ctx, ssn->ssl_session);
}
fr_tls_status_t tls_application_data(tls_session_t *ssn, REQUEST *request)
break;
default:
- DEBUG("Error in fragmentation logic: %s", ERR_error_string(code, NULL));
-
- /*
- * FIXME: Call int_ssl_check?
- */
+ REDEBUG("Error in fragmentation logic");
+ tls_error_io_log(request, ssn, err,
+ "Failed in " STRINGIFY(__FUNCTION__) " (SSL_read)");
break;
}
return FR_TLS_FAIL;
#include <sys/stat.h>
#endif
+#ifdef WITH_TCP
#ifdef WITH_TLS
#ifdef HAVE_OPENSSL_RAND_H
#include <openssl/rand.h>
return 0;
}
+ if (request->reply->data_len > (MAX_PACKET_LEN - 100)) {
+ RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+ request->reply->data_len, MAX_PACKET_LEN);
+ }
+
/*
* Sign the packet.
*/
return -1;
default:
- while ((err = ERR_get_error())) {
- DEBUG("proxy recv says %s",
- ERR_error_string(err, NULL));
- }
+ tls_error_log(NULL, "Failed in proxy receive");
goto do_close;
}
break; /* let someone else retry */
default:
- DEBUG("proxy SSL_write says %s",
- ERR_error_string(err, NULL));
+ tls_error_log(NULL, "Failed in proxy send");
DEBUG("Closing TLS socket to home server");
tls_socket_close(listener);
PTHREAD_MUTEX_UNLOCK(&sock->mutex);
#endif /* WITH_PROXY */
#endif /* WITH_TLS */
+#endif /* WITH_TCP */
if (request->coa && /* match reply with request */
(request->coa->proxy->code == PW_CODE_DISCONNECT_REQUEST) &&
request->coa->proxy_reply) {
- return &request->coa->proxy->vps;
+ return &request->coa->proxy_reply->vps;
}
break;
#endif
#ifdef WITH_COA
case PAIR_LIST_COA:
case PAIR_LIST_DM:
- return request->coa->packet;
+ return request->coa->proxy;
case PAIR_LIST_COA_REPLY:
case PAIR_LIST_DM_REPLY:
- return request->coa->reply;
+ return request->coa->proxy_reply;
#endif
}
return request;
case PAIR_LIST_STATE:
- return request;
+ return request->state_ctx;
#ifdef WITH_PROXY
case PAIR_LIST_PROXY_REQUEST:
/*
* Global variables.
*/
-char const *progname = NULL;
char const *radacct_dir = NULL;
char const *radlog_dir = NULL;
-char const *radlib_dir = NULL;
bool log_stripped_names = false;
static bool memory_report = false;
}
#endif
- if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
- progname = argv[0];
- else
- progname++;
-
rad_debug_lvl = 0;
set_radius_dir(NULL, RADIUS_DIR);
{
FILE *output = status?stderr:stdout;
- fprintf(output, "Usage: %s [options]\n", progname);
+ fprintf(output, "Usage: %s [options]\n", main_config.name);
fprintf(output, "Options:\n");
fprintf(output, " -d raddb_dir Configuration files are in \"raddb_dir/*\".\n");
fprintf(output, " -D dict_dir Dictionary files are in \"dict_dir/*\".\n");
ifneq "$(filter rlm_eap_%,${ALL_TGTS})" ""
TGT_PREREQS += libfreeradius-eap.a
endif
+
+ifneq ($(MAKECMDGOALS),scan)
+SRC_CFLAGS += -DBUILT_WITH_CPPFLAGS=\"$(CPPFLAGS)\" -DBUILT_WITH_CFLAGS=\"$(CFLAGS)\" -DBUILT_WITH_LDFLAGS=\"$(LDFLAGS)\" -DBUILT_WITH_LIBS=\"$(LIBS)\"
+endif
*/
if (*q < ' ') {
*(p++) = '_';
+ q++;
continue;
}
request->home_server = NULL;
#endif
+ /*
+ * This is parented separately.
+ */
+ if (request->state_ctx) {
+ talloc_free(request->state_ctx);
+ }
+
return 0;
}
request->component = "<core>";
request->log.func = vradlog_request;
+ request->state_ctx = talloc_init("session-state");
+
return request;
}
#ifdef WITH_VERIFY_PTR
fr_pair_list_verify(file, line, request, request->config);
- fr_pair_list_verify(file, line, request, request->state);
+ fr_pair_list_verify(file, line, request->state_ctx, request->state);
#endif
if (request->packet) verify_packet(file, line, request, request->packet, "request");
CONF_ITEM *ci;
CONF_PAIR *cp;
- if (DEBUG_ENABLED2) {
+ if (DEBUG_ENABLED3) {
int max = 0, len;
MEM(features = cf_section_alloc(NULL, "feature", NULL));
MEM(versions = cf_section_alloc(NULL, "version", NULL));
version_init_numbers(versions);
- DEBUG3("Server was built with: ");
+ DEBUG2("Server was built with: ");
for (ci = cf_item_find_next(features, NULL);
ci;
cp = cf_item_to_pair(ci);
attr = cf_pair_attr(cp);
- DEBUG3(" %s%.*s : %s", attr,
+ DEBUG2(" %s%.*s : %s", attr,
(int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
}
talloc_free(features);
- DEBUG3("Server core libs:");
+ DEBUG2("Server core libs:");
for (ci = cf_item_find_next(versions, NULL);
ci;
cp = cf_item_to_pair(ci);
attr = cf_pair_attr(cp);
- DEBUG3(" %s%.*s : %s", attr,
+ DEBUG2(" %s%.*s : %s", attr,
(int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
}
talloc_free(versions);
- DEBUG3("Endianness:");
+ DEBUG2("Endianness:");
#if defined(FR_LITTLE_ENDIAN)
- DEBUG3(" little");
+ DEBUG2(" little");
#elif defined(FR_BIG_ENDIAN)
- DEBUG3(" big");
+ DEBUG2(" big");
#else
- DEBUG3(" unknown");
+ DEBUG2(" unknown");
#endif
- DEBUG3("Compilation flags:");
+ DEBUG2("Compilation flags:");
#ifdef BUILT_WITH_CPPFLAGS
- DEBUG3(" cppflags : " BUILT_WITH_CPPFLAGS);
+ DEBUG2(" cppflags : " BUILT_WITH_CPPFLAGS);
#endif
#ifdef BUILT_WITH_CFLAGS
- DEBUG3(" cflags : " BUILT_WITH_CFLAGS);
+ DEBUG2(" cflags : " BUILT_WITH_CFLAGS);
#endif
#ifdef BUILT_WITH_LDFLAGS
- DEBUG3(" ldflags : " BUILT_WITH_LDFLAGS);
+ DEBUG2(" ldflags : " BUILT_WITH_LDFLAGS);
#endif
#ifdef BUILT_WITH_LIBS
- DEBUG3(" libs : " BUILT_WITH_LIBS);
+ DEBUG2(" libs : " BUILT_WITH_LIBS);
#endif
+ DEBUG2(" ");
}
- INFO("Copyright (C) 1999-2015 The FreeRADIUS server project and contributors");
+ INFO("FreeRADIUS Version " RADIUSD_VERSION_STRING);
+ INFO("Copyright (C) 1999-2016 The FreeRADIUS server project and contributors");
INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A");
INFO("PARTICULAR PURPOSE");
INFO("You may redistribute copies of FreeRADIUS under the terms of the");
len = fr_prints(out, outlen, (char const *) p, vp->vp_length, '"');
break;
+ /*
+ * Note that "%{string:...}" is NOT binary safe!
+ * It is explicitly used to get rid of embedded zeros.
+ */
case PW_TYPE_STRING:
len = strlcpy(out, vp->vp_strvalue, outlen);
break;
if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
+ if (vp->da->type != PW_TYPE_STRING) goto nothing;
+
return radius_xlat(out, outlen, request, vp->vp_strvalue, NULL, NULL);
}
* Escape the non-literals we found above.
*/
if (str && escape) {
+ size_t len;
char *escaped;
- escaped = talloc_array(ctx, char, 2048); /* FIXME: do something intelligent */
- escape(request, escaped, 2038, str, escape_ctx);
+ len = talloc_array_length(str) * 3;
+
+ escaped = talloc_array(ctx, char, len);
+ escape(request, escaped, len, str, escape_ctx);
talloc_free(str);
str = escaped;
}
--- /dev/null
+rlm_json
+rlm_winbind
+*_ext
packet->id = ntohl(magic);
code = dhcp_get_option((dhcp_packet_t *) packet->data,
- packet->data_len, 53);
+ packet->data_len, PW_DHCP_MESSAGE_TYPE);
if (!code) {
fr_strerror_printf("No message-type option was found in the packet");
rad_free(&packet);
a_p = p + 2;
/*
+ * Ensure we've not been given a bad length value
+ */
+ if ((a_p + a_len) > q) {
+ fr_strerror_printf("Length field value of option %u is incorrect. "
+ "Got %u bytes, expected <= %zu bytes", p[0], p[1], q - a_p);
+ fr_pair_list_free(out);
+ return -1;
+ }
+
+ /*
* Unknown attribute, create an octets type
* attribute with the contents of the sub-option.
*/
* Decode the header.
*/
for (i = 0; i < 14; i++) {
- char *q;
vp = fr_pair_make(packet, NULL, dhcp_header_names[i], NULL, T_OP_EQ);
if (!vp) {
break;
case PW_TYPE_STRING:
- vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
- vp->type = VT_DATA;
- memcpy(q, p, dhcp_header_sizes[i]);
- q[dhcp_header_sizes[i]] = '\0';
- vp->vp_length = strlen(vp->vp_strvalue);
- if (vp->vp_length == 0) {
- fr_pair_list_free(&vp);
+ /*
+ * According to RFC 2131, these are null terminated strings.
+ * We don't trust everyone to abide by the RFC, though.
+ */
+ if (*p != '\0') {
+ uint8_t *end;
+ int len;
+ end = memchr(p, '\0', dhcp_header_sizes[i]);
+ len = end ? end - p : dhcp_header_sizes[i];
+ fr_pair_value_bstrncpy(vp, p, len);
}
+ if (vp->vp_length == 0) fr_pair_list_free(&vp);
break;
case PW_TYPE_OCTETS:
/*
* DHCP-Message-Type is first, for simplicity.
*/
- if ((my_a->da->attr == 53) && (my_b->da->attr != 53)) return -1;
+ if ((my_a->da->attr == PW_DHCP_MESSAGE_TYPE) && (my_b->da->attr != PW_DHCP_MESSAGE_TYPE)) return -1;
/*
* Relay-Agent is last
*/
- if ((my_a->da->attr == 82) && (my_b->da->attr != 82)) return 1;
+ if ((my_a->da->attr == PW_DHCP_OPTION_82) && (my_b->da->attr != PW_DHCP_OPTION_82)) return 1;
if (my_a->da->attr < my_b->da->attr) return -1;
if (my_a->da->attr > my_b->da->attr) return 1;
if (!vp) return -1;
if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
- if (vp->da->attr == 53) goto next; /* already done */
+ if (vp->da->attr == PW_DHCP_MESSAGE_TYPE) goto next; /* already done */
if ((vp->da->attr > 255) && (DHCP_BASE_ATTR(vp->da->attr) != PW_DHCP_OPTION_82)) goto next;
if (vp->da->flags.extended) {
packet->id = xid;
code = dhcp_get_option((dhcp_packet_t *) packet->data,
- packet->data_len, 53);
+ packet->data_len, PW_DHCP_MESSAGE_TYPE);
if (!code) {
fr_strerror_printf("No message-type option was found in the packet");
rad_free(&packet);
if (c->state) {
rdebug_pair_list(L_DBG_LVL_2, request, c->state, "&session-state:");
- radius_pairmove(request, &request->state, fr_pair_list_copy(request->state, c->state), false);
+
+ fr_pair_list_mcopy_by_num(request->state_ctx, &request->state, &c->state, 0, 0, TAG_ANY);
}
if (inst->stats) {
uint8_t pass_str[MAX_STRING_LEN];
if (!request->username) {
- RWDEBUG("&request:User-Name attribute is required for authentication");
+ REDEBUG("&request:User-Name attribute is required for authentication");
return RLM_MODULE_INVALID;
}
/* do nothing if this is not enabled */
if (inst->check_simul != true) {
- RDEBUG3("mod_checksimul returning noop - not enabled");
+ RWDEBUG("Simultaneous-Use checking requires 'simul_count_query' to be configured");
return RLM_MODULE_NOOP;
}
/* ensure valid username in request */
- if ((!request->username) || (request->username->vp_length == '\0')) {
- RDEBUG3("mod_checksimul - invalid username");
+ if ((!request->username) || (request->username->vp_length == 0)) {
+ REDEBUG("Zero Length username not permitted");
return RLM_MODULE_INVALID;
}
TGT_LDLIBS := @mod_ldflags@
ifneq "$(TARGETNAME)" ""
-install: install.bindir $(R)$(bindir)/rad_counter
+install: $(R)$(bindir)/rad_counter
-$(R)$(bindir)/rad_counter: src/modules/rlm_counter/rad_counter
+$(R)$(bindir)/rad_counter: src/modules/rlm_counter/rad_counter | $(R)$(bindir)
@$(INSTALL) -m 755 src/modules/rlm_counter/rad_counter $(R)$(bindir)/
endif
inst->escape_func = rad_filename_make_safe;
}
- inst->ef = exfile_init(inst, 64, 30, inst->locking);
+ inst->ef = exfile_init(inst, 256, 30, inst->locking);
if (!inst->ef) {
cf_log_err_cs(conf, "Failed creating log file context");
return -1;
int length = i->vp_length;
int attrlen;
uint8_t const *p = &i->vp_octets[0];
- char *q;
VALUE_PAIR *sub;
/*
*/
sub = radius_pair_create(request->packet, &request->packet->vps,
PW_DIGEST_REALM - 1 + p[0], 0);
- sub->vp_length = attrlen - 2;
- sub->vp_strvalue = q = talloc_array(sub, char, sub->vp_length + 1);
- memcpy(q, p + 2, attrlen - 2);
- q[attrlen - 2] = '\0';
+ fr_pair_value_bstrncpy(sub, p + 2, attrlen - 2);
if ((rad_debug_lvl > 1) && fr_log_fp) {
vp_print(fr_log_fp, sub);
p++;
}
-#if defined(HAVE_DLFCN_H) && defined(RTLD_SELF)
- method->type = dlsym(RTLD_SELF, mod_name);
- if (method->type) goto open_self;
-#endif
-
/*
* Link the loaded EAP-Type
*/
return -1;
}
-#if !defined(WITH_LIBLTDL) && defined(HAVE_DLFCN_H) && defined(RTLD_SELF)
-open_self:
-#endif
cf_log_module(cs, "Linked to sub-module %s", mod_name);
/*
if ((nak->data[i] >= PW_EAP_MAX_TYPES) ||
!inst->methods[nak->data[i]]) {
RDEBUG2("Peer NAK'd asking for "
- "unsupported type %s (%d), skipping...",
+ "unsupported EAP type %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;
}
}
/*
- * Multiple levels of nesting are 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) {
- RDEBUG2("Multiple levels of TLS nesting is invalid");
+ 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;
}
if ((next < PW_EAP_MD5) ||
(next >= PW_EAP_MAX_TYPES) ||
(!inst->methods[next])) {
- REDEBUG2("Tried to start unsupported method (%d)", next);
+ REDEBUG2("Tried to start unsupported EAP type %s (%d)",
+ eap_type2name(next), next);
return EAP_INVALID;
}
* We haven't configured it, it doesn't exit.
*/
if (!inst->methods[type->num]) {
- REDEBUG2("Client asked for unsupported method %s (%d)",
+ REDEBUG2("Client asked for unsupported EAP type %s (%d)",
eap_type2name(type->num),
type->num);
if ((eap_packet->data[7] == 0) ||
(eap_packet->data[7] >= PW_EAP_MAX_TYPES)) {
- RAUTH("Unsupported Expanded EAP type %u: ignoring the packet", eap_packet->data[7]);
+ RAUTH("Unsupported Expanded EAP type %s (%u): ignoring the packet",
+ eap_type2name(eap_packet->data[7]), eap_packet->data[7]);
return EAP_INVALID;
}
p = talloc_realloc(talloc_parent(eap_packet), eap_packet, uint8_t, len - 7);
if (!p) {
- RAUTH("Unsupported EAP type %u: ignoring the packet", eap_packet->data[0]);
+ RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
+ eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
return EAP_INVALID;
}
return EAP_VALID;
}
- RAUTH("Unsupported EAP type %u: ignoring the packet", eap_packet->data[0]);
+ RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
+ eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
return EAP_INVALID;
}
len = ntohs(len);
if ((len <= 5) || (eap_packet->data[1] == 0x00)) {
- RDEBUG("EAP-Identity Unknown");
+ REDEBUG("EAP-Identity Unknown");
return NULL;
}
if (len > 1024) {
- RDEBUG("EAP-Identity too long");
+ REDEBUG("EAP-Identity too long");
return NULL;
}
/* Set-up the fake request */
fake = request_alloc_fake(request);
- pair_make_request("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
+ 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) {
status = eaptls_operation(status, handler);
if (status == FR_TLS_SUCCESS) {
#define MAX_SESSION_SIZE (256)
- size_t size;
VALUE_PAIR *vps;
char buffer[2 * MAX_SESSION_SIZE + 1];
+
/*
* Restore the cached VPs before processing the
* application data.
*/
- size = tls_session->ssl->session->session_id_length;
- if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;
-
- fr_bin2hex(buffer, tls_session->ssl->session->session_id, size);
+ 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);
+ vps = SSL_SESSION_get_ex_data(tls_session->ssl_session, fr_tls_ex_index_vps);
if (!vps) {
RWDEBUG("No information in cached session %s", buffer);
} else {
/* MPPE key generation */
+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 *prf_label);
void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size);
void eaptls_gen_eap_key(RADIUS_PACKET *packet, SSL *s, uint32_t header);
+void eap_fast_tls_gen_challenge(SSL *ssl, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label) CC_HINT(nonnull);
#define BUFFER_SIZE 1024
/* big enough to have even a single attribute */
if (attrlen < 5) {
- ERROR("eap: EAP-Sim attribute too short: %d < 5", attrlen);
+ 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;
}
uint8_t *p;
if(attrlen < 2) {
- ERROR("eap: EAP-Sim attribute %d too short: %d < 2", es_attribute_count, attrlen);
+ fr_strerror_printf("EAP-Sim attribute %d too short: %d < 2", es_attribute_count, attrlen);
return 0;
}
eapsim_len = attr[1] * 4;
if (eapsim_len > attrlen) {
- ERROR("eap: EAP-Sim attribute %d (no.%d) has length longer than data (%d > %d)",
- eapsim_attribute, es_attribute_count, 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;
}
eapsim_len = MAX_STRING_LEN;
}
if (eapsim_len < 2) {
- ERROR("eap: EAP-Sim attribute %d (no.%d) has length too small", eapsim_attribute,
- es_attribute_count);
- return 0;
+ fr_strerror_printf("EAP-Sim attribute %d (no.%d) has length too small", eapsim_attribute,
+ es_attribute_count);
+ return 0;
}
newvp = fr_pair_afrom_num(r, eapsim_attribute+PW_EAP_SIM_BASE, 0);
attrlen -= eapsim_len;
es_attribute_count++;
}
+
return 1;
}
#include <openssl/hmac.h>
-#if OPENSSL_VERSION_NUMBER < 0x10001000L
/*
* TLS PRF from RFC 2246
*/
HMAC_CTX_init(&ctx_a);
HMAC_CTX_init(&ctx_out);
+#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
+ HMAC_CTX_set_flags(&ctx_a, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+ HMAC_CTX_set_flags(&ctx_out, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL);
HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL);
memset(a, 0, sizeof(a));
}
+/* 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);
+}
+
static void PRF(unsigned char const *secret, unsigned int secret_len,
unsigned char const *seed, unsigned int seed_len,
unsigned char *out, unsigned char *buf, unsigned int out_len)
out[i] ^= buf[i];
}
}
-#endif
#define EAPTLS_MPPE_KEY_LEN 32
uint8_t *p;
size_t prf_size;
- if (!s->s3) {
- ERROR("No SSLv3 information");
- return;
- }
-
prf_size = strlen(prf_label);
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
*/
void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size)
{
-#if OPENSSL_VERSION_NUMBER < 0x10001000L
- uint8_t out[32], buf[32];
- uint8_t seed[sizeof(FR_TLS_PRF_CHALLENGE)-1 + 2*SSL3_RANDOM_SIZE];
- uint8_t *p = seed;
-#endif
-
- if (!s->s3) {
- ERROR("No SSLv3 information");
- return;
- }
-
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
SSL_export_keying_material(s, buffer, size, FR_TLS_PRF_CHALLENGE,
sizeof(FR_TLS_PRF_CHALLENGE) - 1, NULL, 0, 0);
+
#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);
PRF(s->session->master_key, s->session->master_key_length,
seed, sizeof(seed), out, buf, sizeof(out));
-
memcpy(buffer, out, size);
#endif
}
VALUE_PAIR *vp;
uint8_t *p;
- if (!s->s3) {
- ERROR("No SSLv3 information");
- return;
- }
-
vp = fr_pair_afrom_num(packet, PW_EAP_SESSION_ID, 0);
if (!vp) return;
p = talloc_array(vp, uint8_t, vp->vp_length);
p[0] = header & 0xff;
+
+#ifdef HAVE_SSL_GET_CLIENT_RANDOM
+ SSL_get_client_random(s, p + 1, SSL3_RANDOM_SIZE);
+ SSL_get_server_random(s, p + 1 + SSL3_RANDOM_SIZE, SSL3_RANDOM_SIZE);
+#else
memcpy(p + 1, s->s3->client_random, SSL3_RANDOM_SIZE);
memcpy(p + 1 + SSL3_RANDOM_SIZE,
s->s3->server_random, SSL3_RANDOM_SIZE);
+#endif
vp->vp_octets = p;
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, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label)
+{
+ uint8_t seed[128 + 2*SSL3_RANDOM_SIZE];
+ uint8_t *p = seed;
+ size_t len;
+
+ len = strlen(prf_label);
+ if (len > 128) len = 128;
+
+ memcpy(p, prf_label, len);
+ p += len;
+ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+
+ PRF(s->session->master_key, s->session->master_key_length,
+ seed, p - seed, buffer, scratch, size);
+}
+
+
* must exist.
*/
state = fr_pair_find_by_num(request->packet->vps, PW_STATE, 0, TAG_ANY);
- if (!state ||
- (state->vp_length != EAP_STATE_LEN)) {
+ 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;
}
static int totaldeny = 0;
static char filesecret[256];
static char const *radius_dir = NULL;
-char const *progname = "radeapclient";
+static char const *progname = "radeapclient";
/* fr_randctx randctx; */
main_config_t main_config;
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
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);
* etc. configurations from eap.conf in order to
* have EAP without the TLS types.
*/
- if ((method == PW_EAP_TLS) ||
- (method == PW_EAP_TTLS) ||
- (method == PW_EAP_PEAP)) {
- DEBUG2("rlm_eap (%s): Ignoring EAP method %s because we do not have OpenSSL support",
- inst->xlat_name, name);
+ switch (method) {
+ 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
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 = EAP' for a request that does "
- "not contain an EAP-Message attribute!");
+ REDEBUG("You set 'Auth-Type = %s' for a request that does "
+ "not contain an EAP-Message attribute!", inst->xlat_name);
return RLM_MODULE_INVALID;
}
*/
fr_pair_delete_by_num(&request->proxy->vps, PW_FREERADIUS_PROXIED_TO, VENDORPEC_FREERADIUS, TAG_ANY);
- RDEBUG2("Tunneled session will be proxied. Not doing EAP");
+ RWDEBUG2("Tunneled session will be proxied. Not doing EAP");
return RLM_MODULE_HANDLED;
}
#endif
{
size_t i;
size_t len;
+ ssize_t ret;
char *p;
VALUE_PAIR *vp;
eap_handler_t *handler;
i = 34;
p = talloc_memdup(vp, vp->vp_strvalue, vp->vp_length + 1);
talloc_set_type(p, uint8_t);
- len = rad_tunnel_pwdecode((uint8_t *)p + 17, &i, request->home_server->secret, request->proxy->vector);
+ 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;
- /*
- * FIXME: Assert that i == 16.
- */
+ 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.
*/
- rad_tunnel_pwencode(p + 17, &len,
- request->client->secret,
- request->packet->vector);
+ 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;
--- /dev/null
+TARGETNAME := rlm_eap_fast
+
+ifneq "$(OPENSSL_LIBS)" ""
+TARGET := $(TARGETNAME).a
+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
--- /dev/null
+/*
+ * 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;
+
+ 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);
+ RDEBUG2("OpenSSL: cipher nid %d digest nid %d", cipher, digest);
+ if (cipher < 0 || digest < 0)
+ return -1;
+ c = EVP_get_cipherbynid(cipher);
+ h = EVP_get_digestbynid(digest);
+ if (!c || !h)
+ return -1;
+
+ RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d IV_len=%d",
+ EVP_CIPHER_key_length(c), EVP_MD_size(h),
+ EVP_CIPHER_iv_length(c));
+ return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) +
+ EVP_CIPHER_iv_length(c));
+#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;
+ uint8_t *scratch;
+ 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));
+ scratch = talloc_size(request, ksize + sizeof(*t->keyblock));
+
+ t->keyblock = talloc(t, eap_fast_keyblock_t);
+
+ eap_fast_tls_gen_challenge(tls_session->ssl, buf, scratch, 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);
+ talloc_free(scratch);
+}
+
+/**
+ * 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);
+
+ 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;
+ memset(&binding, 0, sizeof(eap_tlv_crypto_binding_tlv_t));
+ const int len = sizeof(binding) - (&binding.reserved - (uint8_t *)&binding);
+
+ RDEBUG("Sending Cryptobinding");
+
+ 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");
+ 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:
+ memcpy(t->isk.mppe_send, vp->vp_octets, CHAP_VALUE_LENGTH);
+ break;
+
+ case PW_MSCHAP_MPPE_RECV_KEY:
+ 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;
+
+ RWDEBUG2("AUTHENTICATION");
+ vp = fr_pair_make(fake, &fake->config, "EAP-Type", "0", T_OP_EQ);
+ vp->vp_integer = t->default_method;
+ RWDEBUG2("AUTHENTICATION");
+
+ /*
+ * 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;
+
+ 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) {
+ binding = talloc_zero(request->packet, eap_tlv_crypto_binding_tlv_t);
+ memcpy(binding, vp->vp_octets, sizeof(*binding));
+ binding->tlv_type = htons(EAP_FAST_TLV_MANDATORY | EAP_FAST_TLV_CRYPTO_BINDING);
+ binding->length = htons(sizeof(*binding) - 2 * sizeof(uint16_t));
+ }
+ 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 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;
+ }
+
+ if (!t->pac.expires || t->pac.expired || t->pac.expires - time(NULL) < t->pac_lifetime * 0.6)
+ 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 (code == PW_CODE_ACCESS_REJECT)
+ break;
+
+ 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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"
+
+// http://stackoverflow.com/a/29838852
+static void NEVER_RETURNS handleErrors(void)
+{
+ unsigned long errCode;
+
+ fprintf(stderr, "An error occurred\n");
+ while((errCode = ERR_get_error()))
+ {
+ char *err = ERR_error_string(errCode, NULL);
+ fprintf(stderr, "%s\n", err);
+ }
+ abort();
+}
+
+// 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())) handleErrors();
+
+ /* Initialise the encryption operation. */
+ if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
+ handleErrors();
+
+ /* 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))
+ handleErrors();
+
+ /* Initialise key and IV */
+ if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
+
+ /* Provide any AAD data. This can be called zero or more times as
+ * required
+ */
+ if (1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
+ handleErrors();
+
+ /* 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))
+ handleErrors();
+ 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)) handleErrors();
+ ciphertext_len += len;
+
+ /* Get the tag */
+ if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
+ handleErrors();
+
+ /* 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())) handleErrors();
+
+ /* Initialise the decryption operation. */
+ if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
+ handleErrors();
+
+ /* 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))
+ handleErrors();
+
+ /* Initialise key and IV */
+ if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
+
+ /* Provide any AAD data. This can be called zero or more times as
+ * required
+ */
+ if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
+ handleErrors();
+
+ /* 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))
+ handleErrors();
+ 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)) handleErrors();
+ }
+
+ /* 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)
+ {
+ /* Success */
+ plaintext_len += len;
+ return plaintext_len;
+ }
+ else
+ {
+ /* Verify failed */
+ return -1;
+ }
+}
--- /dev/null
+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);
--- /dev/null
+/*
+ * 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.
+ 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},
+
+ { "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;
+ }
+
+ // FIXME TLSv1.2 uses a different PRF and SSL_export_keying_material("key expansion") is forbidden
+ if (!inst->tls_conf->disable_tlsv1_2) {
+ ERROR("rlm_eap_fast.disable_tlsv1_2: require disable_tlsv1_2=yes");
+ return -1;
+ }
+
+ if (!inst->pac_lifetime) {
+ ERROR("rlm_eap_fast.pac_lifetime: must be non-zero");
+ return -1;
+ }
+
+ 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()
+static int _session_secret(SSL *s, void *secret, int *secret_len,
+ UNUSED STACK_OF(SSL_CIPHER) *peer_ciphers,
+ UNUSED SSL_CIPHER **cipher, void *arg)
+{
+ // 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 const client_random[SSL3_RANDOM_SIZE];
+ uint8_t const 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;
+ uint16_t 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 - sizeof(opaque->hdr) < length) {
+ 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 == -1) {
+ 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;
+ t->pac.expired = (vp->vp_integer <= time(NULL));
+ 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;
+ 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 {
+ RDEBUG2("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
+ }
+
+ 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:
+ return 1;
+
+ /*
+ * Handshake is done, proceed with decoding tunneled
+ * data.
+ */
+ case FR_TLS_OK:
+ break;
+
+ /*
+ * Anything else: fail.
+ */
+ default:
+ return 0;
+ }
+
+ /*
+ * 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);
+ return 0;
+
+ /*
+ * 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);
+ return 1;
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ case PW_CODE_ACCESS_ACCEPT:
+ RDEBUG("Note that the 'missing PRF label' message below is harmless. Please ignore it.");
+ 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");
+ }
+ return eaptls_success(handler, EAP_FAST_VERSION);
+
+ /*
+ * 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
+ return 1;
+
+ default:
+ break;
+ }
+
+ /*
+ * Something we don't understand: Reject it.
+ */
+ eaptls_fail(handler, EAP_FAST_VERSION);
+ return 0;
+}
+
+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;
+ }
+ handler->opaque = tls_session = eaptls_session(handler, inst->tls_conf, client_cert);
+
+ if (!tls_session) return 0;
+
+ /*
+ * 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) {
+ 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");
+ return 0;
+ }
+
+ 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 */
+};
*/
} else if (eap_ds->response->type.length <= 128) {
int rcode;
- char *p;
/*
* If there was a User-Password in the request,
if (!vp) {
return 0;
}
- vp->vp_length = eap_ds->response->type.length;
- vp->vp_strvalue = p = talloc_array(vp, char, vp->vp_length + 1);
- vp->type = VT_DATA;
- memcpy(p, eap_ds->response->type.data, vp->vp_length);
- p[vp->vp_length] = 0;
+
+ fr_pair_value_bstrncpy(vp, eap_ds->response->type.data, eap_ds->response->type.length);
/*
* Add the password to the request, and allow
password = fr_pair_find_by_num(handler->request->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
if (!password) {
- RDEBUG2("Cleartext-Password is required for EAP-MD5 authentication");
+ REDEBUG2("Cleartext-Password is required for EAP-MD5 authentication");
return 0;
}
bool with_ntdomain_hack;
bool send_error;
char const *identity;
+ int auth_type_mschap;
} rlm_eap_mschapv2_t;
static CONF_PARSER module_config[] = {
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;
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;
}
* 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) {
+ 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;
}
*/
if (inst->with_ntdomain_hack &&
((challenge = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY)) != NULL) &&
- ((username = strchr(challenge->vp_strvalue, '\\')) != NULL)) {
+ ((username = memchr(challenge->vp_octets, '\\', challenge->vp_length)) != NULL)) {
/*
* Wipe out the NT domain.
*
/*
* This is a wild & crazy hack.
*/
- rcode = process_authenticate(PW_AUTH_TYPE_MS_CHAP, request);
+ rcode = process_authenticate(inst->auth_type_mschap, request);
/*
* Delete MPPE keys & encryption policy. We don't
/*
* Process the PEAP portion of an EAP-PEAP request.
*/
-rlm_rcode_t eappeap_process(eap_handler_t *handler, tls_session_t *tls_session) CC_HINT(nonnull);
+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 */
/*
* Process the pseudo-EAP contents of the tunneled data.
*/
-rlm_rcode_t eappeap_process(eap_handler_t *handler, tls_session_t *tls_session)
+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;
case PEAP_STATUS_WAIT_FOR_SOH_RESPONSE:
fake = request_alloc_fake(request);
rad_assert(!fake->packet->vps);
- eapsoh_verify(request, fake->packet, data, data_len);
+ eapsoh_verify(fake, fake->packet, data, data_len);
setup_fake_request(request, fake, t);
if (t->soh_virtual_server) {
return RLM_MODULE_REJECT;
/*
- * Damned if I know why the clients continue sending EAP
- * packets after we told them to f*ck off.
+ * Supplicant ACKs our failure.
*/
case PEAP_STATUS_SENT_TLV_FAILURE:
RINDENT();
- RINFO("The users session was previously rejected: returning reject (again.)");
- RINFO("This means you need to read the PREVIOUS messages in the debug output");
- RINFO("to find out the reason why the user was rejected");
- RINFO("Look for \"reject\" or \"fail\". Those earlier messages will tell you");
- RINFO("what went wrong, and how to fix the problem");
+ RIDEBUG("The users session was previously rejected: returning reject (again.)");
+ RIDEBUG("This means you need to read the PREVIOUS messages in the debug output");
+ RIDEBUG("to find out the reason why the user was rejected");
+ RIDEBUG("Look for \"reject\" or \"fail\". Those earlier messages will tell you");
+ RIDEBUG("what went wrong, and how to fix the problem");
REXDENT();
return RLM_MODULE_REJECT;
* 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(PW_AUTH_TYPE_EAP, fake);
+ rcode = process_authenticate(auth_type_eap, fake);
if (rcode == RLM_MODULE_OK) {
/*
* Authentication succeeded! Rah!
/*
* Some attributes are handled specially.
*/
- switch (vp->da->attr) {
+ if (!vp->da->vendor) switch (vp->da->attr) {
/*
* NEVER copy Message-Authenticator,
* EAP-Message, or State. They're
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.
{ "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" },
{ "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
};
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;
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.
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;
}
/*
* Process the PEAP portion of the request.
*/
- rcode = eappeap_process(handler, tls_session);
+ rcode = eappeap_process(handler, tls_session, inst->auth_type_eap);
switch (rcode) {
case RLM_MODULE_REJECT:
eaptls_fail(handler, 0);
TARGETNAME := @targetname@
+ifneq "$(OPENSSL_LIBS)" ""
ifneq "$(TARGETNAME)" ""
TARGET := $(TARGETNAME).a
endif
+endif
SOURCES := $(TARGETNAME).c eap_pwd.c
uint8_t exch, *in, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN];
uint8_t peer_confirm[SHA256_DIGEST_LENGTH];
BIGNUM *x = NULL, *y = NULL;
- char *p;
if (((eap_ds = handler->eap_ds) == NULL) || !inst) return 0;
RDEBUG("pwd unable to create fake request!");
return 0;
}
- fake->username = pair_make_request("User-Name", NULL, T_OP_EQ);
+ fake->username = fr_pair_afrom_num(fake->packet, PW_USER_NAME, 0);
if (!fake->username) {
- RDEBUG("pwd unanable to create value pair for username!");
+ RDEBUG("Failed creating pair for peer id");
talloc_free(fake);
return 0;
}
- fake->username->vp_length = session->peer_id_len;
- fake->username->vp_strvalue = p = talloc_array(fake->username, char, fake->username->vp_length + 1);
- memcpy(p, session->peer_id, session->peer_id_len);
- p[fake->username->vp_length] = '\0';
-
+ fr_pair_value_bstrncpy(fake->username, session->peer_id, session->peer_id_len);
fr_pair_add(&fake->packet->vps, fake->username);
if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
/*
* build a reply to be sent.
*/
-static int eap_sim_compose(eap_handler_t *handler)
+static void eap_sim_compose(REQUEST *request, eap_handler_t *handler)
{
/* we will set the ID on requests, since we have to HMAC it */
handler->eap_ds->set_request_id = 1;
- return map_eapsim_basictypes(handler->request->reply,
- handler->eap_ds->request);
+ if (!map_eapsim_basictypes(handler->request->reply,
+ handler->eap_ds->request)) {
+ REDEBUG("Failed decoding EAP-SIM packet: %s", fr_strerror());
+ }
}
static int eap_sim_sendstart(eap_handler_t *handler)
/** Run the server state machine
*
*/
-static void eap_sim_stateenter(eap_handler_t *handler,
- eap_sim_state_t *ess,
- enum eapsim_serverstates newstate)
+static void eap_sim_state_enter(REQUEST *request, eap_handler_t *handler,
+ eap_sim_state_t *ess,
+ enum eapsim_serverstates newstate)
{
switch (newstate) {
/*
ess->state = newstate;
/* build the target packet */
- eap_sim_compose(handler);
+ eap_sim_compose(request, handler);
}
/*
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;
+ return 0; /* already printed error */
}
/*
time(&n);
ess->sim_id = (n & 0xff);
- eap_sim_stateenter(handler, ess, EAPSIM_SERVER_START);
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_START);
return 1;
}
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_stateenter(handler, ess, EAPSIM_SERVER_START);
-
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_START);
return 1;
}
*/
if (selectedversion_vp->vp_length < 2) {
REDEBUG("EAP-SIM version field is too short");
-
return 0;
}
memcpy(&simversion, selectedversion_vp->vp_strvalue, sizeof(simversion));
/*
* Everything looks good, change states
*/
- eap_sim_stateenter(handler, ess, EAPSIM_SERVER_CHALLENGE);
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_CHALLENGE);
return 1;
}
}
/* everything looks good, change states */
- eap_sim_stateenter(handler, ess, EAPSIM_SERVER_SUCCESS);
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_SUCCESS);
return 1;
}
handler->eap_ds->response->type.data,
handler->eap_ds->response->type.length);
- if (!success) return 0;
+ if (!success) {
+ REDEBUG("Failed decoding EAP-SIM packet: %s", fr_strerror());
+ return 0;
+ }
/*
* See what kind of message we have gotten
*/
default:
- eap_sim_stateenter(handler, ess, EAPSIM_SERVER_START);
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_START);
return 1;
/*
* A response to our EAP-Sim/Request/Start!
* Pretty much anything else here is illegal, so we will retransmit the request.
*/
default:
- eap_sim_stateenter(handler, ess, EAPSIM_SERVER_CHALLENGE);
+ eap_sim_state_enter(request, handler, ess, EAPSIM_SERVER_CHALLENGE);
return 1;
/*
* A response to our EAP-Sim/Request/Challenge!
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.
/*
* Tell the request that it's a fake one.
*/
- pair_make_request("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
+ 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);
/*
* Some attributes are handled specially.
*/
- switch (vp->da->attr) {
+ if (!vp->da->vendor) switch (vp->da->attr) {
/*
* NEVER copy Message-Authenticator,
* EAP-Message, or State. They're
VALUE_PAIR **input_pairs = NULL, **output_pairs = NULL;
VALUE_PAIR *answer = NULL;
+ TALLOC_CTX *ctx = NULL;
char out[1024];
/*
if (!output_pairs) {
return RLM_MODULE_INVALID;
}
+
+ ctx = radius_list_ctx(request, inst->output_list);
}
/*
* This function does it's own xlat of the input program
* to execute.
*/
- status = radius_exec_program(request, out, sizeof(out), inst->output ? &answer : NULL, request,
+ status = radius_exec_program(ctx, out, sizeof(out), inst->output ? &answer : NULL, request,
inst->program, inst->input ? *input_pairs : NULL,
inst->wait, inst->shell_escape, inst->timeout);
rcode = rlm_exec_status2rcode(request, out, strlen(out), status);
*
* Probably only works for ASCII
*/
-static ssize_t lc_xlat(UNUSED void *instance, UNUSED REQUEST *request,
- char const *fmt, char *out, size_t outlen)
+static ssize_t tolower_xlat(UNUSED void *instance, UNUSED REQUEST *request, char const *fmt, char *out, size_t outlen)
{
char *q;
char const *p;
*
* Probably only works for ASCII
*/
-static ssize_t uc_xlat(UNUSED void *instance, UNUSED REQUEST *request,
- char const *fmt, char *out, size_t outlen)
+static ssize_t toupper_xlat(UNUSED void *instance, UNUSED REQUEST *request, char const *fmt, char *out, size_t outlen)
{
char *q;
char const *p;
xlat_register("urlunquote", urlunquote_xlat, NULL, inst);
xlat_register("escape", escape_xlat, NULL, inst);
xlat_register("unescape", unescape_xlat, NULL, inst);
- xlat_register("tolower", lc_xlat, NULL, inst);
- xlat_register("toupper", uc_xlat, NULL, inst);
+ xlat_register("tolower", tolower_xlat, NULL, inst);
+ xlat_register("toupper", toupper_xlat, NULL, inst);
xlat_register("md5", md5_xlat, NULL, inst);
xlat_register("sha1", sha1_xlat, NULL, inst);
#ifdef HAVE_OPENSSL_EVP_H
fr_pair_value_strcpy(vp, dn);
*rcode = RLM_MODULE_OK;
}
-
-finish:
ldap_memfree(dn);
+finish:
if ((freeit || (*rcode != RLM_MODULE_OK)) && *result) {
ldap_msgfree(*result);
*result = NULL;
}
#endif
+int rlm_ldap_global_init(rlm_ldap_t *inst)
+{
+ int ldap_errno;
+
+ rad_assert(inst); /* clang scan */
+
+#define do_ldap_global_option(_option, _name, _value) \
+ if (ldap_set_option(NULL, _option, _value) != LDAP_OPT_SUCCESS) { \
+ ldap_get_option(NULL, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
+ ERROR("Failed setting global option %s: %s", _name, \
+ (ldap_errno != LDAP_SUCCESS) ? ldap_err2string(ldap_errno) : "Unknown error"); \
+ return -1;\
+ }
+
+#define maybe_ldap_global_option(_option, _name, _value) \
+ if (_value) do_ldap_global_option(_option, _name, _value)
+
+#ifdef LDAP_OPT_DEBUG_LEVEL
+ /*
+ * Can't use do_ldap_global_option
+ */
+ if (inst->ldap_debug) do_ldap_global_option(LDAP_OPT_DEBUG_LEVEL, "ldap_debug", &(inst->ldap_debug));
+#endif
+
+#ifdef LDAP_OPT_X_TLS_RANDOM_FILE
+ /*
+ * OpenLDAP will error out if we attempt to set
+ * this on a handle. Presumably it's global in
+ * OpenSSL too.
+ */
+ maybe_ldap_global_option(LDAP_OPT_X_TLS_RANDOM_FILE, "random_file", inst->tls_random_file);
+#endif
+ return 0;
+}
+
/** Close and delete a connection
*
* Unbinds the LDAP connection, informing the server and freeing any memory, then releases the memory used by the
goto error;\
}
-#define do_ldap_global_option(_option, _name, _value) \
- if (ldap_set_option(NULL, _option, _value) != LDAP_OPT_SUCCESS) { \
- ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
- LDAP_ERR("Failed setting global option %s: %s", _name, \
- (ldap_errno != LDAP_SUCCESS) ? ldap_err2string(ldap_errno) : "Unknown error"); \
- goto error;\
- }
-
- if (inst->ldap_debug) {
- do_ldap_global_option(LDAP_OPT_DEBUG_LEVEL, "ldap_debug", &(inst->ldap_debug));
- }
+#define maybe_ldap_option(_option, _name, _value) \
+ if (_value) do_ldap_option(_option, _name, _value)
/*
* Leave "dereference" unset to use the OpenLDAP default.
do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(inst->tls_mode));
}
-# define maybe_ldap_option(_option, _name, _value) \
- if (_value) do_ldap_option(_option, _name, _value)
-
maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE, "ca_file", inst->tls_ca_file);
maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR, "ca_path", inst->tls_ca_path);
*/
maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE, "certificate_file", inst->tls_certificate_file);
maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE, "private_key_file", inst->tls_private_key_file);
- maybe_ldap_option(LDAP_OPT_X_TLS_RANDOM_FILE, "random_file", inst->tls_random_file);
# ifdef LDAP_OPT_X_TLS_NEVER
if (inst->tls_require_cert_str) {
char *rlm_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in);
+int rlm_ldap_global_init(rlm_ldap_t *inst) CC_HINT(nonnull);
+
void *mod_conn_create(TALLOC_CTX *ctx, void *instance);
ldap_handle_t *mod_conn_get(rlm_ldap_t const *inst, REQUEST *request);
{ "keyfile", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT | PW_TYPE_DEPRECATED, rlm_ldap_t, tls_private_key_file), NULL }, // OK if it changes on HUP
{ "private_key_file", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_private_key_file), NULL }, // OK if it changes on HUP
- { "randfile", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT | PW_TYPE_DEPRECATED, rlm_ldap_t, tls_random_file), NULL },
- { "random_file", FR_CONF_OFFSET(PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_random_file), NULL },
+ { "randfile", FR_CONF_OFFSET(PW_TYPE_FILE_EXISTS | PW_TYPE_DEPRECATED, rlm_ldap_t, tls_random_file), NULL },
+ { "random_file", FR_CONF_OFFSET(PW_TYPE_FILE_EXISTS, rlm_ldap_t, tls_random_file), NULL },
/*
* LDAP Specific TLS attributes
static const CONF_PARSER module_config[] = {
- { "server", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_ldap_t, config_server), NULL }, /* Do not set to required */
+ { "server", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_MULTI, rlm_ldap_t, config_server), NULL }, /* Do not set to required */
{ "port", FR_CONF_OFFSET(PW_TYPE_SHORT, rlm_ldap_t, port), NULL },
{ "identity", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_ldap_t, admin_identity), NULL },
return -1;
}
- if (ldap_url->lud_dn) {
+ if (ldap_url->lud_dn && (ldap_url->lud_dn[0] != '\0')) {
cf_log_err_cs(conf, "Base DN cannot be specified via server URL");
goto ldap_url_error;
}
}
/*
+ * Set global options
+ */
+ if (rlm_ldap_global_init(inst) < 0) goto error;
+
+ /*
* Initialize the socket pool.
*/
inst->pool = fr_connection_pool_module_init(inst->cs, inst, mod_conn_create, NULL, NULL);
return -1;
}
- inst->ef = exfile_init(inst, 64, 30, true);
+ inst->ef = exfile_init(inst, 256, 30, true);
if (!inst->ef) {
cf_log_err_cs(conf, "Failed creating log file context");
return -1;
char *out, size_t outlen, char const *in,
UNUSED void *arg)
{
- int len = 0;
-
if (outlen == 0) return 0;
+
if (outlen == 1) {
*out = '\0';
return 0;
}
- while (in[0]) {
- if (in[0] >= ' ') {
- if (in[0] == '\\') {
- if (outlen <= 2) break;
- outlen--;
- *out++ = '\\';
- len++;
- }
-
- outlen--;
- if (outlen == 1) break;
- *out++ = *in++;
- len++;
- continue;
- }
-
- switch (in[0]) {
- case '\n':
- if (outlen <= 2) break;
- *out++ = '\\';
- *out++ = 'n';
- in++;
- len += 2;
- break;
-
- case '\r':
- if (outlen <= 2) break;
- *out++ = '\\';
- *out++ = 'r';
- in++;
- len += 2;
- break;
-
- default:
- if (outlen <= 4) break;
- snprintf(out, outlen, "\\%03o", (uint8_t) *in);
- in++;
- out += 4;
- outlen -= 4;
- len += 4;
- break;
- }
- }
-
- *out = '\0';
- return len;
+ return fr_prints(out, outlen, in, -1, 0);
}
static rlm_rcode_t CC_HINT(nonnull) mod_do_linelog(void *instance, REQUEST *request)
{
int fd = -1;
- char *p;
- char line[4096];
rlm_linelog_t *inst = (rlm_linelog_t*) instance;
char const *value = inst->line;
gid_t gid;
char *endptr;
#endif
+ char path[2048];
+ char line[4096];
line[0] = '\0';
CONF_ITEM *ci;
CONF_PAIR *cp;
- p = line + 1;
-
- if (radius_xlat(p, sizeof(line) - 2, request, inst->reference, linelog_escape_func, NULL) < 0) {
+ if (radius_xlat(line + 1, sizeof(line) - 1, request, inst->reference, linelog_escape_func, NULL) < 0) {
return RLM_MODULE_FAIL;
}
cp = cf_item_to_pair(ci);
value = cf_pair_value(cp);
if (!value) {
- RDEBUG2("Entry \"%s\" has no value", line);
- goto do_log;
+ RWDEBUG2("Entry \"%s\" has no value", line);
+ return RLM_MODULE_OK;
}
/*
/*
* FIXME: Check length.
*/
- if (strcmp(inst->filename, "syslog") != 0) {
- char path[2048];
-
- if (radius_xlat(path, sizeof(path), request, inst->filename, inst->escape_func, NULL) < 0) {
- return RLM_MODULE_FAIL;
- }
-
- /* check path and eventually create subdirs */
- p = strrchr(path, '/');
- if (p) {
- *p = '\0';
- if (rad_mkdir(path, 0700, -1, -1) < 0) {
- RERROR("rlm_linelog: Failed to create directory %s: %s", path, fr_syserror(errno));
- return RLM_MODULE_FAIL;
- }
- *p = '/';
- }
-
- fd = exfile_open(inst->ef, path, inst->permissions, true);
- if (fd < 0) {
- ERROR("rlm_linelog: Failed to open %s: %s", path, fr_syserror(errno));
- return RLM_MODULE_FAIL;
- }
-
- if (inst->group != NULL) {
- gid = strtol(inst->group, &endptr, 10);
- if (*endptr != '\0') {
- if (rad_getgid(request, &gid, inst->group) < 0) {
- RDEBUG2("Unable to find system group \"%s\"", inst->group);
- goto skip_group;
- }
- }
-
- if (chown(path, -1, gid) == -1) {
- RDEBUG2("Unable to change system group of \"%s\"", path);
- }
- }
+ if (radius_xlat(line, sizeof(line) - 1, request, value, linelog_escape_func, NULL) < 0) {
+ return RLM_MODULE_FAIL;
}
- skip_group:
+#ifdef HAVE_SYSLOG_H
+ if (strcmp(inst->filename, "syslog") == 0) {
+ syslog(inst->syslog_priority, "%s", line);
+ return RLM_MODULE_OK;
+ }
+#endif
/*
- * FIXME: Check length.
+ * We're using a real filename now.
*/
- if (value && (radius_xlat(line, sizeof(line) - 1, request, value, linelog_escape_func, NULL) < 0)) {
- if (fd >= 0) exfile_close(inst->ef, fd);
+ if (radius_xlat(path, sizeof(path), request, inst->filename, inst->escape_func, NULL) < 0) {
+ return RLM_MODULE_FAIL;
+ }
+ fd = exfile_open(inst->ef, path, inst->permissions, true);
+ if (fd < 0) {
+ ERROR("rlm_linelog: Failed to open %s: %s", path, fr_syserror(errno));
return RLM_MODULE_FAIL;
}
- if (fd >= 0) {
- strcat(line, "\n");
+ if (inst->group != NULL) {
+ gid = strtol(inst->group, &endptr, 10);
+ if (*endptr != '\0') {
+ if (rad_getgid(request, &gid, inst->group) < 0) {
+ RDEBUG2("Unable to find system group \"%s\"", inst->group);
+ goto skip_group;
+ }
+ }
- if (write(fd, line, strlen(line)) < 0) {
- ERROR("rlm_linelog: Failed writing: %s", fr_syserror(errno));
- exfile_close(inst->ef, fd);
- return RLM_MODULE_FAIL;
+ if (chown(path, -1, gid) == -1) {
+ RDEBUG2("Unable to change system group of \"%s\"", path);
}
+ }
- exfile_close(inst->ef, fd);
+ skip_group:
+ strcat(line, "\n");
-#ifdef HAVE_SYSLOG_H
- } else {
- syslog(inst->syslog_priority, "%s", line);
-#endif
+ if (write(fd, line, strlen(line)) < 0) {
+ exfile_close(inst->ef, fd);
+ ERROR("rlm_linelog: Failed writing: %s", fr_syserror(errno));
+ return RLM_MODULE_FAIL;
}
+ exfile_close(inst->ef, fd);
return RLM_MODULE_OK;
}
+++ /dev/null
-New features were added:
-+ LM support to MS-CHAP
-+ support for SAMBA passwd files. It introduces new files smbpass.c and
- smbpass.h
-+ support for MS-CHAPv2. SHA1 digest support was added (sha1.c, sha1.h)
-! module is configurable via radiusd.conf and supports instances
-! module supports both authorization and authentication. Authorization
- sets authentication to MS-CHAP if any NTLM-related things found.
- During authorization new attributes added to config_items:
- LM-Password - LM-encoded password
- NT-Password - NT-encoded password
- SMB-Account-CTRL - account control flags in SAMBA format
- During authentication these attributes are checked against data
- provided by NAS.
-- RFC 2433 text with MS-CHAPv1 removed. Microsoft attributes are covered
- by RFC 2458, MS-CHAPv2 - RFC 2759. You can obtain them from
- www.rfceditor.org
-
-ZARAZA,
-3APA3A@security.nnov.ru
-
-Below is original README by Jay Miller
-
-This is a partial implementation of MS-CHAP for FreeRadius. The patch
-was designed for Cistron-Radius 1.6.4, but the changes to source are
-pretty minimal and should work with previous versions. It is based on
-RFC 2433, which is included with this package.
-
-I have tested this successfully using Windows 98 and Windows 2000 with Cisco
-AS5300 terminal servers. I have not tested it in any other environment, so
-I can't guarantee it's success everywhere. I also don't have time to do
-much troubleshooting, though I am interested to hear about problems anyone
-might have. If you can fix a problem, then I will incorporate the fix into
-the distribution.
-
-Files included:
-mschap.c - MS-CHAP functions
-mschap.h - Definitions and prototypes
-md4c.c, md4.h - RSA Data Security, Inc. MD4 Message-Digest Algorithm
-desport.c,
- deskey.c,
- des.h - Fast DES by Phil Karn (portable C version)
-rfc2433.txt - RFC upon which this algorithm is based
-
-
-ABOUT MS-CHAP
-
-I was driven to write this when a large customer demanded that they be
-able to check "Require Encrypted Password" in their Windows Dial-up
-Networking. Testing showed me that, in Windows 2000 at least, this meant
-MS-CHAP. If you want to specify CHAP, then Windows 2000 requires you to
-select "Allow unencrypted password". Duh.
-
-MS-CHAP is similar to CHAP. The NAS creates a challenge string and gives it
-to the client. The client then uses the password to encrypt the challenge
-and gives it back to the NAS, who then gives them both to Radius. Radius
-performs the same encryption of the challenge string using the locally stored
-password, then compares the result to the response from the client.
-
-The difference between MS-CHAP and CHAP is in the encryption method. CHAP
-performs one MD5 hash to get the response. MS-CHAP first encrypts the password
-with MD4. It then pads the 16-byte hash out to 21 bytes and divides this
-string into 3 parts. Each 7-byte part is used as a key for a DES encryption
-of the challenge string. The 8-byte results are then concatonated together
-into a 24-byte response.
-
-The method just described is called NT-encryption by the RFC. MS-CHAP is
-actually designed for compatability with Microsoft LAN Manager as well.
-The response returned by the client actually contains an LM encrypted
-response as well as the NT-encrypted password. This implementation only
-uses the NT-encrypted response, which seems to work fine for Windows 98
-and Windows 2000. The RFC also has a number of other specs for allowing the
-user to change password and things like that. None of that has been
-implemented here.
-
-A useful extension of this would be in the local storage of passwords.
-Theoretically you should be able to store the MD4 hash rather than the
-plain text password. Then the algorithm could pick it up at the next
-step and still calculate the result. The trouble is that MD4 produces a
-binary hash. That is, any values from 0 to 255 is a valid byte, and I
-don't know how to store this in a users file. If it can be done, then
-we could add a check attribute called "MS-CHAP-Hash" instead of password
-and get both an encrypted protocol and encrypted password storage at the
-same time (CHAP requires plain text passwords, while Crypt-Pass requires
-an unencrypted protocol).
-
-If you find this useful, please send me a note just so I can feel good
-about myself.
-
-Jay Miller
-Columbia, MO, US
-jaymiller@socket.net
memcpy(authparams.password.response.challenge, challenge,
sizeof(authparams.password.response.challenge));
+ authparams.parameter_control |= WBC_MSV1_0_ALLOW_MSVCHAPV2 |
+ WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT |
+ WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
+
/*
* Send auth request across to winbind
#include <wbclient.h>
+/* Samba does not export this constant yet */
+#ifndef WBC_MSV1_0_ALLOW_MSVCHAPV2
+#define WBC_MSV1_0_ALLOW_MSVCHAPV2 0x00010000
+#endif
+
int do_auth_wbclient(rlm_mschap_t *inst, REQUEST *request,
uint8_t const *challenge, uint8_t const *response,
uint8_t nthashhash[NT_DIGEST_LENGTH]);
mod_ldflags="-framework DirectoryService"
fi
- smart_try_dir="$winbind_include_dir"
+ smart_try_dir="$winbind_include_dir /usr/include/samba-4.0"
ac_safe=`echo "wbclient.h" | sed 'y%./+-%__pm%'`
fi
- smart_try_dir="$winbind_lib_dir"
+
+ac_safe=`echo "core/ntstatus.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 core/ntstatus.h in $try" >&5
+$as_echo_n "checking for core/ntstatus.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdint.h>
+ #include <stdbool.h>
+ #include <core/ntstatus.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}/core/ntstatus.h" >&5
+$as_echo_n "checking for ${_prefix}/core/ntstatus.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdint.h>
+ #include <stdbool.h>
+ #include <core/ntstatus.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 core/ntstatus.h" >&5
+$as_echo_n "checking for core/ntstatus.h... " >&6; }
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdint.h>
+ #include <stdbool.h>
+ #include <core/ntstatus.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 prefix in $smart_prefix; do
+
+
+if test "x$LOCATE" != "x"; then
+ DIRS=
+ file="${_prefix}/${1}"
+
+ for x in `${LOCATE} $file 2>/dev/null`; do
+ base=`echo $x | sed "s%/${file}%%"`
+ if test "x$x" = "x$base"; then
+ continue;
+ fi
+
+ dir=`${DIRNAME} $x 2>/dev/null`
+ exclude=`echo ${dir} | ${GREP} /home`
+ if test "x$exclude" != "x"; then
+ continue
+ fi
+
+ already=`echo \$_smart_include_dir ${DIRS} | ${GREP} ${dir}`
+ if test "x$already" = "x"; then
+ DIRS="$DIRS $dir"
+ fi
+ done
+fi
+
+eval "_smart_include_dir=\"\$_smart_include_dir $DIRS\""
+
+ done
+
+
+if test "x$LOCATE" != "x"; then
+ DIRS=
+ file=core/ntstatus.h
+
+ for x in `${LOCATE} $file 2>/dev/null`; do
+ base=`echo $x | sed "s%/${file}%%"`
+ if test "x$x" = "x$base"; then
+ continue;
+ fi
+
+ dir=`${DIRNAME} $x 2>/dev/null`
+ exclude=`echo ${dir} | ${GREP} /home`
+ if test "x$exclude" != "x"; then
+ continue
+ fi
+
+ already=`echo \$_smart_include_dir ${DIRS} | ${GREP} ${dir}`
+ if test "x$already" = "x"; then
+ DIRS="$DIRS $dir"
+ fi
+ done
+fi
+
+eval "_smart_include_dir=\"\$_smart_include_dir $DIRS\""
+
+
+ for try in $_smart_include_dir; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for core/ntstatus.h in $try" >&5
+$as_echo_n "checking for core/ntstatus.h in $try... " >&6; }
+ CPPFLAGS="-isystem $try $old_CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdint.h>
+ #include <stdbool.h>
+ #include <core/ntstatus.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_core_ntstatus_h" != "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: core/ntstatus.h not found. Use --with-winbind-include-dir=<path>." >&5
+$as_echo "$as_me: WARNING: core/ntstatus.h not found. Use --with-winbind-include-dir=<path>." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: silently building without support for direct authentication via winbind. requires: libwbclient" >&5
+$as_echo "$as_me: WARNING: silently building without support for direct authentication via winbind. requires: libwbclient" >&2;}
+ fi
+
+
+ if test "x$ac_cv_header_wbclient_h" = "xyes" && \
+ test "x$ac_cv_header_core_ntstatus_h" = "xyes"; then
+
+ smart_try_dir="$winbind_lib_dir"
sm_lib_safe=`echo "wbclient" | sed 'y%./+-%__p_%'`
SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS"
fi
- if test "x$ac_cv_lib_wbclient_wbcCtxAuthenticateUserEx" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: winbind libraries not found. Use --with-winbind-lib-dir=<path>." >&5
+ if test "x$ac_cv_lib_wbclient_wbcCtxAuthenticateUserEx" != "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: winbind libraries not found. Use --with-winbind-lib-dir=<path>." >&5
$as_echo "$as_me: WARNING: winbind libraries not found. Use --with-winbind-lib-dir=<path>." >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Samba must be version 4.2.1 or higher to use this feature." >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Samba must be version 4.2.1 or higher to use this feature." >&5
$as_echo "$as_me: WARNING: Samba must be version 4.2.1 or higher to use this feature." >&2;}
- elif test "x$ac_cv_header_wbclient_h" = "xyes"; then
- mschap_sources="$mschap_sources auth_wbclient.c"
+ else
+ mschap_sources="$mschap_sources auth_wbclient.c"
$as_echo "#define WITH_AUTH_WINBIND 1" >>confdefs.h
+ fi
fi
targetname=rlm_mschap
mod_ldflags="-framework DirectoryService"
fi
- smart_try_dir="$winbind_include_dir"
+ smart_try_dir="$winbind_include_dir /usr/include/samba-4.0"
FR_SMART_CHECK_INCLUDE(wbclient.h, [#include <stdint.h>
#include <stdbool.h>])
if test "x$ac_cv_header_wbclient_h" != "xyes"; then
AC_MSG_WARN([silently building without support for direct authentication via winbind. requires: libwbclient])
fi
+ FR_SMART_CHECK_INCLUDE(core/ntstatus.h, [#include <stdint.h>
+ #include <stdbool.h>])
+ if test "x$ac_cv_header_core_ntstatus_h" != "xyes"; then
+ AC_MSG_WARN([core/ntstatus.h not found. Use --with-winbind-include-dir=<path>.])
+ AC_MSG_WARN([silently building without support for direct authentication via winbind. requires: libwbclient])
+ fi
+
dnl ############################################################
dnl # Check for libraries
dnl ############################################################
- smart_try_dir="$winbind_lib_dir"
- FR_SMART_CHECK_LIB(wbclient, wbcCtxAuthenticateUserEx)
- if test "x$ac_cv_lib_wbclient_wbcCtxAuthenticateUserEx" != "xyes"; then
- AC_MSG_WARN([winbind libraries not found. Use --with-winbind-lib-dir=<path>.])
- AC_MSG_WARN([Samba must be version 4.2.1 or higher to use this feature.])
- elif test "x$ac_cv_header_wbclient_h" = "xyes"; then
- mschap_sources="$mschap_sources auth_wbclient.c"
- AC_DEFINE([WITH_AUTH_WINBIND],[1],[Build with direct winbind auth support])
+ if test "x$ac_cv_header_wbclient_h" = "xyes" && \
+ test "x$ac_cv_header_core_ntstatus_h" = "xyes"; then
+
+ smart_try_dir="$winbind_lib_dir"
+ FR_SMART_CHECK_LIB(wbclient, wbcCtxAuthenticateUserEx)
+ if test "x$ac_cv_lib_wbclient_wbcCtxAuthenticateUserEx" != "xyes"; then
+ AC_MSG_WARN([winbind libraries not found. Use --with-winbind-lib-dir=<path>.])
+ AC_MSG_WARN([Samba must be version 4.2.1 or higher to use this feature.])
+ else
+ mschap_sources="$mschap_sources auth_wbclient.c"
+ AC_DEFINE([WITH_AUTH_WINBIND],[1],[Build with direct winbind auth support])
+ fi
fi
targetname=modname
return -648;
}
+ if (strcasestr(buffer, "Account locked out") ||
+ strcasestr(buffer, "0xC0000234")) {
+ REDEBUG2("%s", buffer);
+ return -647;
+ }
+
+ if (strcasestr(buffer, "Account disabled") ||
+ strcasestr(buffer, "0xC0000072")) {
+ REDEBUG2("%s", buffer);
+ return -691;
+ }
+
RDEBUG2("External script failed");
p = strchr(buffer, '\n');
if (p) *p = '\0';
char new_challenge[33], buffer[128];
char *p;
- if ((smb_ctrl && ((smb_ctrl->vp_integer & ACB_PW_EXPIRED) != 0)) || (mschap_result == -648)) {
+ if ((mschap_result == -648) ||
+ (smb_ctrl && ((smb_ctrl->vp_integer & ACB_PW_EXPIRED) != 0))) {
REDEBUG("Password has expired. User should retry authentication");
error = 648;
- retry = inst->allow_retry ? 1 : 0;
+
+ /*
+ * A password change is NOT a retry! We MUST have retry=0 here.
+ */
+ retry = 0;
message = "Password expired";
rcode = RLM_MODULE_REJECT;
- } else if (mschap_result < 0) {
- REDEBUG("MS-CHAP2-Response is incorrect");
- error = 691;
- retry = inst->allow_retry ? 1 : 0;
- message = "Authentication failed";
- rcode = RLM_MODULE_REJECT;
- /*
- * Account is disabled.
- *
- * They're found, but they don't exist, so we
- * return 'not found'.
- */
- } else if (smb_ctrl && (((smb_ctrl->vp_integer & ACB_DISABLED) != 0) ||
- ((smb_ctrl->vp_integer & (ACB_NORMAL|ACB_WSTRUST)) == 0))) {
- REDEBUG("SMB-Account-Ctrl says that the account is disabled, or is not a normal "
- "or workstation trust account");
+ /*
+ * Account is disabled.
+ *
+ * They're found, but they don't exist, so we
+ * return 'not found'.
+ */
+ } else if ((mschap_result == -691) ||
+ (smb_ctrl && (((smb_ctrl->vp_integer & ACB_DISABLED) != 0) ||
+ ((smb_ctrl->vp_integer & (ACB_NORMAL|ACB_WSTRUST)) == 0)))) {
+ REDEBUG("SMB-Account-Ctrl (or ntlm_auth) "
+ "says that the account is disabled, "
+ "or is not a normal or workstation trust account");
error = 691;
- retry = 1;
+ retry = 0;
message = "Account disabled";
rcode = RLM_MODULE_NOTFOUND;
- /*
- * User is locked out.
- */
- } else if (smb_ctrl && ((smb_ctrl->vp_integer & ACB_AUTOLOCK) != 0)) {
- REDEBUG("SMB-Account-Ctrl says that the account is locked out");
+
+ /*
+ * User is locked out.
+ */
+ } else if ((mschap_result == -647) ||
+ (smb_ctrl && ((smb_ctrl->vp_integer & ACB_AUTOLOCK) != 0))) {
+ REDEBUG("SMB-Account-Ctrl (or ntlm_auth) "
+ "says that the account is locked out");
error = 647;
retry = 0;
message = "Account locked out";
rcode = RLM_MODULE_USERLOCK;
+
+ } else if (mschap_result < 0) {
+ REDEBUG("MS-CHAP2-Response is incorrect");
+ error = 691;
+ retry = inst->allow_retry;
+ message = "Authentication failed";
+ rcode = RLM_MODULE_REJECT;
}
if (rcode == RLM_MODULE_OK) return RLM_MODULE_OK;
*/
uint8_t new_nt_encrypted[516], old_nt_encrypted[NT_DIGEST_LENGTH];
VALUE_PAIR *nt_enc=NULL;
- int seq, new_nt_enc_len=0;
+ int seq, new_nt_enc_len;
uint8_t *p;
RDEBUG("MS-CHAPv2 password change request received");
if (cpw->vp_length != 68) {
REDEBUG("MS-CHAP2-CPW has the wrong format: length %zu != 68", cpw->vp_length);
return RLM_MODULE_INVALID;
- } else if (cpw->vp_octets[0]!=7) {
+ }
+
+ if (cpw->vp_octets[0] != 7) {
REDEBUG("MS-CHAP2-CPW has the wrong format: code %d != 7", cpw->vp_octets[0]);
return RLM_MODULE_INVALID;
}
* 06:<mschapid>:00:02:<2nd chunk>
* 06:<mschapid>:00:03:<3rd chunk>
*/
+ new_nt_enc_len = 0;
for (seq = 1; seq < 4; seq++) {
vp_cursor_t cursor;
int found = 0;
if (nt_enc->da->attr != PW_MSCHAP_NT_ENC_PW)
continue;
+ if (nt_enc->vp_length < 4) {
+ REDEBUG("MS-CHAP-NT-Enc-PW with invalid format");
+ return RLM_MODULE_INVALID;
+ }
+
if (nt_enc->vp_octets[0] != 6) {
REDEBUG("MS-CHAP-NT-Enc-PW with invalid format");
return RLM_MODULE_INVALID;
}
- if (nt_enc->vp_octets[2]==0 && nt_enc->vp_octets[3]==seq) {
+
+ if ((nt_enc->vp_octets[2] == 0) && (nt_enc->vp_octets[3] == seq)) {
found = 1;
break;
}
return RLM_MODULE_INVALID;
}
- /*
- * copy the data into the buffer
- */
+ if ((new_nt_enc_len + nt_enc->vp_length - 4) > sizeof(new_nt_encrypted)) {
+ REDEBUG("Unpacked MS-CHAP-NT-Enc-PW length > 516");
+ return RLM_MODULE_INVALID;
+ }
+
memcpy(new_nt_encrypted + new_nt_enc_len, nt_enc->vp_octets + 4, nt_enc->vp_length - 4);
new_nt_enc_len += nt_enc->vp_length - 4;
}
+
if (new_nt_enc_len != 516) {
REDEBUG("Unpacked MS-CHAP-NT-Enc-PW length != 516");
return RLM_MODULE_INVALID;
RDEBUG2("Password change payload valid");
/* perform the actual password change */
- rad_assert(nt_password);
if (do_mschap_cpw(inst, request, nt_password, new_nt_encrypted, old_nt_encrypted, auth_method) < 0) {
char buffer[128];
old_value = vp_aprints_value(request, vp, '\'');
new_value = vp_aprints_value(request, new, '\'');
- RDEBUG3("Converted: %s = '%s' -> %s = '%s'", vp->da->name, old_value, new->da->name, new_value);
+ RDEBUG3("Converted: &control:%s = '%s' -> &control:%s = '%s'",
+ vp->da->name, old_value, new->da->name, new_value);
talloc_free(old_value);
talloc_free(new_value);
} else {
- RDEBUG2("Converted: %s -> %s", vp->da->name, new->da->name);
+ RDEBUG2("Converted: &control:%s -> &control:%s", vp->da->name, new->da->name);
}
return new;
(rad_digest_cmp(vp->vp_octets,
request->password->vp_octets,
vp->vp_length) != 0)) {
- REDEBUG("Cleartext password does not match \"known good\" password");
+ REDEBUG("Cleartext password \"%s\" does not match \"known good\" password",
+ request->password->vp_strvalue);
return RLM_MODULE_REJECT;
}
return RLM_MODULE_OK;
*/
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
+static int perl_sys_init3_called = 0;
+
#ifdef USE_ITHREADS
# define dl_librefs "DynaLoader::dl_librefs"
# define dl_modules "DynaLoader::dl_modules"
/*
* This is wrapper for radlog
* Now users can call radiusd::radlog(level,msg) wich is the same
- * calling radlog from C code.
+ * as calling radlog from C code.
*/
static XS(XS_radiusd_radlog)
{
* Create tweak the server's environment to support
* perl. Docs say only call this once... Oops.
*/
- PERL_SYS_INIT3(&argc, &embed, &envp);
+ if (!perl_sys_init3_called) {
+ PERL_SYS_INIT3(&argc, &embed, &envp);
+ perl_sys_init3_called = 1;
+ }
/*
* Allocate a new perl interpreter to do the parsing
* Value Pair Format
*
*/
-static int pairadd_sv(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, char *key, SV *sv, FR_TOKEN op,
+static void pairadd_sv(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, char *key, SV *sv, FR_TOKEN op,
const char *hash_name, const char *list_name)
{
- char *val;
+ char *val = NULL;
VALUE_PAIR *vp;
+ STRLEN len;
- if (SvOK(sv)) {
- STRLEN len;
- val = SvPV(sv, len);
- vp = fr_pair_make(ctx, vps, key, NULL, op);
- if (!vp) {
- fail:
- REDEBUG("Failed to create pair %s:%s %s %s", list_name, key,
- fr_int2str(fr_tokens, op, "<INVALID>"), val);
- return -1;
- }
+ VERIFY_LIST(*vps);
- switch (vp->da->type) {
- case PW_TYPE_STRING:
- fr_pair_value_bstrncpy(vp, val, len);
- break;
+ if (!SvOK(sv)) {
+ fail:
+ REDEBUG("Failed to create pair &%s:%s %s $%s{'%s'} -> '%s'", list_name, key,
+ fr_int2str(fr_tokens, op, "<INVALID>"), hash_name, key, (val ? val : "undef"));
+ return;
+ }
+ val = SvPV(sv, len);
+ vp = fr_pair_make(ctx, vps, key, NULL, op);
+ if (!vp) goto fail;
- default:
- if (fr_pair_value_from_str(vp, val, len) < 0) goto fail;
- }
+ switch (vp->da->type) {
+ case PW_TYPE_STRING:
+ fr_pair_value_bstrncpy(vp, val, len);
+ break;
- RDEBUG("&%s:%s %s $%s{'%s'} -> '%s'", list_name, key, fr_int2str(fr_tokens, op, "<INVALID>"),
- hash_name, key, val);
- return 0;
+ default:
+ VERIFY_VP(vp);
+
+ if (fr_pair_value_from_str(vp, val, len) < 0) goto fail;
}
- return -1;
+
+ RDEBUG("&%s:%s %s $%s{'%s'} -> '%s'", list_name, key, fr_int2str(fr_tokens, op, "<INVALID>"),
+ hash_name, key, val);
}
/*
* Gets the content from hashes
*/
-static int get_hv_content(TALLOC_CTX *ctx, REQUEST *request, HV *my_hv, VALUE_PAIR **vps,
+static void get_hv_content(TALLOC_CTX *ctx, REQUEST *request, HV *my_hv, VALUE_PAIR **vps,
const char *hash_name, const char *list_name)
{
SV *res_sv, **av_sv;
AV *av;
char *key;
I32 key_len, len, i, j;
- int ret = 0;
*vps = NULL;
for (i = hv_iterinit(my_hv); i > 0; i--) {
len = av_len(av);
for (j = 0; j <= len; j++) {
av_sv = av_fetch(av, j, 0);
- ret = pairadd_sv(ctx, request, vps, key, *av_sv, T_OP_ADD, hash_name, list_name) + ret;
+ pairadd_sv(ctx, request, vps, key, *av_sv, T_OP_ADD, hash_name, list_name);
}
- } else ret = pairadd_sv(ctx, request, vps, key, res_sv, T_OP_EQ, hash_name, list_name) + ret;
+ } else {
+ pairadd_sv(ctx, request, vps, key, res_sv, T_OP_EQ, hash_name, list_name);
+ }
}
-
- return ret;
}
/*
perl_store_vps(request->reply, request, &request->reply->vps, rad_reply_hv, "RAD_REPLY", "reply");
perl_store_vps(request, request, &request->config, rad_check_hv, "RAD_CHECK", "control");
perl_store_vps(request, request, &request->config, rad_config_hv, "RAD_CONFIG", "control");
- perl_store_vps(request, request, &request->state, rad_state_hv, "RAD_STATE", "session-state");
+ perl_store_vps(request->state_ctx, request, &request->state, rad_state_hv, "RAD_STATE", "session-state");
#ifdef WITH_PROXY
rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);
LEAVE;
vp = NULL;
- if ((get_hv_content(request->packet, request, rad_request_hv, &vp, "RAD_REQUEST", "request")) == 0) {
+ get_hv_content(request->packet, request, rad_request_hv, &vp, "RAD_REQUEST", "request");
+ if (vp) {
fr_pair_list_free(&request->packet->vps);
request->packet->vps = vp;
vp = NULL;
request->password = fr_pair_find_by_num(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY);
}
- if ((get_hv_content(request->reply, request, rad_reply_hv, &vp, "RAD_REPLY", "reply")) == 0) {
+ get_hv_content(request->reply, request, rad_reply_hv, &vp, "RAD_REPLY", "reply");
+ if (vp) {
fr_pair_list_free(&request->reply->vps);
request->reply->vps = vp;
vp = NULL;
}
- if ((get_hv_content(request, request, rad_check_hv, &vp, "RAD_CHECK", "control")) == 0) {
+ get_hv_content(request, request, rad_check_hv, &vp, "RAD_CHECK", "control");
+ if (vp) {
fr_pair_list_free(&request->config);
request->config = vp;
vp = NULL;
}
- if ((get_hv_content(request, request, rad_state_hv, &vp, "RAD_STATE", "session-state")) == 0) {
+ get_hv_content(request->state_ctx, request, rad_state_hv, &vp, "RAD_STATE", "session-state");
+ if (vp) {
fr_pair_list_free(&request->state);
request->state = vp;
vp = NULL;
}
#ifdef WITH_PROXY
- if (request->proxy &&
- (get_hv_content(request->proxy, request, rad_request_proxy_hv, &vp,
- "RAD_REQUEST_PROXY", "proxy-request") == 0)) {
- fr_pair_list_free(&request->proxy->vps);
- request->proxy->vps = vp;
- vp = NULL;
+ if (request->proxy) {
+ get_hv_content(request->proxy, request, rad_request_proxy_hv, &vp,
+ "RAD_REQUEST_PROXY", "proxy-request");
+ if (vp) {
+ fr_pair_list_free(&request->proxy->vps);
+ request->proxy->vps = vp;
+ vp = NULL;
+ }
}
- if (request->proxy_reply &&
- (get_hv_content(request->proxy_reply, request, rad_request_proxy_reply_hv, &vp,
- "RAD_REQUEST_PROXY_REPLY", "proxy-reply") == 0)) {
- fr_pair_list_free(&request->proxy_reply->vps);
- request->proxy_reply->vps = vp;
- vp = NULL;
+ if (request->proxy_reply) {
+ get_hv_content(request->proxy_reply, request, rad_request_proxy_reply_hv, &vp,
+ "RAD_REQUEST_PROXY_REPLY", "proxy-reply");
+ if (vp) {
+ fr_pair_list_free(&request->proxy_reply->vps);
+ request->proxy_reply->vps = vp;
+ vp = NULL;
+ }
}
#endif
rlm_perl_t *inst = (rlm_perl_t *) instance;
int exitstatus = 0, count = 0;
- if (inst->rad_perlconf_hv != NULL) hv_undef(inst->rad_perlconf_hv);
- if (inst->perl_parsed && inst->func_detach) {
+ if (inst->perl_parsed) {
dTHXa(inst->perl);
PERL_SET_CONTEXT(inst->perl);
- {
+ if (inst->rad_perlconf_hv != NULL) hv_undef(inst->rad_perlconf_hv);
+
+ if (inst->func_detach) {
dSP; ENTER; SAVETMPS;
PUSHMARK(SP);
perl_free(inst->perl);
#endif
- PERL_SYS_TERM();
+ /*
+ * Hope this is not really needed.
+ * Is only allowed to be called once just before exit().
+ *
+ PERL_SYS_TERM();
+ */
return exitstatus;
}
DIAG_ON(nested-externs)
targetname
mod_cflags
mod_ldflags
-PYTHONBIN
+PYTHON_BIN
CPP
OBJEXT
EXEEXT
ac_subst_files=''
ac_user_opts='
enable_option_checking
+with_rlm_python_bin
with_rlm_python_lib_dir
with_rlm_python_include_dir
'
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-rlm-python-bin=PATH Path to python binary
--with-rlm-python-lib-dir=DIR Directory for Python library files
--with-rlm-python-include-dir=DIR Directory for Python include files
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- for ac_prog in python2.7 python2.6 python2.5 python2.4 python
+ PYHTON_BIN=
+
+# Check whether --with-rlm-python-bin was given.
+if test "${with_rlm_python_bin+set}" = set; then :
+ withval=$with_rlm_python_bin; case "$withval" in
+ no)
+ as_fn_error $? "Need rlm-python-bin" "$LINENO" 5
+ ;;
+ yes)
+ ;;
+ *)
+ PYTHON_BIN="$withval"
+ ;;
+ esac
+
+fi
+
+
+ if test "x$PYTHON_BIN" = x; then
+ for ac_prog in python2.7 python2.6 python
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_PYTHONBIN+:} false; then :
+if ${ac_cv_prog_PYTHON_BIN+:} false; then :
$as_echo_n "(cached) " >&6
else
- if test -n "$PYTHONBIN"; then
- ac_cv_prog_PYTHONBIN="$PYTHONBIN" # Let the user override the test.
+ if test -n "$PYTHON_BIN"; then
+ ac_cv_prog_PYTHON_BIN="$PYTHON_BIN" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_dummy="${PATH}:/usr/bin:/usr/local/bin"
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_PYTHONBIN="$ac_prog"
+ ac_cv_prog_PYTHON_BIN="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
fi
fi
-PYTHONBIN=$ac_cv_prog_PYTHONBIN
-if test -n "$PYTHONBIN"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHONBIN" >&5
-$as_echo "$PYTHONBIN" >&6; }
+PYTHON_BIN=$ac_cv_prog_PYTHON_BIN
+if test -n "$PYTHON_BIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_BIN" >&5
+$as_echo "$PYTHON_BIN" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
- test -n "$PYTHONBIN" && break
+ test -n "$PYTHON_BIN" && break
done
-test -n "$PYTHONBIN" || PYTHONBIN="not-found"
+test -n "$PYTHON_BIN" || PYTHON_BIN="not-found"
+ fi
- if test x$PYTHONBIN = xnot-found; then
+ if test "x$PYTHON_BIN" = "xnot-found"; then
fail="python-binary"
fi
if test x$fail = x; then
+ PY_PREFIX=`${PYTHON_BIN} -c 'import sys ; print(sys.prefix)'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Python sys.prefix \"${PY_PREFIX}\"" >&5
+$as_echo "$as_me: Python sys.prefix \"${PY_PREFIX}\"" >&6;}
+
+ PY_EXEC_PREFIX=`${PYTHON_BIN} -c 'import sys ; print(sys.exec_prefix)'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Python sys.exec_prefix \"${PY_EXEC_PREFIX}\"" >&5
+$as_echo "$as_me: Python sys.exec_prefix \"${PY_EXEC_PREFIX}\"" >&6;}
+
+ PY_SYS_VERSION=`${PYTHON_BIN} -c 'import sys ; print(sys.version[0:3])'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Python sys.version \"${PY_SYS_VERSION}\"" >&5
+$as_echo "$as_me: Python sys.version \"${PY_SYS_VERSION}\"" >&6;}
+
+ PY_LIB_DIR="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config"
+ PY_LIB_LOC="-L$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config"
- PY_PREFIX=`${PYTHONBIN} -c 'import sys ; print(sys.prefix)'`
- PY_EXEC_PREFIX=`${PYTHONBIN} -c 'import sys ; print(sys.exec_prefix)'`
- PY_VERSION=`${PYTHONBIN} -c 'import sys ; print(sys.version[0:3])'`
- PY_LIBS="-lpython$PY_VERSION"
- PY_LIB_DIR="$PY_EXEC_PREFIX/lib/python$PY_VERSION/config"
- PY_LIB_LOC="-L$PY_EXEC_PREFIX/lib/python$PY_VERSION/config"
- PY_MAKEFILE="$PY_EXEC_PREFIX/lib/python$PY_VERSION/config/Makefile"
+ PY_MAKEFILE="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config/Makefile"
if test -f ${PY_MAKEFILE}; then
- PY_LOCALMODLIBS=`sed -n -e 's/^LOCALMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE`
- PY_BASEMODLIBS=`sed -n -e 's/^BASEMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE`
- PY_OTHER_LIBS=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $PY_MAKEFILE`
- PY_OTHER_LDFLAGS=`sed -n -e 's/^LINKFORSHARED=\(.*\)/\1/p' $PY_MAKEFILE`
+ PY_LOCAL_MOD_LIBS=`sed -n -e 's/^LOCALMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/^ *//;s/ *$//'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Python local_mod_libs \"${PY_LOCAL_MOD_LIBS}\"" >&5
+$as_echo "$as_me: Python local_mod_libs \"${PY_LOCAL_MOD_LIBS}\"" >&6;}
+
+ PY_BASE_MOD_LIBS=`sed -n -e 's/^BASEMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/^ *//;s/ *$//'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Python base_mod_libs \"${PY_BASE_MOD_LIBS}\"" >&5
+$as_echo "$as_me: Python base_mod_libs \"${PY_BASE_MOD_LIBS}\"" >&6;}
+
+ PY_OTHER_LIBS=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/ / /g;s/^ *//;s/ *$//'`
+ PY_OTHER_LDFLAGS=`sed -n -e 's/^LINKFORSHARED=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/ / /g;s/^ *//;s/ *$//'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Python other_libs \"${PY_OTHER_LDFLAGS} ${PY_OTHER_LIBS}\"" >&5
+$as_echo "$as_me: Python other_libs \"${PY_OTHER_LDFLAGS} ${PY_OTHER_LIBS}\"" >&6;}
fi
- PY_EXTRA_LIBS="$PY_LOCALMODLIBS $PY_BASEMODLIBS $PY_OTHER_LIBS"
+ PY_EXTRA_LIBS="$PY_LOCALMODLIBS $PY_BASE_MOD_LIBS $PY_OTHER_LIBS"
old_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $PY_CFLAGS"
- smart_try_dir="$PY_PREFIX/include/python$PY_VERSION"
+ smart_try_dir="$PY_PREFIX/include/python$PY_SYS_VERSION"
smart_try_dir=$PY_LIB_DIR
-sm_lib_safe=`echo "python${PY_VERSION}" | sed 'y%./+-%__p_%'`
+sm_lib_safe=`echo "python${PY_SYS_VERSION}" | sed 'y%./+-%__p_%'`
sm_func_safe=`echo "Py_Initialize" | sed 'y%./+-%__p_%'`
old_LIBS="$LIBS"
if test "x$smart_try_dir" != "x"; then
for try in $smart_try_dir; do
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_VERSION} in $try" >&5
-$as_echo_n "checking for Py_Initialize in -lpython${PY_VERSION} in $try... " >&6; }
- LIBS="-lpython${PY_VERSION} $old_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try" >&5
+$as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try... " >&6; }
+ LIBS="-lpython${PY_SYS_VERSION} $old_LIBS"
CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- smart_lib="-lpython${PY_VERSION}"
+ smart_lib="-lpython${PY_SYS_VERSION}"
smart_ldflags="-L$try -Wl,-rpath,$try"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
if test "x$smart_lib" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_VERSION}" >&5
-$as_echo_n "checking for Py_Initialize in -lpython${PY_VERSION}... " >&6; }
- LIBS="-lpython${PY_VERSION} $old_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}" >&5
+$as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}... " >&6; }
+ LIBS="-lpython${PY_SYS_VERSION} $old_LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
extern char Py_Initialize();
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- smart_lib="-lpython${PY_VERSION}"
+ smart_lib="-lpython${PY_SYS_VERSION}"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
if test "x$LOCATE" != "x"; then
DIRS=
- file=libpython${PY_VERSION}${libltdl_cv_shlibext}
+ file=libpython${PY_SYS_VERSION}${libltdl_cv_shlibext}
for x in `${LOCATE} $file 2>/dev/null`; do
base=`echo $x | sed "s%/${file}%%"`
if test "x$LOCATE" != "x"; then
DIRS=
- file=libpython${PY_VERSION}.a
+ file=libpython${PY_SYS_VERSION}.a
for x in `${LOCATE} $file 2>/dev/null`; do
base=`echo $x | sed "s%/${file}%%"`
for try in $smart_lib_dir /usr/local/lib /opt/lib; do
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_VERSION} in $try" >&5
-$as_echo_n "checking for Py_Initialize in -lpython${PY_VERSION} in $try... " >&6; }
- LIBS="-lpython${PY_VERSION} $old_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try" >&5
+$as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try... " >&6; }
+ LIBS="-lpython${PY_SYS_VERSION} $old_LIBS"
CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- smart_lib="-lpython${PY_VERSION}"
+ smart_lib="-lpython${PY_SYS_VERSION}"
smart_ldflags="-L$try -Wl,-rpath,$try"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
-sm_lib_safe=`echo "python${PY_VERSION}m" | sed 'y%./+-%__p_%'`
+sm_lib_safe=`echo "python${PY_SYS_VERSION}m" | sed 'y%./+-%__p_%'`
sm_func_safe=`echo "Py_Initialize" | sed 'y%./+-%__p_%'`
old_LIBS="$LIBS"
if test "x$smart_try_dir" != "x"; then
for try in $smart_try_dir; do
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_VERSION}m in $try" >&5
-$as_echo_n "checking for Py_Initialize in -lpython${PY_VERSION}m in $try... " >&6; }
- LIBS="-lpython${PY_VERSION}m $old_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try" >&5
+$as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try... " >&6; }
+ LIBS="-lpython${PY_SYS_VERSION}m $old_LIBS"
CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- smart_lib="-lpython${PY_VERSION}m"
+ smart_lib="-lpython${PY_SYS_VERSION}m"
smart_ldflags="-L$try -Wl,-rpath,$try"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
if test "x$smart_lib" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_VERSION}m" >&5
-$as_echo_n "checking for Py_Initialize in -lpython${PY_VERSION}m... " >&6; }
- LIBS="-lpython${PY_VERSION}m $old_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}m" >&5
+$as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}m... " >&6; }
+ LIBS="-lpython${PY_SYS_VERSION}m $old_LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
extern char Py_Initialize();
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- smart_lib="-lpython${PY_VERSION}m"
+ smart_lib="-lpython${PY_SYS_VERSION}m"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
if test "x$LOCATE" != "x"; then
DIRS=
- file=libpython${PY_VERSION}m${libltdl_cv_shlibext}
+ file=libpython${PY_SYS_VERSION}m${libltdl_cv_shlibext}
for x in `${LOCATE} $file 2>/dev/null`; do
base=`echo $x | sed "s%/${file}%%"`
if test "x$LOCATE" != "x"; then
DIRS=
- file=libpython${PY_VERSION}m.a
+ file=libpython${PY_SYS_VERSION}m.a
for x in `${LOCATE} $file 2>/dev/null`; do
base=`echo $x | sed "s%/${file}%%"`
for try in $smart_lib_dir /usr/local/lib /opt/lib; do
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_VERSION}m in $try" >&5
-$as_echo_n "checking for Py_Initialize in -lpython${PY_VERSION}m in $try... " >&6; }
- LIBS="-lpython${PY_VERSION}m $old_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try" >&5
+$as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try... " >&6; }
+ LIBS="-lpython${PY_SYS_VERSION}m $old_LIBS"
CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- smart_lib="-lpython${PY_VERSION}m"
+ smart_lib="-lpython${PY_SYS_VERSION}m"
smart_ldflags="-L$try -Wl,-rpath,$try"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
targetname=rlm_python
else
targetname=
- fail="$fail libpython$PY_VERSION"
+ fail="$fail libpython$PY_SYS_VERSION"
fi
fi
fi
AC_PROG_CC
AC_PROG_CPP
- AC_CHECK_PROGS(PYTHONBIN, [ python2.7 python2.6 python2.5 python2.4 python ], not-found, [${PATH}:/usr/bin:/usr/local/bin])
+ dnl extra argument: --with-rlm-python-bin
+ PYHTON_BIN=
+ AC_ARG_WITH(rlm-python-bin,
+ [ --with-rlm-python-bin=PATH Path to python binary []],
+ [ case "$withval" in
+ no)
+ AC_MSG_ERROR(Need rlm-python-bin)
+ ;;
+ yes)
+ ;;
+ *)
+ PYTHON_BIN="$withval"
+ ;;
+ esac ]
+ )
+
+ if test "x$PYTHON_BIN" = x; then
+ AC_CHECK_PROGS(PYTHON_BIN, [ python2.7 python2.6 python ], not-found, [${PATH}:/usr/bin:/usr/local/bin])
+ fi
- if test x$PYTHONBIN = xnot-found; then
+ if test "x$PYTHON_BIN" = "xnot-found"; then
fail="python-binary"
fi
)
if test x$fail = x; then
+ PY_PREFIX=`${PYTHON_BIN} -c 'import sys ; print(sys.prefix)'`
+ AC_MSG_NOTICE([Python sys.prefix \"${PY_PREFIX}\"])
+
+ PY_EXEC_PREFIX=`${PYTHON_BIN} -c 'import sys ; print(sys.exec_prefix)'`
+ AC_MSG_NOTICE([Python sys.exec_prefix \"${PY_EXEC_PREFIX}\"])
- PY_PREFIX=`${PYTHONBIN} -c 'import sys ; print(sys.prefix)'`
- PY_EXEC_PREFIX=`${PYTHONBIN} -c 'import sys ; print(sys.exec_prefix)'`
- changequote(<<, >>)dnl
- PY_VERSION=`${PYTHONBIN} -c 'import sys ; print(sys.version[0:3])'`
- changequote([, ])dnl
- PY_LIBS="-lpython$PY_VERSION"
- PY_LIB_DIR="$PY_EXEC_PREFIX/lib/python$PY_VERSION/config"
- PY_LIB_LOC="-L$PY_EXEC_PREFIX/lib/python$PY_VERSION/config"
- PY_MAKEFILE="$PY_EXEC_PREFIX/lib/python$PY_VERSION/config/Makefile"
+ PY_SYS_VERSION=`${PYTHON_BIN} -c 'import sys ; print(sys.version[[0:3]])'`
+ AC_MSG_NOTICE([Python sys.version \"${PY_SYS_VERSION}\"])
+
+ PY_LIB_DIR="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config"
+ PY_LIB_LOC="-L$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config"
+
+ PY_MAKEFILE="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config/Makefile"
if test -f ${PY_MAKEFILE}; then
- PY_LOCALMODLIBS=`sed -n -e 's/^LOCALMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE`
- PY_BASEMODLIBS=`sed -n -e 's/^BASEMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE`
- PY_OTHER_LIBS=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $PY_MAKEFILE`
- PY_OTHER_LDFLAGS=`sed -n -e 's/^LINKFORSHARED=\(.*\)/\1/p' $PY_MAKEFILE`
+ PY_LOCAL_MOD_LIBS=`sed -n -e 's/^LOCALMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/^ *//;s/ *$//'`
+ AC_MSG_NOTICE([Python local_mod_libs \"${PY_LOCAL_MOD_LIBS}\"])
+
+ PY_BASE_MOD_LIBS=`sed -n -e 's/^BASEMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/^ *//;s/ *$//'`
+ AC_MSG_NOTICE([Python base_mod_libs \"${PY_BASE_MOD_LIBS}\"])
+
+ PY_OTHER_LIBS=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/ / /g;s/^ *//;s/ *$//'`
+ PY_OTHER_LDFLAGS=`sed -n -e 's/^LINKFORSHARED=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/ / /g;s/^ *//;s/ *$//'`
+ AC_MSG_NOTICE([Python other_libs \"${PY_OTHER_LDFLAGS} ${PY_OTHER_LIBS}\"])
fi
- PY_EXTRA_LIBS="$PY_LOCALMODLIBS $PY_BASEMODLIBS $PY_OTHER_LIBS"
+ PY_EXTRA_LIBS="$PY_LOCALMODLIBS $PY_BASE_MOD_LIBS $PY_OTHER_LIBS"
old_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $PY_CFLAGS"
- smart_try_dir="$PY_PREFIX/include/python$PY_VERSION"
+ smart_try_dir="$PY_PREFIX/include/python$PY_SYS_VERSION"
FR_SMART_CHECK_INCLUDE(Python.h)
CFLAGS=$old_CFLAGS
old_LIBS=$LIBS
LIBS="$LIBS $PY_LIB_LOC $PY_EXTRA_LIBS -lm"
smart_try_dir=$PY_LIB_DIR
- FR_SMART_CHECK_LIB(python${PY_VERSION}, Py_Initialize)
+ FR_SMART_CHECK_LIB(python${PY_SYS_VERSION}, Py_Initialize)
LIBS=$old_LIBS
eval t=\${ac_cv_lib_${sm_lib_safe}_${sm_func_safe}}
mod_ldflags="$PY_LIB_LOC $PY_EXTRA_LIBS $SMART_LIBS -lm"
targetname=modname
else
- FR_SMART_CHECK_LIB(python${PY_VERSION}m, Py_Initialize)
+ FR_SMART_CHECK_LIB(python${PY_SYS_VERSION}m, Py_Initialize)
eval t=\${ac_cv_lib_${sm_lib_safe}_${sm_func_safe}}
if test "x$t" = "xyes"; then
mod_ldflags="$PY_LIB_LOC $PY_EXTRA_LIBS $SMART_LIBS -lm"
targetname=modname
else
targetname=
- fail="$fail libpython$PY_VERSION"
+ fail="$fail libpython$PY_SYS_VERSION"
fi
fi
fi
def instantiate(p):
print "*** instantiate ***"
print p
+ # return 0 for success or -1 for failure
def authorize(p):
print "*** authorize ***"
radiusd.radlog(radiusd.L_INFO, '*** radlog call in authorize ***')
print
print p
+ print
+ print radiusd.config
+ print
return radiusd.RLM_MODULE_OK
def preacct(p):
# If you want to use different operators
# you can do
# return (radiusd.RLM_MODULE_UPDATED,
- # radiusd.resolve(
- # 'Session-Timeout := %s' % str(sessionTimeout),
- # 'Some-other-option -= Value',
+ # (
+ # ('Session-Timeout', ':=', str(sessionTimeout)),
+ # ('Some-other-option', '-=', Value'),
+ # ),
+ # (
+ # ('Auth-Type', ':=', 'python'),
# ),
- # radiusd.resolve(
- # 'Auth-Type := python'
- # )
# )
- # Edit operators you need in OP_TRY in radiusd.py
def authenticate(p):
p = p
L_PROXY = 5
L_CONS = 128
-OP={ '{':2, '}':3, '(':4, ')':5, ',':6, ';':7, '+=':8, '-=':9, ':=':10,
- '=':11, '!=':12, '>=':13, '>':14, '<=':15, '<':16, '=~':17, '!~':18, '=*':19, '!*':20,
- '==':21 , '#':22 }
-
-OP_TRY = (':=', '+=', '-=', '=' )
-
-def resolve(*lines):
- tuples = []
- for line in lines:
- for op in OP_TRY:
- arr = line.rsplit(op)
- if len(arr)==2:
- tuples.append((str(arr[0].strip()),OP[op],str(arr[1].strip())))
- break
- return tuple(tuples)
-
# log function
def radlog(level, msg):
import sys
*
* @note Rewritten by Paul P. Komkoff Jr <i@stingr.net>.
*
- * @copyright 2000,2006 The FreeRADIUS server project
+ * @copyright 2000,2006,2015-2016 The FreeRADIUS server project
* @copyright 2002 Miguel A.L. Paraz <mparaz@mparaz.com>
* @copyright 2002 Imperium Technology, Inc.
*/
RCSID("$Id$")
+#define LOG_PREFIX "rlm_python - "
+
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
#include <Python.h>
#include <dlfcn.h>
-#ifdef HAVE_PTHREAD_H
-#define Pyx_BLOCK_THREADS {PyGILState_STATE __gstate = PyGILState_Ensure();
-#define Pyx_UNBLOCK_THREADS PyGILState_Release(__gstate);}
-#else
-#define Pyx_BLOCK_THREADS
-#define Pyx_UNBLOCK_THREADS
-#endif
+static uint32_t python_instances = 0;
+static void *python_dlhandle;
-/*
- * TODO: The only needed thing here is function. Anything else is
- * required for initialization only. I will remove it, putting a
- * symbolic constant here instead.
+static PyThreadState *main_interpreter; //!< Main interpreter (cext safe)
+static PyObject *main_module; //!< Pthon configuration dictionary.
+
+/** Specifies the module.function to load for processing a section
+ *
*/
-struct py_function_def {
- PyObject *module;
- PyObject *function;
+typedef struct python_func_def {
+ PyObject *module; //!< Python reference to module.
+ PyObject *function; //!< Python reference to function in module.
- char const *module_name;
- char const *function_name;
-};
+ char const *module_name; //!< String name of module.
+ char const *function_name; //!< String name of function in module.
+} python_func_def_t;
+/** An instance of the rlm_python module
+ *
+ */
typedef struct rlm_python_t {
- void *libpython;
- PyThreadState *main_thread_state;
- char const *python_path;
-
- struct py_function_def
+ char const *name; //!< Name of the module instance
+ PyThreadState *sub_interpreter; //!< The main interpreter/thread used for this instance.
+ char const *python_path; //!< Path to search for python files in.
+ PyObject *module; //!< Local, interpreter specific module, containing
+ //!< FreeRADIUS functions.
+ bool cext_compat; //!< Whether or not to create sub-interpreters per module
+ //!< instance.
+
+ python_func_def_t
instantiate,
authorize,
authenticate,
send_coa,
#endif
detach;
+
+ PyObject *pythonconf_dict; //!< Configuration parameters defined in the module
+ //!< made available to the python script.
} rlm_python_t;
+/** Tracks a python module inst/thread state pair
+ *
+ * Multiple instances of python create multiple interpreters and each
+ * thread must have a PyThreadState per interpreter, to track execution.
+ */
+typedef struct python_thread_state {
+ PyThreadState *state; //!< Module instance/thread specific state.
+ rlm_python_t *inst; //!< Module instance that created this thread state.
+} python_thread_state_t;
+
/*
* A mapping of configuration file names to internal variables.
*/
static CONF_PARSER module_config[] = {
-#define A(x) { "mod_" #x, FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, x.module_name), NULL }, \
+#define A(x) { "mod_" #x, FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, x.module_name), "${.module}" }, \
{ "func_" #x, FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, x.function_name), NULL },
A(instantiate)
#undef A
{ "python_path", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, python_path), NULL },
+ { "cext_compat", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_python_t, cext_compat), "yes" },
+
CONF_PARSER_TERMINATOR
};
#define A(x) { #x, x },
A(L_DBG)
+ A(L_WARN)
A(L_AUTH)
A(L_INFO)
A(L_ERR)
A(L_PROXY)
+ A(L_WARN)
+ A(L_ACCT)
+ A(L_DBG_WARN)
+ A(L_DBG_ERR)
+ A(L_DBG_WARN_REQ)
+ A(L_DBG_ERR_REQ)
A(RLM_MODULE_REJECT)
A(RLM_MODULE_FAIL)
A(RLM_MODULE_OK)
/*
* This allows us to initialise PyThreadState on a per thread basis
*/
-fr_thread_local_setup(PyThreadState *, local_thread_state) /* macro */
-
-
-/*
- * Let assume that radiusd module is only one since we have only
- * one intepreter
- */
-
-static PyObject *radiusd_module = NULL;
+fr_thread_local_setup(rbtree_t *, local_thread_state) /* macro */
/*
* radiusd Python functions
*/
-/* radlog wrapper */
+/** Allow radlog to be called from python
+ *
+ */
static PyObject *mod_radlog(UNUSED PyObject *module, PyObject *args)
{
int status;
return Py_None;
}
-static PyMethodDef radiusd_methods[] = {
+static PyMethodDef module_methods[] = {
{ "radlog", &mod_radlog, METH_VARARGS,
"radiusd.radlog(level, msg)\n\n" \
"Print a message using radiusd logging system. level should be one of the\n" \
{ NULL, NULL, 0, NULL },
};
-
-static void mod_error(void)
+/** Print out the current error
+ *
+ * Must be called with a valid thread state set
+ */
+static void python_error_log(void)
{
PyObject *pType = NULL, *pValue = NULL, *pTraceback = NULL, *pStr1 = NULL, *pStr2 = NULL;
- /* This will be called with the GIL lock held */
-
PyErr_Fetch(&pType, &pValue, &pTraceback);
if (!pType || !pValue)
goto failed;
((pStr2 = PyObject_Str(pValue)) == NULL))
goto failed;
- ERROR("rlm_python:EXCEPT:%s: %s", PyString_AsString(pStr1), PyString_AsString(pStr2));
+ ERROR("%s (%s)", PyString_AsString(pStr1), PyString_AsString(pStr2));
failed:
Py_XDECREF(pStr1);
Py_XDECREF(pTraceback);
}
-static int mod_init(rlm_python_t *inst)
-{
- int i;
- static char name[] = "radiusd";
-
- if (radiusd_module) return 0;
-
- /*
- * Explicitly load libpython, so symbols will be available to lib-dynload modules
- */
- inst->libpython = dlopen("libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) ".so",
- RTLD_NOW | RTLD_GLOBAL);
- if (!inst->libpython) {
- WARN("Failed loading libpython symbols into global symbol table: %s", dlerror());
- }
-
- Py_SetProgramName(name);
-#ifdef HAVE_PTHREAD_H
- Py_InitializeEx(0); /* Don't override signal handlers */
- PyEval_InitThreads(); /* This also grabs a lock */
- inst->main_thread_state = PyThreadState_Get(); /* We need this for setting up thread local stuff */
-#endif
- if (inst->python_path) {
- char *path;
-
- memcpy(&path, &inst->python_path, sizeof(path));
- PySys_SetPath(path);
- }
-
- if ((radiusd_module = Py_InitModule3("radiusd", radiusd_methods,
- "FreeRADIUS Module")) == NULL)
- goto failed;
-
- for (i = 0; radiusd_constants[i].name; i++) {
- if ((PyModule_AddIntConstant(radiusd_module, radiusd_constants[i].name,
- radiusd_constants[i].value)) < 0) {
- goto failed;
- }
- }
-
-#ifdef HAVE_PTHREAD_H
- PyThreadState_Swap(NULL); /* We have to swap out the current thread else we get deadlocks */
- PyEval_ReleaseLock(); /* Drop lock grabbed by InitThreads */
-#endif
- DEBUG("mod_init done");
- return 0;
-
-failed:
- Py_XDECREF(radiusd_module);
-
-#ifdef HAVE_PTHREAD_H
- PyEval_ReleaseLock();
-#endif
-
- Pyx_BLOCK_THREADS
- mod_error();
- Pyx_UNBLOCK_THREADS
-
- radiusd_module = NULL;
-
- Py_Finalize();
- return -1;
-}
-
-#if 0
-
-static int mod_destroy(void)
-{
- Pyx_BLOCK_THREADS
- Py_XDECREF(radiusd_module);
- Py_Finalize();
- Pyx_UNBLOCK_THREADS
-
- return 0;
-}
-
-/*
- * This will need reconsidering in a future. Maybe we'll need to
- * have our own reference counting for radiusd_module
- */
-#endif
-
-/* TODO: Convert this function to accept any iterable objects? */
-
-static void mod_vptuple(TALLOC_CTX *ctx, VALUE_PAIR **vps, PyObject *pValue,
- char const *funcname)
+static void mod_vptuple(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, PyObject *pValue,
+ char const *funcname, char const *list_name)
{
int i;
int tuplesize;
+ vp_tmpl_t dst;
VALUE_PAIR *vp;
+ REQUEST *current = request;
+
+ memset(&dst, 0, sizeof(dst));
/*
* If the Python function gave us None for the tuple,
* then just return.
*/
- if (pValue == Py_None)
- return;
+ if (pValue == Py_None) return;
if (!PyTuple_CheckExact(pValue)) {
- ERROR("rlm_python:%s: non-tuple passed", funcname);
+ ERROR("%s - non-tuple passed to %s", funcname, list_name);
return;
}
/* Get the tuple tuplesize. */
tuplesize = PyTuple_GET_SIZE(pValue);
for (i = 0; i < tuplesize; i++) {
- PyObject *pTupleElement = PyTuple_GET_ITEM(pValue, i);
- PyObject *pStr1;
- PyObject *pStr2;
- PyObject *pOp;
- int pairsize;
- char const *s1;
- char const *s2;
- long op;
+ PyObject *pTupleElement = PyTuple_GET_ITEM(pValue, i);
+ PyObject *pStr1;
+ PyObject *pStr2;
+ PyObject *pOp;
+ int pairsize;
+ char const *s1;
+ char const *s2;
+ FR_TOKEN op = T_OP_EQ;
if (!PyTuple_CheckExact(pTupleElement)) {
- ERROR("rlm_python:%s: tuple element %d is not a tuple", funcname, i);
+ ERROR("%s - Tuple element %d of %s is not a tuple", funcname, i, list_name);
continue;
}
/* Check if it's a pair */
pairsize = PyTuple_GET_SIZE(pTupleElement);
if ((pairsize < 2) || (pairsize > 3)) {
- ERROR("rlm_python:%s: tuple element %d is a tuple of size %d. Must be 2 or 3.", funcname, i, pairsize);
+ ERROR("%s - Tuple element %d of %s is a tuple of size %d. Must be 2 or 3",
+ funcname, i, list_name, pairsize);
continue;
}
- if (pairsize == 2) {
- pStr1 = PyTuple_GET_ITEM(pTupleElement, 0);
- pStr2 = PyTuple_GET_ITEM(pTupleElement, 1);
- op = T_OP_EQ;
- } else {
- pStr1 = PyTuple_GET_ITEM(pTupleElement, 0);
- pStr2 = PyTuple_GET_ITEM(pTupleElement, 2);
- pOp = PyTuple_GET_ITEM(pTupleElement, 1);
- op = PyInt_AsLong(pOp);
- }
+ pStr1 = PyTuple_GET_ITEM(pTupleElement, 0);
+ pStr2 = PyTuple_GET_ITEM(pTupleElement, pairsize-1);
if ((!PyString_CheckExact(pStr1)) || (!PyString_CheckExact(pStr2))) {
- ERROR("rlm_python:%s: tuple element %d must be as (str, str)", funcname, i);
+ ERROR("%s - Tuple element %d of %s must be as (str, str)",
+ funcname, i, list_name);
continue;
}
s1 = PyString_AsString(pStr1);
s2 = PyString_AsString(pStr2);
- vp = fr_pair_make(ctx, vps, s1, s2, op);
- if (vp != NULL) {
- DEBUG("rlm_python:%s: '%s' = '%s'", funcname, s1, s2);
+
+ if (pairsize == 3) {
+ pOp = PyTuple_GET_ITEM(pTupleElement, 1);
+ if (PyString_CheckExact(pOp)) {
+ if (!(op = fr_str2int(fr_tokens, PyString_AsString(pOp), 0))) {
+ ERROR("%s - Invalid operator %s:%s %s %s, falling back to '='",
+ funcname, list_name, s1, PyString_AsString(pOp), s2);
+ op = T_OP_EQ;
+ }
+ } else if (PyInt_Check(pOp)) {
+ op = PyInt_AsLong(pOp);
+ if (!fr_int2str(fr_tokens, op, NULL)) {
+ ERROR("%s - Invalid operator %s:%s %i %s, falling back to '='",
+ funcname, list_name, s1, op, s2);
+ op = T_OP_EQ;
+ }
+ } else {
+ ERROR("%s - Invalid operator type for %s:%s ? %s, using default '='",
+ funcname, list_name, s1, s2);
+ }
+ }
+
+ if (tmpl_from_attr_str(&dst, s1, REQUEST_CURRENT, PAIR_LIST_REPLY, false, false) <= 0) {
+ ERROR("%s - Failed to find attribute %s:%s", funcname, list_name, s1);
+ continue;
+ }
+
+ if (radius_request(¤t, dst.tmpl_request) < 0) {
+ ERROR("%s - Attribute name %s:%s refers to outer request but not in a tunnel, skipping...",
+ funcname, list_name, s1);
+ continue;
+ }
+
+ if (!(vp = fr_pair_afrom_da(ctx, dst.tmpl_da))) {
+ ERROR("%s - Failed to create attribute %s:%s", funcname, list_name, s1);
+ continue;
+ }
+
+ vp->op = op;
+ if (fr_pair_value_from_str(vp, s2, -1) < 0) {
+ DEBUG("%s - Failed: '%s:%s' %s '%s'", funcname, list_name, s1,
+ fr_int2str(fr_tokens, op, "="), s2);
} else {
- DEBUG("rlm_python:%s: Failed: '%s' = '%s'", funcname, s1, s2);
+ DEBUG("%s - '%s:%s' %s '%s'", funcname, list_name, s1,
+ fr_int2str(fr_tokens, op, "="), s2);
}
+
+ radius_pairmove(current, vps, vp, false);
}
}
PyObject *pStr = NULL;
char buf[1024];
- /* Look at the vp_print_name? */
+ /* Look at the fr_pair_fprint_name? */
- if (vp->da->flags.has_tag)
+ if (vp->da->flags.has_tag) {
pStr = PyString_FromFormat("%s:%d", vp->da->name, vp->tag);
- else
+ } else {
pStr = PyString_FromString(vp->da->name);
+ }
- if (!pStr)
- goto failed;
+ if (!pStr) return -1;
PyTuple_SET_ITEM(pPair, 0, pStr);
- vp_prints_value(buf, sizeof(buf), vp, '"');
+ vp_prints_value(buf, sizeof(buf), vp, '\0'); /* Python doesn't need any escaping */
+
+ pStr = PyString_FromString(buf);
+ if (pStr == NULL) return -1;
- if ((pStr = PyString_FromString(buf)) == NULL)
- goto failed;
PyTuple_SET_ITEM(pPair, 1, pStr);
return 0;
-
-failed:
- return -1;
}
-#ifdef HAVE_PTHREAD_H
-/** Cleanup any thread local storage on pthread_exit()
- */
-static void do_python_cleanup(void *arg)
-{
- PyThreadState *my_thread_state = arg;
-
- PyEval_AcquireLock();
- PyThreadState_Swap(NULL); /* Not entirely sure this is needed */
- PyThreadState_Clear(my_thread_state);
- PyThreadState_Delete(my_thread_state);
- PyEval_ReleaseLock();
-}
-#endif
-
-static rlm_rcode_t do_python(rlm_python_t *inst, REQUEST *request, PyObject *pFunc, char const *funcname, bool worker)
+static rlm_rcode_t do_python_single(REQUEST *request, PyObject *pFunc, char const *funcname)
{
vp_cursor_t cursor;
VALUE_PAIR *vp;
int tuplelen;
int ret;
- PyGILState_STATE gstate;
- PyThreadState *prev_thread_state = NULL; /* -Wuninitialized */
- memset(&gstate, 0, sizeof(gstate)); /* -Wuninitialized */
-
- /* Return with "OK, continue" if the function is not defined. */
- if (!pFunc)
- return RLM_MODULE_NOOP;
-
-#ifdef HAVE_PTHREAD_H
- gstate = PyGILState_Ensure();
- if (worker) {
- PyThreadState *my_thread_state;
- my_thread_state = fr_thread_local_init(local_thread_state, do_python_cleanup);
- if (!my_thread_state) {
- my_thread_state = PyThreadState_New(inst->main_thread_state->interp);
- RDEBUG3("Initialised new thread state %p", my_thread_state);
- if (!my_thread_state) {
- REDEBUG("Failed initialising local PyThreadState on first run");
- PyGILState_Release(gstate);
- return RLM_MODULE_FAIL;
- }
-
- ret = fr_thread_local_set(local_thread_state, my_thread_state);
- if (ret != 0) {
- REDEBUG("Failed storing PyThreadState in TLS: %s", fr_syserror(ret));
- PyThreadState_Clear(my_thread_state);
- PyThreadState_Delete(my_thread_state);
- PyGILState_Release(gstate);
- return RLM_MODULE_FAIL;
- }
- }
- RDEBUG3("Using thread state %p", my_thread_state);
- prev_thread_state = PyThreadState_Swap(my_thread_state); /* Swap in our local thread state */
- }
-#endif
-
/* Default return value is "OK, continue" */
ret = RLM_MODULE_OK;
if (request != NULL) {
for (vp = fr_cursor_init(&cursor, &request->packet->vps);
vp;
- vp = fr_cursor_next(&cursor)) {
- tuplelen++;
- }
+ vp = fr_cursor_next(&cursor)) tuplelen++;
}
if (tuplelen == 0) {
/* Call Python function. */
pRet = PyObject_CallFunctionObjArgs(pFunc, pArgs, NULL);
-
if (!pRet) {
ret = RLM_MODULE_FAIL;
goto finish;
}
- if (!request)
+ if (!request) {
+ // check return code at module instantiation time
+ if (PyInt_CheckExact(pRet)) ret = PyInt_AsLong(pRet);
goto finish;
+ }
/*
* The function returns either:
PyObject *pTupleInt;
if (PyTuple_GET_SIZE(pRet) != 3) {
- ERROR("rlm_python:%s: tuple must be (return, replyTuple, configTuple)", funcname);
+ ERROR("%s - Tuple must be (return, replyTuple, configTuple)", funcname);
ret = RLM_MODULE_FAIL;
goto finish;
}
pTupleInt = PyTuple_GET_ITEM(pRet, 0);
if (!PyInt_CheckExact(pTupleInt)) {
- ERROR("rlm_python:%s: first tuple element not an integer", funcname);
+ ERROR("%s - First tuple element not an integer", funcname);
ret = RLM_MODULE_FAIL;
goto finish;
}
/* Now have the return value */
ret = PyInt_AsLong(pTupleInt);
/* Reply item tuple */
- mod_vptuple(request->reply, &request->reply->vps,
- PyTuple_GET_ITEM(pRet, 1), funcname);
+ mod_vptuple(request->reply, request, &request->reply->vps,
+ PyTuple_GET_ITEM(pRet, 1), funcname, "reply");
/* Config item tuple */
- mod_vptuple(request, &request->config,
- PyTuple_GET_ITEM(pRet, 2), funcname);
+ mod_vptuple(request, request, &request->config,
+ PyTuple_GET_ITEM(pRet, 2), funcname, "config");
} else if (PyInt_CheckExact(pRet)) {
/* Just an integer */
ret = RLM_MODULE_OK;
} else {
/* Not tuple or None */
- ERROR("rlm_python:%s: function did not return a tuple or None", funcname);
+ ERROR("%s - Function did not return a tuple or None", funcname);
ret = RLM_MODULE_FAIL;
goto finish;
}
+
finish:
Py_XDECREF(pArgs);
Py_XDECREF(pRet);
-#ifdef HAVE_PTHREAD_H
- if (worker) {
- PyThreadState_Swap(prev_thread_state);
- }
- PyGILState_Release(gstate);
-#endif
-
return ret;
}
-/*
- * Import a user module and load a function from it
+static void python_interpreter_free(PyThreadState *interp)
+{
+ PyEval_AcquireLock();
+ PyThreadState_Swap(interp);
+ Py_EndInterpreter(interp);
+ PyEval_ReleaseLock();
+}
+
+/** Destroy a thread state
+ *
+ * @param thread to destroy.
+ * @return 0
*/
+static int _python_thread_free(python_thread_state_t *thread)
+{
+ PyEval_RestoreThread(thread->state); /* Swap in our local thread state */
+ PyThreadState_Clear(thread->state);
+ PyEval_SaveThread();
-static int mod_load_function(struct py_function_def *def)
+ PyThreadState_Delete(thread->state); /* Don't need to hold lock for this */
+
+ return 0;
+}
+
+/** Callback for rbtree delete walker
+ *
+ */
+static void _python_thread_entry_free(void *arg)
{
- char const *funcname = "mod_load_function";
- PyGILState_STATE gstate;
+ talloc_free(arg);
+}
+
+/** Cleanup any thread local storage on pthread_exit()
+ *
+ * @param arg The thread currently exiting.
+ */
+static void _python_thread_tree_free(void *arg)
+{
+ rad_assert(arg == local_thread_state);
+
+ rbtree_t *tree = talloc_get_type_abort(arg, rbtree_t);
+ rbtree_free(tree); /* Needs to be this not talloc_free to execute delete walker */
+
+ local_thread_state = NULL; /* Prevent double free in unittest env */
+}
- gstate = PyGILState_Ensure();
+/** Compare instance pointers
+ *
+ */
+static int _python_inst_cmp(const void *a, const void *b)
+{
+ python_thread_state_t const *a_p = a, *b_p = b;
- if (def->module_name != NULL && def->function_name != NULL) {
- if ((def->module = PyImport_ImportModule(def->module_name)) == NULL) {
- ERROR("rlm_python:%s: module '%s' is not found", funcname, def->module_name);
- goto failed;
+ if (a_p->inst < b_p->inst) return -1;
+ if (a_p->inst > b_p->inst) return +1;
+ return 0;
+}
+
+/** Thread safe call to a python function
+ *
+ * Will swap in thread state specific to module/thread.
+ */
+static rlm_rcode_t do_python(rlm_python_t *inst, REQUEST *request, PyObject *pFunc, char const *funcname)
+{
+ int ret;
+ rbtree_t *thread_tree;
+ python_thread_state_t *this_thread;
+ python_thread_state_t find;
+
+ /*
+ * It's a NOOP if the function wasn't defined
+ */
+ if (!pFunc) return RLM_MODULE_NOOP;
+
+ /*
+ * Check to see if we've got a thread state tree
+ * If not, create one.
+ */
+ thread_tree = fr_thread_local_init(local_thread_state, _python_thread_tree_free);
+ if (!thread_tree) {
+ thread_tree = rbtree_create(NULL, _python_inst_cmp, _python_thread_entry_free, 0);
+ if (!thread_tree) {
+ RERROR("Failed allocating thread state tree");
+ return RLM_MODULE_FAIL;
}
- if ((def->function = PyObject_GetAttrString(def->module, def->function_name)) == NULL) {
- ERROR("rlm_python:%s: function '%s.%s' is not found", funcname, def->module_name, def->function_name);
- goto failed;
+ ret = fr_thread_local_set(local_thread_state, thread_tree);
+ if (ret != 0) {
+ talloc_free(thread_tree);
+ return RLM_MODULE_FAIL;
}
+ }
+
+ find.inst = inst;
+ /*
+ * Find the thread state associated with this instance
+ * and this thread, or create a new thread state.
+ */
+ this_thread = rbtree_finddata(thread_tree, &find);
+ if (!this_thread) {
+ PyThreadState *state;
- if (!PyCallable_Check(def->function)) {
- ERROR("rlm_python:%s: function '%s.%s' is not callable", funcname, def->module_name, def->function_name);
- goto failed;
+ state = PyThreadState_New(inst->sub_interpreter->interp);
+
+ RDEBUG3("Initialised new thread state %p", state);
+ if (!state) {
+ REDEBUG("Failed initialising local PyThreadState on first run");
+ return RLM_MODULE_FAIL;
+ }
+
+ this_thread = talloc(NULL, python_thread_state_t);
+ this_thread->inst = inst;
+ this_thread->state = state;
+ talloc_set_destructor(this_thread, _python_thread_free);
+
+ if (!rbtree_insert(thread_tree, this_thread)) {
+ RERROR("Failed inserting thread state into TLS tree");
+ talloc_free(this_thread);
+
+ return RLM_MODULE_FAIL;
}
}
- PyGILState_Release(gstate);
- return 0;
+ RDEBUG3("Using thread state %p", this_thread->state);
-failed:
- mod_error();
- ERROR("rlm_python:%s: failed to import python function '%s.%s'", funcname, def->module_name, def->function_name);
- Py_XDECREF(def->function);
- def->function = NULL;
- Py_XDECREF(def->module);
- def->module = NULL;
- PyGILState_Release(gstate);
- return -1;
+ PyEval_RestoreThread(this_thread->state); /* Swap in our local thread state */
+ ret = do_python_single(request, pFunc, funcname);
+ PyEval_SaveThread();
+
+ return ret;
}
+#define MOD_FUNC(x) \
+static rlm_rcode_t CC_HINT(nonnull) mod_##x(void *instance, REQUEST *request) { \
+ return do_python((rlm_python_t *) instance, request, ((rlm_python_t *)instance)->x.function, #x);\
+}
-static void mod_objclear(PyObject **ob)
+MOD_FUNC(authenticate)
+MOD_FUNC(authorize)
+MOD_FUNC(preacct)
+MOD_FUNC(accounting)
+MOD_FUNC(checksimul)
+MOD_FUNC(pre_proxy)
+MOD_FUNC(post_proxy)
+MOD_FUNC(post_auth)
+#ifdef WITH_COA
+MOD_FUNC(recv_coa)
+MOD_FUNC(send_coa)
+#endif
+static void python_obj_destroy(PyObject **ob)
{
if (*ob != NULL) {
- Pyx_BLOCK_THREADS
Py_DECREF(*ob);
- Pyx_UNBLOCK_THREADS
*ob = NULL;
}
}
-static void mod_funcdef_clear(struct py_function_def *def)
+static void python_function_destroy(python_func_def_t *def)
{
- mod_objclear(&def->function);
- mod_objclear(&def->module);
+ python_obj_destroy(&def->function);
+ python_obj_destroy(&def->module);
}
-static void mod_instance_clear(rlm_python_t *inst)
+/** Import a user module and load a function from it
+ *
+ */
+static int python_function_load(python_func_def_t *def)
{
-#define A(x) mod_funcdef_clear(&inst->x)
+ char const *funcname = "python_function_load";
- A(instantiate);
- A(authorize);
- A(authenticate);
- A(preacct);
- A(accounting);
- A(checksimul);
- A(detach);
+ if (def->module_name == NULL || def->function_name == NULL) return 0;
-#undef A
+ def->module = PyImport_ImportModule(def->module_name);
+ if (!def->module) {
+ ERROR("%s - Module '%s' not found", funcname, def->module_name);
+
+ error:
+ python_error_log();
+ ERROR("%s - Failed to import python function '%s.%s'",
+ funcname, def->module_name, def->function_name);
+ Py_XDECREF(def->function);
+ def->function = NULL;
+ Py_XDECREF(def->module);
+ def->module = NULL;
+
+ return -1;
+ }
+
+ def->function = PyObject_GetAttrString(def->module, def->function_name);
+ if (!def->function) {
+ ERROR("%s - Function '%s.%s' is not found", funcname, def->module_name, def->function_name);
+ goto error;
+ }
+
+ if (!PyCallable_Check(def->function)) {
+ ERROR("%s - Function '%s.%s' is not callable", funcname, def->module_name, def->function_name);
+ goto error;
+ }
+
+ return 0;
+}
+
+/*
+ * Parse a configuration section, and populate a dict.
+ * This function is recursively called (allows to have nested dicts.)
+ */
+static void python_parse_config(CONF_SECTION *cs, int lvl, PyObject *dict)
+{
+ int indent_section = (lvl + 1) * 4;
+ int indent_item = (lvl + 2) * 4;
+ CONF_ITEM *ci = NULL;
+
+ if (!cs || !dict) return;
+
+ DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs));
+
+ while ((ci = cf_item_find_next(cs, ci))) {
+ /*
+ * This is a section.
+ * Create a new dict, store it in current dict,
+ * Then recursively call python_parse_config with this section and the new dict.
+ */
+ if (cf_item_is_section(ci)) {
+ CONF_SECTION *sub_cs = cf_item_to_section(ci);
+ char const *key = cf_section_name1(sub_cs); /* dict key */
+ PyObject *sub_dict, *pKey;
+
+ if (!key) continue;
+
+ pKey = PyString_FromString(key);
+ if (!pKey) continue;
+
+ if (PyDict_Contains(dict, pKey)) {
+ WARN("rlm_python: Ignoring duplicate config section '%s'", key);
+ continue;
+ }
+
+ if (!(sub_dict = PyDict_New())) {
+ WARN("rlm_python: Unable to create subdict for config section '%s'", key);
+ }
+
+ (void)PyDict_SetItem(dict, pKey, sub_dict);
+
+ python_parse_config(sub_cs, lvl + 1, sub_dict);
+ } else if (cf_item_is_pair(ci)) {
+ CONF_PAIR *cp = cf_item_to_pair(ci);
+ char const *key = cf_pair_attr(cp); /* dict key */
+ char const *value = cf_pair_value(cp); /* dict value */
+ PyObject *pKey, *pValue;
+
+ if (!key || !value) continue;
+
+ pKey = PyString_FromString(key);
+ pValue = PyString_FromString(value);
+ if (!pKey || !pValue) continue;
+
+ /*
+ * This is an item.
+ * Store item attr / value in current dict.
+ */
+ if (PyDict_Contains(dict, pKey)) {
+ WARN("rlm_python: Ignoring duplicate config item '%s'", key);
+ continue;
+ }
+
+ (void)PyDict_SetItem(dict, pKey, pValue);
+
+ DEBUG("%*s%s = %s", indent_item, " ", key, value);
+ }
+ }
+
+ DEBUG("%*s}", indent_section, " ");
+}
+
+/** Initialises a separate python interpreter for this module instance
+ *
+ */
+static int python_interpreter_init(rlm_python_t *inst, CONF_SECTION *conf)
+{
+ int i;
+
+ /*
+ * Explicitly load libpython, so symbols will be available to lib-dynload modules
+ */
+ if (python_instances == 0) {
+ INFO("Python version: %s", Py_GetVersion());
+
+ python_dlhandle = dlopen("libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) ".so",
+ RTLD_NOW | RTLD_GLOBAL);
+ if (!python_dlhandle) WARN("Failed loading libpython symbols into global symbol table: %s", dlerror());
+
+#if PY_VERSION_HEX > 0x03050000
+ {
+ wchar_t *name;
+
+ wide_name = Py_DecodeLocale(main_config.name, strlen(main_config.name));
+ Py_SetProgramName(name); /* The value of argv[0] as a wide char string */
+ PyMem_RawFree(name);
+ }
+#else
+ {
+ char *name;
+
+ name = talloc_strdup(NULL, main_config.name);
+ Py_SetProgramName(name); /* The value of argv[0] as a wide char string */
+ talloc_free(name);
+ }
+#endif
+
+ Py_InitializeEx(0); /* Don't override signal handlers - noop on subs calls */
+ PyEval_InitThreads(); /* This also grabs a lock (which we then need to release) */
+ main_interpreter = PyThreadState_Get(); /* Store reference to the main interpreter */
+ }
+ rad_assert(PyEval_ThreadsInitialized());
+
+ /*
+ * Increment the reference counter
+ */
+ python_instances++;
+
+ /*
+ * This sets up a separate environment for each python module instance
+ * These will be destroyed on Py_Finalize().
+ */
+ if (!inst->cext_compat) {
+ inst->sub_interpreter = Py_NewInterpreter();
+ } else {
+ inst->sub_interpreter = main_interpreter;
+ }
+
+ PyThreadState_Swap(inst->sub_interpreter);
+
+ /*
+ * Due to limitations in Python, sub-interpreters don't work well
+ * with Python C extensions if they use GIL lock functions.
+ */
+ if (!inst->cext_compat || !main_module) {
+ CONF_SECTION *cs;
+
+ /*
+ * Set the python search path
+ */
+ if (inst->python_path) {
+#if PY_VERSION_HEX > 0x03050000
+ {
+ wchar_t *name;
+
+ path = Py_DecodeLocale(inst->python_path, strlen(inst->python_path));
+ PySys_SetPath(path);
+ PyMem_RawFree(path);
+ }
+#else
+ {
+ char *path;
+
+ path = talloc_strdup(NULL, inst->python_path);
+ PySys_SetPath(path);
+ talloc_free(path);
+ }
+#endif
+ }
+
+ /*
+ * Initialise a new module, with our default methods
+ */
+ inst->module = Py_InitModule3("radiusd", module_methods, "FreeRADIUS python module");
+ if (!inst->module) {
+ error:
+ python_error_log();
+ PyEval_SaveThread();
+ return -1;
+ }
+
+ /*
+ * Py_InitModule3 returns a borrowed ref, the actual
+ * module is owned by sys.modules, so we also need
+ * to own the module to prevent it being freed early.
+ */
+ Py_IncRef(inst->module);
+
+ if (inst->cext_compat) main_module = inst->module;
+
+ for (i = 0; radiusd_constants[i].name; i++) {
+ if ((PyModule_AddIntConstant(inst->module, radiusd_constants[i].name,
+ radiusd_constants[i].value)) < 0)
+ goto error;
+ }
+
+ /*
+ * Convert a FreeRADIUS config structure into a python
+ * dictionary.
+ */
+ inst->pythonconf_dict = PyDict_New();
+ if (!inst->pythonconf_dict) {
+ ERROR("Unable to create python dict for config");
+ python_error_log();
+ return -1;
+ }
+
+ /*
+ * Add module configuration as a dict
+ */
+ if (PyModule_AddObject(inst->module, "config", inst->pythonconf_dict) < 0) goto error;
+
+ cs = cf_section_sub_find(conf, "config");
+ if (cs) python_parse_config(cs, 0, inst->pythonconf_dict);
+ } else {
+ inst->module = main_module;
+ Py_IncRef(inst->module);
+ inst->pythonconf_dict = PyObject_GetAttrString(inst->module, "config");
+ Py_IncRef(inst->pythonconf_dict);
+ }
+
+ PyEval_SaveThread();
+
+ return 0;
}
/*
* in *instance otherwise put a null pointer there.
*
*/
-static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance)
+static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
- rlm_python_t *inst = instance;
+ rlm_python_t *inst = instance;
+ int code = 0;
- if (mod_init(inst) != 0) {
- return -1;
- }
+ inst->name = cf_section_name2(conf);
+ if (!inst->name) inst->name = cf_section_name1(conf);
+
+ /*
+ * Load the python code required for this module instance
+ */
+ if (python_interpreter_init(inst, conf) < 0) return -1;
+
+ /*
+ * Switch to our module specific main thread
+ */
+ PyEval_RestoreThread(inst->sub_interpreter);
-#define A(x) if (mod_load_function(&inst->x) < 0) goto failed
-
- A(instantiate);
- A(authenticate);
- A(authorize);
- A(preacct);
- A(accounting);
- A(checksimul);
- A(pre_proxy);
- A(post_proxy);
- A(post_auth);
+ /*
+ * Process the various sections
+ */
+#define PYTHON_FUNC_LOAD(_x) if (python_function_load(&inst->_x) < 0) goto error
+ PYTHON_FUNC_LOAD(instantiate);
+ PYTHON_FUNC_LOAD(authenticate);
+ PYTHON_FUNC_LOAD(authorize);
+ PYTHON_FUNC_LOAD(preacct);
+ PYTHON_FUNC_LOAD(accounting);
+ PYTHON_FUNC_LOAD(checksimul);
+ PYTHON_FUNC_LOAD(pre_proxy);
+ PYTHON_FUNC_LOAD(post_proxy);
+ PYTHON_FUNC_LOAD(post_auth);
#ifdef WITH_COA
- A(recv_coa);
- A(send_coa);
+ PYTHON_FUNC_LOAD(recv_coa);
+ PYTHON_FUNC_LOAD(send_coa);
#endif
- A(detach);
-
-#undef A
+ PYTHON_FUNC_LOAD(detach);
/*
- * Call the instantiate function. No request. Use the
- * return value.
+ * Call the instantiate function.
*/
- return do_python(inst, NULL, inst->instantiate.function, "instantiate", false);
-failed:
- Pyx_BLOCK_THREADS
- mod_error();
- Pyx_UNBLOCK_THREADS
- mod_instance_clear(inst);
- return -1;
+ code = do_python_single(NULL, inst->instantiate.function, "instantiate");
+ if (code < 0) {
+ error:
+ python_error_log(); /* Needs valid thread with GIL */
+ PyEval_SaveThread();
+ return -1;
+ }
+ PyEval_SaveThread();
+
+ return 0;
}
static int mod_detach(void *instance)
int ret;
/*
- * Master should still have no thread state
+ * Call module destructor
*/
- ret = do_python(inst, NULL, inst->detach.function, "detach", false);
+ PyEval_RestoreThread(inst->sub_interpreter);
- mod_instance_clear(inst);
- dlclose(inst->libpython);
+ ret = do_python_single(NULL, inst->detach.function, "detach");
- return ret;
-}
+#define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x)
+ PYTHON_FUNC_DESTROY(instantiate);
+ PYTHON_FUNC_DESTROY(authorize);
+ PYTHON_FUNC_DESTROY(authenticate);
+ PYTHON_FUNC_DESTROY(preacct);
+ PYTHON_FUNC_DESTROY(accounting);
+ PYTHON_FUNC_DESTROY(checksimul);
+ PYTHON_FUNC_DESTROY(detach);
-#define A(x) static rlm_rcode_t CC_HINT(nonnull) mod_##x(void *instance, REQUEST *request) { \
- return do_python((rlm_python_t *) instance, request, ((rlm_python_t *)instance)->x.function, #x, true);\
- }
+ Py_DecRef(inst->pythonconf_dict);
+ Py_DecRef(inst->module);
-A(authenticate)
-A(authorize)
-A(preacct)
-A(accounting)
-A(checksimul)
-A(pre_proxy)
-A(post_proxy)
-A(post_auth)
-#ifdef WITH_COA
-A(recv_coa)
-A(send_coa)
-#endif
+ PyEval_SaveThread();
-#undef A
+ /*
+ * Force cleaning up of threads if this is *NOT* a worker
+ * thread, which happens if this is being called from
+ * unittest framework, and probably with the server running
+ * in debug mode.
+ */
+ rbtree_free(local_thread_state);
+ local_thread_state = NULL;
+
+ /*
+ * Only destroy if it's a subinterpreter
+ */
+ if (!inst->cext_compat) python_interpreter_free(inst->sub_interpreter);
+
+ if ((--python_instances) == 0) {
+ PyThreadState_Swap(main_interpreter); /* Swap to the main thread */
+ Py_Finalize();
+ dlclose(python_dlhandle);
+ }
+
+ return ret;
+}
/*
* The module name should be the only globally exported symbol.
/*
* Try querying for the dynamic realm.
*/
- if (!realm && inst->trust_router)
+ if (!realm && inst->trust_router) {
realm = tr_query_realm(request, realmname, inst->default_community, inst->rp_realm, inst->trust_router, inst->tr_port);
+ } else {
+ RDEBUG2("No trust router configured, skipping dynamic realm lookup");
+ }
#endif
if (!realm) {
* entered.
*/
if (realm->name[0] != '~') realmname = realm->name;
- pair_make_request("Realm", realmname, T_OP_EQ);
- RDEBUG2("Adding Realm = \"%s\"", realmname);
+
+ /*
+ * A NULL realmname is allowed.
+ */
+ if (realmname) {
+ pair_make_request("Realm", realmname, T_OP_EQ);
+ RDEBUG2("Adding Realm = \"%s\"", realmname);
+ }
talloc_free(namebuf);
username = NULL;
* send it there again.
*/
for (i = 0; i < realm->acct_pool->num_home_servers; i++) {
+ if (realm->acct_pool->servers[i]->ipaddr.af == AF_UNSPEC) continue;
+
if (fr_ipaddr_cmp(&realm->acct_pool->servers[i]->ipaddr, &my_ipaddr) == 0) {
RDEBUG2("Suppressing proxy due to FreeRADIUS-Proxied-To");
return RLM_MODULE_OK;
* send it there again.
*/
for (i = 0; i < realm->acct_pool->num_home_servers; i++) {
+ if (realm->acct_pool->servers[i]->ipaddr.af == AF_UNSPEC) continue;
+
if ((fr_ipaddr_cmp(&realm->acct_pool->servers[i]->ipaddr,
&request->packet->src_ipaddr) == 0) &&
(realm->acct_pool->servers[i]->port == request->packet->src_port)) {
if (!tr_init()) return -1;
} else {
rad_const_free(inst->trust_router);
+ inst->trust_router = NULL;
}
#endif
break;
case HTTP_METHOD_PUT:
- SET_OPTION(CURLOPT_PUT, 1L);
+ /*
+ * Do not set CURLOPT_PUT, this will cause libcurl
+ * to ignore CURLOPT_POSTFIELDs and attempt to read
+ * whatever was set with CURLOPT_READDATA, which by
+ * default is stdin.
+ *
+ * This is many cases will cause the server to block,
+ * indefinitely.
+ */
+ SET_OPTION(CURLOPT_CUSTOMREQUEST, "PUT");
break;
case HTTP_METHOD_PATCH:
ret = rest_request_config(instance, §ion, request, handle, section.method, section.body,
uri, NULL, NULL);
talloc_free(uri);
- if (ret < 0) return -1;
+ if (ret < 0) {
+ outlen = -1;
+ goto finish;
+ }
/*
* Send the CURL request, pre-parse headers, aggregate incoming
* HTTP body data into a single contiguous buffer.
*/
ret = rest_request_perform(instance, §ion, request, handle);
- if (ret < 0) return -1;
+ if (ret < 0) {
+ outlen = -1;
+ goto finish;
+ }
hcode = rest_get_handle_code(handle);
switch (hcode) {
*/
#undef HAVE_CRYPT
+#ifdef __clang__
DIAG_OFF(disabled-macro-expansion)
+#endif
#include <ruby.h>
/*
+++ /dev/null
-FreeRADIUS SQL Module
-
-The core rlm_sql code handles database indepenent stuff and links the specific database drivers depending on your config. Sample sql configurations can be found in the raddb/sql.conf file.
-
-
-Mike Machado
-mike@innercite.com
-InnerCite Inc.
-Engineering Director / CTO
-
-Returning 'SQL_DOWN' allows sql.c to reconnect and try again, in most cases
-
-sql_select_query: returns -1 on failure, SQL_DOWN on 'socket not connected'
-sql_query: returns -1 on failure, SQL_DOWN on 'socket not connected'
-sql_store_result: returns -1 on failure, SQL_DOWN on 'socket not connected'
-sql_num_fields: cannot return an error, complains if zero fields
-sql_finish_select_query: returns 0 always
-sql_finish_query: does nothing, returns 0
-sql_free_result: returns 0 always, mysql_free_result has no return value
-sql_release_socket: returns 1 always
-sql_fetch_row: returns 0 if ok, SQL_DOWN on 'socket not connected', row is
- in sqlsocket->row now
-
-TODO:
-
-db2/iodbc/unixodbc:
- for the above functions, where it can return SQL_DOWN, determine if an
- error with the database exists, if it is down, and return SQL_DOWN
-
rlm_sql_mysql_conn_t *conn = handle->conn;
#if MYSQL_VERSION_ID >= 32224
+ /*
+ * Count takes a connection handle
+ */
if (!(num = mysql_field_count(conn->sock))) {
#else
- if (!(num = mysql_num_fields(conn->sock))) {
+ /*
+ * Fields takes a result struct
+ */
+ if (!(num = mysql_num_fields(conn->result))) {
#endif
return -1;
}
*/
if (OCIHandleAlloc((dvoid *)conn->env, (dvoid **)&conn->query, OCI_HTYPE_STMT, 0, NULL)) {
ERROR("rlm_sql_oracle: Couldn't init Oracle query handles: %s",
- sql_prints_error(errbuff, sizeof(errbuff), handle, config) ? errbuff : "unknown");
+ (sql_prints_error(errbuff, sizeof(errbuff), handle, config) == 0) ? errbuff : "unknown");
return RLM_SQL_ERROR;
}
(OraText const *)config->sql_password, strlen(config->sql_password),
(OraText const *)config->sql_db, strlen(config->sql_db))) {
ERROR("rlm_sql_oracle: Oracle logon failed: '%s'",
- sql_prints_error(errbuff, sizeof(errbuff), handle, config) ? errbuff : "unknown");
+ (sql_prints_error(errbuff, sizeof(errbuff), handle, config) == 0) ? errbuff : "unknown");
return RLM_SQL_ERROR;
}
return RLM_SQL_OK;
}
+ if (status == OCI_NO_DATA) {
+ handle->row = 0;
+
+ return RLM_SQL_OK;
+ }
+
if (status == OCI_ERROR) {
ERROR("rlm_sql_oracle: fetch failed in sql_fetch_row");
return sql_check_error(handle, config);
if (!name) name = cf_section_name1(cs);
snprintf(application_name, sizeof(application_name),
- "FreeRADIUS " RADIUSD_VERSION_STRING " - %s (%s)", progname, name);
+ "FreeRADIUS " RADIUSD_VERSION_STRING " - %s (%s)", main_config.name, name);
}
/*
#endif
#ifndef HAVE_SQLITE3_INT64
-typedef sqlite3_int64 sqlite_int64
+typedef sqlite_int64 sqlite3_int64;
#endif
typedef struct rlm_sql_sqlite_conn {
char **row;
+ TALLOC_FREE(handle->row);
+
/*
* Executes the SQLite query and interates over the results
*/
if (conn->col_count == 0) return RLM_SQL_ERROR;
}
- /*
- * Free the previous result (also gets called on finish_query)
- */
- talloc_free(handle->row);
-
MEM(row = handle->row = talloc_zero_array(handle->conn, char *, conn->col_count + 1));
for (i = 0; i < conn->col_count; i++) {
if (rcode != RLM_SQL_OK) goto query_error;
rcode = rlm_sql_fetch_row(inst, request, &handle);
- if (rcode) {
- (inst->module->sql_finish_select_query)(handle, inst->config);
- goto query_error;
- }
+ if (rcode) goto query_error;
row = handle->row;
if (!row) {
fr_pair_value_strsteal(vp, expanded);
RDEBUG2("SQL-User-Name set to '%s'", vp->vp_strvalue);
- vp->op = T_OP_SET;
- radius_pairmove(request, &request->packet->vps, vp, false); /* needs to be pair move else op is not respected */
+ vp->op = T_OP_SET;
+
+ /*
+ * Delete any existing SQL-User-Name, and replace it with ours.
+ */
+ fr_pair_delete_by_num(&request->packet->vps, vp->da->attr, vp->da->vendor, TAG_ANY);
+ fr_pair_add(&request->packet->vps, vp);
return 0;
}
}
}
- inst->ef = exfile_init(inst, 64, 30, true);
+ inst->ef = exfile_init(inst, 256, 30, true);
if (!inst->ef) {
cf_log_err_cs(conf, "Failed creating log file context");
return -1;
/* If simul_count_query is not defined, we don't do any checking */
if (!inst->config->simul_count_query) {
+ RWDEBUG("Simultaneous-Use checking requires 'simul_count_query' to be configured");
return RLM_MODULE_NOOP;
}
- if ((!request->username) || (request->username->vp_length == '\0')) {
+ if ((!request->username) || (request->username->vp_length == 0)) {
REDEBUG("Zero Length username not permitted");
return RLM_MODULE_INVALID;
if (rlm_sql_select_query(inst, request, &handle, expanded) != RLM_SQL_OK) {
rcode = RLM_MODULE_FAIL;
- goto finish;
+ goto release; /* handle may no longer be valid */
}
ret = rlm_sql_fetch_row(inst, request, &handle);
};
-static int _mod_conn_free(rlm_sql_handle_t *conn)
-{
- rlm_sql_t *inst = conn->inst;
-
- rad_assert(inst);
-
- exec_trigger(NULL, inst->cs, "modules.sql.close", false);
-
- return 0;
-}
-
void *mod_conn_create(TALLOC_CTX *ctx, void *instance)
{
int rcode;
*/
handle->inst = inst;
- /*
- * When something frees this handle the destructor set by
- * the driver will be called first, closing any open sockets.
- * Then we call our destructor to trigger an modules.sql.close
- * event, then all the memory is freed.
- */
- talloc_set_destructor(handle, _mod_conn_free);
-
rcode = (inst->module->sql_socket_init)(handle, inst->config);
if (rcode != 0) {
fail:
- exec_trigger(NULL, inst->cs, "modules.sql.fail", true);
-
/*
* Destroy any half opened connections.
*/
(inst->module->sql_finish_select_query)(handle, inst->config);
}
- exec_trigger(NULL, inst->cs, "modules.sql.open", false);
return handle;
}
char const *ptr, *value;
char buf[MAX_STRING_LEN];
char do_xlat = 0;
- FR_TOKEN token, operator = T_EOL;
+ FR_TOKEN token, op = T_EOL;
/*
* Verify the 'Attribute' field
*/
if (!row[2] || row[2][0] == '\0') {
- REDEBUG("The 'Attribute' field is empty or NULL, skipping the entire row");
+ REDEBUG("Attribute field is empty or NULL, skipping the entire row");
return -1;
}
*/
if (row[4] != NULL && row[4][0] != '\0') {
ptr = row[4];
- operator = gettoken(&ptr, buf, sizeof(buf), false);
- if ((operator < T_OP_ADD) ||
- (operator > T_OP_CMP_EQ)) {
- REDEBUG("Invalid operator \"%s\" for attribute %s", row[4], row[2]);
+ op = gettoken(&ptr, buf, sizeof(buf), false);
+ if (!fr_assignment_op[op] && !fr_equality_op[op]) {
+ REDEBUG("Invalid op \"%s\" for attribute %s", row[4], row[2]);
return -1;
}
/*
* Complain about empty or invalid 'op' field
*/
- operator = T_OP_CMP_EQ;
- REDEBUG("The 'op' field for attribute '%s = %s' is NULL, or non-existent.", row[2], row[3]);
+ op = T_OP_CMP_EQ;
+ REDEBUG("The op field for attribute '%s = %s' is NULL, or non-existent.", row[2], row[3]);
REDEBUG("You MUST FIX THIS if you want the configuration to behave as you expect");
}
/*
* The 'Value' field may be empty or NULL
*/
+ if (!row[3]) {
+ REDEBUG("Value field is empty or NULL, skipping the entire row");
+ return -1;
+ }
+
value = row[3];
+
/*
* If we have a new-style quoted string, where the
* *entire* string is quoted, do xlat's.
* Mark the pair to be allocated later.
*/
case T_BACK_QUOTED_STRING:
- value = NULL;
do_xlat = 1;
- break;
+
+ /* FALL-THROUGH */
/*
* Keep the original string.
/*
* Create the pair
*/
- vp = fr_pair_make(ctx, NULL, row[2], NULL, operator);
+ vp = fr_pair_make(ctx, NULL, row[2], NULL, op);
if (!vp) {
REDEBUG("Failed to create the pair: %s", fr_strerror());
return -1;
if (do_xlat) {
if (fr_pair_mark_xlat(vp, value) < 0) {
- REDEBUG("Error marking pair for xlat");
+ REDEBUG("Error marking pair for xlat: %s", fr_strerror());
talloc_free(vp);
return -1;
size_t len;
bool failed = false; /* Write the log message outside of the critical region */
- if (section) {
- filename = section->logfile;
- } else {
- filename = inst->config->logfile;
- }
+ filename = inst->config->logfile;
+ if (section && section->logfile) filename = section->logfile;
- if (!filename) {
+ if (!filename || !*filename) {
return;
}
rlm_sql_oracle
rlm_sql_unixodbc
rlm_sql_sqlite
+rlm_sql_freetds
* Round down to the prev nearest week.
*/
tm->tm_hour = 0;
- tm->tm_mday -= (7 - tm->tm_wday) +(7*(num-1));
+ tm->tm_mday -= tm->tm_wday +(7*(num-1));
inst->last_reset = mktime(tm);
} else if (strcmp(inst->reset, "monthly") == 0 || last == 'm') {
tm->tm_hour = 0;
* @param param_len ip address string len.
* @return 0 on success or < 0 on error.
*/
-static int sqlippool_command(char const * fmt, rlm_sql_handle_t * handle, rlm_sqlippool_t *data, REQUEST *request,
+static int sqlippool_command(char const *fmt, rlm_sql_handle_t **handle,
+ rlm_sqlippool_t *data, REQUEST *request,
char *param, int param_len)
{
char query[MAX_QUERY_LEN];
*/
sqlippool_expand(query, sizeof(query), fmt, data, param, param_len);
- if (radius_axlat(&expanded, request, query, data->sql_inst->sql_escape_func, data->sql_inst) < 0) {
- return -1;
- }
+ if (radius_axlat(&expanded, request, query, data->sql_inst->sql_escape_func, data->sql_inst) < 0) return -1;
- ret = data->sql_inst->sql_query(data->sql_inst, request, &handle, expanded);
+ ret = data->sql_inst->sql_query(data->sql_inst, request, handle, expanded);
if (ret < 0){
talloc_free(expanded);
return -1;
}
talloc_free(expanded);
- (data->sql_inst->module->sql_finish_query)(handle, data->sql_inst->config);
+ if (*handle) (data->sql_inst->module->sql_finish_query)(*handle, data->sql_inst->config);
+
return 0;
}
*/
#undef DO
#define DO(_x) sqlippool_command(inst->_x, handle, inst, request, NULL, 0)
+#define DO_PART(_x) sqlippool_command(inst->_x, &handle, inst, request, NULL, 0)
/*
* Query the database expecting a single result row
handle = fr_connection_get(inst->sql_inst->pool);
if (!handle) {
- REDEBUG("cannot get sql connection");
+ REDEBUG("Failed reserving SQL connection");
return RLM_MODULE_FAIL;
}
if (inst->last_clear < now) {
inst->last_clear = now;
- DO(allocate_begin);
- DO(allocate_clear);
- DO(allocate_commit);
+ DO_PART(allocate_begin);
+ DO_PART(allocate_clear);
+ DO_PART(allocate_commit);
}
- DO(allocate_begin);
+ DO_PART(allocate_begin);
allocation_len = sqlippool_query1(allocation, sizeof(allocation),
inst->allocate_find, handle,
* Nothing found...
*/
if (allocation_len == 0) {
- DO(allocate_commit);
+ DO_PART(allocate_commit);
/*
*Should we perform pool-check ?
*/
vp = fr_pair_afrom_num(request->reply, inst->framed_ip_address, 0);
if (fr_pair_value_from_str(vp, allocation, allocation_len) < 0) {
- DO(allocate_commit);
+ DO_PART(allocate_commit);
RDEBUG("Invalid IP number [%s] returned from instbase query.", allocation);
fr_connection_release(inst->sql_inst->pool, handle);
/*
* UPDATE
*/
- sqlippool_command(inst->allocate_update, handle, inst, request,
+ sqlippool_command(inst->allocate_update, &handle, inst, request,
allocation, allocation_len);
- DO(allocate_commit);
+ DO_PART(allocate_commit);
fr_connection_release(inst->sql_inst->pool, handle);
return do_logging(request, inst->log_success, RLM_MODULE_OK);
}
-static int mod_accounting_start(rlm_sql_handle_t *handle,
- rlm_sqlippool_t *inst, REQUEST *request)
+static int mod_accounting_start(rlm_sql_handle_t **handle,
+ rlm_sqlippool_t *inst, REQUEST *request)
{
DO(start_begin);
DO(start_update);
return RLM_MODULE_OK;
}
-static int mod_accounting_alive(rlm_sql_handle_t *handle,
- rlm_sqlippool_t *inst, REQUEST *request)
+static int mod_accounting_alive(rlm_sql_handle_t **handle,
+ rlm_sqlippool_t *inst, REQUEST *request)
{
DO(alive_begin);
DO(alive_update);
return RLM_MODULE_OK;
}
-static int mod_accounting_stop(rlm_sql_handle_t *handle,
- rlm_sqlippool_t *inst, REQUEST *request)
+static int mod_accounting_stop(rlm_sql_handle_t **handle,
+ rlm_sqlippool_t *inst, REQUEST *request)
{
DO(stop_begin);
DO(stop_clear);
return do_logging(request, inst->log_clear, RLM_MODULE_OK);
}
-static int mod_accounting_on(rlm_sql_handle_t *handle,
- rlm_sqlippool_t *inst, REQUEST *request)
+static int mod_accounting_on(rlm_sql_handle_t **handle,
+ rlm_sqlippool_t *inst, REQUEST *request)
{
DO(on_begin);
DO(on_clear);
return RLM_MODULE_OK;
}
-static int mod_accounting_off(rlm_sql_handle_t *handle,
- rlm_sqlippool_t *inst, REQUEST *request)
+static int mod_accounting_off(rlm_sql_handle_t **handle,
+ rlm_sqlippool_t *inst, REQUEST *request)
{
DO(off_begin);
DO(off_clear);
*/
static rlm_rcode_t CC_HINT(nonnull) mod_accounting(void *instance, REQUEST *request)
{
- int rcode = RLM_MODULE_NOOP;
- VALUE_PAIR *vp;
- int acct_status_type;
- rlm_sqlippool_t *inst = (rlm_sqlippool_t *) instance;
- rlm_sql_handle_t *handle;
+ int rcode = RLM_MODULE_NOOP;
+ VALUE_PAIR *vp;
+
+ int acct_status_type;
+
+ rlm_sqlippool_t *inst = (rlm_sqlippool_t *) instance;
+ rlm_sql_handle_t *handle;
vp = fr_pair_find_by_num(request->packet->vps, PW_ACCT_STATUS_TYPE, 0, TAG_ANY);
if (!vp) {
handle = fr_connection_get(inst->sql_inst->pool);
if (!handle) {
- RDEBUG("Cannot allocate sql connection");
+ RDEBUG("Failed reserving SQL connection");
return RLM_MODULE_FAIL;
}
- if (inst->sql_inst->sql_set_user(inst->sql_inst, request, NULL) < 0) {
- return RLM_MODULE_FAIL;
- }
+ if (inst->sql_inst->sql_set_user(inst->sql_inst, request, NULL) < 0) return RLM_MODULE_FAIL;
switch (acct_status_type) {
case PW_STATUS_START:
- rcode = mod_accounting_start(handle, inst, request);
+ rcode = mod_accounting_start(&handle, inst, request);
break;
case PW_STATUS_ALIVE:
- rcode = mod_accounting_alive(handle, inst, request);
+ rcode = mod_accounting_alive(&handle, inst, request);
break;
case PW_STATUS_STOP:
- rcode = mod_accounting_stop(handle, inst, request);
+ rcode = mod_accounting_stop(&handle, inst, request);
break;
case PW_STATUS_ACCOUNTING_ON:
- rcode = mod_accounting_on(handle, inst, request);
+ rcode = mod_accounting_on(&handle, inst, request);
break;
case PW_STATUS_ACCOUNTING_OFF:
- rcode = mod_accounting_off(handle, inst, request);
+ rcode = mod_accounting_off(&handle, inst, request);
break;
}
test.conf
radius.log
radiusd.pid
+eapol_test
--- /dev/null
+# PRE: case-empty
+#
+update reply {
+ Filter-Id := "fail"
+}
+
+switch &reply:Filter-Id {
+ # deliberately empty
+ case "filter" {
+ }
+
+ case &Not-Dynamically-Allocated { # ERROR
+ update reply {
+ Filter-Id := "fail"
+ }
+ }
+
+ case {
+ }
+}
--- /dev/null
+#
+# PRE: update if
+#
+
+#
+# Strings which are expanded in a regex have regex special
+# characters escaped. Because the input strings are unsafe.
+#
+update request {
+ Tmp-String-0 := "example.com"
+ Tmp-String-1 := "exampleXcom"
+}
+
+if ("exampleXcom" =~ /%{Tmp-String-0}/) {
+ update reply {
+ Filter-Id := "fail 1"
+ }
+}
+
+elsif (&Tmp-String-1 =~ /%{Tmp-String-0}/) {
+ update reply {
+ Filter-Id := "fail 2"
+ }
+}
+else {
+ update reply {
+ Filter-Id := "filter"
+ }
+}
\ No newline at end of file
--- /dev/null
+#
+# PRE: update if regex-escape
+#
+
+#
+# Strings which are expanded in a regex have regex special
+# characters escaped. Because the input strings are unsafe.
+#
+update request {
+ Tmp-String-0 := "example.com"
+ Tmp-String-1 := "^foo$bar"
+}
+
+if (&Tmp-String-0 !~ /example\.com$/) {
+ update reply {
+ Filter-Id := "fail 1"
+ }
+}
+elsif (&Tmp-String-1 !~ /\^foo\$bar/) {
+ update reply {
+ Filter-Id := "fail 1"
+ }
+} else {
+ update reply {
+ Filter-Id := "filter"
+ }
+}
\ No newline at end of file
--- /dev/null
+#
+# PRE: cmp
+#
+update control {
+ Cleartext-Password := 'hello'
+}
+
+update request {
+ Tmp-String-0 := "this\000is\000a\000string"
+}
+
+#
+# %{string:...} is explicitly not binary safe
+#
+if ("%{string:Tmp-String-0}" == "this") {
+ update reply {
+ Filter-Id := "filter"
+ }
+}
--- /dev/null
+#
+# PRE: update
+#
+update control {
+ Tmp-Integer-0 := 5
+ Tmp-Integer-0 += 10
+ Tmp-Integer-0 += 15
+ Tmp-Integer-0 += 20
+ Tmp-String-0 := 'foo'
+ Tmp-String-0 += 'baz'
+ Tmp-String-0 += 'boink'
+}
+
+#
+# Reset the request list
+#
+update {
+ &request: !* ANY
+ &request: += &control:[*]
+}
+
+debug_request
+
+#
+# Only matching attributes of the specified type should remain
+#
+update request {
+ &Tmp-Integer-0 == 10
+}
+
+if (&Tmp-Integer-0[0] != 10) {
+ update reply {
+ Filter-Id += "fail 1"
+ }
+}
+
+if ("%{Tmp-Integer-0[#]}" != 1) {
+ update reply {
+ Filter-Id += "fail 2"
+ }
+}
+
+if ("%{Tmp-String-0[#]}" != 3) {
+ update reply {
+ Filter-Id += "fail 3"
+ }
+}
+
+debug_request
+
+#
+# Only matching attributes of the specified type should remain
+#
+update request {
+ &Tmp-String-0 == 'baz'
+}
+
+if (&Tmp-String-0[0] != 'baz') {
+ update reply {
+ Filter-Id += "fail 4"
+ }
+}
+
+if ("%{Tmp-String-0[#]}" != 1) {
+ update reply {
+ Filter-Id += "fail 5"
+ }
+}
+
+update {
+ control:Auth-Type := Accept
+ reply:Filter-Id := "filter"
+}
+
+debug_request
MAP_TESTS := $(patsubst $(top_srcdir)/src/tests/map/%,%,$(filter-out %.conf %.md %.attrs %.c %.mk %~ %.rej %.out,$(wildcard $(top_srcdir)/src/tests/map/*)))
MAP_OUTPUT := $(addsuffix .out,$(addprefix $(BUILD_DIR)/tests/map/,$(MAP_TESTS)))
-MAP_UNIT := $(BUILD_DIR)/bin/local/map_unit
+MAP_UNIT_BIN := $(BUILD_DIR)/bin/local/map_unit
+MAP_UNIT := ./build/make/jlibtool --silent --mode=execute $(MAP_UNIT_BIN)
.PHONY: $(BUILD_DIR)/tests/map/
$(BUILD_DIR)/tests/map/:
#
# Create the output directory before the files
#
-$(MAP_OUTPUT): $(MAP_UNIT) | $(BUILD_DIR)/tests/map/
+$(MAP_OUTPUT): $(MAP_UNIT_BIN) | $(BUILD_DIR)/tests/map/
#
# Re-run the tests if the input file changes
+++ /dev/null
-All SQL related tests should be defined here and the driver specific directory need only have links to the tests defined here.
-
-All User-Name attributes, Acct-Session-Id, and Acct-Multi-Session-Id attributes
-
- MUST BE UNIQUE FOR EVERY TEST.
-
-Otherwise the tests will stomp on each other when run in parallel.
TGT_PREREQS := libfreeradius-radius.a
TGT_LDLIBS := $(LIBS)
+TGT_INSTALLDIR :=
# All IP address literals should be parsed as prefixes
condition Framed-IP-Address <= 192.168.0.0/16
-data &Framed-IP-Address <= 192.168.0.0/16
+data <ipv4prefix>&Framed-IP-Address <= 192.168.0.0/16
# string attributes must be string
condition User-Name == "bob"
data &User-Name == 'bar'
condition &Vendor-11344-Attr-1 == 127.0.0.1
-data &FreeRADIUS-Proxied-To == 127.0.0.1/32
+data &FreeRADIUS-Proxied-To == 127.0.0.1
condition &FreeRADIUS-Attr-1 == 127.0.0.1
-data &FreeRADIUS-Proxied-To == 127.0.0.1/32
+data &FreeRADIUS-Proxied-To == 127.0.0.1
#
# Escape the backslashes correctly
condition <ipv4prefix>192.168.0.0/24 > &NAS-IP-Address
data <ipv4prefix>192.168.0.0/24 > &NAS-IP-Address
+
+#
+# We add casts to the LHS if necessary
+#
+condition &NAS-IP-Address < &PMIP6-Home-IPv4-HoA
+data <ipv4prefix>&NAS-IP-Address < &PMIP6-Home-IPv4-HoA
+
+condition &NAS-IP-Address < 192.168/16
+data <ipv4prefix>&NAS-IP-Address < 192.168.0.0/16
+
+condition &NAS-IP-Address < "%{echo: 192.168/16}"
+data <ipv4prefix>&NAS-IP-Address < "%{echo: 192.168/16}"
+
+condition &NAS-IP-Address < `/bin/echo 192.168/16`
+data <ipv4prefix>&NAS-IP-Address < `/bin/echo 192.168/16`
data rad_attr2vp: Insufficient data
encode Attr-26.1.256 = 0x00000001
-data Invalid OID
+data Number '256' out of allowed range in attribute identifier
encode Attr-240.1 = 0x01
data Standard attributes cannot use OIDs
attribute Framed-IP-Address = 127
data Framed-IP-Address = 0.0.0.127
+attribute Framed-IP-Address = 127.0
+data Framed-IP-Address = 127.0.0.0
+
attribute Framed-IPv6-Prefix = ::1
data Framed-IPv6-Prefix = ::1/128
attribute Framed-IPv6-Prefix = *
data Framed-IPv6-Prefix = ::/128
+attribute PMIP6-Home-IPv4-HoA = 127/8
+data PMIP6-Home-IPv4-HoA = 127.0.0.0/8
+
+attribute PMIP6-Home-IPv4-HoA = 127/8
+data PMIP6-Home-IPv4-HoA = 127.0.0.0/8
+
+#
+# Octets outside of the mask are OK, but
+# are mashed to zero.
+#
+attribute PMIP6-Home-IPv4-HoA = 127.63/8
+data PMIP6-Home-IPv4-HoA = 127.0.0.0/8
+
+#
+# Unless you give a good mask.
+#
+attribute PMIP6-Home-IPv4-HoA = 127.63/16
+data PMIP6-Home-IPv4-HoA = 127.63.0.0/16
+
+attribute PMIP6-Home-IPv4-HoA = 127.999/16
+data Failed to parse IPv4 address string "127.999/16"
+
+attribute PMIP6-Home-IPv4-HoA = 127.bob/16
+data Failed to parse IPv4 address string "127.bob/16"
+
+attribute PMIP6-Home-IPv4-HoA = 127.63/15
+data PMIP6-Home-IPv4-HoA = 127.62.0.0/15
+
+attribute PMIP6-Home-IPv4-HoA = 127.63.1/24
+data PMIP6-Home-IPv4-HoA = 127.63.1.0/24
+
+attribute PMIP6-Home-IPv4-HoA = 127.63.1.6
+data PMIP6-Home-IPv4-HoA = 127.63.1.6/32
+
+attribute PMIP6-Home-IPv4-HoA = 256/8
+data Failed to parse IPv4 address string "256/8"
+
+attribute PMIP6-Home-IPv4-HoA = bob/8
+data Failed to parse IPv4 address string "bob/8"
+
$INCLUDE tunnel.txt
$INCLUDE errors.txt
$INCLUDE extended.txt
Name: freeradius-server
-Version: 3.0.10
+Version: 3.0.12
Release: 0
License: GPLv2 ; LGPLv2.1
Group: Productivity/Networking/Radius/Servers