Merge tag 'upstream/0.7'

Upstream version 0.7
This commit is contained in:
Leo Antunes
2016-09-28 19:41:01 +02:00
19 changed files with 8417 additions and 7773 deletions

View File

@@ -1,5 +1,19 @@
VERSION DESCRIPTION
-----------------------------------------------------------------------------
0.7 - Patches from Oswald Buddenhagen:
- Document the 'target' configuration directive.
- Merging OS-specific networking code to reduce LOCs and the
sea of #ifdefs.
- Added 50ms timeout to pcap_open_live() to reduce CPU usage
on network-heavy hosts. Pcap recommends we not use zero.
0.6 - Patches from Oswald Buddenhagen:
- Cleanup: Don't null-check before free
- Cleanup: Consolidate flag-check logic
- Accept single-knock sequences
- Introduce a 'target' configuration directive, enabling
knockd to react to connect attempts to a target host.
Useful in cases where knockd is on a router and you want
to send a target a wakeup packet.
0.5 - Added ability to change the knocking protocol (TCP/UDP) on a
per-port basis using the knock client (instead of the -u
switch)

22
Makefile.am Normal file
View File

@@ -0,0 +1,22 @@
AM_CPPFLAGS=-D_BSD_SOURCE
AM_CFLAGS=-g -Wall -pedantic -fno-exceptions
bin_PROGRAMS = knock
man_MANS = doc/knock.1
if BUILD_KNOCKD
sbin_PROGRAMS = knockd
man_MANS += doc/knockd.1
sysconf_DATA = knockd.conf
endif
dist_doc_DATA = README.md TODO ChangeLog COPYING
knock_SOURCES = src/knock.c
knockd_SOURCES = src/knockd.c src/list.c src/list.h
%.1: %.1.in
sed -e "s/#VERSION#/$(VERSION)/" $< > $@
EXTRA_DIST = doc/knock.1 doc/knock.1.in doc/knockd.1 doc/knockd.1.in knockd.conf

File diff suppressed because it is too large Load Diff

53
README
View File

@@ -1,53 +0,0 @@
knock :: A port-knocking implementation
=======================================
Copyright (c) 2004-2005, Judd Vinet <jvinet@zeroflux.org>
=========
ABOUT
=========
This is a port-knocking server/client. Port-knocking is a method where a
server can sniff one of its interfaces for a special "knock" sequence of
port-hits. When detected, it will run a specified event bound to that port
knock sequence. These port-hits need not be on open ports, since we use
libpcap to sniff the raw interface traffic.
===========
EXAMPLE
===========
The example below could be used to run a strict (DENY policy) firewall that
can only be accessed after a successful knock sequence.
1) Client sends four TCP SYN packets to Server, at the following ports:
38281, 29374, 4921, 54918
2) Server detects this and runs an iptables command to open port 22 to Client.
3) Client connects to Server via SSH and does whatever it needs to do.
4) Client sends four more TCP SYN packets to Server:
37281, 8529, 40127, 10100
5) Server detects this and runs another iptables to close port 22 to Client.
====================
KNOCKING CLIENTS
====================
The accompanying knock client is very basic. If you want to more advanced
knocks (eg, setting specific tcp flags) then you should take look at hping,
sendip or packit.
http://freshmeat.net/projects/hping/
http://freshmeat.net/projects/sendip/
http://freshmeat.net/projects/packit/
=========================
OTHER IMPLEMENTATIONS
=========================
Here are some other implementations of port-knocking:
http://sourceforge.net/projects/pasmal/
http://doorman.sourceforge.net/

58
README.md Normal file
View File

