fwknop-2.6.9/0000775000175000017500000000000012726140436010044 500000000000000fwknop-2.6.9/aclocal.m40000664000175000017500000012216512726140343011630 00000000000000# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-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. # 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($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-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. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.14' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.14.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # 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/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # 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 # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # 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` ]) # AM_CONDITIONAL -*- Autoconf -*- # 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. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-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. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-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. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-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. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # 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. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-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. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # 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. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # 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. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # 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 if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # 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. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-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. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # 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. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-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. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-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. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # 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. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-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. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-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. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/gpgme.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) fwknop-2.6.9/configure.ac0000664000175000017500000006135412726140001012247 00000000000000dnl Fwknop AutoConf script... dnl ========================= dnl dnl Created by Damien Stuart dnl dnl Inspiration from RRDtool configure.ac, the AutoConf Archive dnl (http://www.nongnu.org/autoconf-archive/), and other examples. dnl Minimum Autoconf version required. AC_PREREQ(2.62) dnl Define our name, version and email. m4_define(my_package, [fwknop]) m4_define(my_version, [2.6.9]) m4_define(my_bug_email, [dstuart@dstuart.org]) AC_INIT(my_package, my_version, my_bug_email) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR(config) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE([subdir-objects]) dnl AM_MAINTAINER_MODE AC_CONFIG_HEADERS([config.h]) dnl The top of our header dnl AH_TOP([ #ifndef FWKNOP_CONFIG_H #define FWKNOP_CONFIG_H ]) dnl The bottom of our header file dnl AH_BOTTOM([ #endif /* FWKNOP_CONFIG_H */ ]) dnl FKO_CHECK_COMPILER_ARG([COMPILER FLAG]) dnl dnl Macro to check compiler support for the given compiler option. dnl Adds to CFLAGS and LDFLAGS if supported. dnl dnl The structure of this macro was adapted from OpenSSH. dnl AC_DEFUN([FKO_CHECK_COMPILER_ARG], [ saved_CFLAGS="$CFLAGS" saved_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $1 -Werror" LDFLAGS="$LDFLAGS $1 -Werror" AC_MSG_CHECKING([if $CC supports $1]) AC_LINK_IFELSE( [AC_LANG_SOURCE([ #include int main(void){char x[[256]]; snprintf(x, sizeof(x), "NNN"); return 0;} ])], [ CFLAGS="$saved_CFLAGS $1" LDFLAGS="$saved_LDFLAGS $1" AC_RUN_IFELSE( [AC_LANG_SOURCE([ #include int main(void){char x[[256]]; snprintf(x, sizeof(x), "NNN"); return 0;} ])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS"], [AC_MSG_WARN([cross compiling: cannot test])]) ], [AC_MSG_RESULT(no) CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS"] )])dnl dnl FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([COMPILER FLAG]) dnl dnl Macro to check compiler support for the given compiler option. dnl Adds to LDFLAGS only if supported. dnl AC_DEFUN([FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY], [ saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $1 -Werror" AC_MSG_CHECKING([if $CC supports $1]) AC_LINK_IFELSE( [AC_LANG_SOURCE([ #include int main(void){char x[[256]]; snprintf(x, sizeof(x), "NNN"); return 0;} ])], [ LDFLAGS="$saved_LDFLAGS $1" AC_RUN_IFELSE( [AC_LANG_SOURCE([ #include int main(void){char x[[256]]; snprintf(x, sizeof(x), "NNN"); return 0;} ])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) LDFLAGS="$saved_LDFLAGS"], [AC_MSG_WARN([cross compiling: cannot test])]) ], [AC_MSG_RESULT(no) LDFLAGS="$saved_LDFLAGS"] )])dnl AC_GNU_SOURCE AC_PROG_CC AM_PROG_CC_C_O AC_PROG_CPP AC_PROG_AWK AC_PROG_SED AC_PROG_GREP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_LIBTOOL dnl Detect if we are on and Apple platform dnl AM_CONDITIONAL([APPLE_PLATFORM], [test `uname -s` = Darwin]) dnl Decide whether or not to build binaries with profiling coverage support dnl want_profile_coverage=no AC_ARG_ENABLE([profile-coverage], [AS_HELP_STRING([--enable-profile-coverage], [Build fwknop binaries with profile coverage support @<:@default is to disable@:>@])], [want_profile_coverage=$enableval], []) if test "x$want_profile_coverage" = "xyes"; then FKO_CHECK_COMPILER_ARG([-fprofile-arcs -ftest-coverage -fno-inline]) FKO_CHECK_COMPILER_ARG([-g]) FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-lgcov]) AC_DEFINE([CODE_COVERAGE], [1], [Define for code coverage support]) fi dnl Decide whether or not to build binaries with fault injection support dnl provided by libfiu (see: http://blitiri.com.ar/p/libfiu/) for fault dnl testing dnl want_libfiu_support=no AC_ARG_ENABLE([libfiu-support], [AS_HELP_STRING([--enable-libfiu-support], [Build fwknop binaries with fault injection testing support @<:@default is to disable@:>@])], [want_libfiu_support=$enableval], []) if test "x$want_libfiu_support" = "xyes"; then AC_DEFINE([HAVE_LIBFIU], [1], [Define for fault injection testing support]) FKO_CHECK_COMPILER_ARG([-DFIU_ENABLE]) FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-lfiu]) fi AM_CONDITIONAL([WANT_LIBFIU_SUPPORT], [test "$want_libfiu_support" = yes]) dnl Decide whether or not to enable C unit testing dnl want_c_unit_tests=no AC_ARG_ENABLE([c-unit-tests], [AS_HELP_STRING([--enable-c-unit-tests], [Enable C unit testing with libcunit support @<:@default is to disable@:>@])], [want_c_unit_tests=$enableval], []) if test "x$want_c_unit_tests" = "xyes"; then AC_DEFINE([HAVE_C_UNIT_TESTS], [1], [Define for C unit testing support]) FKO_CHECK_COMPILER_ARG([-DHAVE_C_UNIT_TESTS]) FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-lcunit]) fi AM_CONDITIONAL([WANT_C_UNIT_TESTS], [test "$want_c_unit_tests" = yes]) dnl Decide whether or not to enable address sanitizer support dnl want_asan_support=no AC_ARG_ENABLE([asan-support], [AS_HELP_STRING([--enable-asan-support], [Build fwknop binaries with AddressSanitizer support @<:@default is to disable@:>@])], [want_asan_support=$enableval], []) if test "x$want_asan_support" = "xyes"; then FKO_CHECK_COMPILER_ARG([-fsanitize=address -fno-omit-frame-pointer]) fi dnl Decide whether or not to enable MemorySanitizer support dnl want_ubsan_support=no AC_ARG_ENABLE([ubsan-support], [AS_HELP_STRING([--enable-ubsan-support], [Build fwknop binaries with UndefinedBehaviorSanitizer support @<:@default is to disable@:>@])], [want_ubsan_support=$enableval], []) if test "x$want_ubsan_support" = "xyes"; then FKO_CHECK_COMPILER_ARG([-fsanitize=undefined]) fi dnl Decide whether or not force 32-bit mode dnl want_32bit_mode=no AC_ARG_ENABLE([32bit-mode], [AS_HELP_STRING([--enable-32bit-mode], [Build 32-bit fwknop binaries @<:@default is to disable@:>@])], [want_32bit_mode=$enableval], []) if test "x$want_32bit_mode" = "xyes"; then FKO_CHECK_COMPILER_ARG([-m32]) fi dnl Decide whether or not to compile in certain features that enable fuzzing dnl of fwknop code - this is for testing purposes only. dnl want_fuzzing_interfaces=no AC_ARG_ENABLE([fuzzing-interfaces], [AS_HELP_STRING([--enable-fuzzing-interfaces], [Build fwknop binaries with support for fuzzing interfaces @<:@default is to disable@:>@])], [want_fuzzing_interfaces=$enableval], []) if test "x$want_fuzzing_interfaces" = "xyes"; then AC_DEFINE([FUZZING_INTERFACES], [1], [Define for fuzzing interfaces support]) fi dnl Decide whether or not to compile in support for the 'American Fuzzy Lop' dnl fuzzer from Michal Zalewski - this is for testing purposes only dnl want_afl_fuzzing_support=no AC_ARG_ENABLE([afl-fuzzing], [AS_HELP_STRING([--enable-afl-fuzzing], [Build fwknop binaries with support for the American Fuzzy Lop fuzzer @<:@default is to disable@:>@])], [want_afl_fuzzing_support=$enableval], []) if test "x$want_afl_fuzzing_support" = "xyes"; then AC_DEFINE([AFL_FUZZING], [1], [Define for AFL fuzzing support]) AC_DEFINE([FUZZING_INTERFACES], [1], [Define for fuzzing interfaces support]) fi dnl Decide whether or not to enable UDP server mode (no libpcap dependency) dnl want_udp_server=no AC_ARG_ENABLE([udp-server], [AS_HELP_STRING([--enable-udp-server], [Enable UDP server mode for no libpcap dependency @<:@default is to disable@:>@])], [want_udp_server=$enableval], []) AM_CONDITIONAL([UDP_SERVER], [test "$want_udp_server" = yes]) dnl Decide whether or not to enable UDP server mode (no libpcap dependency) dnl want_nfq_capture=no AC_ARG_ENABLE([nfq-capture], [AS_HELP_STRING([--enable-nfq-capture], [Enable NF_QUEUE server mode for no libpcap dependency @<:@default is to disable@:>@])], [want_nfq_capture=$enableval], []) AM_CONDITIONAL([NFQ_CAPTURE], [test "$want_nfq_capture" = yes]) dnl Decide whether or not to enable all warnings with -Wall dnl use_wall=yes AC_ARG_ENABLE([wall], [AS_HELP_STRING([--disable-wall], [Do not enable warnings via -Wall -Wformat -Wformat-security @<:@default is on@:>@])], [use_wall=$enableval], []) if test "x$use_wall" = "xyes"; then FKO_CHECK_COMPILER_ARG([-Wall -Wformat -Wformat-security]) fi dnl Check for security features offered by the compiler dnl -fstack-protector-all doesn't always work for some GCC versions dnl and/or platforms, so we test if we can. If it's not supported dnl on a given platform gcc will emit a warning so we use -Werror. dnl dnl Decide whether or not to enable -fstack-protector dnl use_stack_protector=yes AC_ARG_ENABLE([stack-protector], [AS_HELP_STRING([--disable-stack-protector], [Do not enable -fstack-protector @<:@default is on@:>@])], [use_stack_protector=$enableval], []) if test "x$use_stack_protector" = "xyes"; then FKO_CHECK_COMPILER_ARG([-fstack-protector-all -fstack-protector]) fi dnl Decide whether or not to enable Position Independent Executable (PIE) dnl support dnl use_pie=yes AC_ARG_ENABLE([pie], [AS_HELP_STRING([--disable-pie], [Do not enable Position Independent Executable support @<:@default is on@:>@])], [use_pie=$enableval], []) if test "x$use_pie" = "xyes"; then FKO_CHECK_COMPILER_ARG([-fPIE -fPIC]) FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-pie -fPIC]) fi dnl Decide whether or not to enable -D_FORTIFY_SOURCE support dnl use_fortify_source=yes AC_ARG_ENABLE([fortify-source], [AS_HELP_STRING([--disable-fortify-source], [Do not enable -D_FORTIFY_SOURCE support @<:@default is on@:>@])], [use_fortify_source=$enableval], []) if test "x$use_fortify_source" = "xyes"; then FKO_CHECK_COMPILER_ARG([-D_FORTIFY_SOURCE=2]) fi dnl Decide whether or not to use read-only relocations protection dnl use_ro_relocations=yes AC_ARG_ENABLE([ro-relocations], [AS_HELP_STRING([--disable-ro-relocations], [Do not enable read-only relocations protection @<:@default is on@:>@])], [use_ro_relocations=$enableval], []) if test "x$use_ro_relocations" = "xyes"; then FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-Wl,-z,relro]) fi dnl Decide whether or not to use immediate binding protection dnl use_immediate_binding=yes AC_ARG_ENABLE([immediate-binding], [AS_HELP_STRING([--disable-immediate-binding], [Do not enable immediate binding protection @<:@default is on@:>@])], [use_immediate_binding=$enableval], []) if test "x$use_immediate_binding" = "xyes"; then FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-Wl,-z,now]) fi # Checks for header files. # AC_HEADER_STDC AC_HEADER_TIME AC_HEADER_RESOLV AC_CHECK_HEADERS([arpa/inet.h ctype.h endian.h errno.h locale.h netdb.h net/ethernet.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/byteorder.h sys/endian.h sys/ethernet.h sys/socket.h sys/stat.h sys/time.h sys/wait.h termios.h time.h unistd.h]) # Type checks. # AC_C_CONST AC_TYPE_INT8_T AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_UINT8_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_OFF_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_CHECK_SIZEOF(unsigned int) dnl AC_CHECK_TYPES([uint8_t, uint32_t]) AC_C_BIGENDIAN AC_SYS_LARGEFILE # Checks for library functions. # AC_FUNC_MALLOC AC_FUNC_REALLOC AC_FUNC_STAT AC_CHECK_FUNCS([bzero gettimeofday memmove memset socket strchr strcspn strdup strncasecmp strndup strrchr strspn strnlen stat lstat chmod chown strlcat strlcpy]) dnl Decide whether or not to check for the execvpe() function dnl use_execvpe=yes AC_ARG_ENABLE([execvpe], [AS_HELP_STRING([--disable-execvpe], [Do not check for the execvpe() function for command execution @<:@default is on@:>@])], [use_execvpe=$enableval], []) if test "x$use_execvpe" = "xyes"; then AC_CHECK_FUNCS([execvpe]) fi AC_SEARCH_LIBS([socket], [socket]) AC_SEARCH_LIBS([inet_addr], [nsl]) AM_CONDITIONAL(MINGW, false) use_mingw=no case "$host" in *-*-linux*) ;; *-*-openbsd*) AC_DEFINE_UNQUOTED([PLATFORM_OPENBSD], [1], [Define if you are running on OpenBSD]) ;; *-mingw32*) AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system]) use_mingw=yes ;; esac AM_CONDITIONAL(USE_MINGW, [test x$use_mingw = xyes]) dnl Decide whether or not to build the client dnl want_client=yes AC_ARG_ENABLE([client], [AS_HELP_STRING([--disable-client], [Do not build the fwknop client @<:@default is to build@:>@])], [want_client=$enableval], []) AM_CONDITIONAL([WANT_CLIENT], [test "$want_client" = yes]) dnl Decide whether or not to build the server dnl want_server=yes AC_ARG_ENABLE([server], [AS_HELP_STRING([--disable-server], [Do not build the fwknop server @<:@default is to build@:>@])], [want_server=$enableval], []) AM_CONDITIONAL([WANT_SERVER], [test "$want_server" = yes]) dnl Decide whether or not to enable the digest-cache dnl want_digest_cache=yes AC_ARG_ENABLE([digest-cache], [AS_HELP_STRING([--disable-digest-cache], [Do not enable the fwknopd digest-cache @<:@default is to build@:>@])], [want_digest_cache=$enableval], []) dnl AM_CONDITIONAL([WANT_DIGEST_CACHE], [test "$want_digest_cache" = yes]) dnl Decide whether or not to try to look for gdbm/ndbm (default to just dnl use a file-based solution - reduces dependencies) dnl want_file_cache=yes AC_ARG_ENABLE([file-cache], [AS_HELP_STRING([--disable-file-cache], [Replace file cache with gdbm/ndbm @<:@default=no@:>@])], [want_file_cache=$enableval], []) AS_IF([test "$want_file_cache" = yes], [ AC_DEFINE([USE_FILE_CACHE], [1], [Define this to enable non-gdbm/ndbm digest storing (eliminates gdbm/ndbm dependency).]) ]) # Check for 3rd-party libs # AC_ARG_WITH([gpgme], [AS_HELP_STRING([--with-gpgme], [support for gpg encryption using libgpgme @<:@default=check@:>@])], [], [with_gpgme=check]) have_gpgme=yes AS_IF([test "x$with_gpgme" != xno], [AM_PATH_GPGME([], [AC_DEFINE([HAVE_LIBGPGME], [1], [Define if you have libgpgme])], [if test "x$with_gpgme" != xcheck; then AC_MSG_FAILURE( [--with-gpgme was given, but test for gpgme failed]) else have_gpgme=no fi ], [have_gpgme=no])], [have_gpgme=no]) dnl Add various common way to sbin dir to the path (just in case) APP_PATH=$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/usr/local/sbin dnl Check for gpg (not gpg2) dnl AC_ARG_WITH([gpg], [AS_HELP_STRING([--with-gpg=/path/to/gpg], [Specify path to the gpg executable that gpgme will use @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = x -o "x$withval" = xyes -o "x$withval" = xno ], [AC_MSG_ERROR([--with-gpg requires an argument specifying a path to gpg])], [ GPG_EXE=$withval ] ) ], [ AC_PATH_PROG(GPG_EXE, [gpg], [], [$APP_PATH]) ] ) AS_IF([test "x$GPG_EXE" != x], [ AC_DEFINE_UNQUOTED([GPG_EXE], ["$GPG_EXE"], [Path to gpg executable]) gpg_exe=$GPG_EXE ], [ gpg_exe="(not found)"] ) if [test "$have_gpgme" = "yes" ]; then case "$host" in *-*-linux*) ;; *-*-freebsd*) if [ test "x$CPPFLAGS" = "x" ] ; then CPPFLAGS="-I/usr/local/include -I/usr/local/include/gpgme" fi if [ test "x$LDFLAGS" = "x" ] ; then LDFLAGS="-L/usr/local/lib" fi ;; esac fi dnl Check for wget (used by the fwknop client for SSL external IP resolution) dnl AC_ARG_WITH([wget], [AS_HELP_STRING([--with-wget=/path/to/wget], [Specify path to the wget executable @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = x -o "x$withval" = xyes -o "x$withval" = xno ], [AC_MSG_ERROR([--with-wget requires an argument specifying a path to wget])], [ WGET_EXE=$withval ] ) ], [ AC_PATH_PROG(WGET_EXE, [wget], [], [$APP_PATH]) ] ) AS_IF([test "x$WGET_EXE" != x], [ AC_DEFINE_UNQUOTED([WGET_EXE], ["$WGET_EXE"], [Path to wget executable]) wget_exe=$WGET_EXE ], [ wget_exe="(not found)"] ) dnl Check for libpcap, gdbm (or ndbm) if we are building the server component dnl AS_IF([test "$want_server" = yes], [ AS_IF([test "$want_udp_server" = no -a "$want_nfq_capture" = no], [ # Looking for libpcap # AC_CHECK_LIB([pcap],[pcap_open_live], [ AC_DEFINE([USE_LIBPCAP], [1], [Define if you have libpcap]) ], [ AC_MSG_ERROR([fwknopd needs libpcap])] ) ]) AS_IF([test "$want_nfq_capture" = yes], [ # Check for libnetfilter_queue # AC_CHECK_LIB([netfilter_queue],[nfq_open], [ AC_DEFINE([USE_LIBNETFILTER_QUEUE], [1], [Define if you have libnetfilter_queue]) ], [ AC_MSG_ERROR([fwknopd needs libnetfilter_queue])] ) ]) AS_IF([test "$want_digest_cache" = yes], [ use_ndbm=no have_digest_cache=yes AS_IF([test "$want_file_cache" = no], [ # Looking for gdbm or fallback to ndbm or bail # AC_CHECK_LIB([gdbm],[gdbm_open], [ AC_DEFINE([HAVE_LIBGDBM], [1], [Define if you have libgdbm]) ], [ AC_CHECK_LIB([ndbm],[dbm_open], [ AC_DEFINE([HAVE_LIBNDBM], [1], [Define if you have libndbm]) use_ndbm=yes ], [ AC_CHECK_HEADER([ndbm.h], [ AC_CHECK_FUNC([dbm_open], [ AC_DEFINE([HAVE_LIBNDBM], [1], [Define if you have libndbm])], [ AC_DEFINE([NO_DIGEST_CACHE], [1], [Define this to disable the digest cache for replay detection - not recommended.]) AC_MSG_WARN([No DBM implementation found. Replay detection will be disabled.]) have_digest_cache=no ] )] )] )] )] )], [ AC_DEFINE([NO_DIGEST_CACHE], [1], [Define this to disable the digest cache for replay detection - not recommended.]) have_digest_cache=no ] ) AM_CONDITIONAL([USE_NDBM], [test x$use_ndbm = xyes]) AM_CONDITIONAL([CONFIG_FILE_CACHE], [test x$want_file_cache = xyes]) dnl Check for firewalld dnl AC_ARG_WITH([firewall-cmd], [AS_HELP_STRING([--with-firewall-cmd=/path/to/firewall-cmd], [Specify path to the firewall-cmd executable @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = xno ], [], AS_IF([ test "x$withval" = x -o "x$withval" = xyes ], [AC_MSG_ERROR([--with-firewall-cmd requires an argument specifying a path to firewall-cmd])], [ FORCE_FIREWALLD_EXE=$withval ] ) ) ], [ AC_PATH_PROG(FIREWALLD_EXE, [firewall-cmd], [], [$APP_PATH]) ] ) AC_ARG_WITH([firewalld], [AS_HELP_STRING([--with-firewalld=/path/to/firewall-cmd], [Synonym for --with-firewall-cmd, specify path to the firewall-cmd executable @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = xno ], [], AS_IF([ test "x$withval" = x -o "x$withval" = xyes ], [AC_MSG_ERROR([--with-firewalld requires an argument specifying a path to firewall-cmd])], [ FORCE_FIREWALLD_EXE=$withval ] ) ) ], [ AC_PATH_PROG(FIREWALLD_EXE, [firewalld], [], [$APP_PATH]) ] ) dnl Check for iptables dnl AC_ARG_WITH([iptables], [AS_HELP_STRING([--with-iptables=/path/to/iptables], [Specify path to the iptables executable @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = xno ], [], AS_IF([ test "x$withval" = x -o "x$withval" = xyes ], [AC_MSG_ERROR([--with-iptables requires an argument specifying a path to iptables])], [ FORCE_IPTABLES_EXE=$withval ] ) ) ], [ AC_PATH_PROG(IPTABLES_EXE, [iptables], [], [$APP_PATH]) ] ) dnl Check for ipfw dnl AC_ARG_WITH([ipfw], [AS_HELP_STRING([--with-ipfw=/path/to/ipfw], [Specify path to the ipfw executable @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = xno ], [], AS_IF([ test "x$withval" = x -o "x$withval" = xyes ], [AC_MSG_ERROR([--with-ipfw requires an argument specifying a path to ipfw])], [ FORCE_IPFW_EXE=$withval ] ) ) ], [ AC_PATH_PROG(IPFW_EXE, [ipfw], [], [$APP_PATH]) ] ) dnl Check for pf from OpenBSD dnl AC_ARG_WITH([pf], [AS_HELP_STRING([--with-pf=/path/to/pfctl], [Specify path to the pf executable @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = xno ], [], AS_IF([ test "x$withval" = x -o "x$withval" = xyes ], [AC_MSG_ERROR([--with-pf requires an argument specifying a path to pf])], [ FORCE_PF_EXE=$withval ] ) ) ], [ AC_PATH_PROG(PF_EXE, [pfctl], [], [$APP_PATH]) ] ) dnl Check for ipf (ipfilter) dnl AC_ARG_WITH([ipf], [AS_HELP_STRING([--with-ipf=/path/to/ipf], [Specify path to the ipf executable @<:@default=check path@:>@])], [ AS_IF([ test "x$withval" = xno ], [], AS_IF([ test "x$withval" = x -o "x$withval" = xyes ], [AC_MSG_ERROR([--with-ipf requires an argument specifying a path to ipf])], [ FORCE_IPF_EXE=$withval ] ) ) ], [ AC_PATH_PROG(IPF_EXE, [ipf], [], [$APP_PATH]) ] ) dnl If a firewall was forced. set the appropriate _EXE var and clear the others. dnl AS_IF([test "x$FORCE_FIREWALLD_EXE" != x], [ FIREWALLD_EXE="$FORCE_FIREWALLD_EXE" ],[ AS_IF([test "x$FORCE_IPTABLES_EXE" != x], [ IPTABLES_EXE="$FORCE_IPTABLES_EXE" FIREWALLD_EXE="" ],[ AS_IF([test "x$FORCE_IPFW_EXE" != x], [ IPFW_EXE="$FORCE_IPFW_EXE" IPTABLES_EXE="" FIREWALLD_EXE="" ],[ AS_IF([test "x$FORCE_PF_EXE" != x], [ PF_EXE="$FORCE_PF_EXE" IPFW_EXE="" IPTABLES_EXE="" FIREWALLD_EXE="" ],[ AS_IF([test "x$FORCE_IPF_EXE" != x], [ IPF_EXE="$FORCE_IPF_EXE" PF_EXE="" IPFW_EXE="" IPTABLES_EXE="" FIREWALLD_EXE="" ] ] ] ] ] ))))) dnl Determine which firewall exe we use (if we have one). dnl If firewalld was found or specified, it wins, then we fallback to iptables, dnl then ipfw, pf, and otherwise we try ipf. dnl AS_IF([test "x$FIREWALLD_EXE" != x], [ FW_DEF="FW_FIREWALLD" FIREWALL_TYPE="firewalld" FIREWALL_EXE=$FIREWALLD_EXE AC_DEFINE_UNQUOTED([FIREWALL_FIREWALLD], [1], [The firewall type: firewalld.]) ],[ AS_IF([test "x$IPTABLES_EXE" != x], [ FW_DEF="FW_IPTABLES" FIREWALL_TYPE="iptables" FIREWALL_EXE=$IPTABLES_EXE AC_DEFINE_UNQUOTED([FIREWALL_IPTABLES], [1], [The firewall type: iptables.]) ],[ AS_IF([test "x$IPFW_EXE" != x], [ FW_DEF="FW_IPFW" FIREWALL_TYPE="ipfw" FIREWALL_EXE=$IPFW_EXE AC_DEFINE_UNQUOTED([FIREWALL_IPFW], [1], [The firewall type: ipfw.]) ],[ AS_IF([test "x$PF_EXE" != x], [ FW_DEF="FW_PF" FIREWALL_TYPE="pf" FIREWALL_EXE=$PF_EXE AC_DEFINE_UNQUOTED([FIREWALL_PF], [1], [The firewall type: pf.]) ],[ AS_IF([test "x$IPF_EXE" != x], [ AC_MSG_ERROR([Sorry - ipf was specified or the only one found, however, it is not supported yet.]) FIREWALL_TYPE="ipf" FIREWALL_EXE=$IPF_EXE AC_DEFINE_UNQUOTED([FIREWALL_IPF], [1], [The firewall type: ipf.]) ], [AC_MSG_ERROR([No firewall program was found or specified.]) ] ] ] ] ] ))))) AC_DEFINE_UNQUOTED([FIREWALL_EXE], ["$FIREWALL_EXE"], [Path to firewall command executable (it should match the firewall type).]) ], [test "$want_server" = no], [ use_ndbm=no AM_CONDITIONAL([USE_NDBM], [test x$use_ndbm = xno]) AM_CONDITIONAL([CONFIG_FILE_CACHE], [test x$use_ndbm = xno]) ] ) AC_CONFIG_FILES([Makefile lib/Makefile client/Makefile server/Makefile common/Makefile doc/Makefile]) AC_OUTPUT if [test "$have_gpgme" = "yes" ]; then have_gpgme="$have_gpgme Gpgme engine: $GPG_EXE" fi echo " $PACKAGE_NAME-$PACKAGE_VERSION configuration. ========================================================== Client build: $want_client Server build: $want_server GPG encryption support: $have_gpgme Installation prefix: $prefix " if [test "$want_server" = "yes" ]; then echo " Server support: firewall type: $FIREWALL_TYPE firewall program path: $FIREWALL_EXE " if [test "$want_udp_server" = "yes" ]; then echo " UDP server mode enabled, no libpcap dependency " fi if [test "$want_nfq_capture" = "yes" ]; then echo " Netfilter Queue server mode enabled, no libpcap dependency " fi if [test "$want_digest_cache" = "no" ]; then echo " *WARNING* The digest-cache functionality is not enabled. This could leave the fwknopd server open to replay attacks! " fi fi fwknop-2.6.9/AUTHORS0000664000175000017500000000337312726140001011026 00000000000000Package: fwknop Maintainer: Damien Stuart , Michael Rash Bug reports: dstuart@dstuart.org, mbr@cipherdyne.org License: GPLv2, See the COPYING file Primary authors: Michael Rash - Creator of the fwknop project and wrote the original fwknop Perl implementation with contributions from open source developers. - Continued authorship and maintenance of fwknop code. Damien Stuart - Ported fwknop to C. - libfko, fwknop (client), fwknopd (server) - Continued authorship and maintenance of fwknop code. Significant contributions from individuals are listed in the CREDITS file, and a special thanks is due to: Jonathan Bennett (Major contributor, OpenWRT support, new Android client) Franck Joncourt (Major contributor and Debian package maintainer) Sebastien Jeanquier (Masters thesis analysis of Port Knocking and SPA) Hank Leininger (libfko error code patch, various architecture ideas) Max Kastanas (iPhone and Android clients) Gerry Reno (Android client development) Ozmart (various architecture ideas) Geoff Carstairs (various architecture ideas) Fernando Arnaboldi (vulnerability discovery and responsible disclosure) Sean Greven (FreeBSD port) Vlad Glagolev (OpenBSD port) Blair Zajac (PPC architecture fixes, various architecture ideas) Radostan Riedel (AppArmor policy) Copyright (C) 2009-2015 fwknop developers and contributors. For a full list of contributors, see the file 'CREDITS'. This file 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. fwknop-2.6.9/README0000664000175000017500000003670612726140001010644 00000000000000# fwknop - Single Packet Authorization ## Introduction fwknop implements an authorization scheme known as Single Packet Authorization (SPA) for strong service concealment. SPA requires only a single packet which is encrypted, non-replayable, and authenticated via an HMAC in order to communicate desired access to a service that is hidden behind a firewall in a default-drop filtering stance. The main application of SPA is to use a firewall to drop all attempts to connect to services such as SSH in order to make the exploitation of vulnerabilities (both 0-day and unpatched code) more difficult. Because there are no open ports, any service that is concealed by SPA naturally cannot be scanned for with Nmap. The fwknop project supports four different firewalls: firewalld and iptables on Linux systems, pf on OpenBSD, and ipfw on FreeBSD and Mac OS X. SPA is essentially next generation Port Knocking (PK), but solves many of the limitations exhibited by PK while retaining its core benefits. PK limitations include a general difficulty in protecting against replay attacks, asymmetric ciphers and HMAC schemes are not usually possible to reliably support, and it is trivially easy to mount a DoS attack against a PK server just by spoofing an additional packet into a PK sequence as it traverses the network (thereby convincing the PK server that the client doesn't know the proper sequence). All of these shortcomings are solved by SPA. At the same time, SPA hides services behind a default-drop firewall policy, acquires SPA data passively (usually via libpcap or other means), and implements standard cryptographic operations for SPA packet authentication and encryption/decryption. SPA packets generated by fwknop leverage HMAC for authenticated encryption in the encrypt-then-authenticate model. Although the usage of an HMAC is currently optional (enabled via the `--use-hmac` command line switch), it is highly recommended for three reasons: 1. Without an HMAC, cryptographically strong authentication is not possible with fwknop unless GnuPG is used, but even then an HMAC should still be applied. 2. An HMAC applied after encryption protects against cryptanalytic CBC-mode padding oracle attacks such as the Vaudenay attack and related trickery (like the more recent "Lucky 13" attack against SSL). 3. The code required by the fwknopd daemon to verify an HMAC is much more simplistic than the code required to decrypt an SPA packet, so an SPA packet without a proper HMAC isn't even sent through the decryption routines. The final reason above is why an HMAC should still be used even when SPA packets are encrypted with GnuPG due to the fact that SPA data is not sent through libgpgme functions unless the HMAC checks out first. GnuPG and libgpgme are relatively complex bodies of code, and therefore limiting the ability of a potential attacker to interact with this code through an HMAC operation helps to maintain a stronger security stance. Generating an HMAC for SPA communications requires a dedicated key in addition to the normal encryption key, and both can be generated with the `--key-gen` option. fwknop encrypts SPA packets either with the Rijndael block cipher or via GnuPG and associated asymmetric cipher. If the symmetric encryption method is chosen, then as usual the encryption key is shared between the client and server (see the `/etc/fwknop/access.conf` file for details). The actual encryption key used for Rijndael encryption is generated via the standard PBKDF1 key derivation algorithm, and CBC mode is set. If the GnuPG method is chosen, then the encryption keys are derived from GnuPG key rings. ## Use Cases People who use Single Packet Authorization (SPA) or its security-challenged cousin Port Knocking (PK) usually access SSHD running on the same system where the SPA/PK software is deployed. That is, a firewall running on a host has a default-drop policy against all incoming SSH connections so that SSHD cannot be scanned, but a SPA daemon reconfigures the firewall to temporarily grant access to a passively authenticated SPA client: ![alt text][SPA-basic-access-SSHD] [SPA-basic-access-SSHD]: /doc/images/SPA_basic.png "Basic SPA usage to access SSHD" fwknop supports the above, but also goes much further and makes robust usage of NAT (for iptables/firewalld firewalls). After all, *important* firewalls are usually gateways between networks as opposed to just being deployed on standalone hosts. NAT is commonly used on such firewalls (at least for IPv4 communications) to provide Internet access to internal networks that are on RFC 1918 address space, and also to allow external hosts access to services hosted on internal systems. Because fwknop integrates with NAT, SPA can be leveraged to access internal services *through* the firewall by users on the external Internet. Although this has plenty of applications on modern traditional networks, it also allows fwknop to support cloud computing environments such as Amazon's AWS: ![alt text][SPA-Amazon-AWS-cloud] [SPA-Amazon-AWS-cloud]: /doc/images/SPA_AWS_network_setup.png "SPA usage on Amazon AWS cloud environments" ## User Interface The official cross-platform fwknop client user interface *fwknop-gui* ([download](https://incomsystems.biz/fwknop-gui/), [github](https://github.com/oneru/fwknop-gui)) is developed by Jonathan Bennett. Most major client-side SPA modes are supported including NAT requests, HMAC and Rijndael keys (GnuPG is not yet supported), fwknoprc stanza saving, and more. Currently fwknop-gui runs on Linux, Mac OS X, and Windows - here is a screenshot from OS X: ![alt text][fwknop-gui-OS-X-screenshot] [fwknop-gui-OS-X-screenshot]: /doc/images/fwknop-gui-OSX.png "fwknop-gui on Mac OS X" Similarly, an updated [Android client](https://github.com/oneru/Fwknop2) is [available](https://incomsystems.biz/fwknop-gui/android.php) as well. ## Tutorial A comprehensive tutorial on fwknop can be found here: [http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html](http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html) ## Features The following is a complete list of features supported by the fwknop project: * Implements Single Packet Authorization around iptables and firewalld firewalls on Linux, ipfw firewalls on *BSD and Mac OS X, and PF on OpenBSD. * The fwknop client runs on Linux, Mac OS X, *BSD, and Windows under Cygwin. In addition, there is an [Android app](https://github.com/oneru/Fwknop2/releases) to generate SPA packets. * Supports both Rijndael and GnuPG methods for the encryption/decryption of SPA packets. * Supports HMAC authenticated encryption for both Rijndael and GnuPG. The order of operation is encrypt-then-authenticate to avoid various cryptanalytic problems. * Replay attacks are detected and thwarted by SHA-256 digest comparison of valid incoming SPA packets. Other digest algorithms are also supported, but SHA-256 is the default. * SPA packets are passively sniffed from the wire via libpcap. The fwknopd server can also acquire packet data from a file that is written to by a separate Ethernet sniffer (such as with `tcpdump -w `), from the iptables ULOG pcap writer, or directly via a UDP socket in `--udp-server` mode. * For iptables firewalls, ACCEPT rules added by fwknop are added and deleted (after a configurable timeout) from custom iptables chains so that fwknop does not interfere with any existing iptables policy that may already be loaded on the system. * Supports inbound NAT connections for authenticated SPA communications (iptables firewalls only for now). This means fwknop can be configured to create DNAT rules so that you can reach a service (such as SSH) running on an internal system on an RFC 1918 IP address from the open Internet. SNAT rules are also supported which essentially turns fwknopd into a [SPA-authenticating gateway](https://www.cipherdyne.org/blog/2015/04/nat-and-single-packet-authorization.html) to access the Internet from an internal network. * Multiple users are supported by the fwknop server, and each user can be assigned their own symmetric or asymmetric encryption key via the /etc/fwknop/access.conf file. * Automatic resolution of external IP address via [https://www.cipherdyne.org/cgi-bin/myip](https://www.cipherdyne.org/cgi-bin/myip) (this is useful when the fwknop client is run from behind a NAT device). Because the external IP address is encrypted within each SPA packet in this mode, Man-in-the-Middle (MITM) attacks where an inline device intercepts an SPA packet and only forwards it from a different IP in an effort to gain access are thwarted. * [Port randomization](https://www.cipherdyne.org/blog/2008/06/single-packet-authorization-with-port-randomization.html) is supported for the destination port of SPA packets as well as the port over which the follow-on connection is made via the iptables NAT capabilities. The later applies to forwarded connections to internal services and to access granted to local sockets on the system running fwknopd. * Integration with Tor (as described in this [DefCon 14](http://www.cipherdyne.org/fwknop/docs/talks/dc14_fwknop_slides.pdf) presentation). Note that because Tor uses TCP for transport, sending SPA packets through the Tor network requires that each SPA packet is sent over an established TCP connection, so technically this breaks the "single" aspect of "Single Packet Authorization". However, Tor provides anonymity benefits that can outweigh this consideration in some deployments. * Implements a versioned protocol for SPA communications, so it is easy to extend the protocol to offer new SPA message types and maintain backwards compatibility with older fwknop clients at the same time. * Supports the execution of shell commands on behalf of valid SPA packets. * The fwknop server can be configured to place multiple restrictions on inbound SPA packets beyond those enforced by encryption keys and replay attack detection. Namely, packet age, source IP address, remote user, access to requested ports, and more. * Bundled with fwknop is a comprehensive test suite that issues a series of tests designed to verify that both the client and server pieces of fwknop work properly. These tests involve sniffing SPA packets over the local loopback interface, building temporary firewall rules that are checked for the appropriate access based on the testing config, and parsing output from both the fwknop client and fwknopd server for expected markers for each test. Test suite output can easily be anonymized for communication to third parties for analysis. * fwknop was the first program to integrate port knocking with passive OS fingerprinting. However, Single Packet Authorization offers many security benefits beyond port knocking, so the port knocking mode of operation is generally deprecated. ## License The fwknop project is released as open source software under the terms of the **GNU General Public License (GPL v2)** or (at your option) any later version. The latest release can be found at [http://www.cipherdyne.org/fwknop/](http://www.cipherdyne.org/fwknop/) ## Current State This README file describes the present state of the fwknop project as of the 2.5 release made in July, 2013. At present, we have an implementation of the Firewall Knock Operator library; `libfko`, as well as the fwknop client and server applications. The library provides the API and back-end functionality for managing the Single Packet Authorization (SPA) data that the other fwknop components employ. It also can be used by other programs that need SPA functionality (see the `perl` directory for the FKO perl module as an example, and there are python bindings as well in the `python` directory). ## Upgrading If you are upgrading from an older version of fwknop (and this includes the original perl implementation as well), then you will want to read the following link to ensure a smooth transition to fwknop-2.5 or later: [http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html#backwards-compatibility](http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html#backwards-compatibility) ## Misc * Questions or comments about fwknop will be fielded on the [fwknop mailing list](http://lists.sourceforge.net/lists/listinfo/fwknop-discuss]). * For static analysis, fwknop uses the CLANG static analyzer and also the powerful Coverity Scan tool: ![](https://scan.coverity.com/projects/403/badge.svg) ## Building fwknop This distribution uses GNU autoconf for setting up the build. Please see the `INSTALL` file for the general basics on using autoconf. There are some "configure" options that are specific to fwknop. They are (extracted from *./configure --help*): --disable-client Do not build the fwknop client component. The default is to build the client. --disable-server Do not build the fwknop server component. The default is to build the server. --with-gpgme support for gpg encryption using libgpgme [default=check] --with-gpgme-prefix=PFX prefix where GPGME is installed (optional) --with-gpg=/path/to/gpg Specify path to the gpg executable that gpgme will use [default=check path] --with-firewalld=/path/to/firewalld Specify path to the firewalld executable [default=check path] --with-iptables=/path/to/iptables Specify path to the iptables executable [default=check path] --with-ipfw=/path/to/ipfw Specify path to the ipfw executable [default=check path] --with-pf=/path/to/pfctl Specify path to the pf executable [default=check path] --with-ipf=/path/to/ipf Specify path to the ipf executable [default=check path] Examples: ./configure --disable-client --with-firewalld=/bin/firewall-cmd ./configure --disable-client --with-iptables=/sbin/iptables --with-firewalld=no ## Notes ### Migrating from the Perl version of fwknop For those of you who are currently using the Perl version and plan to migrate to this version, there are some things to be aware of: * Not all of the features and functionality of the Perl-based fwknop were ported to this implementation. We felt it important to keep the C version as lean and lightweight as possible. Most of the omitted feature/functions (like email alerts) can be accomplished through other means (i.e. use an external script to monitor log files and alert based on appropriate log messages). * There are some differences in the fwknop configuration and access file directives and values. Some of these are fairly subtle. You should pay careful attention to the documentation and comments in those files. ### For fwknop developers If you are pulling this distribution from git, you should run the `autogen.sh` script to generate the autoconf files. If you get errors about missing directories or files, try running `autogen.sh` again. After that you can run the `autoreconf -i` when you want to regenerate the configuration. If, for some reason, autoreconf does not work for you, the `autogen.sh` script should suffice. The fwknop and fwknopd man page nroff sources are included in their respective directories (client and server). These nroff files are derived from the asciidoc sources in the 'docs' directory. See the README in docs for details. fwknop-2.6.9/test/0000775000175000017500000000000012726140436011023 500000000000000fwknop-2.6.9/test/run-test-suite.sh0000775000175000017500000000107012726140001014174 00000000000000#!/bin/sh # # The safeest way to run the fwknop test suite is by using this script - on # some platforms setting the LD_LIBRARY_PATH variable via the standard perl # perl %ENV hash does not seem to work properly when running in # --enable-perl-module-checks mode. This mode is used to test the perl FKO # libfko bindings. CentOS 6.3 was one platform where this seemed to be an # issue, but setting LD_LIBRARY_PATH on the command line manually causes things # to work properly. # LD_LIBRARY_PATH=../lib/.libs DYLD_LIBRARY_PATH=../lib/.libs ./test-fwknop.pl $@ exit fwknop-2.6.9/test/README0000664000175000017500000000271412726140001011613 00000000000000 This directory contains the fwknop test suite. After compiling the fwknop sources in the parent directory of test/ the test suite can be executed. One of the most comprehensive ways of executing the test suite is as follows: # ./run-test-suite.sh --enable-all This mode enables IP resolution tests, so you will need Internet access in this case. If this is not possible or desirable, then another comprehensive testing mode can be achieved with: # ./run-test-suite.sh --enable-recompile --enable-perl-module-checks --enable-distcheck Additional detail on the test suite (including --diff and --enable-valgrind modes) may be found in the fwknop tutorial available here: http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html#3.5 For even more comprehensive testing than the --enable-all switch, you can use --enable-complete. However, before doing this, you will want to install the 'libfiu' fault injection library (available here: http://blitiri.com.ar/p/libfiu/), and then compile fwknop with the 'test/configure_max_coverage.sh' script. This provides additional arguments to the 'configure' script to build fwknop with a maximal testing and code coverage stance. Once fwknop is compiled, then run: # ./run-test-suite.sh --enable-complete Note that in this mode the test suite will consume about close to 500MB of disk space in the test/output/ directory. The main source of this data consumption is the usage of the python SPA packet fuzzer 'test/spa_fuzzing.py'. fwknop-2.6.9/test/invalid3.key0000664000175000017500000000001212726140001013143 00000000000000127.0.0.1 fwknop-2.6.9/test/fko-python.py0000775000175000017500000000246312726140001013407 00000000000000#!/usr/bin/env python # # Import the Fko class and all constants. # from fko import * def main(): # Create an Fko instance with an empty context. # fko = Fko() # Set the HMAC digest algorithm # fko.hmac_type(FKO_HMAC_SHA512) # Set the SPA message (Note: Access request is default if not specified). # fko.spa_message("127.0.0.2,tcp/22") # Create the final SPA data message string. # fko.spa_data_final("testkey1", "testkey2") # print the spa message. # print "SPA packet data:", fko.spa_data() # Print some of the data: # print "Version:", fko.version() print "Timestamp:", fko.timestamp() print "Username:", fko.username() print "Encryption Type (value):", fko.encryption_type() print "Encryption Type (string):", fko.encryption_type_str() print "Encryption Mode (value):", fko.encryption_mode() print "Encryption Mode (string):", fko.encryption_mode_str() print "Digest Type (value):", fko.digest_type() print "Digest Type (string):", fko.digest_type_str() print "Digest:", fko.spa_digest() print "HMAC Type (value):", fko.hmac_type() print "HMAC Type (string):", fko.hmac_type_str() print "HMAC:", fko.get_spa_hmac() print "SPA Message:", fko.spa_message() if __name__ == "__main__": main() fwknop-2.6.9/test/local_spa.key0000664000175000017500000000012412726140001013373 00000000000000127.0.0.1: fwknoptest localhost: fwknoptest some.host.through.proxy.com: fwknoptest fwknop-2.6.9/test/hardening-check0000775000175000017500000001633312726140001013675 00000000000000#!/bin/sh # Report the hardening characterists of a set of binaries. # Copyright (C) 2009, 2010 Kees Cook # License: GPLv2 or newer skip_pie=no skip_stackprotector=no skip_fortify=no skip_relro=no skip_bindnow=no quiet=no while getopts psfrbq opt do case "$opt" in p) skip_pie=yes ;; s) skip_stackprotector=yes ;; f) skip_fortify=yes ;; r) skip_relro=yes ;; b) skip_bindnow=yes ;; q) quiet=yes ;; [?]) echo >&2 "Usage: $0 [-p] [-s] [-f] [-r] [-b] file ..." echo >&2 " -p Do not require PIE binary" echo >&2 " -s Do not require stack protector" echo >&2 " -f Do not require fortify source" echo >&2 " -r Do not require RELRO markings" echo >&2 " -b Do not require BIND_NOW markings" echo >&2 " -q Only report failures" exit 1 ;; esac done shift $(( $OPTIND-1 )) overall=0 rc=0 report="" good () { if [ "$quiet" != "yes" ]; then report="$report $1" fi } bad () { report="$report $1" rc=1 } for file in "$@" do rc=0 report="$file:" PROG_REPORT=$(LANG=C readelf -lW "$file") if [ -z "$PROG_REPORT" ]; then rc=1; continue; fi DYN_REPORT=$(LANG=C readelf -dW "$file" 2>/dev/null) RELOC_REPORT=$(LANG=C readelf -sW "$file" 2>/dev/null | \ egrep ' FUNC .* UND ' | \ sed -re 's/ \([0-9]+\)$//g; s/.* //g; s/@.*//g;') # PIE # First, verify this is an executable, not a library. This seems to be # best seen by checking for the PHDR program header. name=" Position Independent Executable" if echo "$PROG_REPORT" | awk '{print $1}' | grep -q '^PHDR$'; then if echo "$PROG_REPORT" | grep -q '^Elf file type is DYN '; then good "$name: yes" else msg="$name: no, normal executable!" if [ "$skip_pie" = "yes" ]; then good "$msg (ignored)" else bad "$msg" fi fi else if echo "$PROG_REPORT" | grep -q '^Elf file type is DYN '; then good "$name: no, regular shared library (ignored)" else bad "$name: not a known ELF type!?" fi fi # Stack-protected name=" Stack protected" if echo "$RELOC_REPORT" | grep -q '^__stack_chk_fail$'; then good "$name: yes" else msg="$name: no, not found!" if [ "$skip_stackprotector" = "yes" ]; then good "$msg (ignored)" else bad "$msg" fi fi if echo "$RELOC_REPORT" | grep -q '^__stack_chk_fail$'; then good "$name: yes" else ### for OpenBSD if echo "$RELOC_REPORT" | grep -q '^__stack_smash_handler$'; then good "$name: yes" else msg="$name: no, not found!" if [ "$skip_stackprotector" = "yes" ]; then good "$msg (ignored)" else bad "$msg" fi fi fi # Fortified name=" Fortify Source functions" if echo "$RELOC_REPORT" | grep -q '^__.*_chk$'; then good "$name: yes" else msg="$name: no, not found!" if [ "$skip_fortify" = "yes" ]; then good "$msg (ignored)" else bad "$msg" fi fi # Format # unfortunately, I haven't thought of a way to test for this after # compilation. What it really needs is a lintian-like check that # reviews the build logs and looks for the warnings, or that the # argument is changed to use -Werror,format-security to stop the build. # RELRO name=" Read-only relocations" if echo "$PROG_REPORT" | awk '{print $1}' | grep -q '^GNU_RELRO$'; then good "$name: yes" else msg="$name: no, not found!" if [ "$skip_relro" = "yes" ]; then good "$msg (ignored)" else bad "$msg" fi fi # BIND_NOW name=" Immediate binding" if echo "$DYN_REPORT" | awk '{print $2}' | grep -q '^(BIND_NOW)$'; then good "$name: yes" else msg="$name: no, not found!" if [ "$skip_bindnow" = "yes" ]; then good "$msg (ignored)" else bad "$msg" fi fi if [ "$quiet" != "yes" ] || [ $rc -ne 0 ]; then echo "$report" fi if [ $rc -ne 0 ]; then overall=$rc fi done exit $overall :<<=cut =pod =head1 NAME hardening-check - check binaries for security hardening features =head1 SYNOPSIS Examine a given set of ELF binaries and check for several security hardening features, failing if they are not all found. =head1 DESCRIPTION This utility checks a given list of ELF binaries for several security hardening features that can be compiled into an executable. These features are: =over 8 =item B This indicates that the executable was built in such a way (PIE) that the "text" section of the program can be relocated in memory. To take full advantage of this feature, the executing kernel must support text Address Space Layout Randomization (ASLR). =item B This indicates that the executable was compiled with the L option B<-fstack-protector>. The program will be resistant to have its stack overflowed. =item B This indicates that the executable was compiled with B<-D_FORTIFY_SOURCE=2> and B<-O2> or higher. This causes certain unsafe glibc functions with their safer counterparts (e.g. strncpy instead of strcpy). =item B This indicates that the executable was build with B<-Wl,-z,relro> to have ELF markings (RELRO) that ask the runtime linker to mark any regions of the relocation table as "read-only" if they were resolved before execution begins. This reduces the possible areas of memory in a program that can be used by an attacker that performs a successful memory corruption exploit. =item B This indicates that the executable was built with B<-Wl,-z,now> to have ELF markings (BIND_NOW) that ask the runtime linker to resolve all relocations before starting program execution. When combined with RELRO above, this further reduces the regions of memory available to memory corruption attacks. =back =head1 OPTIONS =over 8 =item B<-p> No not require that the checked binaries be built as PIE. =item B<-s> No not require that the checked binaries be built with the stack protector. =item B<-f> No not require that the checked binaries be built with Fority Source. =item B<-r> No not require that the checked binaries be built with RELRO. =item B<-b> No not require that the checked binaries be built with BIND_NOW. =item B<-q> Only report failures. =back =head1 RETURN VALUE When all checked binaries have all checkable hardening features detected, this program will finish with an exit code of 0. If any check fails, the exit code with be 1. Individual checks can be disabled via command line options. =head1 AUTHOR Kees Cook =head1 COPYRIGHT AND LICENSE Copyright 2009 Kees Cook . 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; version 2 or later. =head1 SEE ALSO L, L =cut fwknop-2.6.9/test/test-fwknop.pl0000775000175000017500000105663512726140001013570 00000000000000#!/usr/bin/perl -w # # This is the main driver program for the fwknop test suite. Test definitions # are imported from the tests/ directory. # use Cwd; use File::Copy; use File::Path; use IO::Socket; use Data::Dumper; use Getopt::Long 'GetOptions'; use Getopt::Long 'GetOptionsFromString'; use strict; use POSIX; #==================== config ===================== my $logfile = 'test.log'; our $local_key_file = 'local_spa.key'; our $long_key_file = 'long_spa.key'; ### > 16 bytes our $local_spa_key = 'fwknoptest'; our $local_hmac_key_file = 'local_hmac_spa.key'; my $output_dir = 'output'; our $conf_dir = 'conf'; my $run_dir = 'run'; our $run_tmp_dir_top = 'runtmp'; our $run_tmp_dir = "$run_tmp_dir_top/subdir1/subdir2"; my $cmd_out_tmp = 'cmd.out'; my $server_cmd_tmp = 'server_cmd.out'; my $openssl_cmd_tmp = 'openssl_cmd.out'; my $data_tmp = 'data.tmp'; my $key_tmp = 'key.tmp'; my $enc_save_tmp = 'openssl_save.enc'; my $test_suite_path = 'test-fwknop.pl'; my $username = ''; our $access_include_dir = "$conf_dir/access-include"; my $gpg_dirs_tar = 'gpg_dirs.tar.gz'; my $access_include_dirs_tar = 'access-include.tar.gz'; our $gpg_client_home_dir = "$conf_dir/client-gpg"; our $gpg_client_home_dir_no_pw = "$conf_dir/client-gpg-no-pw"; our $gpg_client_4096_bit_key_no_pw = "$conf_dir/client-gpg-large-no-pw"; our $gpg_client_subkey_no_pw = "$conf_dir/client-gpg-subkeys-no-pw"; our $replay_pcap_file = "$conf_dir/spa_replay.pcap"; our $multi_pkts_pcap_file = "$conf_dir/multi_pkts.pcap"; our $fcs_pcap_file = "$conf_dir/fcs_spa.pcap"; our $spa_over_http_pcap_file = "$conf_dir/spa_over_http.pcap"; our $spa_x_forwarded_for_pcap_file = "$conf_dir/spa_x_forwarded_for.pcap"; our $lib_dir = '../lib/.libs'; our $default_digest_file = "$run_dir/digest.cache"; our $default_pid_file = "$run_dir/fwknopd.pid"; our $tmp_rc_file = "$run_dir/fwknoprc"; our $rewrite_rc_file = "$run_dir/rewrite_fwknoprc"; our $rewrite_fwknopd_conf = "$run_dir/rewrite_fwknopd.conf"; our $rewrite_access_conf = "$run_dir/rewrite_access.conf"; our $rewrite_include_keys_access_conf = "$run_dir/rewrite_include_keys_access.conf"; our $rewrite_digest_file = "$run_dir/rewrite_digest.cache"; our $save_rc_file = "$run_dir/save_fwknoprc"; our $tmp_pkt_file = "$run_dir/tmp_spa.pkt"; our $tmp_args_file = "$run_dir/args.save"; our $fwknopCmd = '../client/.libs/fwknop'; our $fwknopdCmd = '../server/.libs/fwknopd'; our $gpg_server_key = '361BBAD4'; our $gpg_client_key = '6A3FAD56'; our $gpg_server_key2 = 'EF5AF06A'; our $gpg_client_large_key = '31415ADE'; our $gpg_server_large_key = '40051F51'; #gpg --homedir ./client-gpg-subkeys-no-pw/ --list-keys #./client-gpg-subkeys-no-pw//pubring.gpg #--------------------------------------- #pub 4096R/31415ADE 2015-03-23 #uid fwknop project (client multi subkeys, TESTING ONLY) #sub 4096R/82E1000B 2015-03-23 #sub 2048R/8377E3D8 2015-03-25 #sub 2048R/9CF38326 2015-03-25 our $gpg_client_subkey = '9CF38326'; ### last subkey in the keyring as shown above, ### and GPG_REMOTE_ID must match in access.conf our $loopback_ip = '127.0.0.1'; our $fake_ip = '127.0.0.2'; our $spoof_ip = '1.2.3.4'; our $internal_nat_host = '192.168.1.2'; our $force_nat_host = '192.168.1.123'; our $force_nat_host2 = '123.4.4.4'; our $force_nat_host3 = '8.1.2.3'; our $force_snat_host = '33.3.3.3'; our $default_spa_port = 62201; our $non_std_spa_port = 12345; our $invalid_key_file = 'invalid.key'; our $invalid_key_file2 = 'invalid2.key'; our $invalid_key_file3 = 'invalid2.key'; our $FW_TYPE = 'iptables'; ### default to iptables our $FW_PREFIX = 'IPT'; our $fw_conf_prefix = 'ipt'; my $prefer_iptables = 0; my $fw_bin = ''; my $fw_bin_and_prefix = ''; our $spoof_user = 'testuser'; my $valgrind_cov_dir = 'valgrind-coverage'; my $lcov_results_dir = 'lcov-results'; my $perl_mod_fko_dir = 'FKO'; my $python_fko_dir = 'python_fko'; my $python_script = 'fko-python.py'; my $python_path = ''; our $cmd_exec_test_file = '/tmp/fwknoptest'; my $default_key = 'fwknoptest'; my $asan_dir = 'asan'; my $tests_dir = 'tests'; our $rerun_failed_mode = 0; my @test_files = ( "$tests_dir/configure_args.pl", "$tests_dir/build_security.pl", "$tests_dir/preliminaries.pl", "$tests_dir/code_structure.pl", "$tests_dir/basic_operations.pl", "$tests_dir/cunit_tests.pl", "$tests_dir/rijndael.pl", "$tests_dir/rijndael_cmd_exec.pl", "$tests_dir/rijndael_hmac_cmd_exec.pl", "$tests_dir/rijndael_hmac_cmd_open_close.pl", "$tests_dir/rijndael_replay_attacks.pl", "$tests_dir/rijndael_fuzzing.pl", "$tests_dir/rijndael_backwards_compatibility.pl", "$tests_dir/rijndael_hmac.pl", "$tests_dir/rijndael_hmac_fuzzing.pl", "$tests_dir/fault_injection.pl", "$tests_dir/afl_fuzzing.pl", "$tests_dir/address_sanitizer.pl", "$tests_dir/os_compatibility.pl", "$tests_dir/perl_FKO_module.pl", "$tests_dir/python_fko.pl", "$tests_dir/gpg_no_pw.pl", "$tests_dir/gpg_no_pw_hmac.pl", "$tests_dir/gpg.pl", "$tests_dir/gpg_hmac.pl", ); #================== end config =================== our @build_security_client = (); ### imported from tests/build_security.pl our @build_security_server = (); our @build_security_libfko = (); our @preliminaries = (); ### from tests/preliminaries.pl our @code_structure_errstr = (); ### from tests/code_structure.pl (may include Coccinelle matches eventually) our @configure_args = (); ### from tests/configure_args.pl our @basic_operations = (); ### from tests/basic_operations.pl our @cunit_tests = (); ### from tests/cunit_tests.pl our @rijndael = (); ### from tests/rijndael.pl our @rijndael_cmd_exec = (); ### from tests/rijndael_cmd_exec.pl our @rijndael_hmac_cmd_exec = (); ### from tests/rijndael_hmac_cmd_exec.pl our @rijndael_hmac_cmd_open_close = (); ### from tests/rijndael_hmac_cmd_open_close.pl our @rijndael_replay_attacks = (); ### from tests/rijndael_replay_attacks.pl our @rijndael_hmac = (); ### from tests/rijndael_hmac.pl our @rijndael_fuzzing = (); ### from tests/rijndael_fuzzing.pl our @rijndael_hmac_fuzzing = (); ### from tests/rijndael_hmac_fuzzing.pl our @fault_injection = (); ### from tests/fault_injection.pl our @afl_fuzzing = (); ### from tests/alf_fuzzing.pl our @address_sanitizer = (); ### from tests/address_sanitizer.pl our @gpg_no_pw = (); ### from tests/gpg_now_pw.pl our @gpg_no_pw_hmac = (); ### from tests/gpg_now_pw_hmac.pl our @gpg = (); ### from tests/gpg.pl our @gpg_hmac = (); ### from tests/gpg_hmac.pl our @perl_FKO_module = (); ### from tests/perl_FKO_module.pl our @python_fko = (); ### from tests/python_fko.pl our @os_compatibility = (); ### from tests/os_compatibility.pl our @rijndael_backwards_compatibility = (); ### from tests/rijndael_backwards_compatibility.pl my $passed = 0; my $failed = 0; my $executed = 0; my $test_include = ''; my @tests_to_include = (); my $test_exclude = ''; my @tests_to_exclude = (); my %include_tracking = (); my %exclude_tracking = (); my $do_crash_check = 1; my %valgrind_flagged_fcns = (); my %valgrind_flagged_fcns_unique = (); my $previous_valgrind_coverage_dir = ''; our $uniq_keys = 100; my $test_limit = 0; my $list_mode = 0; my $diff_dir1 = ''; my $diff_dir2 = ''; our $loopback_intf = ''; my $default_pkt_tries = 20; my $send_all_loop_once = 0; my $detect_server_loop_once = 0; my $default_server_tries = 10; my $anonymize_results = 0; my $orig_config_args = ''; my $curr_test_file = 'init'; my $init_file = $curr_test_file; my $config_log = '../config.log'; my $tarfile = 'test_fwknop.tar.gz'; our $key_gen_file = "$output_dir/key_gen"; our $verbose_str = "--verbose --verbose"; my $gdb_test_file = ''; our $resolve_url = 'http://www.cipherdyne.org/cgi-bin/myip/'; ### with trailing slash for test coverage our $resolve_url_with_port = 'http://www.cipherdyne.org:80/cgi-bin/myip'; my $fuzzing_pkts_file = '../perl/FKO/t/fuzzing_spa_packets'; my $fuzzing_pkts_append = 0; my $fuzzing_key = 'testtest'; my $fuzzing_num_pkts = 0; my $fuzzing_test_tag = ''; my $fuzzing_class = 'bogus data'; my %fuzzing_spa_packets = (); my $total_fuzzing_pkts = 0; our $sudo_access_conf = "$run_dir/sudo_access.conf"; my $sudo_conf_testing = ''; my $server_test_file = ''; my $client_only_mode = 0; my $server_only_mode = 0; my $enable_cores_pattern_mode = 0; my $cores_pattern_sh = './generate_cores.sh'; my $enable_fault_injection = 0; my $disable_fault_injection = 0; my $enable_valgrind = 0; my $disable_valgrind = 0; my $enable_valgrind_gen_suppressions = 0; my $valgrind_disable_suppressions = 0; my $valgrind_disable_child_silent = 0; my $valgrind_suppressions_file = cwd() . '/valgrind_suppressions'; our $valgrind_str = ''; my $asan_mode = 0; my $ubsan_mode = 0; my %cached_fw_policy = (); my $cpan_valgrind_mod = 'Test::Valgrind'; my %prev_valgrind_cov = (); my %prev_valgrind_file_titles = (); my $libfko_hdr_file = '../lib/fko.h'; my $libfko_errstr_file = '../lib/fko_error.c'; my $perl_libfko_constants_file = '../perl/FKO/lib/FKO_Constants.pl'; my $python_libfko_constants_file = '../python/fko.py'; our $fko_wrapper_dir = 'fko-wrapper'; our $wrapper_exec_script = 'run.sh'; our $wrapper_exec_script_valgrind = 'run_valgrind.sh'; my $fuzz_spa_payloads_file = $fko_wrapper_dir . '/fuzz_spa_payloads'; our $send_fuzz_payloads_file = $fko_wrapper_dir . '/send_spa_payloads'; my $python_spa_packet = ''; my $pkts_file = ''; my $enable_fuzzing_interfaces_tests = 0; my $enable_client_ip_resolve_test = 0; my $enable_all = 0; my $enable_complete = 0; my $saved_last_results = 0; my $diff_mode = 0; my $enc_dummy_key = 'A'x8; my $fko_obj = (); my $enable_recompilation_warnings_check = 0; my $enable_configure_args_checks = 0; my $enable_profile_coverage_check = 0; my $enable_profile_coverage_init = 0; my $profile_gen_report_sh = './gen-coverage-report.sh'; my $profile_init_sh = './init-lcov.sh'; my $profile_rm_files_sh = './rm-coverage-files.sh'; my $do_profile_init = 0; my $enable_make_distcheck = 0; my $enable_perl_module_checks = 0; my $enable_perl_module_fuzzing_spa_pkt_generation = 0; my $enable_python_module_checks = 0; my $enable_openssl_compatibility_tests = 0; my $enable_cunit_tests = 0; my $openssl_success_ctr = 0; my $openssl_failure_ctr = 0; my $openssl_ctr = 0; my $openssl_hmac_success_ctr = 0; my $openssl_hmac_failure_ctr = 0; my $openssl_hmac_ctr = 0; my $openssl_hmac_hexkey_supported = 0; my $fuzzing_success_ctr = 0; my $fuzzing_failure_ctr = 0; my $fuzzing_ctr = 0; my $include_permissions_warnings = 0; my $lib_view_cmd = ''; my $git_path = ''; our $valgrind_path = ''; our $fiu_run_path = ''; our $sudo_path = ''; our $gcov_path = ''; my $touch_path = ''; my $lcov_path = ''; my $coverage_diff_path = 'coverage_diff.py'; my $genhtml_path = ''; our $killall_path = ''; our $pgrep_path = ''; our $pkill_path = ''; our $openssl_path = ''; our $base64_path = ''; our $pinentry_fail = 0; our $perl_path = ''; our $prove_path = ''; our $ifconfig_path = ''; our $platform = ''; our $help = 0; our $YES = 1; our $NO = 0; our $IGNORE = 2; our $PRINT_LEN = 68; our $USE_PREDEF_PKTS = 1; our $READ_PKTS_FROM_FILE = 4; our $USE_CLIENT = 2; our $USE_PCAP_FILE = 3; our $REQUIRED = 1; our $OPTIONAL = 0; our $OPTIONAL_NUMERIC = 2; our $NEW_RULE_REQUIRED = 1; our $REQUIRE_NO_NEW_RULE = 2; our $NEW_RULE_REMOVED = 1; our $REQUIRE_NO_NEW_REMOVED = 2; our $MATCH_ANY = 1; our $MATCH_ALL = 2; our $REQUIRE_SUCCESS = 0; our $REQUIRE_FAILURE = 1; my $TIMESTAMP_DIFF = 2; my $ENC_RIJNDAEL = 1; my $ENC_GPG = 2; our $LINUX = 1; our $FREEBSD = 2; our $MACOSX = 3; our $OPENBSD = 4; our $start_time = time(); my $SERVER_RECEIVE_CHECK = 1; my $NO_SERVER_RECEIVE_CHECK = 2; my $APPEND_RESULTS = 1; my $NO_APPEND_RESULTS = 2; my %sigs = ( 'SIGHUP' => 1, 'SIGINT' => 2, 'SIGUSR1' => 10, 'SIGUSR2' => 12, 'SIGTSTP' => 20, ); my @sigs_ordered = ( 'SIGHUP', 'SIGINT', 'SIGUSR1', 'SIGUSR2', 'SIGTSTP', ); my $ip_re = qr|(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}|; ### IPv4 my @args_cp = @ARGV; exit 1 unless GetOptions( 'Anonymize-results' => \$anonymize_results, 'fwknop-path=s' => \$fwknopCmd, 'fwknopd-path=s' => \$fwknopdCmd, 'lib-dir=s' => \$lib_dir, ### for LD_LIBRARY_PATH 'loopback-intf=s' => \$loopback_intf, 'test-include=s' => \$test_include, 'include=s' => \$test_include, ### synonym 'test-exclude=s' => \$test_exclude, 'exclude=s' => \$test_exclude, ### synonym 'enable-perl-module-checks' => \$enable_perl_module_checks, 'enable-perl-module-pkt-generation' => \$enable_perl_module_fuzzing_spa_pkt_generation, 'enable-python-module-checks' => \$enable_python_module_checks, 'fuzzing-pkts-file=s' => \$fuzzing_pkts_file, 'fuzzing-pkts-append' => \$fuzzing_pkts_append, 'fuzzing-test-tag=s' => \$fuzzing_test_tag, 'fuzzing-class=s' => \$fuzzing_class, 'prefer-iptables' => \$prefer_iptables, 'enable-recompile-check' => \$enable_recompilation_warnings_check, 'enable-configure-args-checks' => \$enable_configure_args_checks, 'enable-profile-coverage-check' => \$enable_profile_coverage_check, 'enable-cores-pattern' => \$enable_cores_pattern_mode, 'enable-profile-coverage-init' => \$enable_profile_coverage_init, 'enable-ip-resolve' => \$enable_client_ip_resolve_test, 'enable-distcheck' => \$enable_make_distcheck, 'enable-dist-check' => \$enable_make_distcheck, ### synonym 'enable-openssl-checks' => \$enable_openssl_compatibility_tests, 'enable-cunit' => \$enable_cunit_tests, 'gdb-test=s' => \$gdb_test_file, 'List-mode' => \$list_mode, 'test-limit=i' => \$test_limit, 'enable-fault-injection' => \$enable_fault_injection, 'disable-fault-injection' => \$disable_fault_injection, 'enable-valgrind' => \$enable_valgrind, 'disable-valgrind' => \$disable_valgrind, 'valgrind-disable-suppressions' => \$valgrind_disable_suppressions, 'valgrind-disable-child-silent' => \$valgrind_disable_child_silent, 'enable-all' => \$enable_all, 'enable-complete' => \$enable_complete, 'enable-fuzzing-interfaces-tests' => \$enable_fuzzing_interfaces_tests, 'valgrind-path=s' => \$valgrind_path, 'valgrind-suppression-file' => \$valgrind_suppressions_file, 'enable-valgrind-gen-suppressions' => \$enable_valgrind_gen_suppressions, ### can set the following to "output.last/valgrind-coverage" if ### a full test suite run has already been executed with --enable-valgrind 'valgrind-prev-cov-dir=s' => \$previous_valgrind_coverage_dir, 'openssl-path=s' => \$openssl_path, 'fiu-run-path=s' => \$fiu_run_path, 'output-dir=s' => \$output_dir, 'cmd-verbose=s' => \$verbose_str, 'client-only-mode' => \$client_only_mode, 'server-only-mode' => \$server_only_mode, 'rerun-failed-mode' => \$rerun_failed_mode, 'diff' => \$diff_mode, 'diff-dir1=s' => \$diff_dir1, 'diff-dir2=s' => \$diff_dir2, 'help' => \$help ); &usage() if $help; our @last_logfile = (); if ($rerun_failed_mode) { unless (open (RE, "<", "test.log")) { # check for test.log die "[*] Can't find test.log"; } while () { push @last_logfile, $_; } close RE; my $arg_line = ""; for my $line (@last_logfile) { if ($line =~ /args:(.+)/) { $arg_line = $1; last; } } unless ($arg_line) { die "[*] Can't find arguments"; } system("cp -f test.log test.log.bak"); my $ret = 0; my $leftovers = ""; ($ret, $leftovers) = GetOptionsFromString( $arg_line, 'fwknop-path=s' => \$fwknopCmd, 'fwknopd-path=s' => \$fwknopdCmd, 'lib-dir=s' => \$lib_dir, ### for LD_LIBRARY_PATH 'loopback-intf=s' => \$loopback_intf, 'test-include=s' => \$test_include, 'include=s' => \$test_include, ### synonym 'test-exclude=s' => \$test_exclude, 'exclude=s' => \$test_exclude, ### synonym 'enable-perl-module-checks' => \$enable_perl_module_checks, 'enable-perl-module-pkt-generation' => \$enable_perl_module_fuzzing_spa_pkt_generation, 'enable-python-module-checks' => \$enable_python_module_checks, 'fuzzing-pkts-file=s' => \$fuzzing_pkts_file, 'fuzzing-pkts-append' => \$fuzzing_pkts_append, 'fuzzing-test-tag=s' => \$fuzzing_test_tag, 'fuzzing-class=s' => \$fuzzing_class, 'prefer-iptables' => \$prefer_iptables, 'enable-recompile-check' => \$enable_recompilation_warnings_check, 'enable-configure-args-checks' => \$enable_configure_args_checks, 'enable-profile-coverage-check' => \$enable_profile_coverage_check, 'enable-cores-pattern' => \$enable_cores_pattern_mode, 'enable-profile-coverage-init' => \$enable_profile_coverage_init, 'enable-ip-resolve' => \$enable_client_ip_resolve_test, 'enable-distcheck' => \$enable_make_distcheck, 'enable-dist-check' => \$enable_make_distcheck, ### synonym 'enable-openssl-checks' => \$enable_openssl_compatibility_tests, 'enable-cunit' => \$enable_cunit_tests, 'gdb-test=s' => \$gdb_test_file, 'List-mode' => \$list_mode, 'test-limit=i' => \$test_limit, 'enable-fault-injection' => \$enable_fault_injection, 'disable-fault-injection' => \$disable_fault_injection, 'enable-valgrind' => \$enable_valgrind, 'disable-valgrind' => \$disable_valgrind, 'valgrind-disable-suppressions' => \$valgrind_disable_suppressions, 'valgrind-disable-child-silent' => \$valgrind_disable_child_silent, 'enable-all' => \$enable_all, 'enable-complete' => \$enable_complete, 'enable-fuzzing-interfaces-tests' => \$enable_fuzzing_interfaces_tests, 'valgrind-path=s' => \$valgrind_path, 'valgrind-suppression-file' => \$valgrind_suppressions_file, 'enable-valgrind-gen-suppressions' => \$enable_valgrind_gen_suppressions, ### can set the following to "output.last/valgrind-coverage" if ### a full test suite run has already been executed with --enable-valgrind 'valgrind-prev-cov-dir=s' => \$previous_valgrind_coverage_dir, 'openssl-path=s' => \$openssl_path, 'fiu-run-path=s' => \$fiu_run_path, 'output-dir=s' => \$output_dir, 'cmd-verbose=s' => \$verbose_str, 'client-only-mode' => \$client_only_mode, 'server-only-mode' => \$server_only_mode, 'diff' => \$diff_mode, 'diff-dir1=s' => \$diff_dir1, 'diff-dir2=s' => \$diff_dir2 ); } &os_fw_detect(); ### main configuration file paths our %cf = ( "${fw_conf_prefix}_nat" => "$conf_dir/${fw_conf_prefix}_nat_fwknopd.conf", "${fw_conf_prefix}_nat_disable_aging" => "$conf_dir/${fw_conf_prefix}_nat_disable_aging_fwknopd.conf", "${fw_conf_prefix}_snat" => "$conf_dir/${fw_conf_prefix}_snat_fwknopd.conf", "${fw_conf_prefix}_snat_no_translate_ip" => "$conf_dir/${fw_conf_prefix}_snat_no_translate_ip_fwknopd.conf", "${fw_conf_prefix}_snat_translate_ip" => "$conf_dir/${fw_conf_prefix}_snat_translate_ip_fwknopd.conf", 'def' => "$conf_dir/default_fwknopd.conf", 'def_access' => "$conf_dir/default_access.conf", 'portrange_filter' => "$conf_dir/portrange_fwknopd.conf", 'hmac_access' => "$conf_dir/hmac_access.conf", 'include1_hmac_access' => "$conf_dir/include1_hmac_access.conf", 'include2_hmac_access' => "$conf_dir/include2_hmac_access.conf", 'include_r1_hmac_access' => "$conf_dir/include_r1_hmac_access.conf", 'include_r2_hmac_access' => "$conf_dir/include_r2_hmac_access.conf", 'include_m1_hmac_access' => "$conf_dir/include_m1_hmac_access.conf", 'include_def_hmac_access' => "$conf_dir/include_def_hmac_access.conf", 'include_keys1_hmac_access' => "$conf_dir/include_keys1_hmac_access.conf", 'prepend_fwknopd' => "$conf_dir/prepend_fwknopd.conf", "${fw_conf_prefix}_no_nat_dns_fwknopd" => "$conf_dir/${fw_conf_prefix}_no_nat_dns_fwknopd.conf", 'hmac_cmd_access' => "$conf_dir/hmac_cmd_access.conf", 'hmac_cmd_setuid_access' => "$conf_dir/hmac_cmd_setuid_access.conf", 'hmac_cmd_giduid_access' => "$conf_dir/hmac_cmd_giduid_access.conf", 'hmac_get_key_access' => "$conf_dir/hmac_get_key_access.conf", 'hmac_equal_keys_access' => "$conf_dir/hmac_equal_keys_access.conf", 'hmac_no_b64_access' => "$conf_dir/hmac_no_b64_access.conf", 'hmac_md5_access' => "$conf_dir/hmac_md5_access.conf", 'hmac_md5_short_key_access' => "$conf_dir/hmac_md5_short_key_access.conf", 'hmac_md5_long_key_access' => "$conf_dir/hmac_md5_long_key_access.conf", 'hmac_sha1_access' => "$conf_dir/hmac_sha1_access.conf", 'hmac_sha1_short_key_access' => "$conf_dir/hmac_sha1_short_key_access.conf", 'hmac_sha1_long_key_access' => "$conf_dir/hmac_sha1_long_key_access.conf", 'hmac_sha256_access' => "$conf_dir/hmac_sha256_access.conf", 'hmac_sha3_256_access' => "$conf_dir/hmac_sha3_256_access.conf", 'hmac_sha256_digest1_mismatch_access' => "$conf_dir/hmac_sha256_digest1_mismatch_access.conf", 'hmac_sha256_digest2_mismatch_access' => "$conf_dir/hmac_sha256_digest2_mismatch_access.conf", 'hmac_sha256_digest3_mismatch_access' => "$conf_dir/hmac_sha256_digest3_mismatch_access.conf", 'hmac_sha256_digest4_mismatch_access' => "$conf_dir/hmac_sha256_digest4_mismatch_access.conf", 'hmac_sha256_short_key_access' => "$conf_dir/hmac_sha256_short_key_access.conf", 'hmac_sha256_long_key_access' => "$conf_dir/hmac_sha256_long_key_access.conf", 'hmac_sha384_access' => "$conf_dir/hmac_sha384_access.conf", 'hmac_sha384_short_key_access' => "$conf_dir/hmac_sha384_short_key_access.conf", 'hmac_sha384_long_key_access' => "$conf_dir/hmac_sha384_long_key_access.conf", 'hmac_sha512_access' => "$conf_dir/hmac_sha512_access.conf", 'hmac_sha3_512_access' => "$conf_dir/hmac_sha3_512_access.conf", 'hmac_sha512_short_key_access' => "$conf_dir/hmac_sha512_short_key_access.conf", 'hmac_sha512_short_key2_access' => "$conf_dir/hmac_sha512_short_key2_access.conf", 'hmac_sha512_long_key_access' => "$conf_dir/hmac_sha512_long_key_access.conf", 'hmac_simple_keys_access' => "$conf_dir/hmac_simple_keys_access.conf", 'hmac_invalid_type_access' => "$conf_dir/hmac_invalid_type_access.conf", 'hmac_cygwin_access' => "$conf_dir/hmac_no_b64_cygwin_access.conf", 'hmac_cmd_open_close_cycle_access' => "$conf_dir/hmac_cmd_open_close_cycle_access.conf", 'hmac_cmd_open_close_cycle_access2' => "$conf_dir/hmac_cmd_open_close_cycle_access2.conf", 'hmac_cmd_open_close_cycle_access3' => "$conf_dir/hmac_cmd_open_close_cycle_access3.conf", 'hmac_cmd_open_close_cycle_access4' => "$conf_dir/hmac_cmd_open_close_cycle_access4.conf", 'hmac_cmd_open_close_cycle_access5' => "$conf_dir/hmac_cmd_open_close_cycle_access5.conf", 'hmac_cmd_open_close_cycle_access6' => "$conf_dir/hmac_cmd_open_close_cycle_access6.conf", 'hmac_cmd_open_close_cycle_access7' => "$conf_dir/hmac_cmd_open_close_cycle_access7.conf", 'hmac_cmd_open_close_cycle_access8' => "$conf_dir/hmac_cmd_open_close_cycle_access8.conf", 'hmac_cmd_open_close_multi_cycle_access' => "$conf_dir/hmac_cmd_open_close_multi_cycle_access.conf", 'spa_destination' => "$conf_dir/destination_rule_fwknopd.conf", "${fw_conf_prefix}_spa_dst_snat" => "$conf_dir/${fw_conf_prefix}_spa_dst_snat_fwknopd.conf", 'hmac_spa_destination_access' => "$conf_dir/hmac_spa_destination_access.conf", 'hmac_spa_destination2_access' => "$conf_dir/hmac_spa_destination2_access.conf", 'hmac_spa_destination3_access' => "$conf_dir/hmac_spa_destination3_access.conf", 'hmac_spa_destination4_access' => "$conf_dir/hmac_spa_destination4_access.conf", 'hmac_spa_destination5_access' => "$conf_dir/hmac_spa_destination5_access.conf", 'exp_access' => "$conf_dir/expired_stanza_access.conf", 'future_exp_access' => "$conf_dir/future_expired_stanza_access.conf", 'exp_epoch_access' => "$conf_dir/expired_epoch_stanza_access.conf", 'invalid_exp_access' => "$conf_dir/invalid_expire_access.conf", 'require_force_nat_access' => "$conf_dir/require_force_nat_access.conf", "${fw_conf_prefix}_output_chain" => "$conf_dir/${fw_conf_prefix}_output_chain_fwknopd.conf", "invalid_${fw_conf_prefix}_input_chain" => "$conf_dir/invalid_${fw_conf_prefix}_input_chain_fwknopd.conf", "invalid_${fw_conf_prefix}_input_chain2" => "$conf_dir/invalid_${fw_conf_prefix}_input_chain_2_fwknopd.conf", "invalid_${fw_conf_prefix}_input_chain3" => "$conf_dir/invalid_${fw_conf_prefix}_input_chain_3_fwknopd.conf", "invalid_${fw_conf_prefix}_input_chain4" => "$conf_dir/invalid_${fw_conf_prefix}_input_chain_4_fwknopd.conf", "invalid_${fw_conf_prefix}_input_chain5" => "$conf_dir/invalid_${fw_conf_prefix}_input_chain_5_fwknopd.conf", "invalid_${fw_conf_prefix}_input_chain6" => "$conf_dir/invalid_${fw_conf_prefix}_input_chain_6_fwknopd.conf", 'invalid_run_dir_path' => "$conf_dir/invalid_run_dir_path_fwknopd.conf", 'force_nat_access' => "$conf_dir/force_nat_access.conf", 'hmac_force_nat_access' => "$conf_dir/hmac_force_nat_access.conf", 'hmac_force_nat_forward_all_access' => "$conf_dir/hmac_force_nat_forward_all_access.conf", 'hmac_force_snat_access' => "$conf_dir/hmac_force_snat_access.conf", 'hmac_force_masq_access' => "$conf_dir/hmac_force_masq_access.conf", 'hmac_force_masq_no_dnat_access' => "$conf_dir/hmac_force_masq_no_dnat_access.conf", 'hmac_forward_all_access' => "$conf_dir/hmac_forward_all_access.conf", 'hmac_forward_all_masq_access' => "$conf_dir/hmac_forward_all_masq_access.conf", 'hmac_forward_all_and_dna_access' => "$conf_dir/hmac_forward_all_and_dnat_access.conf", 'cmd_access' => "$conf_dir/cmd_access.conf", 'cmd_setuid_access' => "$conf_dir/cmd_setuid_access.conf", 'cmd_giduid_access' => "$conf_dir/cmd_giduid_access.conf", "${fw_conf_prefix}_local_nat" => "$conf_dir/${fw_conf_prefix}_local_nat_fwknopd.conf", "${fw_conf_prefix}_no_flush_init" => "$conf_dir/${fw_conf_prefix}_no_flush_init_fwknopd.conf", "${fw_conf_prefix}_no_flush_exit" => "$conf_dir/${fw_conf_prefix}_no_flush_exit_fwknopd.conf", "${fw_conf_prefix}_no_flush_init_or_exit" => "$conf_dir/${fw_conf_prefix}_no_flush_init_or_exit_fwknopd.conf", 'ipfw_active_expire' => "$conf_dir/ipfw_active_expire_equal_fwknopd.conf", 'hmac_android_access' => "$conf_dir/hmac_android_access.conf", 'hmac_android_fdroid_access' => "$conf_dir/hmac_android_fdroid_access.conf", 'android_access' => "$conf_dir/android_access.conf", 'android_legacy_iv_access' => "$conf_dir/android_legacy_iv_access.conf", 'dual_key_access' => "$conf_dir/dual_key_usage_access.conf", 'dual_key_legacy_iv_access' => "$conf_dir/dual_key_legacy_iv_access.conf", 'hmac_dual_key_access' => "$conf_dir/hmac_dual_key_usage_access.conf", 'no_exit_down_intf' => "$conf_dir/no_exit_down_intf_fwknopd.conf", 'gpg_access' => "$conf_dir/gpg_access.conf", 'gpg_hmac_access' => "$conf_dir/gpg_hmac_access.conf", 'gpg_invalid_exe_access' => "$conf_dir/gpg_invalid_exe_access.conf", 'gpg_hmac_sha512_access' => "$conf_dir/gpg_hmac_sha512_access.conf", 'gpg_hmac_sha3_512_access' => "$conf_dir/gpg_hmac_sha3_512_access.conf", 'legacy_iv_access' => "$conf_dir/legacy_iv_access.conf", 'hmac_fuzzing_access' => "$conf_dir/hmac_fuzzing_access.conf", 'legacy_iv_long_key_access' => "$conf_dir/legacy_iv_long_key_access.conf", 'legacy_iv_long_key2_access' => "$conf_dir/legacy_iv_long_key2_access.conf", 'gpg_no_pw_access' => "$conf_dir/gpg_no_pw_access.conf", 'gpg_no_pw_fpr_access' => "$conf_dir/gpg_no_pw_fpr_access.conf", 'gpg_no_pw_bad_fpr_access' => "$conf_dir/gpg_no_pw_bad_fpr_access.conf", 'gpg_no_pw_no_fpr_access' => "$conf_dir/gpg_no_pw_no_fpr_access.conf", 'gpg_no_sig_no_fpr_access' => "$conf_dir/gpg_no_sig_no_fpr_access.conf", 'gpg_no_pw_hmac_access' => "$conf_dir/gpg_no_pw_hmac_access.conf", 'gpg_no_pw_hmac_clientdir_access' => "$conf_dir/gpg_no_pw_hmac_clientdir_access.conf", 'gpg_no_pw_hmac_serverdir_access' => "$conf_dir/gpg_no_pw_hmac_serverdir_access.conf", 'gpg_no_pw_hmac_sha512_access' => "$conf_dir/gpg_no_pw_hmac_sha512_access.conf", 'gpg_no_sig_verify_access' => "$conf_dir/gpg_no_sig_verify_access.conf", 'gpg_invalid_sig_id_access' => "$conf_dir/gpg_invalid_sig_id_access.conf", 'gpg_large_signing_key_access' => "$conf_dir/gpg_large_signing_key_access.conf", 'gpg_subkey_access' => "$conf_dir/gpg_subkey_access.conf", 'gpg_server_large_key_access' => "$conf_dir/gpg_server_large_key_access.conf", 'tcp_server' => "$conf_dir/tcp_server_fwknopd.conf", 'udp_server' => "$conf_dir/udp_server_fwknopd.conf", 'spa_over_http' => "$conf_dir/spa_over_http_fwknopd.conf", 'spa_x_forwarded_for' => "$conf_dir/spa_x_forwarded_for_fwknopd.conf", 'tcp_pcap_filter' => "$conf_dir/tcp_pcap_filter_fwknopd.conf", 'icmp_pcap_filter' => "$conf_dir/icmp_pcap_filter_fwknopd.conf", 'open_ports_access' => "$conf_dir/open_ports_access.conf", 'open_ports_force_masq_access' => "$conf_dir/open_ports_force_masq_access.conf", 'hmac_open_ports_access' => "$conf_dir/hmac_sha256_open_ports_access.conf", 'multi_gpg_access' => "$conf_dir/multi_gpg_access.conf", 'multi_gpg_no_pw_access' => "$conf_dir/multi_gpg_no_pw_access.conf", 'multi_stanza_access' => "$conf_dir/multi_stanzas_access.conf", 'broken_keys_access' => "$conf_dir/multi_stanzas_with_broken_keys.conf", 'ecb_mode_access' => "$conf_dir/ecb_mode_access.conf", 'ctr_mode_access' => "$conf_dir/ctr_mode_access.conf", 'cfb_mode_access' => "$conf_dir/cfb_mode_access.conf", 'ofb_mode_access' => "$conf_dir/ofb_mode_access.conf", 'open_ports_mismatch' => "$conf_dir/mismatch_open_ports_access.conf", 'require_user_access' => "$conf_dir/require_user_access.conf", 'user_mismatch_access' => "$conf_dir/mismatch_user_access.conf", 'require_src_access' => "$conf_dir/require_src_access.conf", 'invalid_src_access' => "$conf_dir/invalid_source_access.conf", 'no_src_match' => "$conf_dir/no_source_match_access.conf", 'no_subnet_match' => "$conf_dir/no_subnet_source_match_access.conf", 'no_multi_src' => "$conf_dir/no_multi_source_match_access.conf", 'multi_src_access' => "$conf_dir/multi_source_match_access.conf", 'ip_src_match' => "$conf_dir/ip_source_match_access.conf", 'subnet_src_match' => "$conf_dir/ip_source_match_access.conf", 'rc_def_key' => "$conf_dir/fwknoprc_with_default_key", 'rc_def_b64_key' => "$conf_dir/fwknoprc_with_default_base64_key", 'rc_named_key' => "$conf_dir/fwknoprc_named_key", 'rc_hmac_equal_keys' => "$conf_dir/fwknoprc_hmac_equal_keys", 'rc_invalid_b64_key' => "$conf_dir/fwknoprc_invalid_base64_key", 'rc_hmac_b64_key' => "$conf_dir/fwknoprc_default_hmac_base64_key", 'rc_hmac_defaults' => "$conf_dir/fwknoprc_hmac_defaults", 'rc_hmac_http_resolve' => "$conf_dir/fwknoprc_hmac_http_resolve", 'rc_hmac_https_resolve' => "$conf_dir/fwknoprc_hmac_https_resolve", 'rc_hmac_http_only_resolve' => "$conf_dir/fwknoprc_hmac_http_only_resolve", 'rc_hmac_nat_rand_b64_key' => "$conf_dir/fwknoprc_hmac_nat_rand_base64_key", 'rc_hmac_spoof_src_b64_key' => "$conf_dir/fwknoprc_hmac_spoof_src_base64_key", 'rc_hmac_sha512_b64_key' => "$conf_dir/fwknoprc_hmac_sha512_base64_key", 'rc_hmac_b64_key2' => "$conf_dir/fwknoprc_hmac_key2", 'rc_hmac_time_offset_mins' => "$conf_dir/fwknoprc_hmac_time_offset_mins", 'rc_hmac_time_offset_hours' => "$conf_dir/fwknoprc_hmac_time_offset_hours", 'rc_hmac_time_offset_days' => "$conf_dir/fwknoprc_hmac_time_offset_days", 'rc_rand_port_hmac_b64_key' => "$conf_dir/fwknoprc_rand_port_hmac_base64_key", 'rc_gpg_signing_pw' => "$conf_dir/fwknoprc_gpg_signing_pw", 'rc_gpg_named_signing_pw' => "$conf_dir/fwknoprc_named_gpg_signing_pw", 'rc_gpg_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_hmac_key", 'rc_gpg_invalid_gpg_exe' => "$conf_dir/fwknoprc_gpg_invalid_exe", 'rc_gpg_hmac_sha512_b64_key' => "$conf_dir/fwknoprc_gpg_hmac_sha512_key", 'rc_gpg_args_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_args_hmac_key", 'rc_gpg_args_no_pw_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_args_no_pw_hmac_key", 'rc_hmac_simple_key' => "$conf_dir/fwknoprc_hmac_simple_keys", 'rc_hmac_invalid_type' => "$conf_dir/fwknoprc_hmac_invalid_type", 'rc_hmac_invalid_type' => "$conf_dir/fwknoprc_hmac_invalid_type", 'rc_hmac_md5_key' => "$conf_dir/fwknoprc_hmac_md5_key", 'rc_hmac_md5_short_key' => "$conf_dir/fwknoprc_hmac_md5_short_key", 'rc_hmac_md5_long_key' => "$conf_dir/fwknoprc_hmac_md5_long_key", 'rc_hmac_sha1_key' => "$conf_dir/fwknoprc_hmac_sha1_key", 'rc_hmac_sha1_short_key' => "$conf_dir/fwknoprc_hmac_sha1_short_key", 'rc_hmac_sha1_long_key' => "$conf_dir/fwknoprc_hmac_sha1_long_key", 'rc_hmac_sha256_key' => "$conf_dir/fwknoprc_hmac_sha256_key", 'rc_hmac_sha3_256_key' => "$conf_dir/fwknoprc_hmac_sha3_256_key", 'rc_hmac_sha256_short_key' => "$conf_dir/fwknoprc_hmac_sha256_short_key", 'rc_hmac_sha256_long_key' => "$conf_dir/fwknoprc_hmac_sha256_long_key", 'rc_hmac_sha384_key' => "$conf_dir/fwknoprc_hmac_sha384_key", 'rc_hmac_sha384_short_key' => "$conf_dir/fwknoprc_hmac_sha384_short_key", 'rc_hmac_sha384_long_key' => "$conf_dir/fwknoprc_hmac_sha384_long_key", 'rc_hmac_sha512_key' => "$conf_dir/fwknoprc_hmac_sha512_key", 'rc_hmac_sha3_512_key' => "$conf_dir/fwknoprc_hmac_sha3_512_key", 'rc_hmac_sha512_short_key' => "$conf_dir/fwknoprc_hmac_sha512_short_key", 'rc_hmac_sha512_long_key' => "$conf_dir/fwknoprc_hmac_sha512_long_key", 'rc_stanza_list' => "$conf_dir/fwknoprc_stanza_list", 'rc_cmd_open_close_multi_cycle' => "$conf_dir/fwknoprc_hmac_multi_base64_key", 'base64_key_access' => "$conf_dir/base64_key_access.conf", "${fw_conf_prefix}_custom_input_chain" => "$conf_dir/${fw_conf_prefix}_custom_input_chain_fwknopd.conf", "${fw_conf_prefix}_custom_nat_chain" => "$conf_dir/${fw_conf_prefix}_custom_nat_chain_fwknopd.conf", 'disable_aging' => "$conf_dir/disable_aging_fwknopd.conf", 'disable_aging_nat' => "$conf_dir/disable_aging_nat_fwknopd.conf", 'fuzz_source' => "$conf_dir/fuzzing_source_access.conf", 'fuzz_open_ports' => "$conf_dir/fuzzing_open_ports_access.conf", 'fuzz_restrict_ports' => "$conf_dir/fuzzing_restrict_ports_access.conf", ); our $lib_view_str = "LD_LIBRARY_PATH=$lib_dir"; our $libfko_bin = "$lib_dir/libfko.so"; ### this is usually a link if ($enable_all or $enable_complete) { $enable_valgrind = 1; $enable_recompilation_warnings_check = 1; $enable_configure_args_checks = 1; $enable_make_distcheck = 1; $enable_client_ip_resolve_test = 1; $enable_perl_module_checks = 1; $enable_python_module_checks = 1; $enable_openssl_compatibility_tests = 1; $enable_cunit_tests = 1; } if ($enable_complete) { $enable_fault_injection = 1; $enable_profile_coverage_check = 1; $enable_fuzzing_interfaces_tests = 1; $enable_cores_pattern_mode = 1; } $enable_valgrind = 0 if $disable_valgrind; $enable_fault_injection = 0 if $disable_fault_injection; unless (-d $output_dir) { mkdir $output_dir or die "[*] Could not mkdir $output_dir: $!"; } ### create an anonymized tar file of test suite results that can be ### emailed around to assist in debugging fwknop communications exit &anonymize_results() if $anonymize_results; exit &diff_test_results() if $diff_mode; ### run an fwknop command under gdb from a previous test run exit &gdb_test_cmd() if $gdb_test_file; $ifconfig_path = &find_command('ifconfig') unless $ifconfig_path; &identify_loopback_intf() unless $list_mode or $client_only_mode; ### make sure everything looks as expected before continuing &init(); if ($enable_valgrind) { $valgrind_str = "$valgrind_path --leak-check=full " . "--show-reachable=yes --track-origins=yes"; unless ($valgrind_disable_suppressions) { $valgrind_str .= " --suppressions=$valgrind_suppressions_file"; } if ($enable_valgrind_gen_suppressions) { $valgrind_str .= ' --gen-suppressions=all'; } unless ($valgrind_disable_child_silent) { $valgrind_str .= ' --child-silent-after-fork=yes'; } } our $intf_str = "-i $loopback_intf --foreground $verbose_str"; our $default_client_args = "$lib_view_str $valgrind_str " . "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " . "$local_key_file --no-save-args $verbose_str"; our $default_client_args_long_key = "$lib_view_str $valgrind_str " . "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " . "$long_key_file --no-save-args $verbose_str"; our $default_client_args_no_get_key = "$lib_view_str " . "$valgrind_str $fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip " . "--no-save-args $verbose_str"; our $default_client_args_no_verbose = "$lib_view_str " . "$valgrind_str $fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip " . '--no-save-args '; our $client_rewrite_rc_args = "$default_client_args_no_get_key " . "--rc-file $rewrite_rc_file --test"; our $client_save_rc_args = "$default_client_args_no_get_key " . "--rc-file $save_rc_file --save-rc-stanza --force-stanza --test"; our $client_save_rc_args_no_verbose = "$default_client_args_no_verbose " . "--rc-file $save_rc_file --save-rc-stanza --force-stanza --test"; our $client_save_rc_args_no_force = "$default_client_args_no_get_key " . "--rc-file $save_rc_file --save-rc-stanza --test"; our $client_save_rc_args_no_test = "$lib_view_str $valgrind_str " . "$fwknopCmd -A tcp/22 -D $loopback_ip --no-save-args " . "--rc-file $save_rc_file --save-rc-stanza --force-stanza -v -v -v"; our $server_rewrite_conf_files = "$lib_view_str $valgrind_str $fwknopdCmd " . "-c $rewrite_fwknopd_conf -a $rewrite_access_conf " . "-d $default_digest_file -p $default_pid_file $intf_str"; our $default_client_hmac_args = "$default_client_args_no_get_key " . "--rc-file $cf{'rc_hmac_b64_key'}"; our $client_hmac_rc_defaults = "$lib_view_str $valgrind_str " . "$fwknopCmd --no-save-args --rc-file $cf{'rc_hmac_defaults'}"; our $client_hmac_rc_http_resolve = "$lib_view_str $valgrind_str " . "$fwknopCmd --no-save-args --rc-file $cf{'rc_hmac_http_resolve'}"; our $client_hmac_rc_https_resolve = "$lib_view_str $valgrind_str " . "$fwknopCmd --no-save-args --rc-file $cf{'rc_hmac_https_resolve'}"; our $client_hmac_rc_http_only_resolve = "$lib_view_str $valgrind_str " . "$fwknopCmd --no-save-args --rc-file $cf{'rc_hmac_http_only_resolve'}"; our $client_ip_resolve_args = "$lib_view_str $valgrind_str " . "$fwknopCmd -A tcp/22 -R -D $loopback_ip --get-key " . "$local_key_file $verbose_str"; our $client_ip_resolve_hmac_args = "$lib_view_str $valgrind_str " . "$fwknopCmd -A tcp/22 -R -D $loopback_ip --rc-file " . "$cf{'rc_hmac_b64_key'} $verbose_str"; our $default_client_gpg_args = "$default_client_args " . "--gpg-recipient-key $gpg_server_key " . "--gpg-signer-key $gpg_client_key " . "--gpg-home-dir $gpg_client_home_dir"; our $default_client_gpg_args_no_homedir = "$default_client_args " . "--gpg-recipient-key $gpg_server_key " . "--gpg-signer-key $gpg_client_key "; our $default_client_gpg_args_same_key_signer = "$default_client_args " . "--gpg-recipient-key $gpg_client_key " . "--gpg-signer-key $gpg_client_key "; our $default_client_gpg_args_same_key_recip = "$default_client_args " . "--gpg-recipient-key $gpg_server_key " . "--gpg-signer-key $gpg_server_key "; our $default_client_gpg_args_no_get_key = "$default_client_args_no_get_key " . "--gpg-recipient-key $gpg_server_key " . "--gpg-signer-key $gpg_client_key " . "--gpg-home-dir $gpg_client_home_dir"; our $default_client_gpg_args_no_pw = "$default_client_args_no_get_key " . "--gpg-no-signing-pw " . "--gpg-recipient-key $gpg_server_key " . "--gpg-signer-key $gpg_client_key " . "--gpg-home-dir $gpg_client_home_dir_no_pw"; our $client_gpg_large_key_args_no_pw = "$default_client_args_no_get_key " . "--gpg-no-signing-pw " . "--gpg-recipient-key $gpg_server_key2 " . "--gpg-signer-key $gpg_client_large_key " . "--gpg-home-dir $gpg_client_4096_bit_key_no_pw"; our $client_gpg_subkey_args_no_pw = "$default_client_args_no_get_key " . "--gpg-no-signing-pw " . "--gpg-recipient-key $gpg_server_key2 " . "--gpg-signer-key $gpg_client_subkey " . "--gpg-home-dir $gpg_client_subkey_no_pw"; our $client_gpg_server_4096_args_no_pw = "$default_client_args_no_get_key " . "--gpg-no-signing-pw " . "--gpg-recipient-key $gpg_server_large_key " . "--gpg-signer-key $gpg_client_subkey " . "--gpg-home-dir $gpg_client_subkey_no_pw"; our $client_and_server_gpg_4096_args_no_pw = "$default_client_args_no_get_key " . "--gpg-no-signing-pw " . "--gpg-recipient-key $gpg_server_large_key " . "--gpg-signer-key $gpg_client_large_key " . "--gpg-home-dir $gpg_client_4096_bit_key_no_pw"; our $default_server_conf_args = "-c $cf{'def'} -a $cf{'def_access'} " . "-d $default_digest_file -p $default_pid_file"; our $default_server_hmac_conf_args = "-c $cf{'def'} -a $cf{'hmac_access'} " . "-d $default_digest_file -p $default_pid_file"; our $default_server_gpg_args = "$lib_view_str " . "$valgrind_str $fwknopdCmd -c $cf{'def'} " . "-a $cf{'gpg_access'} $intf_str " . "-d $default_digest_file -p $default_pid_file"; our $default_server_gpg_args_no_pw = "$lib_view_str " . "$valgrind_str $fwknopdCmd -c $cf{'def'} " . "-a $cf{'gpg_no_pw_access'} $intf_str " . "-d $default_digest_file -p $default_pid_file"; our $default_server_gpg_args_hmac = "$lib_view_str " . "$valgrind_str $fwknopdCmd -c $cf{'def'} " . "-a $cf{'gpg_hmac_access'} $intf_str " . "-d $default_digest_file -p $default_pid_file"; our $invalid_gpg_exe_server_args = "$lib_view_str " . "$valgrind_str $fwknopdCmd -c $cf{'def'} " . "-a $cf{'gpg_invalid_exe_access'} $intf_str " . "-d $default_digest_file -p $default_pid_file"; our $default_server_gpg_args_no_pw_hmac = "$lib_view_str " . "$valgrind_str $fwknopdCmd -c $cf{'def'} " . "-a $cf{'gpg_no_pw_hmac_access'} $intf_str " . "-d $default_digest_file -p $default_pid_file"; ### point the compiled binaries at the local library path ### instead of any installed libfko instance $ENV{'LD_LIBRARY_PATH'} = $lib_dir; $ENV{'DYLD_LIBRARY_PATH'} = $lib_dir if $lib_view_cmd =~ /otool/; ### import the tests from the various tests/ files &import_test_files(); ### ### main array that defines the tests we will run ### my @tests = ( { 'category' => 'recompilation', 'detail' => 'recompile and look for compilation warnings', 'function' => \&compile_warnings, }, { 'category' => 'make distcheck', 'detail' => 'ensure proper distribution creation', 'function' => \&make_distcheck, }, { 'category' => 'Makefile.am', 'detail' => 'test suite conf/ files included', 'function' => \&test_suite_conf_files, }, { 'category' => 'max coverage', 'detail' => 'interact with terminal for pw - TYPE ANY KEY HERE:', 'cmdline' => "$fwknopCmd -A tcp/22 -a 1.1.1.1 -D $loopback_ip -v -v -v ", 'function' => \&use_terminal_run_client, }, @build_security_client, @build_security_server, @build_security_libfko, @preliminaries, @code_structure_errstr, @basic_operations, @cunit_tests, @rijndael, @rijndael_cmd_exec, @rijndael_hmac_cmd_exec, @rijndael_hmac_cmd_open_close, @rijndael_replay_attacks, @rijndael_backwards_compatibility, @rijndael_fuzzing, @rijndael_hmac, @rijndael_hmac_fuzzing, @fault_injection, @address_sanitizer, @afl_fuzzing, @os_compatibility, @perl_FKO_module, @python_fko, @gpg_no_pw, @gpg_no_pw_hmac, @gpg, @gpg_hmac, ); if ($enable_profile_coverage_check) { push @tests, { 'category' => 'profile coverage', 'detail' => 'gcov profile coverage', 'function' => \&profile_coverage }; } ### the configure args tests recompile fwknop, so only do this ### after the profile coverage stats have been created for the main ### test run push @tests, @configure_args; if ($enable_valgrind) { push @tests, { 'category' => 'valgrind output', 'subcategory' => 'flagged functions', 'detail' => '', 'function' => \&parse_valgrind_flagged_functions }; } if ($do_crash_check) { push @tests, { 'category' => 'Look for crashes', 'detail' => 'checking for segfault/core dump messages', 'function' => \&look_for_crashes }; } my %test_keys = ( 'category' => $REQUIRED, 'subcategory' => $OPTIONAL, 'detail' => $REQUIRED, 'function' => $REQUIRED, 'binary' => $OPTIONAL, 'multi_cmds' => $OPTIONAL, 'cmdline' => $OPTIONAL, 'fwknopd_cmdline' => $OPTIONAL, 'fatal' => $OPTIONAL_NUMERIC, 'key_file' => $OPTIONAL, 'exec_err' => $OPTIONAL, 'server_exec_err' => $OPTIONAL, 'fw_rule_created' => $OPTIONAL, 'fw_rule_removed' => $OPTIONAL, 'sudo_test' => $OPTIONAL, 'sudo_conf' => $OPTIONAL, 'sudo_exec_user' => $OPTIONAL, 'sudo_exec_group' => $OPTIONAL, 'exec_user' => $OPTIONAL, 'server_conf' => $OPTIONAL, 'client_only' => $OPTIONAL_NUMERIC, 'server_only' => $OPTIONAL_NUMERIC, 'pkt' => $OPTIONAL, 'spa_pkts_file' => $OPTIONAL, 'fuzzing_pkt' => $OPTIONAL, 'pkt_prefix' => $OPTIONAL, 'no_ip_check' => $OPTIONAL, 'get_key' => $OPTIONAL, 'get_hmac_key' => $OPTIONAL, 'set_legacy_iv' => $OPTIONAL, 'sleep_cycles' => $OPTIONAL_NUMERIC, 'write_rc_file' => $OPTIONAL, 'save_rc_stanza' => $OPTIONAL, 'client_pkt_tries' => $OPTIONAL_NUMERIC, 'max_pkt_tries' => $OPTIONAL_NUMERIC, 'client_popen' => $OPTIONAL, 'disable_valgrind' => $OPTIONAL, 'wrapper_compile' => $OPTIONAL, 'wrapper_script' => $OPTIONAL, 'wrapper_binary' => $OPTIONAL, 'fiu_run' => $OPTIONAL_NUMERIC, 'fiu_injection_style' => $OPTIONAL, 'fiu_iterations' => $OPTIONAL_NUMERIC, 'server_access_file' => $OPTIONAL, 'server_include_keys_access_file' => $OPTIONAL, 'server_conf_file' => $OPTIONAL, 'digest_cache_file' => $OPTIONAL, 'cmd_cycle_open_file' => $OPTIONAL, 'cmd_cycle_close_file' => $OPTIONAL, 'cmd_exec_file_owner' => $OPTIONAL, 'cmd_exec_file_not_created' => $OPTIONAL, 'user_group_mismatch' => $OPTIONAL, 'sudo_user_group_mismatch' => $OPTIONAL, 'rm_rule_mid_cycle' => $OPTIONAL, 'server_receive_re' => $OPTIONAL, 'no_exit_intf_down' => $OPTIONAL, 'positive_output_matches' => $OPTIONAL, 'negative_output_matches' => $OPTIONAL, 'client_and_server_mode' => $OPTIONAL_NUMERIC, 'insert_rule_before_exec' => $OPTIONAL, 'insert_rule_while_running' => $OPTIONAL, 'insert_duplicate_rule_while_running' => $OPTIONAL, 'fw_dupe_rule_args' => $OPTIONAL, 'expect_server_stopped' => $OPTIONAL, 'ignore_client_error' => $OPTIONAL, 'weak_server_receive_check' => $OPTIONAL, 'search_for_rule_after_exit' => $OPTIONAL, 'rc_positive_output_matches' => $OPTIONAL, 'rc_negative_output_matches' => $OPTIONAL, 'mv_and_restore_replay_cache' => $OPTIONAL, 'relax_receive_cycle_num_check' => $OPTIONAL, 'client_positive_output_matches' => $OPTIONAL, 'client_negative_output_matches' => $OPTIONAL, 'server_positive_output_matches' => $OPTIONAL, 'server_positive_num_matches' => $OPTIONAL, 'server_negative_output_matches' => $OPTIONAL, 'server_negative_num_matches' => $OPTIONAL, 'client_cycles_per_server_instance' => $OPTIONAL_NUMERIC, 'iptables_rm_chains_after_server_start' => $OPTIONAL, ); &validate_test_hashes(); ### make sure no fwknopd instance is currently running die "[*] Please stop the running fwknopd instance." if &global_fwknopd_pgrep_check(); if ($rerun_failed_mode) { my $test_num = 0; my $test_category = ""; my $test_subcategory = ""; my $test_detail = ""; &logr("\nRunning previously failed tests\n"); for my $line (@last_logfile) { if ($line =~ /fail \((\d+)\)/ || $line =~ /valgrind output/ || $line =~ /Look for crashes/ || $line =~ /profile coverage/ ) { $test_num = $line =~ /\((\d+)\)\n/; $test_num = $1; $executed = $test_num - 1; if( $line =~ /\[(.+)\]\s+\[(.+)\]\s+([\w \(\)\/\-\>]+)/) { $test_category = $1; $test_subcategory = $2; $test_detail = $3; } elsif ($line =~ /^\[(.+)\]\s+\[(.+)\]/) { $test_category = $1; $test_subcategory = $2; } elsif ($line =~ /^\[(.+)\]/) { $test_category = $1; } for my $test_hr (@tests) { if ($test_hr->{'category'} eq $test_category && $test_hr->{'detail'} eq $test_detail) { &run_test($test_hr); } elsif ($test_hr->{'category'} eq "valgrind output" && $test_category eq "valgrind output") { &run_test($test_hr); if ($line =~ /pass \(\d+\)/) { $passed--; } } elsif ($test_hr->{'category'} eq "profile coverage" && $test_category eq "profile coverage") { &run_test($test_hr); if ($line =~ /pass \(\d+\)/) { $passed--; } } elsif ($test_hr->{'category'} eq "Look for crashes" && $test_category eq "Look for crashes") { &run_test($test_hr); if ($line =~ /pass \(\d+\)/) { $passed--; } } } } elsif ($line =~ /Run time: ([\d\.]+) minutes/) { my $total_elapsed_seconds = time() - $start_time; my $total_elapsed_minutes = sprintf "%.2f", ($total_elapsed_seconds / 60); $total_elapsed_minutes = $total_elapsed_minutes + $1; &logr(" Run time: $total_elapsed_minutes minutes\n"); } elsif ($line =~ /Run time: ([\d\.]+) seconds/) { my $total_elapsed_seconds = time() - $start_time + $1; if ($total_elapsed_seconds > 60) { my $total_elapsed_minutes = sprintf "%.2f", ($total_elapsed_seconds / 60); &logr(" Run time: $total_elapsed_minutes minutes\n"); } else { &logr(" Run time: $total_elapsed_seconds seconds\n"); } # } elsif ($line =~ /OpenSSL tests passed/) { # } elsif ($line =~ /OpenSSL HMAC tests passed/) { # } elsif ($line =~ /Fuzzing tests passed/) { } elsif ($line =~ /(\d+)\/(\d+)\/(\d+) test buckets passed/) { $passed = $1 + $passed; $executed = $3; &logr("[+] $passed/$failed/$executed test buckets passed/failed/executed\n"); } else { &logr($line); } } exit 0; } ### now that we're ready to run, preserve any previous test ### suite output &preserve_previous_test_run_results(); &logr("\n[+] Starting the fwknop test suite...\n\n" . " args: @args_cp\n\n" ); ### save the results from any previous test suite run ### so that we can potentially compare them with --diff if ($saved_last_results) { &logr(" Saved results from previous run " . "to: ${output_dir}.last/\n\n"); } unless ($list_mode) { copy $init_file, "$output_dir/init" if -e $init_file; } if ($enable_valgrind) { if ($previous_valgrind_coverage_dir) { die "[*] $previous_valgrind_coverage_dir does not exist" unless -d $previous_valgrind_coverage_dir; if (-d "${previous_valgrind_coverage_dir}/valgrind-coverage") { $previous_valgrind_coverage_dir .= '/valgrind-coverage'; } } else { ### try the previous output.last/valgrind-coverage dir first $previous_valgrind_coverage_dir = "${output_dir}.last/$valgrind_cov_dir"; unless (-d $previous_valgrind_coverage_dir) { my $os = 'linux'; $os = 'freebsd' if $platform == $FREEBSD; $previous_valgrind_coverage_dir = "valgrind-coverage/$os"; } } if (-d $previous_valgrind_coverage_dir) { &logr(" Valgrind mode enabled, will import previous coverage from:\n" . " $previous_valgrind_coverage_dir/\n\n"); } } ### print a summary of how many test buckets will be run my $test_buckets = 0; for my $test_hr (@tests) { next unless &process_include_exclude(&get_msg($test_hr)); $test_buckets++; if ($test_limit > 0) { last if $test_buckets >= $test_limit; } } &logr("[+] Total test buckets to execute: $test_buckets\n\n"); ### main loop through all of the tests my $run_flag = 1; for my $test_hr (@tests) { if ($run_flag or $test_hr->{'category'} eq 'valgrind output' or $test_hr->{'category'} eq 'Look for crashes' or $test_hr->{'category'} eq 'profile coverage') { &run_test($test_hr); } if ($test_limit > 0) { $run_flag = 0 if $executed >= $test_limit; } } &logr("\n"); unless ($list_mode) { &remove_permissions_warnings() unless $include_permissions_warnings; &restore_dir($gpg_dirs_tar); &restore_dir($access_include_dirs_tar); } my $total_elapsed_seconds = time() - $start_time; my $total_elapsed_minutes = sprintf "%.2f", ($total_elapsed_seconds / 60); if ($total_elapsed_seconds > 60) { &logr(" Run time: $total_elapsed_minutes minutes\n"); } else { &logr(" Run time: $total_elapsed_seconds seconds\n"); } if (@tests_to_include and keys %include_tracking) { my $tot_included = 0; for my $re (keys %include_tracking) { $tot_included += keys %{$include_tracking{$re}}; for my $test (keys %{$include_tracking{$re}}) { &write_test_file("$re: $test\n", "$output_dir/tests.included"); } } &logr(" Tests included (see $output_dir/tests.included): " . $tot_included . "\n"); } if (@tests_to_exclude and keys %exclude_tracking) { my $tot_excluded = 0; for my $re (keys %exclude_tracking) { $tot_excluded += keys %{$exclude_tracking{$re}}; for my $test (keys %{$exclude_tracking{$re}}) { &write_test_file("$re: $test\n", "$output_dir/tests.excluded"); } } &logr(" Tests excluded (see $output_dir/tests.excluded): " . $tot_excluded . "\n"); } &logr("\n"); if ($enable_openssl_compatibility_tests) { &logr("[+] $openssl_success_ctr/$openssl_failure_ctr/$openssl_ctr " . "OpenSSL tests passed/failed/executed\n"); &logr("[+] $openssl_hmac_success_ctr/$openssl_hmac_failure_ctr/$openssl_hmac_ctr " . "OpenSSL HMAC tests passed/failed/executed\n"); } if ($fuzzing_ctr > 0) { &logr("[+] $fuzzing_success_ctr/$fuzzing_failure_ctr/$fuzzing_ctr " . "Fuzzing tests passed/failed/executed\n"); } &logr("[+] $passed/$failed/$executed test buckets passed/failed/executed\n\n"); unless ($list_mode) { copy $logfile, "$output_dir/$logfile" or die $!; } if ($pinentry_fail) { if ($killall_path) { ### kill all gpg processes in the fwknop client ### process group (this will kill the test suite ### too, but we're already done) system "$killall_path -g fwknop"; } } exit 0; #===================== end main ======================= sub run_test() { my $test_hr = shift; &validate_test_hash($test_hr); ### prepare for test run &rm_tmp_files(); my $msg = &get_msg($test_hr); $msg =~ s/REPLPKTS/-->$total_fuzzing_pkts<-- pkts/; if ($client_only_mode) { return unless $test_hr->{'client_only'} or $test_hr->{'subcategory'} eq 'client' or $test_hr->{'category'} eq 'perl FKO module' or $test_hr->{'category'} eq 'python fko extension'; return if $msg =~ /server/i; } elsif ($server_only_mode) { return unless $test_hr->{'server_only'} or $test_hr->{'subcategory'} eq 'server' or $test_hr->{'category'} eq 'perl FKO module' or $test_hr->{'category'} eq 'python fko extension'; return if $msg =~ /client/i; } if ($list_mode) { if (&process_include_exclude($msg)) { print $msg, "\n"; } else { print "$msg (requires an --enable-* arg, see -h)\n"; } return; } return unless &process_include_exclude($msg); &dots_print($msg); $executed++; $curr_test_file = "$output_dir/$executed.test"; $server_test_file = "$output_dir/${executed}_fwknopd.test"; &write_test_file("[+] TEST: $msg\n", $curr_test_file); $test_hr->{'msg'} = $msg; if ($test_hr->{'mv_and_restore_replay_cache'}) { unlink "${default_digest_file}.mv" if -e "${default_digest_file}.mv"; move $default_digest_file, "${default_digest_file}.mv"; } my $rv = &{$test_hr->{'function'}}($test_hr); ### if we're in valgrind mode, make sure there were no memory leaks if ($enable_valgrind) { for my $file ($curr_test_file, $server_test_file) { next unless -e $file; if ($rv) { &write_test_file("[+] VERDICT: pass ($executed)\n", $file); } else { &write_test_file("[-] VERDICT: fail ($executed)\n", $file); } if (&file_find_regex([qr/^==\d+==\sHEAP\sSUMMARY/], $MATCH_ALL, $NO_APPEND_RESULTS, $file)) { unless (&valgrind_results($file)) { &write_test_file("[-] valgrind criteria failed, setting rv=0.\n", $file); $rv = 0; } } } } if ($rv) { &logr("pass ($executed)\n"); $passed++; } else { &logr("fail ($executed)\n"); $failed++; if ($test_hr->{'fatal'} eq $YES) { die "[*] required test failed, exiting."; } } if ($test_hr->{'mv_and_restore_replay_cache'}) { unlink $default_digest_file if -e $default_digest_file; move "${default_digest_file}.mv", $default_digest_file; } if ($enable_valgrind and &is_valgrind_running()) { if ($pkill_path) { for my $cmd ('memcheck', 'valgrind') { system "$pkill_path -f $cmd"; } } elsif ($killall_path) { for my $cmd ('memcheck', 'valgrind') { system "$killall_path -g -r $cmd > /dev/null 2>&1"; } } } if ($enable_perl_module_fuzzing_spa_pkt_generation) { if ($msg =~ /perl FKO module.*FUZZING/) { print "\n[+] Wrote $fuzzing_num_pkts fuzzing SPA ", "packets to $fuzzing_pkts_file.tmp...\n\n"; exit 0; } } if ($enable_profile_coverage_check) { if ($username) { for my $extension ('*.gcno', '*.gcda', '*.gcov') { system qq/find .. -name $extension | xargs -r chown $username/; } } for my $extension ('*.gcno', '*.gcda', '*.gcov') { system qq/find .. -name $extension | xargs -r chmod a+w/; } } ### clean up tmp files now that the test is complete &rm_tmp_files(); return; } sub precise_sleep { my ($sleeptime) = @_; select(undef, undef, undef, $sleeptime); } sub get_msg() { my $test_hr = shift; my $msg = "[$test_hr->{'category'}]"; $msg .= " [$test_hr->{'subcategory'}]" if $test_hr->{'subcategory'}; $msg .= " $test_hr->{'detail'}"; return $msg; } sub process_include_exclude() { my $msg = shift; ### inclusions/exclusions if (@tests_to_include) { my $found = 0; for my $test (@tests_to_include) { if ($msg =~ $test or ($enable_valgrind and $msg =~ /valgrind\soutput/) or ($enable_profile_coverage_check and $msg =~ /profile\scoverage/) or ($msg =~ /segfault.*dump\smessages/) ) { $include_tracking{$test}{$msg} = ''; $found = 1; last; } } return 0 unless $found; } if (@tests_to_exclude) { my $found = 0; for my $test (@tests_to_exclude) { if ($msg =~ $test) { $exclude_tracking{$test}{$msg} = ''; $found = 1; last; } } return 0 if $found; } return 1; } sub gdb_test_cmd() { die "[*] previous test file: $gdb_test_file does not exist." unless -e $gdb_test_file; my $gdb_cmd = ''; open F, "< $gdb_test_file" or die "[*] Could not open $gdb_test_file: $!"; while () { if (/CMD\:\sLD_LIBRARY_PATH=(\S+).*\s($fwknopCmd\s.*)/ or /CMD\:\sLD_LIBRARY_PATH=(\S+).*\s($fwknopdCmd\s.*)/) { $gdb_cmd = "LD_LIBRARY_PATH=$1 gdb --args $2"; last; } } close F; print "\n[+] Running the following command under gdb: $gdb_cmd\n\n"; if ($gdb_cmd) { system $gdb_cmd; } else { die "[*] Could not extract fwknop/fwknopd command from $gdb_test_file"; } return 1; } sub diff_test_results() { $diff_dir1 = "${output_dir}.last" unless $diff_dir1; $diff_dir2 = $output_dir unless $diff_dir2; die "[*] Need results from a previous run before running --diff" unless -d $diff_dir2; die "[*] Current results set does not exist." unless -d $diff_dir1; my %curr_tests = (); my %prev_tests = (); ### Only diff results for matching tests (parse the logfile to see which ### test numbers match across the two test cycles). &build_results_hash(\%curr_tests, $diff_dir1); &build_results_hash(\%prev_tests, $diff_dir2); for my $test_msg (sort {$curr_tests{$a}{'num'} <=> $curr_tests{$b}{'num'}} keys %curr_tests) { my $curr_result = $curr_tests{$test_msg}{'pass_fail'}; my $curr_num = $curr_tests{$test_msg}{'num'}; if (defined $prev_tests{$test_msg}) { print "[+] Diff check: $test_msg\n"; my $prev_result = $prev_tests{$test_msg}{'pass_fail'}; my $prev_num = $prev_tests{$test_msg}{'num'}; if ($curr_result ne $prev_result) { print " ** Verdict diff: current: $curr_result, ", "previous: $prev_result $test_msg\n"; } &diff_results($prev_num, $curr_num, $diff_dir1, $diff_dir2); print "\n"; } } if (-d "$diff_dir1/$valgrind_cov_dir" and -d "$diff_dir2/$valgrind_cov_dir") { &diff_valgrind_results(\%curr_tests, \%prev_tests) } exit 0; } sub diff_valgrind_results() { my ($curr_tests_hr, $prev_tests_hr) = @_; print "\n\n\n[+] Valgrind differences:\n\n"; for my $test_msg (sort {$curr_tests_hr->{$a}->{'num'} <=> $curr_tests_hr->{$b}->{'num'}} keys %$curr_tests_hr) { my $curr_num = $curr_tests_hr->{$test_msg}->{'num'}; if (defined $prev_tests_hr->{$test_msg}) { print "[+] Valgrind diff check: $test_msg\n"; my $prev_result = $prev_tests_hr->{$test_msg}->{'pass_fail'}; my $prev_num = $prev_tests_hr->{$test_msg}->{'num'}; &diff_results($prev_num, $curr_num, "$diff_dir1/$valgrind_cov_dir", "$diff_dir2/$valgrind_cov_dir"); print "\n"; } } return; } sub diff_results() { my ($prev_num, $curr_num, $dir1, $dir2) = @_; ### edit out any valgrind "==354==" prefixes my $valgrind_search_re = qr/^==\d+==\s/; ### remove CMD timestamps my $cmd_search_re = qr/^\S+\s.*?\s\d{4}\sCMD\:/; for my $file ("$dir1/${prev_num}.test", "$dir1/${prev_num}_fwknopd.test", "$dir2/${curr_num}.test", "$dir2/${curr_num}_fwknopd.test", ) { system qq{perl -p -i -e 's|$valgrind_search_re||' $file} if -e $file; system qq{perl -p -i -e 's|$cmd_search_re|CMD:|' $file} if -e $file; } if (-e "$dir1/${prev_num}.test" and -e "$dir2/${curr_num}.test") { system "diff -u $dir1/${prev_num}.test " . "$dir2/${curr_num}.test"; } if (-e "$dir1/${prev_num}_fwknopd.test" and -e "$dir2/${curr_num}_fwknopd.test") { system "diff -u $dir1/${prev_num}_fwknopd.test " . "$dir2/${curr_num}_fwknopd.test"; } return; } sub build_results_hash() { my ($hr, $dir) = @_; open F, "< $dir/$logfile" or die "[*] Could not open $dir/$logfile: $!"; while () { if (/^(.*?)\.\.\..*(pass|fail)\s\((\d+)\)/) { $hr->{$1}{'pass_fail'} = $2; $hr->{$1}{'num'} = $3; } } return; } sub asan_verification() { my $test_hr = shift; my $rv = 1; chdir $asan_dir or die $!; unless (&run_cmd('make clean', "../$cmd_out_tmp", "../$curr_test_file")) { chdir '..' or die $!; return 0; } if ($sudo_path) { unless (&run_cmd("$sudo_path -u $username make", "../$cmd_out_tmp", "../$curr_test_file")) { unless (&run_cmd('make', "../$cmd_out_tmp", "../$curr_test_file")) { $rv = 0; } } } else { unless (&run_cmd('make', "../$cmd_out_tmp", "../$curr_test_file")) { $rv = 0; } } if ($rv) { &run_cmd('./a.out', "../$cmd_out_tmp", "../$curr_test_file"); $rv = 0 unless &is_sanitizer_crash("../$curr_test_file"); } chdir '..' or die $!; return $rv; } sub compile_warnings() { my $curr_pwd = cwd() or die $!; chdir '..' or die $!; &config_recompile(''); ### look for compilation warnings - something like: ### warning: ‘test’ is used uninitialized in this function if (&file_find_regex([qr/\swarning:\s/i, qr/gcc\:.*\sunused/], $MATCH_ANY, $APPEND_RESULTS, "test/$curr_test_file")) { chdir $curr_pwd or die $!; return 0; } chdir $curr_pwd or die $!; ### the new binaries should exist unless (-e $fwknopCmd and -x $fwknopCmd) { &write_test_file("[-] $fwknopCmd does not exist or not executable.\n", $curr_test_file); } unless (-e $fwknopdCmd and -x $fwknopdCmd) { &write_test_file("[-] $fwknopdCmd does not exist or not executable.\n", $curr_test_file); } return 1; } sub profile_coverage() { my $rv = 1; ### check for any *.gcno files - if they don't exist, then fwknop was ### not compiled with profile support unless (glob('../client/*.gcno') and glob('../server/*.gcno')) { &write_test_file("[-] ../client/*.gcno and " . "../server/*.gcno files do not exist.\n", $curr_test_file); return 0; } my $curr_dir = getcwd() or die $!; unless ($lcov_path) { &write_test_file( "[-] lcov command not found, skipping code coverage report generation.", $curr_test_file); return 0; } &run_cmd($profile_gen_report_sh, $cmd_out_tmp, $curr_test_file); if (-d $lcov_results_dir) { move $lcov_results_dir, "$output_dir/$lcov_results_dir"; for my $f ('lcov_coverage.info', 'lcov_coverage_final.info') { move $f, "$output_dir/$f" if -e $f; } } else { &write_test_file("[-] $lcov_results_dir does not exist.", $cmd_out_tmp, $curr_test_file); $rv = 0; } if (-d "${output_dir}.last") { &run_cmd("./$coverage_diff_path", $cmd_out_tmp, $curr_test_file); } if ($username) { for my $extension ('*.gcno', '*.gcda', '*.gcov') { system qq/find .. -name $extension | xargs -r chown $username/; } } for my $extension ('*.gcno', '*.gcda', '*.gcov') { system qq/find .. -name $extension | xargs -r chmod a+w/; } return $rv; } sub fiu_run_fault_injection() { my $test_hr = shift; my $rv = 1; my $iterations = $test_hr->{'fiu_iterations'}; $iterations = 1 if $iterations < 1; ### assume we want at least 1 for (my $i=0; $i < $iterations; $i++) { &run_cmd("$lib_view_str $fiu_run_path -x " . "-c '$test_hr->{'fiu_injection_style'}' $test_hr->{'cmdline'}", $cmd_out_tmp, $curr_test_file); } return $rv; } sub fault_injection_tag() { my $test_hr = shift; my $rv = 1; my $server_was_stopped = 0; my $fw_rule_created = 0; my $fw_rule_removed = 0; my $tag_name = ''; if ($test_hr->{'cmdline'}) { if ($test_hr->{'cmdline'} =~ /fault\-injection\-tag\s(S+)/) { $tag_name = $1; } } elsif ($test_hr->{'fwknopd_cmdline'}) { if ($test_hr->{'fwknopd_cmdline'} =~ /fault\-injection\-tag\s(S+)/) { $tag_name = $1; } } if ($tag_name) { unless ($test_hr->{'detail'} =~ /\s$tag_name/) { &write_test_file( "[-] tag_name '$tag_name' not in test message.\n", $curr_test_file); return 0; } } if ($test_hr->{'pkt'} or ($test_hr->{'cmdline'} and $test_hr->{'fwknopd_cmdline'})) { ### we are testing the fwknopd server if ($test_hr->{'pkt'}) { my @packets = ( { 'proto' => 'udp', 'port' => $default_spa_port, 'dst_ip' => $loopback_ip, 'data' => $test_hr->{'pkt'}, }, ); ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed) = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS); } else { ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed) = &client_server_interaction($test_hr, [], $USE_CLIENT); } $rv = 0 unless $server_was_stopped; if ($test_hr->{'server_positive_output_matches'}) { unless (&file_find_regex( $test_hr->{'server_positive_output_matches'}, $MATCH_ALL, $APPEND_RESULTS, $server_test_file)) { &write_test_file( "[-] server_positive_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } } else { ### we are testing the fwknop client, server, or other command ### and expect an error $rv = not &run_cmd($test_hr->{'cmdline'}, $cmd_out_tmp, $curr_test_file); if ($test_hr->{'positive_output_matches'}) { unless (&file_find_regex( $test_hr->{'positive_output_matches'}, $MATCH_ALL, $APPEND_RESULTS, $curr_test_file)) { &write_test_file( "[-] positive_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } } return $rv; } sub fko_wrapper_exec() { my $test_hr = shift; my $make_arg = $test_hr->{'wrapper_compile'}; $make_arg = 'asan' if $asan_mode; $make_arg = 'ubsan' if $ubsan_mode; if ($test_hr->{'wrapper_binary'} =~ m|/fko_wrapper$|) { if ($enable_fuzzing_interfaces_tests) { $make_arg = 'fuzzing'; ### generate the fko-wrapper/fuzz_spa_payloads file ### if necessary - it is consumed by the wrapper in ### -DFUZZING_INTERFACES mode &write_test_file("[-] Generating SPA fuzzing packets " . "file: $fuzz_spa_payloads_file with ./spa_fuzzing.py...\n", $curr_test_file); unless (-e $fuzz_spa_payloads_file) { system "./spa_fuzzing.py > $fuzz_spa_payloads_file"; } } } my $rv = &compile_wrapper($make_arg); if ($rv) { chdir $fko_wrapper_dir or die $!; my $iterations = $test_hr->{'fiu_iterations'}; $iterations = 1 if $iterations < 1; ### assume we want at least 1 if ($test_hr->{'fiu_run'} == $YES) { my $lib_path = $lib_view_str; $lib_path =~ s|_PATH=|_PATH=../|; ### hack for (my $i=0; $i < $iterations; $i++) { &run_cmd("$lib_path $fiu_run_path -x " . "-c '$test_hr->{'fiu_injection_style'}' $test_hr->{'wrapper_binary'}", "../$cmd_out_tmp", "../$curr_test_file"); } } else { &run_cmd("./$test_hr->{'wrapper_script'} $test_hr->{'wrapper_binary'}", "../$cmd_out_tmp", "../$curr_test_file"); if ($test_hr->{'wrapper_script'} =~ /valgrind/) { $rv = 0 unless &valgrind_results("../$curr_test_file"); } } chdir '..' or die $!; if ($test_hr->{'wrapper_binary'} =~ m|/fko_wrapper$|) { if ($enable_fuzzing_interfaces_tests) { ### make sure the send_spa_payloads file exists unless (-e $send_fuzz_payloads_file) { &write_test_file("[-] Generating SPA fuzzing packets " . "file: $send_fuzz_payloads_file for fwknopd consumption...\n", $curr_test_file); unless (-e $send_fuzz_payloads_file) { system "grep PKT_ID $curr_test_file > $send_fuzz_payloads_file"; } } } } $rv = 0 if &is_crash($curr_test_file); } else { ### could not compile, so disable remaining fault injection ### "tag" tests push @tests_to_exclude, qr/fault\sinjection.*\stag\s/; } return $rv; } sub valgrind_results() { my $file = shift; my $rv = 1; $rv = 0 if &file_find_regex( [qr/definitely\slost\:\s[1-9]\d*\sbytes/], $MATCH_ALL, $APPEND_RESULTS, $file); $rv = 0 if &file_find_regex( [qr/indirectly\slost\:\s[1-9]\d*\sbytes/], $MATCH_ALL, $APPEND_RESULTS, $file); return $rv; } sub test_suite_conf_files() { my $make_file = '../Makefile.am'; my $rv = 1; my %makefile_conf_files = (); my %makefile_test_scripts = (); unless (-e $make_file) { &write_test_file("[-] $make_file does not exist.\n", $curr_test_file); return 0; } open F, "< $make_file" or die $!; while () { if (m|test/$conf_dir/(\S+)|) { $makefile_conf_files{$1} = ''; } elsif (m|test/$tests_dir/(\S+)|) { $makefile_test_scripts{$1} = ''; } } close F; for my $f (glob("$conf_dir/*")) { next if -d $f; next unless $f =~ /\.conf/ or $f =~ /fwknop/; if ($f =~ m|$conf_dir/(\S+)|) { unless (defined $makefile_conf_files{$1}) { &write_test_file("[-] test suite conf file $1 not in $make_file.\n", $curr_test_file); $rv = 0; } } } for my $f (glob("$tests_dir/*.pl")) { if ($f =~ m|$tests_dir/(\S+)|) { unless (defined $makefile_test_scripts{$1}) { &write_test_file("[-] test suite script file $1 not in $make_file.\n", $curr_test_file); $rv = 0; } } } return $rv; } sub look_for_crashes() { my $rv = 1; for my $f (glob("$output_dir/*")) { next if -d $f; next unless $f =~ /\.test$/; ### only look for ASAN crashes in normal test files next if &file_find_regex([qr/ASAN.*crash\sverification/i], $MATCH_ALL, $NO_APPEND_RESULTS, $f); $rv = 0 if &is_crash($f); } $do_crash_check = 0; return $rv; } sub is_sanitizer_crash() { my $file = shift; my $rv = 0; if (&file_find_regex([qr/ERROR\:\s\w+Sanitizer/, qr/SUMMARY\:\s\w+Sanitizer/], $MATCH_ANY, $NO_APPEND_RESULTS, $file)) { &write_test_file("[-] Sanitizer crash found in: $file\n", $curr_test_file); $rv = 1; } return $rv; } sub is_crash() { my $file = shift; my $rv = 0; if (&file_find_regex([qr/segmentation\sfault/i, qr/core\sdumped/i], $MATCH_ANY, $NO_APPEND_RESULTS, $file)) { &write_test_file("[-] crash message found in: $file\n", $curr_test_file); $rv = 1; } $rv = 1 if &is_sanitizer_crash($file); ### ASan and valgrind don't appear to be compatible, and and ASan ### will throw an error when the two are mixed if (&file_find_regex([qr/Shadow memory range interleaves/], $MATCH_ANY, $NO_APPEND_RESULTS, $file)) { &write_test_file("[-] Sanitizer infrastructure not " . "compatible with valgrind: $file\n", $curr_test_file); $rv = 1; } return $rv; } sub config_recompile() { my $config_cmd = shift; my $rv = 1; &run_cmd('make clean', $cmd_out_tmp, "test/$curr_test_file"); if ($config_cmd) { &run_cmd($config_cmd, $cmd_out_tmp, "test/$curr_test_file"); } if ($sudo_path) { unless (&run_cmd("$sudo_path -u $username make", $cmd_out_tmp, "test/$curr_test_file")) { $rv = 0 unless &run_cmd('make', $cmd_out_tmp, "test/$curr_test_file"); } } else { $rv = 0 unless &run_cmd('make', $cmd_out_tmp, "test/$curr_test_file"); } unless ($rv) { ### override the failure if makeinfo is missing since this ### this doesn't affect run time operations if (&file_find_regex([qr/makeinfo.*is\smissing/], $MATCH_ALL, $NO_APPEND_RESULTS, $cmd_out_tmp)) { $rv = 1; } } return 1; } sub configure_args_restore_orig() { my $rv = 1; my $curr_pwd = cwd() or die $!; chdir '..' or die $!; unless (&config_recompile($orig_config_args)) { &write_test_file("[-] configure/recompile failure.\n", "test/$curr_test_file"); chdir $curr_pwd or die $!; $rv = 0; } chdir $curr_pwd or die $!; return $rv; } sub configure_args_disable_execvpe() { my $rv = 1; my $curr_pwd = cwd() or die $!; chdir '..' or die $!; unless (&config_recompile('./extras/apparmor/configure_args.sh --disable-execvpe')) { &write_test_file("[-] configure/recompile failure.\n", "test/$curr_test_file"); chdir $curr_pwd or die $!; $rv = 0; } chdir $curr_pwd or die $!; return $rv; } sub configure_args_udp_server_no_libpcap() { my $rv = 1; my $curr_pwd = cwd() or die $!; chdir '..' or die $!; unless (&config_recompile('./extras/apparmor/configure_args.sh --enable-udp-server')) { &write_test_file("[-] configure/recompile failure.\n", "test/$curr_test_file"); $rv = 0; } chdir $curr_pwd or die $!; &run_cmd("$lib_view_str $lib_view_cmd $fwknopdCmd", $cmd_out_tmp, $curr_test_file); if (&file_find_regex([qr/pcap/], $MATCH_ALL, $APPEND_RESULTS, $cmd_out_tmp)) { &write_test_file("[-] fwknopd appears to still link against libpcap.\n", $curr_test_file); $rv = 0; } return $rv; } sub code_structure_search_sources_for_non_ascii_chars() { my $rv = 1; for my $src_dir ('client', 'server', 'win32', 'common', 'lib') { next unless (glob("../$src_dir/*.c"))[0]; &run_cmd($perl_path . q{ -lwne 'print "non-ascii char in $ARGV" and exit 0 if /[^\w\s\x20-\x7e]/' } . "../$src_dir/*.c", $cmd_out_tmp, $curr_test_file); next unless (glob("../$src_dir/*.h"))[0]; &run_cmd($perl_path . q{ -lwne 'print "non-ascii char in $ARGV" and exit 0 if /[^\w\s\x20-\x7e]/' } . "../$src_dir/*.h", $cmd_out_tmp, $curr_test_file); } if (&file_find_regex( [qr/^non\-ascii/], $MATCH_ALL, $APPEND_RESULTS, $curr_test_file)) { &write_test_file( "[-] non-ascii char found in source file, setting rv=0\n", $curr_test_file); $rv = 0; } return $rv; } sub code_structure_fko_error_strings() { my $rv = 1; ### parse error codes from lib/fko.h and make sure each is handled in ### fko_errstr(), and that both the perl and python libfko extensions also ### handle each error code. for my $file ($libfko_hdr_file, $libfko_errstr_file, $perl_libfko_constants_file, $python_libfko_constants_file) { unless (-e $file) { &write_test_file("[-] file: $file does not exist.\n", $curr_test_file); return 0; } } ### this is a basic parser that relies on the current structure of fko.h my $found_starting_code = 0; my @fko_error_codes = (); my $starting_code = 'FKO_SUCCESS'; open F, "< $libfko_hdr_file" or die "[*] Could not open $libfko_hdr_file: $!"; while () { if (/$starting_code\s=\s0/) { $found_starting_code = 1; push @fko_error_codes, $starting_code; next; } next unless $found_starting_code; if (/^\s{4}([A-Z]\S+),/) { push @fko_error_codes, $1; } last if $found_starting_code and /^\}\sfko_error_codes_t\;/; } close F; ### now make sure that lib/fko_error.c has an error string for each code ### in order my $found_errstr_func = 0; my $expected_var_index = 0; my $prev_var = $fko_error_codes[0]; open F, "< $libfko_errstr_file" or die "[*] Could not open $libfko_errstr_file: $!"; while () { if (/^fko_errstr\(/) { $found_errstr_func = 1; next; } next unless $found_errstr_func; if (/^\s+case\s(\S+)\:/) { my $var_str = $1; if ($fko_error_codes[$expected_var_index] eq 'GPGME_ERR_START') { $expected_var_index++; } if ($fko_error_codes[$expected_var_index] eq $var_str) { $expected_var_index++; $prev_var = $var_str; } else { &write_test_file("[-] $libfko_errstr_file: expected var $fko_error_codes[$expected_var_index] " . "in position: $expected_var_index in fko_errstr(), previous var: $prev_var\n", $curr_test_file); $rv = 0; last; } } last if $found_errstr_func and /^\}/; } close F; ### validate perl error code constants $expected_var_index = 0; $prev_var = $fko_error_codes[0]; my $found_err_code_arr = 0; open F, "< $perl_libfko_constants_file" or die "[*] Could not open $perl_libfko_constants_file: $!"; while () { if (/our\s\@ERROR_CODES\s=/) { $found_err_code_arr = 1; next; } next unless $found_err_code_arr; if (/^\s{4}(\S+)/) { my $var_str = $1; if ($fko_error_codes[$expected_var_index] eq $var_str) { $expected_var_index++; $prev_var = $var_str; } else { &write_test_file("[-] $perl_libfko_constants_file: perl FKO module - " . "expected var $fko_error_codes[$expected_var_index] " . "at position: $expected_var_index in ERROR_CODES array, previous var: $prev_var\n", $curr_test_file); $rv = 0; last; } } last if $found_err_code_arr and /^\)\;/; } close F; ### same thing, but now validate 'use constant' values too $expected_var_index = 0; $prev_var = $fko_error_codes[0]; my $found_use_constant = 0; my $found_fko_success = 0; open F, "< $perl_libfko_constants_file" or die "[*] Could not open $perl_libfko_constants_file: $!"; while () { if (/^use\sconstant\s\{/) { $found_use_constant = 1; next; } next unless $found_use_constant; if (/^\s{4}$starting_code\s+=\>\s(\d+),/) { my $val = $1; unless ($fko_error_codes[$val] eq $starting_code) { &write_test_file("[-] $perl_libfko_constants_file: perl FKO module " . "- expected var $starting_code " . "value of zero, got $val\n", $curr_test_file); $rv = 0; last; } $found_fko_success = 1; } next unless $found_fko_success; if (/^\s{4}([A-Z]\S+)\s+=\>\s(\d+),/) { my $var_str = $1; my $val = $2; if ($fko_error_codes[$val] eq $var_str) { $expected_var_index++; $prev_var = $var_str; } else { &write_test_file("[-] $perl_libfko_constants_file: perl FKO module " . "- expected var $fko_error_codes[$expected_var_index] " . "in position: $expected_var_index in 'use constants' definition, previous var: $prev_var\n", $curr_test_file); $rv = 0; last; } } last if $found_fko_success and /^\)\;/; } close F; ### validate python error code constants $expected_var_index = 0; $prev_var = $fko_error_codes[0]; $found_use_constant = 0; $found_fko_success = 0; open F, "< $python_libfko_constants_file" or die "[*] Could not open $python_libfko_constants_file: $!"; while () { if (/^$starting_code\s=\s0/) { $found_fko_success = 1; next; } next unless $found_fko_success; if (/^([A-Z]\S+)\s=\s(\d+)/) { my $var_str = $1; my $val = $2; if ($fko_error_codes[$val] eq $var_str) { $expected_var_index++; $prev_var = $var_str; } else { &write_test_file("[-] python extension - expected var $fko_error_codes[$expected_var_index] " . "in position: $expected_var_index in FKO constants section, previous var: $prev_var\n", $curr_test_file); $rv = 0; last; } } last if $found_fko_success and /^\s/; } close F; return $rv; } sub make_distcheck() { ### 'make clean' as root return 0 unless &run_cmd('make -C .. distcheck', $cmd_out_tmp, $curr_test_file); return 1 if &file_find_regex([qr/archives\sready\sfor\sdistribution/], $MATCH_ALL, $APPEND_RESULTS, $curr_test_file); return 0; } sub binary_exists() { my $test_hr = shift; return 0 unless $test_hr->{'binary'}; ### account for different libfko.so paths (e.g. libfko.so.0.3 with no ### libfko.so link on OpenBSD, and libfko.dylib path on Mac OS X) if ($test_hr->{'binary'} =~ /libfko/) { unless (-e $test_hr->{'binary'}) { my $file = "$lib_dir/libfko.dylib"; if (-e $file) { $test_hr->{'binary'} = $file; $libfko_bin = $file; } else { for my $f (glob("$lib_dir/libfko.so*")) { if (-e $f and -x $f) { $test_hr->{'binary'} = $f; $libfko_bin = $f; last; } } } } } return 0 unless -e $test_hr->{'binary'} and -x $test_hr->{'binary'}; return 1; } sub expected_code_version() { my $test_hr = shift; unless (-e '../VERSION') { &write_test_file("[-] ../VERSION file does not exist.\n", $curr_test_file); return 0; } open F, '< ../VERSION' or die $!; my $line = ; close F; if ($line =~ /(\d.*\d)/) { my $version = $1; return 0 unless &run_cmd($test_hr->{'cmdline'}, $cmd_out_tmp, $curr_test_file); return 1 if &file_find_regex([qr/$version/], $MATCH_ALL, $APPEND_RESULTS, $curr_test_file); } return 0; } sub write_rc_file() { my ($rc_hr, $rc_file) = @_; open RC, "> $rc_file" or die "[*] Could not open $rc_file: $!"; for my $hr (@$rc_hr) { print RC "[$hr->{'name'}]\n"; for my $var (keys %{$hr->{'vars'}}) { print RC "$var $hr->{'vars'}->{$var}\n"; } } close RC; return; } sub cunit_tests() { my $test_hr = shift; my $rv = 1; &run_cmd("$lib_view_str $valgrind_str" . $test_hr->{'cmdline'}, $cmd_out_tmp, $curr_test_file); if ($test_hr->{'negative_output_matches'}) { $rv = 0 if &file_find_regex( $test_hr->{'negative_output_matches'}, $MATCH_ANY, $APPEND_RESULTS, $curr_test_file); } return $rv } sub server_start_stop_cycle() { my $test_hr = shift; my $rv = 1; &write_test_file("[+] TEST: " . &get_msg($test_hr) . "\n", $server_test_file); &run_cmd("$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -S", $cmd_out_tmp, $curr_test_file); &run_cmd("$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -K", $cmd_out_tmp, $curr_test_file); &run_cmd("$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -R", $cmd_out_tmp, $curr_test_file); ### send additional signals for code coverage for my $sig_name (@sigs_ordered) { my $sig = $sigs{$sig_name}; &run_cmd("$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args " . "-i $loopback_intf $verbose_str", $cmd_out_tmp, $curr_test_file); sleep 1; open F, "< $default_pid_file" or die "[*] Could not open $default_pid_file: $!"; my $pid = ; close F; chomp $pid; if (kill 0, $pid) { &write_test_file( "[+] Sending daemonized fwknopd PID: $pid signal: $sig_name($sig)\n", $curr_test_file); kill $sig, $pid; sleep 1; if (kill 0, $pid) { &run_cmd( "$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -K", $cmd_out_tmp, $curr_test_file); } } else { &write_test_file( "[-] Daemonized fwknopd PID: $pid not running?\n", $curr_test_file); } } &run_cmd("$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -S", $cmd_out_tmp, $curr_test_file); &run_cmd("$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -K", $cmd_out_tmp, $curr_test_file); ### now send the signals against a non-daemon fwknopd process for my $sig_name (@sigs_ordered) { my $sig = $sigs{$sig_name}; &do_fwknopd_cmd("$lib_view_str $valgrind_str " . "$fwknopdCmd $default_server_conf_args -i $loopback_intf -f"); open F, "< $default_pid_file" or die "[*] Could not open $default_pid_file: $!"; my $pid = ; close F; chomp $pid; if (kill 0, $pid) { &write_test_file( "[+] Sending foreground fwknopd PID: $pid signal: $sig_name($sig)\n", $curr_test_file); kill $sig, $pid; sleep 1; if (kill 0, $pid) { &run_cmd( "$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -K", $cmd_out_tmp, $curr_test_file); } } else { &write_test_file( "[-] Foreground fwknopd PID: $pid not running?\n", $curr_test_file); } } return $rv; } sub server_conf_files() { my $test_hr = shift; my $rv = 1; if ($test_hr->{'digest_cache_file'}) { &write_server_conf_file($test_hr->{'digest_cache_file'}, $rewrite_digest_file); } if ($test_hr->{'server_access_file'}) { if ($test_hr->{'sudo_user_group_mismatch'} eq $YES) { push @{$test_hr->{'server_access_file'}}, "CMD_SUDO_EXEC_USER $username"; push @{$test_hr->{'server_access_file'}}, "CMD_SUDO_EXEC_GROUP root"; } if ($test_hr->{'user_group_mismatch'} eq $YES) { push @{$test_hr->{'server_access_file'}}, "CMD_EXEC_USER $username"; push @{$test_hr->{'server_access_file'}}, "CMD_EXEC_GROUP root"; } &write_server_conf_file($test_hr->{'server_access_file'}, $rewrite_access_conf); } if ($test_hr->{'server_include_keys_access_file'}) { &write_server_conf_file($test_hr->{'server_include_keys_access_file'}, $rewrite_include_keys_access_conf); } if ($test_hr->{'server_conf_file'}) { &write_server_conf_file($test_hr->{'server_conf_file'}, $rewrite_fwknopd_conf); } $rv = 0 unless &run_cmd($test_hr->{'fwknopd_cmdline'}, $cmd_out_tmp, $curr_test_file); if ($rv == 0) { $rv = 1 if $test_hr->{'exec_err'} eq $YES; } if ($test_hr->{'positive_output_matches'}) { unless (&file_find_regex( $test_hr->{'positive_output_matches'}, $MATCH_ALL, $APPEND_RESULTS, $curr_test_file)) { &write_test_file( "[-] positive_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } if ($test_hr->{'negative_output_matches'}) { if (&file_find_regex( $test_hr->{'negative_output_matches'}, $MATCH_ANY, $APPEND_RESULTS, $curr_test_file)) { &write_test_file( "[-] negative_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } return $rv; } sub write_server_conf_file() { my ($lines_ar, $file) = @_; open F, "> $file" or die "[*] Could not open $file $!"; &write_test_file("[+] write_server_conf_file(): $file\n", $curr_test_file); for my $line (@$lines_ar) { &write_test_file("$line\n", $curr_test_file); print F $line, "\n"; } close F; return; } sub client_rc_file() { my $test_hr = shift; my $rv = 1; my $rc_file = ''; if ($test_hr->{'write_rc_file'}) { &write_rc_file($test_hr->{'write_rc_file'}, $rewrite_rc_file); $rc_file = $rewrite_rc_file; } elsif ($test_hr->{'save_rc_stanza'}) { &write_rc_file($test_hr->{'save_rc_stanza'}, $save_rc_file); $rc_file = $save_rc_file; } else { &write_test_file( "[-] test hash does not include 'write_rc_file' or 'save_rc_stanza'\n", $curr_test_file); return 0; } if ($test_hr->{'client_popen'}) { $rv = &popen_cmd($test_hr, $cmd_out_tmp, $curr_test_file); } else { $rv = 0 unless &run_cmd($test_hr->{'cmdline'}, $cmd_out_tmp, $curr_test_file); } if ($rv == 0) { $rv = 1 if $test_hr->{'exec_err'} eq $YES; } unless ($test_hr->{'cmdline'} =~ /key\-gen/ or $test_hr->{'cmdline'} =~ /\-k/ or $test_hr->{'exec_err'} eq $YES) { $rv = 0 unless &file_find_regex([qr/Final\sSPA\sData/i], $MATCH_ALL, $NO_APPEND_RESULTS, $curr_test_file); } if ($test_hr->{'positive_output_matches'}) { unless (&file_find_regex( $test_hr->{'positive_output_matches'}, $MATCH_ALL, $APPEND_RESULTS, $curr_test_file)) { &write_test_file( "[-] positive_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } if ($test_hr->{'negative_output_matches'}) { if (&file_find_regex( $test_hr->{'negative_output_matches'}, $MATCH_ANY, $APPEND_RESULTS, $curr_test_file)) { &write_test_file( "[-] negative_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } unless (&validate_fko_decode()) { &write_test_file( "[-] validate_fko_decode() returned zero, setting rv=0\n", $curr_test_file); $rv = 0; } if ($test_hr->{'rc_positive_output_matches'}) { unless (&file_find_regex( $test_hr->{'rc_positive_output_matches'}, $MATCH_ALL, $NO_APPEND_RESULTS, $rc_file)) { &write_test_file( "[-] rc_positive_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } if ($test_hr->{'rc_negative_output_matches'}) { if (&file_find_regex( $test_hr->{'rc_negative_output_matches'}, $MATCH_ANY, $NO_APPEND_RESULTS, $rc_file)) { &write_test_file( "[-] rc_negative_output_matches not met, setting rv=0\n", $curr_test_file); $rv = 0; } } return $rv; } sub validate_fko_decode() { return 0 unless -e $curr_test_file; ### make sure that the before and after FKO decode ### sections are the same - this ensures that libfko ### encoding / decoding cycles match up my @before_lines = (); my @after_lines = (); my $found_fko_field_values = 0; my $finished_first_section = 0; open F, "< $curr_test_file" or die "[*] Could not open $curr_test_file: $!"; while () { if (/^FKO\sField\sValues/) { $found_fko_field_values = 1; next; } next unless $found_fko_field_values; if (/Final\sSPA\sData/) { $found_fko_field_values = 0; last if $finished_first_section; $finished_first_section = 1; } if ($found_fko_field_values) { if ($finished_first_section) { push @after_lines, $_ if $_ =~ /\S/; } else { push @before_lines, $_ if $_ =~ /\S/; } } } close F; my $found_difference = 0; for (my $i=0; $i < $#before_lines; $i++) { unless (defined $after_lines[$i]) { $found_difference = 1; last; } if ($before_lines[$i] ne $after_lines[$i]) { chomp $before_lines[$i]; chomp $after_lines[$i]; &write_test_file( "[-] Line mismatch, before '$before_lines[$i]', after '$after_lines[$i]'\n", $curr_test_file); $found_difference = 1; } } if ($found_difference) { return 0; } return 1; } sub insert_dupe_rule() { my $test_hr = shift; ### insert duplicate rules my ($prv, $lib_path, $fwknopd_conf, $access_conf) = &parse_fwknopd_cmdline($test_hr); return unless $prv; &write_test_file("[+] Policy before inserting duplicate rules:\n", $curr_test_file); &run_cmd("LD_LIBRARY_PATH=$lib_path $fwknopdCmd -c " . "$fwknopd_conf -a $access_conf --fw-list", $cmd_out_tmp, $curr_test_file); my $time_now = time(); for (my $i=0; $i < 15; $i++) { my $time_prefix = '_exp_' . ($time_now + 45+$i); ### default timeout &write_test_file("[+] Inserting duplicate rule with expire comment: $time_prefix\n", $curr_test_file); if ($test_hr->{'fw_dupe_rule_args'}) { for my $fw_args (@{$test_hr->{'fw_dupe_rule_args'}}) { my $cp = $fw_args; if ($cp =~ /EXP_TIME/) { $cp =~ s/EXP_TIME/$time_prefix/; } &run_cmd("$fw_bin_and_prefix $cp", $cmd_out_tmp, $curr_test_file); } } else { ### assume SSH &run_cmd("$fw_bin_and_prefix -A FWKNOP_INPUT -p 6 -s $fake_ip -d 0.0.0.0/0 " . "--dport 22 -m comment --comment $time_prefix -j ACCEPT", $cmd_out_tmp, $curr_test_file); } } &write_test_file("[+] Policy after inserting duplicate rules:\n", $curr_test_file); &run_cmd("LD_LIBRARY_PATH=$lib_path $fwknopdCmd -c " . "$fwknopd_conf -a $access_conf --fw-list", $cmd_out_tmp, $curr_test_file); &cache_fw_policy($cmd_out_tmp); until($time_now + 44 < time()) { sleep 1; } return; } sub client_send_spa_packet() { my $test_hr = shift; my $client_cycles = 1; $client_cycles = $test_hr->{'client_cycles_per_server_instance'} if $test_hr->{'client_cycles_per_server_instance'} > 0; return &_client_send_spa_packet($test_hr, $client_cycles, $SERVER_RECEIVE_CHECK); } sub _client_send_spa_packet() { my ($test_hr, $cycle_ctr, $server_receive_check) = @_; my $rv = 1; if ($test_hr->{'get_key'}) { &write_key($test_hr->{'get_key'}->{'key'}, $test_hr->{'get_key'}->{'file'}); } else { &write_key($default_key, $local_key_file); } if ($test_hr->{'get_hmac_key'}) { &write_key($test_hr->{'get_hmac_key'}->{'key'}, $test_hr->{'get_hmac_key'}->{'file'}); } else { &write_key($default_key, $local_key_file); } if (-e $server_cmd_tmp) { my $tries = 0; my $quickcount = 0; my $nummatches = 0; for (;;) { $rv = 1; $tries++; ### default stanza regex match my $server_receive_re = qr/stanza\s.*\sSPA Packet from IP/; $server_receive_re = $test_hr->{'server_receive_re'} if $test_hr->{'server_receive_re'}; my $matches = &file_find_num_matches($server_receive_re, $NO_APPEND_RESULTS, $server_cmd_tmp); if ($test_hr->{'weak_server_receive_check'}) { last if $matches > 0; } else { last if $matches == $cycle_ctr+1; } &write_test_file("[.] client_send_spa_packet() " . "executing client and looking for fwknopd receiving " . "packet, try: $tries\n", $curr_test_file); ### run the client if ($test_hr->{'multi_cmds'}) { for my $cmd (@{$test_hr->{'multi_cmds'}}) { $rv = 0 unless &run_cmd($cmd, $cmd_out_tmp, $curr_test_file); } } else { $rv = 0 unless &run_cmd($test_hr->{'cmdline'}, $cmd_out_tmp, $curr_test_file); } $quickcount = 0; $nummatches = 0; $nummatches = &file_find_num_matches(qr/Final\sSPA\sData/, $NO_APPEND_RESULTS, $server_cmd_tmp); while ($nummatches < 1 && $quickcount < 10 ) { print "."; precise_sleep(.5); $quickcount++; $nummatches = &file_find_num_matches(qr/Final\sSPA\sData/, $NO_APPEND_RESULTS, $server_cmd_tmp); }; if ($test_hr->{'relax_receive_cycle_num_check'}) { $rv = 0 unless &file_find_regex([qr/Final\sSPA\sData/], $MATCH_ALL, $NO_APPEND_RESULTS, $curr_test_file); } else { $rv = 0 unless (&file_find_num_matches(qr/Final\sSPA\sData/, $NO_APPEND_RESULTS, $server_cmd_tmp) > 0) || (&file_find_num_matches(qr/SPA\sPacket\sfrom\sIP:/, $NO_APPEND_RESULTS, $server_cmd_tmp) > 0) || (&file_find_num_matches(qr/SPA\sdata:/, $NO_APPEND_RESULTS, $server_cmd_tmp) > 0); } last if $server_receive_check == $NO_SERVER_RECEIVE_CHECK; if ($test_hr->{'client_pkt_tries'} > 0) { last if $tries == $test_hr->{'client_pkt_tries'}; } else { last if $tries == 10; } sleep 1; } } else { &write_test_file("[.] client_send_spa_packet() " . "server tmp file $server_cmd_tmp does not exist.\n", $curr_test_file); ### run the client if ($test_hr->{'multi_cmds'}) { for my $cmd (@{$test_hr->{'multi_cmds'}}) { $rv = 0 unless &run_cmd($cmd, $cmd_out_tmp, $curr_test_file); } } else { $rv = 0 unless &run_cmd($test_hr->{'cmdline'}, $cmd_out_tmp, $curr_test_file); } $rv = 0 unless &file_find_regex([qr/Final\sSPA\sData/i], $MATCH_ALL, $NO_APPEND_RESULTS, $curr_test_file); } unless ($server_receive_check == $NO_SERVER_RECEIVE_CHECK) { if ($rv) { &write_test_file("[+] fwknopd received SPA packet.\n", $curr_test_file); } else { &write_test_file("[-] fwknopd did not receive SPA packet.\n", $curr_test_file); } } if ($enable_openssl_compatibility_tests) { ### extract the SPA packet from the cmd tmp file my $encoded_msg = ''; my $digest = ''; my $enc_mode = 0; my $is_hmac_type = 1; my $hmac_digest = ''; my $hmac_mode = 'sha256'; open SPA, "< $cmd_out_tmp" or die $!; while () { if (/^\s+Encoded\sData\:\s+(\S+)/) { $encoded_msg = $1; } elsif (/Data\sDigest\:\s(\S+)/) { $digest = $1; } elsif (/Encryption\sMode\:\s+(\d+)/) { $enc_mode = $1; } elsif (/^\s+HMAC\:\s\/) { $is_hmac_type = 0; } elsif (/^\s+HMAC\:\s(\S+)/) { $hmac_digest = $1; } elsif (/^\s+HMAC\sType\:\s\d+\s\((\S+)\)/) { $hmac_mode = lc($1); } } close SPA; $encoded_msg .= ":$digest"; my $ssl_test_flag = $REQUIRE_SUCCESS; $ssl_test_flag = $REQUIRE_FAILURE if $enc_mode != 2; ### CBC mode $ssl_test_flag = $REQUIRE_FAILURE if $is_hmac_type; my $encrypted_msg = &get_spa_packet_from_file($cmd_out_tmp); my $key = ''; my $hmac_key = ''; my $num_hmac_keys = 0; my $b64_decode_key = 0; if ($test_hr->{'key_file'}) { open K, "< $test_hr->{'key_file'}" or die $!; while () { if (/^KEY_BASE64\:?\s+(\S+)/) { $key = $1; $b64_decode_key = 1; } elsif (/^KEY\:?\s+(\S+)/) { $key = $1; } elsif (/^HMAC_KEY_BASE64\:?\s+(\S+)/) { $hmac_key = $1; $b64_decode_key = 1; $num_hmac_keys++; } elsif (/^HMAC_KEY\:?\s+(\S+)/) { $hmac_key = $1; $num_hmac_keys++; } } close K; } $key = $default_key unless $key; unless (&openssl_enc_verification($encrypted_msg, $encoded_msg, '', $key, $b64_decode_key, $ssl_test_flag)) { $rv = 0; } if ($is_hmac_type and $hmac_key) { my $enc_mode = $ENC_RIJNDAEL; $enc_mode = $ENC_GPG if $test_hr->{'msg'} =~ /gpg/i or $test_hr->{'msg'} =~ /gnupg/i; if ($num_hmac_keys == 1) { unless (&openssl_hmac_verification($encrypted_msg, $encoded_msg, '', $hmac_key, $b64_decode_key, $hmac_digest, $hmac_mode, $enc_mode, 0)) { $rv = 0; } } else { #Try for each of the keys my $found_success = 0; open K, "< $test_hr->{'key_file'}" or die $!; while () { if (/^HMAC_KEY_BASE64\:?\s+(\S+)/) { $hmac_key = $1; $b64_decode_key = 1; if (&openssl_hmac_verification($encrypted_msg, $encoded_msg, '', $hmac_key, $b64_decode_key, $hmac_digest, $hmac_mode, $enc_mode, 1)) { $found_success = 1; } } elsif (/^HMAC_KEY\:?\s+(\S+)/) { $hmac_key = $1; if (&openssl_hmac_verification($encrypted_msg, $encoded_msg, '', $hmac_key, $b64_decode_key, $hmac_digest, $hmac_mode, $enc_mode, 1)) { $found_success = 1; } } } close K; if (!$found_success) { $rv = 0; } } } } &write_test_file("[.] client_send_spa_packet() rv: $rv\n", $curr_test_file); return $rv; } sub permissions_check() { my $test_hr = shift; for my $f (keys %cf) { next unless -f $cf{$f}; chmod 0777, $cf{$f} or die $!; } my $rv = &spa_cycle($test_hr); for my $f (keys %cf) { next unless -f $cf{$f}; chmod 0600, $cf{$f} or die $!; } return $rv; } sub rotate_digest_file() { my $test_hr = shift; my $rv = 1; unless (-e $default_digest_file) { open DIGEST, "> $default_digest_file" or die "[*] Could not open $default_digest_file: $!"; print DIGEST "# " . "