@@ -0,0 +1,58 @@
## knock: A port-knocking implementation
Copyright (c) 2004, Judd Vinet <jvinet@zeroflux.org>
### ABOUT
This is a port-knocking server/client. Port-knocking is a method where a
server can sniff one of its interfaces for a special "knock" sequence of
port-hits. When detected, it will run a specified event bound to that port
knock sequence. These port-hits need not be on open ports, since we use
libpcap to sniff the raw interface traffic.
### BUILDING
To build knockd, make sure you have libpcap and the autoconf tools
installed. Then run the following:
$ autoreconf -fi
$ ./configure --prefix=/usr/local
$ make
$ sudo make install
### EXAMPLE
The example below could be used to run a strict (DENY policy) firewall that
can only be accessed after a successful knock sequence.
1. Client sends four TCP SYN packets to Server, at the following ports:
38281, 29374, 4921, 54918
2. Server detects this and runs an iptables command to open port 22 to
Client.
3. Client connects to Server via SSH and does whatever it needs to do.
4. Client sends four more TCP SYN packets to Server: 37281, 8529,
40127, 10100
5. Server detects this and runs another iptables command to close port
22 to Client.
### KNOCKING CLIENTS
The accompanying knock client is very basic. If you want to do more advanced
knocks (eg, setting specific tcp flags) then you should take look at hping,
sendip or packit.
- [hping](http://freshmeat.net/projects/hping/)
- [sendip](http://freshmeat.net/projects/sendip/)
- [packit](http://freshmeat.net/projects/packit/)
### OTHER IMPLEMENTATIONS
Here are some other implementations of port-knocking:
- [pasmal](http://sourceforge.net/projects/pasmal/)
- [doorman](http://doorman.sourceforge.net/)

1149
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

347
compile Executable file
View File

@@ -0,0 +1,347 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

1321
config.guess vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,95 +1,37 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if you have the `inet_ntoa' function. */
#undef HAVE_INET_NTOA
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `pcap' library (-lpcap). */
#undef HAVE_LIBPCAP
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the <pcap.h> header file. */
#undef HAVE_PCAP_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to 1 if `fork' works. */
#undef HAVE_WORKING_FORK
/* Define to 1 if `vfork' works. */
#undef HAVE_WORKING_VFORK
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
@@ -103,29 +45,46 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Version number of package */
#undef VERSION
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define as `fork' if `vfork' does not work. */
#undef vfork
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE

1443
config.sub vendored

File diff suppressed because it is too large Load Diff

8312
configure vendored

File diff suppressed because it is too large Load Diff

22
configure.ac Normal file
View File

@@ -0,0 +1,22 @@
AC_PREREQ(2.60)
AC_INIT([knock], [0.7], [https://github.com/jvinet/knock/issues])
AM_INIT_AUTOMAKE([dist-xz no-dist-gzip foreign subdir-objects])
AC_CONFIG_HEADER([config.h])
AC_PROG_CC
AC_USE_SYSTEM_EXTENSIONS
AC_ARG_ENABLE([knockd],
[AS_HELP_STRING([--disable-knockd], [Disable building knockd (requires libpcap) @<:@default=enabled@:>@])])
AS_IF([test "x$enable_knockd" != "xno"], [
AC_CHECK_LIB([pcap], [pcap_dispatch], ,
[AC_MSG_ERROR([you need the libpcap library to build knockd])])
])
AM_CONDITIONAL([BUILD_KNOCKD], [test "x$enable_knockd" != "xno"])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

791
depcomp Executable file
View File

@@ -0,0 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -15,6 +15,12 @@ Make all port hits use UDP (default is TCP).
If you want each port to use a different protocol (TCP or UDP), then you
can specify the protocol on a per-port basis. See the example below.
.TP
.B "\-d <t>, \-\-delay <t>"
Wait <t> milliseconds between each port hit. This can be used in situations
where a router mistakes your stream of SYN packets as a port scan and blocks
them. If the packet rate is slowed with --delay, then the router should let
the packets through.
.TP
.B "\-v, \-\-verbose"
Output verbose status messages.
.TP

View File

@@ -60,13 +60,13 @@ firewall and would like to access it discreetly.
sequence = 7000,8000,9000
seq_timeout = 10
tcpflags = syn
command = /usr/sbin/iptables -A INPUT -s %IP% -j ACCEPT
command = /usr/sbin/iptables -A INPUT -s %IP% --dport 22 -j ACCEPT
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 10
tcpflags = syn
command = /usr/sbin/iptables -D INPUT -s %IP% -j ACCEPT
command = /usr/sbin/iptables -D INPUT -s %IP% --dport 22 -j ACCEPT
.fi
.RE
@@ -135,7 +135,7 @@ Network interface to listen on. Only its name has to be given, not the path to
the device (eg, "eth0" and not "/dev/eth0"). Default: eth0.
.SH CONFIGURATION: KNOCK/EVENT DIRECTIVES
.TP
.B "Sequence = <port1>[:<tcp|udp>][,<port2>[:<tcp|udp>] ...]"
.B "Sequence = <port1>[:<tcp|udp>],<port2>[:<tcp|udp>][,<port3>[:<tcp|udp>] ...]"
Specify the sequence of ports in the special knock. If a wrong port with
the same flags is received, the knock is discarded. Optionally, you can
define the protocol to be used on a per-port basis (default is TCP).
@@ -172,6 +172,13 @@ interfere with (and thus invalidate) the knock.
Separate multiple flags with commas (eg, TCPFlags = syn,ack,urg). Flags can be
explicitly excluded by a "!" (eg, TCPFlags = syn,!ack).
.TP
.B "Target = <ip-address>"
Use the specified IP address instead of the address determined for the
\fBInterface\fP when matching the \fBSequence\fP.
This is useful if knockd is running on a router and you want to do something
in response to an actual connection attempt to a routed host - e.g., invoking
etherwake to send the host a WOL packet.
.TP
.B "Start_Command = <command>"
Specify the command to be executed when a client makes the correct
port-knock. All instances of \fB%IP%\fP will be replaced with the
@@ -179,8 +186,8 @@ knocker's IP address. The \fBCommand\fP directive is an alias for
\fBStart_Command\fP.
.TP
.B "Cmd_Timeout = <timeout>"
Time to wait between \fBStart_Command\fP and \fBStop_Command\fP. This
directive is optional, only required if \fBStop_Command\fP is used.
Time to wait (in seconds) between \fBStart_Command\fP and \fBStop_Command\fP.
This directive is optional, only required if \fBStop_Command\fP is used.
.TP
.B "Stop_Command = <command>"
Specify the command to be executed when \fBCmd_Timeout\fP seconds have passed

View File

@@ -1,251 +1,527 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
scriptversion=2011-11-20.07; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright 1991 by the Massachusetts Institute of Technology
# Copyright (C) 1994 X Consortium
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
# put in absolute paths if you don't have them in your path; or use env. vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
stripcmd=
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
src=
dst=
dir_arg=
dst_arg=
-d) dir_arg=true
shift
continue;;
copy_on_change=false
no_target_directory=
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
Options:
--help display this help and exit.
--version display version info and exit.
-s) stripcmd="$stripprog"
shift
continue;;
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
while test $# -ne 0; do
case $1 in
-c) ;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
done
fi
if [ x"$src" = x ]
then
echo "install: no input file specified"
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
else
:
fi
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
test -d "$dstdir"
dstdir_status=$?
fi
fi
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
obsolete_mkdir_used=false
if [ -f $src -o -d $src ]
then
:
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
:
mkdir_mode=
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if [ -d $dst ]
then
dst="$dst"/`basename $src`
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
:
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
fi
prefix=$prefix/
done
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
pathcomp=''
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
:
fi
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
pathcomp="${pathcomp}/"
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
:
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

215
missing Executable file
View File

@@ -0,0 +1,215 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -1,8 +1,8 @@
/*
* knock.c
*
* Copyright (c) 2004-2005 by Judd Vinet <jvinet@zeroflux.org>
*
*
* Copyright (c) 2004-2012 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -23,16 +23,20 @@
#include <stdlib.h>
#include <stdarg.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <netinet/in.h>
#endif
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <resolv.h>
#include <getopt.h>
#include <fcntl.h>
static char version[] = "0.5";
static char version[] = "0.7";
#define PROTO_TCP 1
#define PROTO_UDP 2
@@ -44,6 +48,7 @@ void usage();
int o_verbose = 0;
int o_udp = 0;
int o_delay = 0;
int main(int argc, char** argv)
{
@@ -55,12 +60,13 @@ int main(int argc, char** argv)
{
{"verbose", no_argument, 0, 'v'},
{"udp", no_argument, 0, 'u'},
{"delay", required_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
while((opt = getopt_long(argc, argv, "vuhV", opts, &optidx))) {
while((opt = getopt_long(argc, argv, "vud:hV", opts, &optidx))) {
if(opt < 0) {
break;
}
@@ -68,6 +74,7 @@ int main(int argc, char** argv)
case 0: break;
case 'v': o_verbose = 1; break;
case 'u': o_udp = 1; break;
case 'd': o_delay = (int)atoi(optarg); break;
case 'V': ver();
case 'h': /* fallthrough */
default: usage();
@@ -77,6 +84,11 @@ int main(int argc, char** argv)
usage();
}
if(o_delay < 0) {
fprintf(stderr, "error: delay cannot be negative\n");
exit(1);
}
host = gethostbyname(argv[optind++]);
if(host == NULL) {
fprintf(stderr, "Cannot resolve hostname\n");
@@ -98,16 +110,16 @@ int main(int argc, char** argv)
} else {
port = atoi(arg);
}
if(o_udp || proto == PROTO_UDP) {
sd = socket(PF_INET, SOCK_DGRAM, 0);
sd = socket(PF_INET, SOCK_DGRAM, 0);
if(sd == -1) {
fprintf(stderr, "Cannot open socket\n");
exit(1);
}
} else {
int flags;
sd = socket(PF_INET, SOCK_STREAM, 0);
sd = socket(PF_INET, SOCK_STREAM, 0);
if(sd == -1) {
fprintf(stderr, "Cannot open socket\n");
exit(1);
@@ -121,13 +133,13 @@ int main(int argc, char** argv)
addr.sin_port = htons(port);
if(o_udp || proto == PROTO_UDP) {
vprint("hitting udp %s:%u\n", inet_ntoa(addr.sin_addr), port);
connect(sd, (struct sockaddr*)&addr, sizeof(struct sockaddr));
send(sd, NULL, 0, MSG_DONTWAIT);
sendto(sd, "", 1, 0, (struct sockaddr*)&addr, sizeof(addr));
} else {
vprint("hitting tcp %s:%u\n", inet_ntoa(addr.sin_addr), port);
connect(sd, (struct sockaddr*)&addr, sizeof(struct sockaddr));
}
close(sd);
usleep(1000*o_delay);
}
return(0);
@@ -148,6 +160,7 @@ void usage() {
printf("usage: knock [options] <host> <port[:proto]> [port[:proto]] ...\n");
printf("options:\n");
printf(" -u, --udp make all ports hits use UDP (default is TCP)\n");
printf(" -d, --delay <t> wait <t> milliseconds between port hits\n");
printf(" -v, --verbose be verbose\n");
printf(" -V, --version display version\n");
printf(" -h, --help this help\n");
@@ -159,7 +172,7 @@ void usage() {
void ver() {
printf("knock %s\n", version);
printf("Copyright (C) 2004-2005 Judd Vinet <jvinet@zeroflux.org>\n");
printf("Copyright (C) 2004-2012 Judd Vinet <jvinet@zeroflux.org>\n");
exit(0);
}

View File

@@ -1,8 +1,8 @@
/*
* knockd.c
*
* Copyright (c) 2004-2005 by Judd Vinet <jvinet@zeroflux.org>
*
*
* Copyright (c) 2004-2012 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
@@ -28,6 +28,9 @@
#include <ctype.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
@@ -35,8 +38,6 @@
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <net/if.h>
#include <bits/time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
@@ -48,7 +49,7 @@
#include <errno.h>
#include "list.h"
static char version[] = "0.5";
static char version[] = "0.7";
#define SEQ_TIMEOUT 25 /* default knock timeout in seconds */
#define CMD_TIMEOUT 10 /* default timeout in seconds between start and stop commands */
@@ -66,6 +67,7 @@ typedef struct opendoor {
unsigned short seqcount;
unsigned short sequence[SEQ_MAX];
unsigned short protocol[SEQ_MAX];
char *target;
time_t seq_timeout;
char *start_command;
time_t cmd_timeout;
@@ -81,7 +83,7 @@ typedef struct opendoor {
} opendoor_t;
PMList *doors = NULL;
/* we keep one list of knock attempts, one per IP address,
/* we keep one list of knock attempts per IP address,
* and increment the stage as they progress through the sequence.
*/
typedef struct knocker {
@@ -100,9 +102,9 @@ void logprint(char *fmt, ...);
void dprint_sequence(opendoor_t *door, char *fmt, ...);
void cleanup(int signum);
void child_exit(int signum);
void read_cfg(int signum);
void reload(int signum);
void ver();
void usage();
void usage(int exit_code);
char* strtoupper(char *str);
char* trim(char *str);
void runCommand(char *cmd);
@@ -115,10 +117,10 @@ long get_current_one_time_sequence_position(opendoor_t *door);
void generate_pcap_filter();
size_t realloc_strcat(char **dest, const char *src, size_t size);
void close_door(opendoor_t *door);
char* get_ip(const char* iface, char *buf, int bufsize);
size_t parse_cmd(char* dest, size_t size, const char* command, const char* src);
int exec_cmd(char* command, char* name);
void sniff(u_char* arg, const struct pcap_pkthdr* hdr, const u_char* packet);
char* get_ip(const char *iface, char *buf, int bufsize);
size_t parse_cmd(char *dest, size_t size, const char *command, const char *src);
int exec_cmd(char *command, char *name);
void sniff(u_char *arg, const struct pcap_pkthdr *hdr, const u_char *packet);
pcap_t *cap = NULL;
FILE *logfd = NULL;
@@ -139,6 +141,7 @@ int main(int argc, char **argv)
{
char pcapErr[PCAP_ERRBUF_SIZE] = "";
int opt, ret, optidx = 1;
static struct option opts[] =
{
{"verbose", no_argument, 0, 'v'},
@@ -148,11 +151,13 @@ int main(int argc, char **argv)
{"interface", required_argument, 0, 'i'},
{"config", required_argument, 0, 'c'},
{"help", no_argument, 0, 'h'},
{"pidfile", required_argument, 0, 'p'},
{"logfile", required_argument, 0, 'g'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
while((opt = getopt_long(argc, argv, "vDdli:c:hV", opts, &optidx))) {
while((opt = getopt_long(argc, argv, "vDdli:c:p:g:hV", opts, &optidx))) {
if(opt < 0) {
break;
}
@@ -168,15 +173,22 @@ int main(int argc, char **argv)
case 'c': strncpy(o_cfg, optarg, sizeof(o_cfg)-1);
o_cfg[sizeof(o_cfg)-1] = '\0';
break;
case 'p': strncpy(o_pidfile, optarg, sizeof(o_pidfile)-1);
o_pidfile[sizeof(o_pidfile)-1] = '\0';
break;
case 'g': strncpy(o_logfile, optarg, sizeof(o_logfile)-1);
o_logfile[sizeof(o_logfile)-1] = '\0';
break;
case 'V': ver();
case 'h': /* fallthrough */
default: usage();
default: usage(0);
}
}
if(parseconfig(o_cfg)) {
exit(1);
usage(1);
}
/* set o_int to a default value if it has not been set by the -i switch nor by
* the config file */
if(strlen(o_int) == 0) {
@@ -193,7 +205,9 @@ int main(int argc, char **argv)
}
}
cap = pcap_open_live(o_int, 65535, 0, 0, pcapErr);
/* 50ms timeout for packet capture. See pcap(3pcap) manpage, which
* recommends that a timeout of 0 not be used. */
cap = pcap_open_live(o_int, 65535, 0, 50, pcapErr);
if(strlen(pcapErr)) {
fprintf(stderr, "could not open %s: %s\n", o_int, pcapErr);
}
@@ -212,7 +226,7 @@ int main(int argc, char **argv)
case DLT_RAW:
dprint("raw interface detected, no encapsulation\n");
break;
default:
default:
fprintf(stderr, "error: unsupported link-layer type: %d\n", lltype);
cleanup(1);
break;
@@ -247,7 +261,7 @@ int main(int argc, char **argv)
signal(SIGINT, cleanup);
signal(SIGTERM, cleanup);
signal(SIGCHLD, child_exit);
signal(SIGHUP, read_cfg);
signal(SIGHUP, reload);
vprint("listening on %s...\n", o_int);
logprint("starting up, listening on %s", o_int);
@@ -301,7 +315,7 @@ void logprint(char *fmt, ...)
struct tm *tm;
t = time(NULL);
tm = localtime(&t);
fprintf(logfd, "[%04d-%02d-%02d %02d:%02d] %s\n", tm->tm_year+1900,
tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, msg);
fflush(logfd);
@@ -357,7 +371,7 @@ void child_exit(int signum)
return;
}
void read_cfg(int signum)
void reload(int signum)
{
PMList *lp;
opendoor_t *door;
@@ -372,10 +386,23 @@ void read_cfg(int signum)
list_free(doors);
parseconfig(o_cfg);
vprint("Closing and re-opening log file: %s\n", o_logfile);
logprint("Closing and re-opening log file: %s\n", o_logfile);
/* close and re-open the log file */
if(logfd) {
fclose(logfd);
}
logfd = fopen(o_logfile, "a");
if(logfd == NULL) {
perror("warning: cannot open logfile");
}
return;
}
void usage() {
void usage(int exit_code) {
printf("usage: knockd [options]\n");
printf("options:\n");
printf(" -i, --interface <int> network interface to listen on (default \"eth0\")\n");
@@ -383,16 +410,18 @@ void usage() {
printf(" -c, --config <file> use an alternate config file\n");
printf(" -D, --debug output debug messages\n");
printf(" -l, --lookup lookup DNS names (may be a security risk)\n");
printf(" -p, --pidfile use an alternate pidfile\n");
printf(" -g, --logfile use an alternate logfile\n");
printf(" -v, --verbose be verbose\n");
printf(" -V, --version display version\n");
printf(" -h, --help this help\n");
printf("\n");
exit(1);
exit(exit_code);
}
void ver() {
printf("knockd %s\n", version);
printf("Copyright (C) 2004-2005 Judd Vinet <jvinet@zeroflux.org>\n");
printf("Copyright (C) 2004-2012 Judd Vinet <jvinet@zeroflux.org>\n");
exit(0);
}
@@ -420,7 +449,7 @@ char* trim(char *str)
if(pch != str) {
memmove(str, pch, (strlen(pch) + 1));
}
pch = (char*)(str + (strlen(str) - 1));
while(isspace(*pch)) {
pch--;
@@ -474,6 +503,7 @@ int parseconfig(char *configfile)
}
strncpy(door->name, section, sizeof(door->name)-1);
door->name[sizeof(door->name)-1] = '\0';
door->target = 0;
door->seqcount = 0;
door->seq_timeout = SEQ_TIMEOUT; /* default sequence timeout (seconds) */
door->start_command = NULL;
@@ -503,7 +533,7 @@ int parseconfig(char *configfile)
dprint("config: usesyslog\n");
} else {
fprintf(stderr, "config: line %d: syntax error\n", linenum);
return(1);
return(1);
}
} else {
trim(ptr);
@@ -533,7 +563,15 @@ int parseconfig(char *configfile)
linenum, key);
return(1);
}
if(!strcmp(key, "SEQUENCE")) {
if(!strcmp(key, "TARGET")) {
door->target = malloc(sizeof(char) * (strlen(ptr)+1));
if(door->target == NULL) {
perror("malloc");
exit(1);
}
strcpy(door->target, ptr);
dprint("config: %s: target: %s\n", door->name, door->target);
} else if(!strcmp(key, "SEQUENCE")) {
int i;
i = parse_port_sequence(ptr, door);
if (i > 0) {
@@ -681,7 +719,7 @@ int get_new_one_time_sequence(opendoor_t *door)
return(1);
}
dprint_sequence(door, "new sequence for door %s: ", door->name);
return(0);
}
@@ -694,7 +732,7 @@ long get_next_one_time_sequence(opendoor_t *door)
{
char line[PATH_MAX+1];
int pos;
pos = ftell(door->one_time_sequences_fd);
while(fgets(line, PATH_MAX, door->one_time_sequences_fd)) {
trim(line);
@@ -746,7 +784,7 @@ long get_current_one_time_sequence_position(opendoor_t *door)
rewind(door->one_time_sequences_fd);
pseudo_door.one_time_sequences_fd = door->one_time_sequences_fd;
pos = get_next_one_time_sequence(&pseudo_door);
while(pos >= 0) {
if(door->seqcount == pseudo_door.seqcount) {
@@ -768,20 +806,18 @@ long get_current_one_time_sequence_position(opendoor_t *door)
*/
void generate_pcap_filter()
{
/* NOTE: We're doing string manipulations in a daemon -- use defensive programming! */
PMList *lp;
opendoor_t *door;
char *buffer = NULL; /* temporary buffer to create the individual filter strings */
size_t bufsize = 0; /* size of buffer */
char port_str[10]; /* used by snprintf to convert unsigned short --> string */
short head_set = 0; /* flag indicating if protocol head is set (i.e. "((tcp dst port") */
short tcp_present = 0; /* flag indicating if TCP is used */
short udp_present = 0; /* flag indicating if UDP is used */
char *buffer = NULL; /* temporary buffer to create the individual filter strings */
size_t bufsize = 0; /* size of buffer */
char port_str[10]; /* used by snprintf to convert unsigned short --> string */
short head_set = 0; /* flag indicating if protocol head is set (i.e. "((tcp dst port") */
short tcp_present = 0; /* flag indicating if TCP is used */
short udp_present = 0; /* flag indicating if UDP is used */
unsigned int i;
short modified_filters = 0; /* flag indicating if at least one filter has changed --> recompile the filter */
struct bpf_program bpf_prog; /* compiled BPF filter program */
short modified_filters = 0; /* flag indicating if at least one filter has changed --> recompile the filter */
struct bpf_program bpf_prog; /* compiled BPF filter program */
/* generate subfilters for each door having a NULL pcap_filter_exp
*
* Example filter for one single door:
@@ -796,11 +832,11 @@ void generate_pcap_filter()
/* if we get here at least one door had a pcap_filter_exp == NULL */
modified_filters = 1;
head_set = 0;
tcp_present = 0;
udp_present = 0;
/* allocate memory for buffer if needed.
* The first allocation will be 200 Bytes (should be large enough for common sequences). If there is
* not enough space, a call to realloc_strcat() will eventually increase its size. The buffer will be
@@ -815,6 +851,10 @@ void generate_pcap_filter()
buffer[0] = '\0';
}
bufsize = realloc_strcat(&buffer, "(dst host ", bufsize); /* accept only incoming packets */
bufsize = realloc_strcat(&buffer, door->target ? door->target : myip, bufsize);
bufsize = realloc_strcat(&buffer, " and (", bufsize);
/* generate filter for all TCP ports (i.e. "((tcp dst port 4000 or 4001 or 4002) and tcp[tcpflags] & tcp-syn != 0)" */
for(i = 0; i < door->seqcount; i++) {
if(door->protocol[i] == IPPROTO_TCP) {
@@ -913,7 +953,9 @@ void generate_pcap_filter()
if(udp_present) {
bufsize = realloc_strcat(&buffer, ")", bufsize); /* close parentheses of UDP ports */
}
bufsize = realloc_strcat(&buffer, "))", bufsize); /* close parantheses around port filters */
/* test if in any of the precedent calls to realloc_strcat() failed. We can do this safely here because
* realloc_strcat() returns 0 on failure and if a buffer size of 0 is passed to it, the function does
* nothing but returning 0 again. Because we never read buffer in the above code, it is secure to test
@@ -930,8 +972,8 @@ void generate_pcap_filter()
perror("malloc");
cleanup(1);
}
strcpy(door->pcap_filter_exp, buffer);
strcpy(door->pcap_filter_exp, buffer);
dprint("Adding pcap expression for door '%s': %s\n", door->name, door->pcap_filter_exp);
buffer[0] = '\0'; /* "clear" the buffer */
}
@@ -949,9 +991,6 @@ void generate_pcap_filter()
* )
*/
if(modified_filters) {
bufsize = realloc_strcat(&buffer, "dst host ", bufsize); /* accept only incoming packets */
bufsize = realloc_strcat(&buffer, myip, bufsize);
bufsize = realloc_strcat(&buffer, " and (", bufsize);
/* iterate over all doors */
for(lp = doors; lp; lp = lp->next) {
door = (opendoor_t*)lp->data;
@@ -960,7 +999,6 @@ void generate_pcap_filter()
bufsize = realloc_strcat(&buffer, " or ", bufsize);
}
}
bufsize = realloc_strcat(&buffer, ")", bufsize); /* close parantheses around port filters */
/* test if in any of the precedent calls to realloc_strcat() failed. See above why this is ok to do this only
* at this point */
@@ -1005,7 +1043,7 @@ size_t realloc_strcat(char **dest, const char *src, size_t size)
needed_size = strlen(*dest) + strlen(src) + 1; /* '+ 1' for '\0' */
new_size = size;
while(needed_size > new_size) {
new_size *= 2;
}
@@ -1018,7 +1056,7 @@ size_t realloc_strcat(char **dest, const char *src, size_t size)
/* now dest is large enough to strcat() the src */
strcat(*dest, src);
return new_size;
}
@@ -1027,19 +1065,14 @@ size_t realloc_strcat(char **dest, const char *src, size_t size)
void close_door(opendoor_t *door)
{
doors = list_remove(doors, door);
if (door) {
if (door->start_command) {
free(door->start_command);
}
if (door->stop_command) {
free(door->stop_command);
}
if(door) {
free(door->target);
free(door->start_command);
free(door->stop_command);
if (door->one_time_sequences_fd) {
fclose(door->one_time_sequences_fd);
}
if (door->pcap_filter_exp) {
free(door->pcap_filter_exp);
}
free(door->pcap_filter_exp);
free(door);
}
}
@@ -1093,24 +1126,30 @@ size_t parse_cmd(char* dest, size_t size, const char* command, const char* src)
size_t n = size;
size_t command_len = strlen(command);
size_t total_len = 0;
int size_larger_than_zero = 1; /* allows us to calculate total length of result string even if the size is zero
by setting n to 1 (--> noting will be ever written to dest) */
/* allows us to calculate total length of result string even if the size */
/* is zero by setting n to 1 (--> noting will be ever written to dest) */
int size_larger_than_zero = 1;
if(size == 0) {
size_larger_than_zero = 0;
n = 1;
}
token = strstr(c, "%IP%"); /* get location of first token */
/* get location of first token */
token = strstr(c, "%IP%");
if(!token) {
token = (char*) (c + command_len + 1); /* point token past command (we won't access it anymore) */
/* point token past command (we won't access it anymore) */
token = (char*) (c + command_len + 1);
}
while(*c != '\0') {
if(c < token) { /* not reached a token yet --> append from command */
/* not reached a token yet --> append from command */
if(c < token) {
if(n != 1) {
*d++ = *c;
n--;
}
} else { /* we reached a token --> append from src */
} else {
/* we reached a token --> append from src */
while(*s != '\0') {
if(n != 1) {
*d++ = *s;
@@ -1119,19 +1158,21 @@ size_t parse_cmd(char* dest, size_t size, const char* command, const char* src)
s++;
total_len++;
}
c += 4; /* skip the token in command */
s = src; /* "rewind" src string for next token */
token = strstr(c, "%IP%"); /* get location of next token */
c += 4; /* skip the token in command */
s = src; /* "rewind" src string for next token */
token = strstr(c, "%IP%"); /* get location of next token */
if(!token) {
token = (char*) (c + command_len + 1); /* point token past command (we won't access it anymore) */
/* point token past command (we won't access it anymore) */
token = (char*) (c + command_len + 1);
}
c--; /* compensate for the following c++ */
total_len--; /* compensate for the following total_len++ */
c--; /* compensate for the following c++ */
total_len--; /* compensate for the following total_len++ */
}
c++;
total_len++;
}
if(size_larger_than_zero) { /* terminate dest if its size is larger than 0 */
if(size_larger_than_zero) {
/* terminate dest if its size is larger than 0 */
*d = '\0';
}
@@ -1156,13 +1197,171 @@ int exec_cmd(char* command, char* name){
return ret;
}
/*
* If examining a TCP packet, try to match flags against those in
* the door config.
*/
int flags_match(opendoor_t* door, struct ip* ip, struct tcphdr* tcp)
{
/* if tcp, check the flags to ignore the packets we don't want
* (don't even use it to cancel sequences)
*/
if(ip->ip_p == IPPROTO_TCP) {
if(door->flag_fin != DONT_CARE) {
if(door->flag_fin == SET && !(tcp->th_flags & TH_FIN)) {
dprint("packet is not FIN, ignoring...\n");
return 0;
}
if(door->flag_fin == NOT_SET && (tcp->th_flags & TH_FIN)) {
dprint("packet is not !FIN, ignoring...\n");
return 0;
}
}
if(door->flag_syn != DONT_CARE) {
if(door->flag_syn == SET && !(tcp->th_flags & TH_SYN)) {
dprint("packet is not SYN, ignoring...\n");
return 0;
}
if(door->flag_syn == NOT_SET && (tcp->th_flags & TH_SYN)) {
dprint("packet is not !SYN, ignoring...\n");
return 0;
}
}
if(door->flag_rst != DONT_CARE) {
if(door->flag_rst == SET && !(tcp->th_flags & TH_RST)) {
dprint("packet is not RST, ignoring...\n");
return 0;
}
if(door->flag_rst == NOT_SET && (tcp->th_flags & TH_RST)) {
dprint("packet is not !RST, ignoring...\n");
return 0;
}
}
if(door->flag_psh != DONT_CARE) {
if(door->flag_psh == SET && !(tcp->th_flags & TH_PUSH)) {
dprint("packet is not PSH, ignoring...\n");
return 0;
}
if(door->flag_psh == NOT_SET && (tcp->th_flags & TH_PUSH)) {
dprint("packet is not !PSH, ignoring...\n");
return 0;
}
}
if(door->flag_ack != DONT_CARE) {
if(door->flag_ack == SET && !(tcp->th_flags & TH_ACK)) {
dprint("packet is not ACK, ignoring...\n");
return 0;
}
if(door->flag_ack == NOT_SET && !(tcp->th_flags & TH_ACK)) {
dprint("packet is not !ACK, ignoring...\n");
return 0;
}
}
if(door->flag_urg != DONT_CARE) {
if(door->flag_urg == SET && !(tcp->th_flags & TH_URG)) {
dprint("packet is not URG, ignoring...\n");
return 0;
}
if(door->flag_urg == NOT_SET && !(tcp->th_flags & TH_URG)) {
dprint("packet is not !URG, ignoring...\n");
return 0;
}
}
}
return 1;
}
/**
* Process a knock attempt to see if the knocker has graduated to the next
* sequence. If they've completed all sequences correctly, then we open the
* door.
*/
void process_attempt(knocker_t *attempt)
{
/* level up! */
attempt->stage++;
if(attempt->srchost) {
vprint("%s (%s): %s: Stage %d\n", attempt->src, attempt->srchost, attempt->door->name, attempt->stage);
logprint("%s (%s): %s: Stage %d", attempt->src, attempt->srchost, attempt->door->name, attempt->stage);
} else {
vprint("%s: %s: Stage %d\n", attempt->src, attempt->door->name, attempt->stage);
logprint("%s: %s: Stage %d", attempt->src, attempt->door->name, attempt->stage);
}
if(attempt->stage >= attempt->door->seqcount) {
if(attempt->srchost) {
vprint("%s (%s): %s: OPEN SESAME\n", attempt->src, attempt->srchost, attempt->door->name);
logprint("%s (%s): %s: OPEN SESAME", attempt->src, attempt->srchost, attempt->door->name);
} else {
vprint("%s: %s: OPEN SESAME\n", attempt->src, attempt->door->name);
logprint("%s: %s: OPEN SESAME", attempt->src, attempt->door->name);
}
if(attempt->door->start_command && strlen(attempt->door->start_command)) {
/* run the associated command */
if(fork() == 0) {
/* child */
char parsed_start_cmd[PATH_MAX];
char parsed_stop_cmd[PATH_MAX];
size_t cmd_len = 0;
setsid();
/* parse start and stop command and check if the parsed commands fit in the given buffer. Don't
* execute any command if one of them has been truncated */
cmd_len = parse_cmd(parsed_start_cmd, sizeof(parsed_start_cmd), attempt->door->start_command, attempt->src);
if(cmd_len >= sizeof(parsed_start_cmd)) { /* command has been truncated --> do NOT execute it */
fprintf(stderr, "error: parsed start command has been truncated! --> won't execute it\n");
logprint("error: parsed start command has been truncated! --> won't execute it");
exit(0); /* exit child */
}
if(attempt->door->stop_command) {
cmd_len = parse_cmd(parsed_stop_cmd, sizeof(parsed_stop_cmd), attempt->door->stop_command, attempt->src);
if(cmd_len >= sizeof(parsed_stop_cmd)) { /* command has been truncated --> do NOT execute it */
fprintf(stderr, "error: parsed stop command has been truncated! --> won't execute start command\n");
logprint("error: parsed stop command has been truncated! --> won't execute start command");
exit(0); /* exit child */
}
}
/* all parsing ok --> execute the parsed (%IP% = source IP) command */
exec_cmd(parsed_start_cmd, attempt->door->name);
/* if stop_command is set, sleep for cmd_timeout and run it*/
if(attempt->door->stop_command){
sleep(attempt->door->cmd_timeout);
if(attempt->srchost) {
vprint("%s (%s): %s: command timeout\n", attempt->src, attempt->srchost, attempt->door->name);
logprint("%s (%s): %s: command timeout", attempt->src, attempt->srchost, attempt->door->name);
} else {
vprint("%s: %s: command timeout\n", attempt->src, attempt->door->name);
logprint("%s: %s: command timeout", attempt->src, attempt->door->name);
}
exec_cmd(parsed_stop_cmd, attempt->door->name);
}
exit(0); /* exit child */
}
}
/* change to next sequence if one time sequences are used.
* Note that here the door will eventually be closed in
* get_new_one_time_sequence() if no more sequences are left */
if(attempt->door->one_time_sequences_fd) {
disable_used_one_time_sequence(attempt->door);
get_new_one_time_sequence(attempt->door);
/* update pcap filter */
free(attempt->door->pcap_filter_exp);
attempt->door->pcap_filter_exp = NULL;
generate_pcap_filter();
}
}
}
/* Sniff an interface, looking for port-knock sequences
*/
void sniff(u_char* arg, const struct pcap_pkthdr* hdr, const u_char* packet)
{
/* packet structs */
struct ethhdr* eth = NULL;
struct iphdr* ip = NULL;
struct ether_header* eth = NULL;
struct ip* ip = NULL;
struct tcphdr* tcp = NULL;
struct udphdr* udp = NULL;
char proto[8];
@@ -1179,51 +1378,46 @@ void sniff(u_char* arg, const struct pcap_pkthdr* hdr, const u_char* packet)
knocker_t *attempt = NULL;
if(lltype == DLT_EN10MB) {
eth = (struct ethhdr*)packet;
if(ntohs(eth->h_proto) != ETH_P_IP) {
eth = (struct ether_header*)packet;
if(ntohs(eth->ether_type) != ETHERTYPE_IP) {
return;
}
ip = (struct iphdr*)(packet + sizeof(struct ethhdr));
ip = (struct ip*)(packet + sizeof(struct ether_header));
#ifdef __linux__
} else if(lltype == DLT_LINUX_SLL) {
ip = (struct iphdr*)((u_char*)packet + 16);
ip = (struct ip*)((u_char*)packet + 16);
#endif
} else if(lltype == DLT_RAW) {
ip = (struct iphdr*)((u_char*)packet);
ip = (struct ip*)((u_char*)packet);
} else {
dprint("link layer header type of packet not recognized, ignoring...\n");
return;
}
if(ip->version != 4) {
if(ip->ip_v != 4) {
/* no IPv6 yet */
dprint("packet is not IPv4, ignoring...\n");
return;
}
if(ip->protocol == IPPROTO_ICMP) {
if(ip->ip_p == IPPROTO_ICMP) {
/* we don't do ICMP */
return;
}
/* make sure this packet was sent TO us, not FROM us or THROUGH us.
* Actually the pcap filter will take care of forwarding only packets
* destined for us, but another check won't hurt... */
if(inet_aton(myip, &inaddr) == 0) {
fprintf(stderr, "error: could not understand IP address: %s\n", myip);
return;
}
if(ip->daddr != inaddr.s_addr) {
dprint("packet destined for another host, ignoring...\n");
return;
}
sport = dport = 0;
if(ip->protocol == IPPROTO_TCP) {
if(ip->ip_p == IPPROTO_TCP) {
strncpy(proto, "tcp", sizeof(proto));
tcp = (struct tcphdr*)((u_char*)ip + (ip->ihl * 4));
sport = ntohs(tcp->source);
dport = ntohs(tcp->dest);
tcp = (struct tcphdr*)((u_char*)ip + (ip->ip_hl *4));
sport = ntohs(tcp->th_sport);
dport = ntohs(tcp->th_dport);
}
if(ip->protocol == IPPROTO_UDP) {
if(ip->ip_p == IPPROTO_UDP) {
strncpy(proto, "udp", sizeof(proto));
udp = (struct udphdr*)((u_char*)ip + (ip->ihl * 4));
sport = ntohs(udp->source);
dport = ntohs(udp->dest);
udp = (struct udphdr*)((u_char*)ip + (ip->ip_hl * 4));
sport = ntohs(udp->uh_sport);
dport = ntohs(udp->uh_dport);
}
/* get the date/time */
@@ -1234,10 +1428,10 @@ void sniff(u_char* arg, const struct pcap_pkthdr* hdr, const u_char* packet)
pkt_tm->tm_sec);
/* convert IPs from binary to string */
inaddr.s_addr = ip->saddr;
inaddr.s_addr = ip->ip_src.s_addr;
strncpy(srcIP, inet_ntoa(inaddr), sizeof(srcIP)-1);
srcIP[sizeof(srcIP)-1] = '\0';
inaddr.s_addr = ip->daddr;
inaddr.s_addr = ip->ip_dst.s_addr;
strncpy(dstIP, inet_ntoa(inaddr), sizeof(dstIP)-1);
dstIP[sizeof(dstIP)-1] = '\0';
@@ -1286,156 +1480,19 @@ void sniff(u_char* arg, const struct pcap_pkthdr* hdr, const u_char* packet)
attempt = NULL;
/* look for this guy in our attempts list */
for(lp = attempts; lp; lp = lp->next) {
if(!strncmp(((knocker_t*)lp->data)->src, srcIP, sizeof(srcIP))) {
attempt = (knocker_t*)lp->data;
knocker_t *att = (knocker_t*)lp->data;
if(!strncmp(att->src, srcIP, sizeof(srcIP)) &&
!strncmp(att->door->target ? att->door->target : myip, dstIP, sizeof(dstIP))) {
attempt = att;
break;
}
}
if(attempt) {
int flagsmatch = 1;
/* if tcp, check the flags to ignore the packets we don't want
* (don't even use it to cancel sequences)
*/
if(ip->protocol == IPPROTO_TCP) {
if(attempt->door->flag_fin != DONT_CARE) {
if(attempt->door->flag_fin == SET && tcp->fin != 1) {
dprint("packet is not FIN, ignoring...\n");
flagsmatch = 0;
}
if(attempt->door->flag_fin == NOT_SET && tcp->fin == 1) {
dprint("packet is not !FIN, ignoring...\n");
flagsmatch = 0;
}
}
if(attempt->door->flag_syn != DONT_CARE) {
if(attempt->door->flag_syn == SET && tcp->syn != 1) {
dprint("packet is not SYN, ignoring...\n");
flagsmatch = 0;
}
if(attempt->door->flag_syn == NOT_SET && tcp->syn == 1) {
dprint("packet is not !SYN, ignoring...\n");
flagsmatch = 0;
}
}
if(attempt->door->flag_rst != DONT_CARE) {
if(attempt->door->flag_rst == SET && tcp->rst != 1) {
dprint("packet is not RST, ignoring...\n");
flagsmatch = 0;
}
if(attempt->door->flag_rst == NOT_SET && tcp->rst == 1) {
dprint("packet is not !RST, ignoring...\n");
flagsmatch = 0;
}
}
if(attempt->door->flag_psh != DONT_CARE) {
if(attempt->door->flag_psh == SET && tcp->psh != 1) {
dprint("packet is not PSH, ignoring...\n");
flagsmatch = 0;
}
if(attempt->door->flag_psh == NOT_SET && tcp->psh == 1) {
dprint("packet is not !PSH, ignoring...\n");
flagsmatch = 0;
}
}
if(attempt->door->flag_ack != DONT_CARE) {
if(attempt->door->flag_ack == SET && tcp->ack != 1) {
dprint("packet is not ACK, ignoring...\n");
flagsmatch = 0;
}
if(attempt->door->flag_ack == NOT_SET && tcp->ack == 1) {
dprint("packet is not !ACK, ignoring...\n");
flagsmatch = 0;
}
}
if(attempt->door->flag_urg != DONT_CARE) {
if(attempt->door->flag_urg == SET && tcp->urg != 1) {
dprint("packet is not URG, ignoring...\n");
flagsmatch = 0;
}
if(attempt->door->flag_urg == NOT_SET && tcp->urg == 1) {
dprint("packet is not !URG, ignoring...\n");
flagsmatch = 0;
}
}
}
if(flagsmatch && ip->protocol == attempt->door->protocol[attempt->stage] &&
int flagsmatch = flags_match(attempt->door, ip, tcp);
if(flagsmatch && ip->ip_p == attempt->door->protocol[attempt->stage] &&
dport == attempt->door->sequence[attempt->stage]) {
/* level up! */
attempt->stage++;
if(attempt->srchost) {
vprint("%s (%s): %s: Stage %d\n", attempt->src, attempt->srchost, attempt->door->name, attempt->stage);
logprint("%s (%s): %s: Stage %d", attempt->src, attempt->srchost, attempt->door->name, attempt->stage);
} else {
vprint("%s: %s: Stage %d\n", attempt->src, attempt->door->name, attempt->stage);
logprint("%s: %s: Stage %d", attempt->src, attempt->door->name, attempt->stage);
}
if(attempt->stage >= attempt->door->seqcount) {
if(attempt->srchost) {
vprint("%s (%s): %s: OPEN SESAME\n", attempt->src, attempt->srchost, attempt->door->name);
logprint("%s (%s): %s: OPEN SESAME", attempt->src, attempt->srchost, attempt->door->name);
} else {
vprint("%s: %s: OPEN SESAME\n", attempt->src, attempt->door->name);
logprint("%s: %s: OPEN SESAME", attempt->src, attempt->door->name);
}
if(attempt->door->start_command && strlen(attempt->door->start_command)) {
/* run the associated command */
if(fork() == 0) {
/* child */
char parsed_start_cmd[PATH_MAX];
char parsed_stop_cmd[PATH_MAX];
size_t cmd_len = 0;
setsid();
/* parse start and stop command and check if the parsed commands fit in the given buffer. Don't
* execute any command if one of them has been truncated */
cmd_len = parse_cmd(parsed_start_cmd, sizeof(parsed_start_cmd), attempt->door->start_command, attempt->src);
if(cmd_len >= sizeof(parsed_start_cmd)) { /* command has been truncated --> do NOT execute it */
fprintf(stderr, "error: parsed start command has been truncated! --> won't execute it\n");
logprint("error: parsed start command has been truncated! --> won't execute it");
exit(0); /* exit child */
}
if(attempt->door->stop_command) {
cmd_len = parse_cmd(parsed_stop_cmd, sizeof(parsed_stop_cmd), attempt->door->stop_command, attempt->src);
if(cmd_len >= sizeof(parsed_stop_cmd)) { /* command has been truncated --> do NOT execute it */
fprintf(stderr, "error: parsed stop command has been truncated! --> won't execute start command\n");
logprint("error: parsed stop command has been truncated! --> won't execute start command");
exit(0); /* exit child */
}
}
/* all parsing ok --> execute the parsed (%IP% = source IP) command */
exec_cmd(parsed_start_cmd, attempt->door->name);
/* if stop_command is set, sleep for cmd_timeout and run it*/
if(attempt->door->stop_command){
sleep(attempt->door->cmd_timeout);
if(attempt->srchost) {
vprint("%s (%s): %s: command timeout\n", attempt->src, attempt->srchost, attempt->door->name);
logprint("%s (%s): %s: command timeout", attempt->src, attempt->srchost, attempt->door->name);
} else {
vprint("%s: %s: command timeout\n", attempt->src, attempt->door->name);
logprint("%s: %s: command timeout", attempt->src, attempt->door->name);
}
exec_cmd(parsed_stop_cmd, attempt->door->name);
}
exit(0); /* exit child */
}
}
/* change to next sequence if one time sequences are used.
* Note that here the door will eventually be closed in
* get_new_one_time_sequence() if no more sequences are left */
if(attempt->door->one_time_sequences_fd) {
disable_used_one_time_sequence(attempt->door);
get_new_one_time_sequence(attempt->door);
/* update pcap filter */
free(attempt->door->pcap_filter_exp);
attempt->door->pcap_filter_exp = NULL;
generate_pcap_filter();
}
}
process_attempt(attempt);
} else if(flagsmatch == 0) {
/* TCP flags didn't match -- just ignore this packet, don't
* invalidate the knock.
@@ -1451,34 +1508,11 @@ void sniff(u_char* arg, const struct pcap_pkthdr* hdr, const u_char* packet)
for(lp = doors; lp; lp = lp->next) {
opendoor_t *door = (opendoor_t*)lp->data;
/* if we're working with TCP, try to match the flags */
if(ip->protocol == IPPROTO_TCP){
if(door->flag_fin != DONT_CARE) {
if(door->flag_fin == SET && tcp->fin != 1) {dprint("packet is not FIN, ignoring...\n");continue;}
if(door->flag_fin == NOT_SET && tcp->fin == 1) {dprint("packet is not !FIN, ignoring...\n");continue;}
}
if(door->flag_syn != DONT_CARE) {
if(door->flag_syn == SET && tcp->syn != 1) {dprint("packet is not SYN, ignoring...\n");continue;}
if(door->flag_syn == NOT_SET && tcp->syn == 1) {dprint("packet is not !SYN, ignoring...\n");continue;}
}
if(door->flag_rst != DONT_CARE) {
if(door->flag_rst == SET && tcp->rst != 1) {dprint("packet is not RST, ignoring...\n");continue;}
if(door->flag_rst == NOT_SET && tcp->rst == 1) {dprint("packet is not !RST, ignoring...\n");continue;}
}
if(door->flag_psh != DONT_CARE) {
if(door->flag_psh == SET && tcp->psh != 1) {dprint("packet is not PSH, ignoring...\n");continue;}
if(door->flag_psh == NOT_SET && tcp->psh == 1) {dprint("packet is not !PSH, ignoring...\n");continue;}
}
if(door->flag_ack != DONT_CARE) {
if(door->flag_ack == SET && tcp->ack != 1) {dprint("packet is not ACK, ignoring...\n");continue;}
if(door->flag_ack == NOT_SET && tcp->ack == 1) {dprint("packet is not !ACK, ignoring...\n");continue;}
}
if(door->flag_urg != DONT_CARE) {
if(door->flag_urg == SET && tcp->urg != 1) {dprint("packet is not URG, ignoring...\n");continue;}
if(door->flag_urg == NOT_SET && tcp->urg == 1) {dprint("packet is not !URG, ignoring...\n");continue;}
}
if(!flags_match(door, ip, tcp)) {
continue;
}
if(ip->protocol == door->protocol[0] && dport == door->sequence[0]) {
if(ip->ip_p == door->protocol[0] && dport == door->sequence[0] &&
!strcmp(dstIP, door->target ? door->target : myip)) {
struct hostent *he;
/* create a new entry */
attempt = (knocker_t*)malloc(sizeof(knocker_t));
@@ -1490,24 +1524,18 @@ void sniff(u_char* arg, const struct pcap_pkthdr* hdr, const u_char* packet)
strcpy(attempt->src, srcIP);
/* try a reverse lookup if enabled */
if (o_lookup) {
inaddr.s_addr = ip->saddr;
inaddr.s_addr = ip->ip_src.s_addr;
he = gethostbyaddr((void *)&inaddr, sizeof(inaddr), AF_INET);
if(he) {
attempt->srchost = strdup(he->h_name);
}
}
attempt->stage = 1;
attempt->stage = 0;
attempt->seq_start = pkt_secs;
attempt->door = door;
if(attempt->srchost) {
vprint("%s (%s): %s: Stage 1\n", attempt->src, attempt->srchost, door->name);
logprint("%s (%s): %s: Stage 1", attempt->src, attempt->srchost, door->name);
} else {
vprint("%s: %s: Stage 1\n", attempt->src, door->name);
logprint("%s: %s: Stage 1", attempt->src, door->name);
}
attempts = list_add(attempts, attempt);
process_attempt(attempt);
}
}
}