summaryrefslogtreecommitdiffstats
path: root/ncat
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 07:42:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 07:42:04 +0000
commit0d47952611198ef6b1163f366dc03922d20b1475 (patch)
tree3d840a3b8c0daef0754707bfb9f5e873b6b1ac13 /ncat
parentInitial commit. (diff)
downloadnmap-upstream.tar.xz
nmap-upstream.zip
Adding upstream version 7.94+git20230807.3be01efb1+dfsg.upstream/7.94+git20230807.3be01efb1+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ncat')
-rw-r--r--ncat/ChangeLog229
-rw-r--r--ncat/INSTALL19
-rw-r--r--ncat/LICENSE3
-rw-r--r--ncat/Makefile.in209
-rw-r--r--ncat/base64.c118
-rw-r--r--ncat/base64.h65
-rw-r--r--ncat/certs/README50
-rw-r--r--ncat/certs/ca-bundle.crt3240
-rwxr-xr-xncat/config.guess1421
-rw-r--r--ncat/config.h.in197
-rwxr-xr-xncat/config.sub1807
-rw-r--r--ncat/config_win.h66
-rwxr-xr-xncat/configure6596
-rw-r--r--ncat/configure.ac327
-rw-r--r--ncat/docs/AUTHORS28
-rw-r--r--ncat/docs/README146
-rw-r--r--ncat/docs/THANKS29
-rw-r--r--ncat/docs/examples/README15
-rw-r--r--ncat/docs/examples/ipaccess23
-rw-r--r--ncat/docs/examples/logs/ascii-output3
-rw-r--r--ncat/docs/examples/logs/hex-output47
-rw-r--r--ncat/docs/examples/scripts/README6
-rwxr-xr-xncat/docs/examples/scripts/http-proxy5
-rw-r--r--ncat/docs/examples/scripts/http-scan/README14
-rw-r--r--ncat/docs/examples/scripts/http-scan/get.request3
-rw-r--r--ncat/docs/examples/scripts/http-scan/iplist5
-rwxr-xr-xncat/docs/examples/scripts/http-scan/scan-example7
-rw-r--r--ncat/docs/examples/scripts/http-scan/scanner-output57
-rw-r--r--ncat/docs/ncat-ascii-art.txt11
-rw-r--r--ncat/docs/ncat.1787
-rw-r--r--ncat/docs/ncat.usage.txt57
-rw-r--r--ncat/docs/ncat.xml1225
-rw-r--r--ncat/docs/ncatguide.xml2008
-rw-r--r--ncat/docs/ncatguidehtml.xml12
-rw-r--r--ncat/docs/ncatmanhtml.xml12
-rw-r--r--ncat/http.c1633
-rw-r--r--ncat/http.h225
-rw-r--r--ncat/http_digest.c376
-rwxr-xr-xncat/missing198
-rwxr-xr-xncat/mkinstalldirs40
-rw-r--r--ncat/ncat.h218
-rw-r--r--ncat/ncat.vcxproj262
-rw-r--r--ncat/ncat_config.h72
-rw-r--r--ncat/ncat_connect.c1425
-rw-r--r--ncat/ncat_connect.h67
-rw-r--r--ncat/ncat_core.c645
-rw-r--r--ncat/ncat_core.h245
-rw-r--r--ncat/ncat_exec.h76
-rw-r--r--ncat/ncat_exec_win.c698
-rw-r--r--ncat/ncat_listen.c902
-rw-r--r--ncat/ncat_listen.h64
-rw-r--r--ncat/ncat_lua.c118
-rw-r--r--ncat/ncat_lua.h94
-rw-r--r--ncat/ncat_main.c1091
-rw-r--r--ncat/ncat_posix.c388
-rw-r--r--ncat/ncat_proxy.c867
-rw-r--r--ncat/ncat_proxy.h74
-rw-r--r--ncat/ncat_ssl.c669
-rw-r--r--ncat/ncat_ssl.h101
-rw-r--r--ncat/ncat_win.c116
-rw-r--r--ncat/scripts/chargen.lua7
-rw-r--r--ncat/scripts/conditional.lua51
-rw-r--r--ncat/scripts/date.lua3
-rw-r--r--ncat/scripts/discard.lua11
-rw-r--r--ncat/scripts/echo.lua16
-rw-r--r--ncat/scripts/hello-luaexec.lua4
-rw-r--r--ncat/scripts/httpd.lua402
-rw-r--r--ncat/scripts/log_ips.sh10
-rwxr-xr-xncat/scripts/p0fme.py97
-rw-r--r--ncat/scripts/whatismyip.lua4
-rw-r--r--ncat/sockaddr_u.h128
-rw-r--r--ncat/sys_wrap.c190
-rw-r--r--ncat/sys_wrap.h111
-rw-r--r--ncat/test/addrset.c104
-rwxr-xr-xncat/test/ncat-test.pl3283
-rwxr-xr-xncat/test/test-addrset.sh333
-rw-r--r--ncat/test/test-cert.pem47
-rw-r--r--ncat/test/test-cmdline-split.c100
-rw-r--r--ncat/test/test-environment.lua13
-rwxr-xr-xncat/test/test-environment.sh11
-rw-r--r--ncat/test/test-uri.c129
-rw-r--r--ncat/test/test-wildcard.c626
-rw-r--r--ncat/test/toupper.lua14
-rw-r--r--ncat/util.c773
-rw-r--r--ncat/util.h179
85 files changed, 36157 insertions, 0 deletions
diff --git a/ncat/ChangeLog b/ncat/ChangeLog
new file mode 100644
index 0000000..344fdad
--- /dev/null
+++ b/ncat/ChangeLog
@@ -0,0 +1,229 @@
+# Ncat Changelog ($Id$); -*-text-*-
+
+o Reworked the test program test/test-cmdline-split slightly and added
+ additional test cases. Rewrote cmdline_split in ncat_posix.c [Josh Marlow]
+
+o Added a test program, test/test-cmdline-split to test the cmdline_split
+ function in test/test-cmdline-split in preparation for an eventual rewrite of
+ cmdline_split [Josh Marlow].
+
+Ncat 0.2
+
+o Ported to Windows on Visual C++ Express 2008. Support isn't perfect because
+ of the lack of a fork() call and because we had to implement a hack to get
+ select()-like support for stdin on Windows, but most everything works fine.
+ We hope to get around these issues in the future. [Kris Katterjohn, Mixter]
+
+o Added IPv6 listen support (including --broker). Host access control is not
+ yet supported. [Kris]
+
+o Added SSL listen support (including --broker) [Kris]
+
+o Fixed SSL and IPv6 connect issues [Mixter]
+
+o Added IPv4 host access control to UDP listener and --broker [Kris]
+
+o Brokering mode now continually listens for connections rather than exiting
+ after the last client disconnects. [Kris]
+
+o Changed -l to mostly behave like OpenBSD Netcat. Instead of -l specifying
+ the local port number and -s specifying the local address to listen on, -l
+ is a non-option flag and you specify the local address/port like you do
+ a host to connect to in client-mode. [Kris]
+
+o Ncat's default port number is now 31337 instead of 5000. This because 5000
+ is used for other protocols, such as UPnP. [Kris]
+
+o Specifying no port number with -l now works to listen on Ncat's default
+ port number. The original Netcat seems to just use an ephemeral port in
+ this case, and other incarnations make you specify a port number. So now
+ you don't have to specify a host or port number with -l, in which case
+ Ncat listens on any address, port 31337. [Kris]
+
+o Fixed Ncat so that it actually works like it should when transferring a file
+ between instances. Running "ncat -l 3333 <input" and then connecting with
+ "ncat host 3333 >output" should send the input file from the server to the
+ client. However actually doing this would either silently fail or complain
+ about a broken pipe. Thanks to eldraco for reporting this problem. [Kris]
+
+o Client-mode Ncat now exits upon receipt of EOF from the network side [Kris]
+
+o Client-mode Ncat now just tries to read anything from the network (still via
+ the Nsock library) rather than reading in a line-based manner. While being
+ an improvement in its own right, this is especially helpful for the new
+ Telnet negotiation option. [Kris]
+
+o Increased the default network data buffer sizes (reading and writing) from
+ a measly 256 bytes to a more respectable 8K for TCP and 128K for UDP. UDP's
+ is this large because a read returns an entire datagram, or discards what's
+ left if there is no room. [Kris]
+
+o The proxy options have now changed. Instead of having separate option names
+ for all of the different types of proxy protocols that will be supported,
+ --proxy is available to specify the proxy address and optional port, and
+ --proxy-type is available to specify the proxy protocol to use. [Kris]
+
+o Added an HTTP proxy server feature, which creates a simple forking HTTP proxy
+ server on the listening port (only supports CONNECT). This is specified by
+ "--proxy-type http" in server mode. [Kris]
+
+o The SOCKSv4 proxy option is now specified by "--proxy-type socks4" instead
+ of --socks4-proxy. This option also now takes the username from --proxy-auth
+ rather than the previous user@host:port syntax. [Kris]
+
+o The HTTP proxy option is now specified by "--proxy-type http" instead of
+ --http-proxy. Also, the HTTP CONNECT request now uses CRLF for the EOL
+ instead of just LF. [Kris]
+
+o Removed the SOCKS proxy server support because it was broken, didn't have
+ any support for SOCKSv5, and we now have an HTTP proxy server for a similar
+ purpose. [Kris]
+
+o Fixed --proxy-auth which always caused a segmentation fault. [Kris]
+
+o Fixed an issue which commonly occurred when using --proxy-type socks4 and
+ when reading from a piped or redirected stdin. The problem was that Ncat
+ was sending the data read from stdin across the network before it was fully
+ connected to the proxy. Thanks to Jah for noticing this problem. [Kris]
+
+o The output options -o and -x are no longer mutually exclusive. Also, the
+ documented alias for -x (--hex-dump) now works. [Kris]
+
+o Renamed -t (--idle-timeout) to -i [Kris]
+
+o Added -t/--telnet to handle DO/DONT WILL/WONT Telnet negotiations [Kris]
+
+o Added -C/--crlf to try to use CRLF for line-endings. This comes in handy
+ when talking to some stringent servers directly from a terminal in one of
+ the many common plain-text protocols which specify CRLF as the required EOL
+ sequence. [Kris]
+
+o Added -w/--wait for specifying a connect timeout [Kris]
+
+o Added -g and -G for IPv4 loose source routing [Kris]
+
+o Added -p to specify a local port to bind to in client-mode [Kris]
+
+o Added -n/--nodns to not resolve any hostnames [Mixter]
+
+o Added -c/--sh-exec, which is like -e but executes via /bin/sh [Kris]
+
+o Made -s (set source address) actually work in client-mode [Kris]
+
+o Changed --recvonly and --sendonly to --recv-only and --send-only [Kris]
+
+o Options taking a time (-d, -i, -w) are now more flexible: you can append
+ an "s" for seconds, "m" for minutes or "h" for hours (e.g. 30s) [Kris]
+
+o Fixed a bug which could cause Nsock tracing (use of -v one or more times)
+ to print very inaccurate times [Kris]
+
+o Removed unused XOR code [Kris]
+
+o Added file dependency checking to the Makefile. So now, for instance, if
+ a header file is modified, running make again will recompile all of the
+ files which depend on it. [Kris]
+
+o Improved the build system by removing the automake requirement ([Mixter])
+ and by cutting down configure.ac and Makefile.in a lot ([Kris]). Other
+ various build/configure improvements were made as well.
+
+o Lots of documentation rewrites/updates, including separating the man page
+ into sections such as "Proxy Options", "Client-Mode Options", etc. [Kris]
+
+o Lots of code cleaning up [Kris]
+
+Ncat 0.10rc3
+
+o Autoconf build process. ./configure;make!
+
+o Fixed Segmentation faults on outgoing connections that appeared on on
+ certain platforms/architectures/compilers.
+
+o Improved overall build quality and portability to other platforms and
+ architectures. Should build on multiple different platforms quite well.
+
+o Fixed some bounds checking on a SOCKS4 server buffer in ncat_connect.c
+
+o Fixed some documentation typos and --help/usage typos.
+
+Ncat 0.10rc2
+
+o Fixed inetd-like support so executed programs actually exit when the
+ client does and don't hang.
+
+o Fixed some looping read/write issue with EOF handling.
+ -- Thanks to Sebastian Garcia.
+
+o Moved connect message "Lookup of $foo returned $bar" to the verbosity
+ output set instead of the default output.
+
+o Fixed bug in SOCKS4 server on rejected/refused connections.
+
+o First official release!
+
+Ncat 0.10rc1
+
+o Removed access to XOR code with a view to totally removing it in the next
+ release of Ncat
+
+o One or two minor bug fixes.
+
+Ncat 0.09
+
+o Added hexdump() support.
+
+o Added XOR cipher support.
+
+o Added --allow, --deny support IP address handling CIDR.
+
+o General code tidy up; better documentation in header file.
+
+o Various error messages cleaned up. Added new #define for NCAT_SHORT.
+
+o Added missing 'strerror(errno)' handling to some error messages.
+
+o Cleaned up various bits of code.
+
+o Reformatted code heavily into K&R layout.
+
+o Fixed XOR so it'll use longer passwords.
+
+o Worked on various cross-platform portability issues.
+ -- Thanks to Jonathan Saylor.
+
+Ncat 0.08
+
+o Added millisecond resolution timer for blocking read/writes.
+
+o Added HTTP/1.1 CONNECT method proxying support.
+
+o Added Base64 encoder for handling Proxy-Authorization support.
+
+o Support added for --broker, full I/O multiplexing support.
+
+o Added additional feature of --talk
+
+Ncat 0.07
+
+o Added feature of fork()'ing off on executing a 3rd party program to allow
+ continued incoming connections.
+
+o Added support for ASCII logging.
+
+o Added support for hexdump logging.
+
+o Various bits of code cleaned up.
+
+Ncat 0.06
+
+o Added --listen support.
+
+o Added TCP/UDP support for --listen.
+
+o Added command line parser for handling options to pass to the command to
+ be executed.
+
+o Polished up --help, --verbose & --version.
+
+
diff --git a/ncat/INSTALL b/ncat/INSTALL
new file mode 100644
index 0000000..b26ba77
--- /dev/null
+++ b/ncat/INSTALL
@@ -0,0 +1,19 @@
+Building Ncat
+=============
+
+On UNIX systems, ideally, you should just be able to do:
+
+./configure
+make
+
+After building is successful, to install:
+make install
+
+For instructions on how to build Ncat for Microsoft Windows or for far more
+in-depth compilation, installation, and removal notes, read the Nmap Install
+Guide at https://nmap.org/install/.
+
+For instructions on how to build Ncat Portable for Microsoft Windows, read
+the how-to available at https://secwiki.org/w/Nmap/Ncat_Portable.
+
+
diff --git a/ncat/LICENSE b/ncat/LICENSE
new file mode 100644
index 0000000..debee8f
--- /dev/null
+++ b/ncat/LICENSE
@@ -0,0 +1,3 @@
+Ncat is distributed under the same license terms as Nmap. See the
+LICENSE file in the Nmap tarball, the man page legal section, or
+https://nmap.org/man/man-legal.html .
diff --git a/ncat/Makefile.in b/ncat/Makefile.in
new file mode 100644
index 0000000..c8c3fb7
--- /dev/null
+++ b/ncat/Makefile.in
@@ -0,0 +1,209 @@
+# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Ncat Makefile
+
+
+SHELL = @SHELL@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+datarootdir = @datarootdir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+top_builddir = .
+
+pkgdatadir = $(datadir)/ncat
+
+INSTALL = @INSTALL@
+transform = @program_transform_name@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+mandir = @mandir@
+srcdir = @srcdir@
+
+NBASEDIR = ../nbase
+NSOCKDIR = ../nsock/src
+NSOCKLIB = $(NSOCKDIR)/libnsock.a
+NBASELIB = $(NBASEDIR)/libnbase.a
+
+CC = @CC@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+DEFS = @DEFS@ -DNCAT_DATADIR="\"$(pkgdatadir)\""
+# With GCC, add extra security checks to source code.
+DEFS += -D_FORTIFY_SOURCE=2
+INCLS = -I. -I.. -I../nsock/include/ -I$(NBASEDIR)
+RM = rm -f
+STRIP = @STRIP@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+HAVE_OPENSSL = @HAVE_OPENSSL@
+PCAP_LIBS = @PCAP_LIBS@
+NOLUA = @NOLUA@
+LIBLUADIR = @LIBLUADIR@
+LUA_CFLAGS = @LUA_CFLAGS@
+
+
+CPPFLAGS += $(DEFS) $(INCLS)
+
+SHTOOL = ../shtool
+
+# DESTDIR can be used by package maintainers to install Ncat under its
+# usual directory structure into a different tree.
+DESTDIR =
+
+SRCS = ncat_main.c ncat_connect.c ncat_core.c ncat_posix.c ncat_listen.c ncat_proxy.c ncat_ssl.c base64.c http.c util.c sys_wrap.c
+OBJS = ncat_main.o ncat_connect.o ncat_core.o ncat_posix.o ncat_listen.o ncat_proxy.o ncat_ssl.o base64.o http.o util.o sys_wrap.o
+DATAFILES =
+
+ifneq ($(HAVE_OPENSSL),)
+SRCS += http_digest.c
+OBJS += http_digest.o
+DATAFILES = certs/ca-bundle.crt
+endif
+
+ifneq ($(NOLUA),yes)
+LUA_SRCS = ncat_lua.c
+LUA_OBJS = ncat_lua.o
+LUA_LIBS = @LIBLUA_LIBS@ -lm
+LUA_CFLAGS += -DHAVE_LUA=1 -I../liblua
+else
+LUA_SRCS =
+LUA_OBJS =
+LUA_LIBS =
+LUA_CFLAGS =
+endif
+
+SRCS += $(LUA_SRCS)
+OBJS += $(LUA_OBJS)
+
+TARGET = ncat
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = $(CONFIG_HEADER) config.cache config.log config.status
+
+TEST_PROGS = test/addrset test/test-uri test/test-cmdline-split
+ifneq ($(HAVE_OPENSSL),)
+TEST_PROGS += test/test-wildcard
+endif
+
+all: $(TARGET)
+
+$(LIBLUADIR)/liblua.a: @LUA_BUILD@
+
+build-lua: $(LIBLUADIR)/Makefile
+ @echo Compiling liblua; cd $(LIBLUADIR) && $(MAKE) liblua.a CC="$(CC)" MYCFLAGS="$(CFLAGS) $(LUA_CFLAGS)"
+
+
+$(TARGET): @LUA_DEPENDS@ $(OBJS) $(NSOCKLIB)
+ $(CC) -o $@ $(CFLAGS) $(lua_cflags) $(LDFLAGS) $(OBJS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
+
+%.o: %.c
+ $(CC) $(CPPFLAGS) $(LUA_CFLAGS) $(CFLAGS) -c $< -o $@
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(srcdir)/configure: $(srcdir)/configure.ac $(CONFIGURE_DEPENDENCIES)
+ cd $(srcdir) && autoconf
+
+config.h:
+ @if test ! -f config.h; then \
+ cd $(top_builddir) && CONFIG_FILES= CONFIG_HEADERS=config.h \
+ $(SHELL) ./config.status; \
+ fi
+
+test/addrset: test/addrset.o ncat_core.o sys_wrap.o util.o ncat_posix.o $(LUA_OBJS) @LUA_DEPENDS@
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
+
+test/test-uri: test/test-uri.o base64.o http.o ncat_core.o sys_wrap.o util.o ncat_posix.o $(LUA_OBJS) @LUA_DEPENDS@
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
+
+test/test-cmdline-split: test/test-cmdline-split.o ncat_posix.o ncat_core.o sys_wrap.o util.o $(LUA_OBJS) @LUA_DEPENDS@
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
+
+test/test-wildcard: test/test-wildcard.o ncat_core.o ncat_ssl.o sys_wrap.o util.o ncat_posix.o $(LUA_OBJS) @LUA_DEPENDS@
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
+
+.PHONY: uninstall all clean distclean build-lua
+
+$(NBASEDIR)/libnbase.a: $(NBASEDIR)/Makefile
+ @echo Compiling libnbase;
+ cd $(NBASEDIR) && $(MAKE)
+
+$(NSOCKDIR)/libnsock.a: $(NSOCKDIR)/Makefile
+ @echo Compiling libnsock;
+ cd $(NSOCKDIR) && $(MAKE)
+
+install: $(TARGET)
+ @echo Installing Ncat;
+ $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+ $(INSTALL) -c -m 755 ncat $(DESTDIR)$(bindir)/ncat
+ $(STRIP) -x $(DESTDIR)$(bindir)/ncat
+ if [ -n "$(DATAFILES)" ]; then \
+ $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(pkgdatadir); \
+ $(INSTALL) -c -m 644 $(DATAFILES) $(DESTDIR)$(pkgdatadir)/; \
+ fi
+ $(INSTALL) -c -m 644 docs/$(TARGET).1 $(DESTDIR)$(mandir)/man1/$(TARGET).1
+
+uninstall:
+ @echo Uninstalling Ncat;
+ $(RM) -f $(DESTDIR)$(bindir)/$(TARGET)
+ $(RM) -f $(DESTDIR)$(mandir)/man1/$(TARGET).1
+ $(RM) -rf $(DESTDIR)$(pkgdatadir)/
+
+clean-ncat:
+ $(RM) -f *.o test/*.o $(TARGET) $(TEST_PROGS)
+
+clean: clean-ncat @LUA_CLEAN@
+
+clean-lua:
+ -cd $(LIBLUADIR) && $(MAKE) clean
+
+distclean-lua:
+ -cd $(LIBLUADIR) && $(MAKE) clean
+
+distclean: clean @LUA_DIST_CLEAN@
+ -rm -f Makefile makefile.dep $(CONFIG_CLEAN_FILES)
+
+TESTS = ./test-addrset.sh ./test-cmdline-split ./test-uri
+ifneq ($(HAVE_OPENSSL),)
+TESTS += ./test-wildcard
+endif
+
+check: $(TARGET) $(TEST_PROGS)
+ cd test && ($(addsuffix &&,$(TESTS)) echo "All tests passed.")
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+makefile.dep:
+ $(CC) -MM $(CPPFLAGS) $(SRCS) > $@
+-include makefile.dep
+
diff --git a/ncat/base64.c b/ncat/base64.c
new file mode 100644
index 0000000..28a1ac0
--- /dev/null
+++ b/ncat/base64.c
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * base64.c -- Base64 encoding. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "base64.h"
+#include "nbase.h"
+
+static int b64enc_internal(const unsigned char *data, int len, char *dest)
+{
+ /* base64 alphabet, taken from rfc3548 */
+ char *b64alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ char *buf = dest;
+
+ /* Encode three bytes per iteration a la rfc3548. */
+ while (len >= 3) {
+ buf[0] = b64alpha[(data[0] >> 2) & 0x3f];
+ buf[1] = b64alpha[((data[0] << 4) & 0x30) | ((data[1] >> 4) & 0xf)];
+ buf[2] = b64alpha[((data[1] << 2) & 0x3c) | ((data[2] >> 6) & 0x3)];
+ buf[3] = b64alpha[data[2] & 0x3f];
+ data += 3;
+ buf += 4;
+ len -= 3;
+ }
+
+ /* Pad the remaining bytes. len is 0, 1, or 2 here. */
+ if (len > 0) {
+ buf[0] = b64alpha[(data[0] >> 2) & 0x3f];
+ if (len > 1) {
+ buf[1] = b64alpha[((data[0] << 4) & 0x30) | ((data[1] >> 4) & 0xf)];
+ buf[2] = b64alpha[(data[1] << 2) & 0x3c];
+ } else {
+ buf[1] = b64alpha[(data[0] << 4) & 0x30];
+ buf[2] = '=';
+ }
+ buf[3] = '=';
+ buf += 4;
+ }
+
+ /*
+ * As mentioned in rfc3548, we need to be careful about
+ * how we null terminate and handle embedded null-termination.
+ */
+ *buf = '\0';
+
+ return (buf - dest);
+}
+
+/* Take in plain text and encode into base64. */
+char *b64enc(const unsigned char *data, int len)
+{
+ char *dest;
+
+ /* malloc enough space to do something useful */
+ dest = (char *) safe_malloc(4 * len / 3 + 4);
+
+ dest[0] = '\0';
+
+ /* Call internal function to base64 encode data */
+ b64enc_internal(data, len, dest);
+
+ return (dest);
+}
diff --git a/ncat/base64.h b/ncat/base64.h
new file mode 100644
index 0000000..90d2618
--- /dev/null
+++ b/ncat/base64.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * base64.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef NCAT_BASE64_H
+#define NCAT_BASE64_H
+
+char *b64enc(const unsigned char *data, int len);
+
+#endif
diff --git a/ncat/certs/README b/ncat/certs/README
new file mode 100644
index 0000000..39d511b
--- /dev/null
+++ b/ncat/certs/README
@@ -0,0 +1,50 @@
+The file ca-bundle.crt contains root certificates.
+These are installed and used as the default trusted root
+certificates when SSL certificate verification is requested with
+--ssl-verify. On some platforms (some Unixes), these certificates are
+used in addition to any certificates installed by the operating system.
+
+Originally, these certificates were extracted from Windows' certificate store.
+Microsoft's bundle was preferred over Mozilla's because Microsoft may be
+more selective in the organizations it trusts. When this bundle was
+created, Microsoft's store had 107 certificates while Mozilla's had 126.
+
+Unfortunately for us, Windows' certificate trust store is not accessible in this
+way any longer. Therefore we have migrated to the Mozilla trust store.
+
+== How to extract the trusted root CA certificates on Windows (obsolete)
+
+These instructions require the openssl command-line utility.
+
+On Windows XP, run the rootsupd.exe tool to downoad the full list of
+trusted certificates. Otherwise there is only a partial list
+(certificates are downloaded on demand).
+
+http://support.microsoft.com/kb/931125
+http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/rootsupd.exe
+
+Press "Start", then "Run...". Type "certmgr.msc" and press Enter. Open
+the folder "Trusted Root Certification Authorities" and its subfolder
+"Certificates". Click on "Expiration Date" to sort. Select the first
+certificate that is not expired, then press Shift+down arrow until all
+the non-expired certificates are selected. Right-click on the list of
+certificates, and in the context menu, select "All Tasks", then
+"Export...". Export to the file ca-bundle.p7b.
+
+In a Cygwin shell, enter the directory containing ca-bundle.p7b and run
+the command
+ openssl pkcs7 -in ca-bundle.p7b -inform der -print_certs -out ca-bundle.crt
+That will create a file ca-bundle.crt containing all the certificates,
+each preceded by its subject and issuer.
+
+== Retrieving the Mozilla trust store.
+
+Another commonly used trust store is the one provided by Mozilla. The
+cURL package includes a script that automatically creates a suitable PEM
+file from a file in Mozilla's source repository. They also provide
+ready-made PEM files to download. See http://curl.haxx.se/docs/caextract.html.
+
+Here is how to download Mozilla's trust store:
+
+$ wget https://raw.github.com/bagder/curl/master/lib/mk-ca-bundle.pl
+$ perl mk-ca-bundle.pl
diff --git a/ncat/certs/ca-bundle.crt b/ncat/certs/ca-bundle.crt
new file mode 100644
index 0000000..c8c0ff9
--- /dev/null
+++ b/ncat/certs/ca-bundle.crt
@@ -0,0 +1,3240 @@
+##
+## Bundle of CA Root Certificates
+##
+## Certificate data from Mozilla as of: Tue Oct 16 14:41:05 2018
+##
+## This is a bundle of X.509 certificates of public Certificate Authorities
+## (CA). These were automatically extracted from Mozilla's root certificates
+## file (certdata.txt). This file can be found in the mozilla source tree:
+## http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
+##
+## It contains the certificates in PEM format and therefore
+## can be directly used with curl / libcurl / php_curl, or with
+## an Apache+mod_ssl webserver for SSL client authentication.
+## Just configure this file as the SSLCACertificateFile.
+##
+## Conversion done with mk-ca-bundle.pl version 1.25.
+## SHA1: ec3c12e239d9e94861d77abe5e8fce6222f16c2f
+##
+
+
+GlobalSign Root CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
+GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
+b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
+VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
+DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
+THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
+Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
+c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
+gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
+AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
+Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
+j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
+hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
+X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
+ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
+s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
+S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
+TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
+ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
+YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
+BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
+9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
+01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
+9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
+EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
+cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
+EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
+055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
+j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
+xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
+t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+Entrust.net Premium 2048 Secure Server CA
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
+ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
+bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
+BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
+NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
+d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
+MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
+ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
+Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
+hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
+nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
+VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
+KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
+T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
+J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
+nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+Baltimore CyberTrust Root
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
+ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
+ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
+SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
+dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
+uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
+UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
+G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
+XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
+l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
+VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
+BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
+cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
+hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
+Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
+RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+AddTrust External Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
+VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
+NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
+cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
+Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
+Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
+aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
+2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
+7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
+VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
+VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
+IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
+j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
+e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
+G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
+BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
+b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
+A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
+MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
+MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
+Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
+dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
+A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
+Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
+j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
+rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
+MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
+hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
+Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
+v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
+W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
+tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+GeoTrust Global CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
+MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
+LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
+BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
+8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
+T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
+vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
+DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
+zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
+d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
+mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
+XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
+Mw==
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
+MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
+Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
+JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
+RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
+7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
+8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
+qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
+Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
+Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
+KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
+ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
+XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
+qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
+oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
+xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
+KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
+DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
+xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
+p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
+P/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA 2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
+MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
+SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
+DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
+j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
+JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
+QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
+WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
+20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
+ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
+SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
+8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
+BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
+4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
+A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
+Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
+pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
+FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
+gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
+X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+Visa eCommerce Root
+===================
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
+EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
+QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
+WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
+VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
+bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
+F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
+RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
+TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
+/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
+GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
+MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
+CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
+YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
+zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
+YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
+398znM/jra6O1I7mT1GvFpLgXPYHDw==
+-----END CERTIFICATE-----
+
+Comodo AAA Services root
+========================
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
+MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
+c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
+BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
+C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
+i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
+Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
+Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
+Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
+BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
+cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
+LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
+7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
+8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
+12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+QuoVadis Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
+ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
+MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
+cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
+EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
+J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
+F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
+YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
+AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
+PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
+ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
+MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
+YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
+ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
+Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
+BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
+FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
+tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
+fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
+LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
+gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
+5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
+5nrQNiOKSnQ2+Q==
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 2
+==================
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
+ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
+XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
+lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
+lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
+lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
+66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
+wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
+D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
+BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
+J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
+DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
+a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
+Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
+UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
+VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
+IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
+WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
+f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
+4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
+VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3
+==================
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
+OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
+DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
+KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
+DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
+BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
+p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
+nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
+MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
+Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
+uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
+BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
+YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
+BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
+VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
+ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
+AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
+qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
+hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
+POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
+Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
+8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
+bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
+g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
+vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
+qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+Security Communication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
+8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
+DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
+5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
+DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
+JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
+0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
+mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
+s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
+6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
+FL39vmwLAw==
+-----END CERTIFICATE-----
+
+Sonera Class 2 Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
+U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
+NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
+IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
+/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
+dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
+f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
+tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
+nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
+XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
+0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
+cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
+Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
+EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
+llpwrN9M
+-----END CERTIFICATE-----
+
+XRamp Global CA Root
+====================
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
+BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
+dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
+HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
+U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
+IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
+foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
+zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
+AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
+xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
+oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
+AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
+/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
+nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
+8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+Go Daddy Class 2 CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
+VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
+A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
+ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
+2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
+qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
+YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
+vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
+BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
+atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
+MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
+PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
+I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
+Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
+vZ8=
+-----END CERTIFICATE-----
+
+Starfield Class 2 CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
+U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
+MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
+A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
+SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
+bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
+JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
+epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
+F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
+MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
+hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
+bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
+afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
+PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
+KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
+QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+Taiwan GRCA
+===========
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
+EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
+DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
+dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
+w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
+BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
+1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
+htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
+J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
+Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
+B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
+O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
+lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
+HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
+09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
+TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
+Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
+Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
+D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
+DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
+Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
+7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
+CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
+IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
+MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
+ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
+9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
+UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
+/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
+oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
+GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
+66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
+hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
+EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
+SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
+8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+DigiCert Global Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
+HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
+MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
+dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
+TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
+BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
+4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
+7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
+o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
+8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
+BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
+EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
+tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
+UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+DigiCert High Assurance EV Root CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
+KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
+MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
+MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
+Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
+Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
+OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
+MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
+NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
+h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
+Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
+JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
+V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
+myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
+mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
+-----END CERTIFICATE-----
+
+Certplus Class 2 Primary CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
+BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
+OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
+dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
+5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
+Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
+YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
+e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
+CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
+YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
+L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
+P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
+TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
+7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
+//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
+l7+ijrRU
+-----END CERTIFICATE-----
+
+DST Root CA X3
+==============
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
+ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
+DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
+cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
+rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
+UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
+xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
+utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
+MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
+dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
+GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
+RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
+fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
+
+SwissSign Gold CA - G2
+======================
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
+EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
+MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
+c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
+t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
+jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
+vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
+ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
+AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
+jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
+peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
+7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
+GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
+OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
+5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
+44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
+Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
+Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
+mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
+vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
+KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
+NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
+viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+SwissSign Silver CA - G2
+========================
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
+BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
+DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
+aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
+N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
+6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
+MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
+qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
+FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
+ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
+celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
+CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
+tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
+4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
+kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
+3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
+/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
+DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
+e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
+WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
+DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
+DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
+CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
+cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
+b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
+nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
+RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
+tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
+hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
+Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
+NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
+Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
+1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+thawte Primary Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
+MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
+SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
+KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
+FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
+oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
+1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
+q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
+aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
+afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
+AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
+uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
+jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
+z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G5
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
+biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
+dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
+j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
+Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
+Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
+fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
+BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
+Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
+SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
+KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
+Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
+ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+SecureTrust CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
+dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
+BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
+OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
+DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
+GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
+01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
+ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
+aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
+SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
+mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
+nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+Secure Global CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
+bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
+MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
+Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
+YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
+bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
+8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
+HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
+0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
+oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
+MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
+CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
+3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+COMODO Certification Authority
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
+BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
+A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
+MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
+T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
+xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
+4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
+1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
+rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
+b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
+AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
+OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
+IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
+-----END CERTIFICATE-----
+
+Network Solutions Certificate Authority
+=======================================
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
+EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
+IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
+MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
+jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
+aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
+crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
+/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
+AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
+bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
+A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
+4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
+GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
+ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+COMODO ECC Certification Authority
+==================================
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
+R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
+ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
+GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
+4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
+wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
+FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
+U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GA CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
+BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
+A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
+bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
+VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
+IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
+IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
+Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
+Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
+d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
+/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
+LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
+MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
+hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
+okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
+-----END CERTIFICATE-----
+
+Certigna
+========
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
+EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
+MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
+Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
+XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
+GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
+ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
+DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
+Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
+tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
+BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
+SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
+hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
+PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
+1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+Deutsche Telekom Root CA 2
+==========================
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
+RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
+A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
+MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
+A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
+b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
+bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
+KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
+AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
+Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
+jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
+HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
+E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
+zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
+rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
+dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
+Cm26OWMohpLzGITY+9HPBVZkVw==
+-----END CERTIFICATE-----
+
+Cybertrust Global Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
+ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
+MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
+ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
+0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
+AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
+89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
+8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
+MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
+A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
+lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
+5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
+hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
+X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+ePKI Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
+MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
+MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
+IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
+lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
+qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
+12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
+WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
+lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
+vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
+Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
+MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
+1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
+KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
+xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
+NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
+GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
+xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
+gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
+sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
+BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+certSIGN ROOT CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
+VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
+Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
+CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
+JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
+rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
+ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
+0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
+AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
+Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
+AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
+SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
+x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
+vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
+TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G3
+=============================================
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
+IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
+NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
+YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
+LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
+K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
+c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
+IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
+dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
+2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
+cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
+Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
+t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G2
+===========================
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
+VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
+IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
+Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
+MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
+b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
+IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
+LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
+8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
+mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
+G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
+rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
+ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
+VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
+A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
+P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
+7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
+vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
+KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
+A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
+8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
+er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G2
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
+Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
+OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
+b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
+BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
+KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
+EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
+ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
+npaqBA+K
+-----END CERTIFICATE-----
+
+VeriSign Universal Root Certification Authority
+===============================================
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
+1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
+MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
+9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
+AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
+tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
+CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
+a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
+Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
+Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
+P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
+wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
+mJO37M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G4
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
+VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
+b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
+ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
+cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
+b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
+Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
+rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
+HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
+Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
+A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
+AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+NetLock Arany (Class Gold) Főtanúsítvány
+============================================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
+A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
+dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
+cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
+MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
+ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
+c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
+0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
+/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
+H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
+fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
+neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
+qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
+YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
+NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
+dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA - G2
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
+CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
+TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
+ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
+5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
+vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
+CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
+e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
+OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
+CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
+48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
+trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
+qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
+AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
+ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
+A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
++51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
+f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
+kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
+CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
+URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
+CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
+oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
+IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
+66+KAQ==
+-----END CERTIFICATE-----
+
+Hongkong Post Root CA 1
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
+DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
+NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
+IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
+ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
+auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
+qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
+V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
+HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
+h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
+l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
+IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
+T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
+c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
+-----END CERTIFICATE-----
+
+SecureSign RootCA11
+===================
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
+SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
+b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
+KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
+cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
+TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
+wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
+g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
+O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
+bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
+t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
+OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
+bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
+Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
+y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
+lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
+MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
+c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
+BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
+U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
+fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
+0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
+pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
+1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
+AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
+QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
+FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
+lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
+I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
+yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
+LXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
+iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
+0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
+rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
+OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
+xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
+lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
+EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
+bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
+YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
+kpeDMdmztcpHWD9f
+-----END CERTIFICATE-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
+QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
+NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
+Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
+B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
+7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
+ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
+plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
+MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
+LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
+bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
+vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
+EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
+DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
+bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
+ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
+51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
+R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
+T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
+Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
+osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
+crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
+saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
+KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
+6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
+
+Izenpe.com
+==========
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
+EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
+MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
+QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
+03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
+ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
+PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
+OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
+F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
+0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
+leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
+AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
+SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
+NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
+Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
+kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
+hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
+g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
+aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
+nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
+ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
+Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
+WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+Chambers of Commerce Root - 2008
+================================
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
+Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
+ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
+EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
+cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
+XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
+h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
+ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
+NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
+D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
+lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
+0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
+ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
+EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
+G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
+BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
+bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
+bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
+CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
+AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
+wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
+3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
+RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
+M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
+YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
+9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
+zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
+nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
+OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
+-----END CERTIFICATE-----
+
+Global Chambersign Root - 2008
+==============================
+-----BEGIN CERTIFICATE-----
+MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
+NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
+Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
+QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
+aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
+VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
+XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
+ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
+/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
+TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
+H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
+Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
+HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
+wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
+AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
+BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
+BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
+aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
+aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
+1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
+dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
+/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
+ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
+dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
+9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
+foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
+qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
+P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
+c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
+09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
+-----END CERTIFICATE-----
+
+Go Daddy Root Certificate Authority - G2
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
+MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
+A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
+9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
+fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
+NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
+BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
+vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
+5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
+N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+Starfield Root Certificate Authority - G2
+=========================================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
+eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
+DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
+VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
+W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
+bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
+N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
+ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
+JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
+TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
+4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
+F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
+c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+Starfield Services Root Certificate Authority - G2
+==================================================
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
+IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
+dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
+h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
+hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
+LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
+rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
+SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
+E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
+xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
+YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
+-----END CERTIFICATE-----
+
+AffirmTrust Commercial
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
+MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
+DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
+C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
+BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
+MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
+HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
+hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
+qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
+0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
+sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+AffirmTrust Networking
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
+MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
+Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
+dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
+/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
+h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
+HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
+UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
+12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
+WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
+/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+AffirmTrust Premium
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
+OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
+dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
+BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
+5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
+GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
+p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
+S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
+6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
+/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
+MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
+6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
+L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
+BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
+IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
+g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
+zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+AffirmTrust Premium ECC
+=======================
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
+BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
+MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
+cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
+N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
+BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
+BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
+57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
+eQ==
+-----END CERTIFICATE-----
+
+Certum Trusted Network CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
+ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
+MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
+ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
+l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
+J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
+fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
+cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
+Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
+DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
+jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
+mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
+Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+TWCA Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
+VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
+EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
+IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
+QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
+oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
+4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
+y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
+9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
+mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
+QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
+T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
+Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+Security Communication RootCA2
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
+SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
+aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
+3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
+spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
+EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
+QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
+u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
+3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
+tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
+mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+EC-ACC
+======
+-----BEGIN CERTIFICATE-----
+MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
+BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
+ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
+VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
+CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
+BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
+MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
+SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
+Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
+cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
+w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
+ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
+HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
+E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
+0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
+VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
+Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
+dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
+lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
+Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
+l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
+E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
+5EI=
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions RootCA 2011
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
+O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
+aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
+AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
+IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
+1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
+71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
+8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
+3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
+MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
+MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
+b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
+XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
+/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
+7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
+
+Actalis Authentication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
+BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
+AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
+MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
+IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
+wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
+by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
+zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
+YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
+oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
+EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
+hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
+EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
+jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
+iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
+WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
+JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
+K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
+Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
+4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
+2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
+lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
+OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
+vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+Trustis FPS Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
+EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
+IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
+BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
+RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
+H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
+cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
+o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
+AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
+BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
+GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
+yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
+8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
+l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
+iB6XzCGcKQENZetX2fNXlrtIzYE=
+-----END CERTIFICATE-----
+
+Buypass Class 2 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
+DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
+g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
+9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
+/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
+CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
+awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
+zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
+Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
+Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
+M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
+osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
+aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
+DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
+LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
+oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
+wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
+CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
+rJgWVqA=
+-----END CERTIFICATE-----
+
+Buypass Class 3 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
+DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
+sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
+5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
+7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
+ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
+2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
+/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
+RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
+Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
+j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
+uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
+Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
+ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
+KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
+6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
+UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
+eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
+Cp/HuZc=
+-----END CERTIFICATE-----
+
+T-TeleSec GlobalRoot Class 3
+============================
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
+IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
+cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
+MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
+dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
+ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
+9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
+NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
+iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
+0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
+AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
+fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
+ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
+P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
+-----END CERTIFICATE-----
+
+EE Certification Centre Root CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
+EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
+dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
+MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
+UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
+ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
+TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
+rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
+93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
+P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
+MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
+BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
+xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
+lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
+uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
+3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
+dcGWxZ0=
+-----END CERTIFICATE-----
+
+D-TRUST Root Class 3 CA 2 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
+Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
+LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
+ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
+BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
+KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
+p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
+AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
+4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
+eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
+MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
+PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
+OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
+2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
+dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
+X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+D-TRUST Root Class 3 CA 2 EV 2009
+=================================
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
+OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
+OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
+egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
+zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
+7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
+sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
+11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
+cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
+ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
+MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
+b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
+c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
+PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
+ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
+NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
+w9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+CA Disig Root R2
+================
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
+EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
+ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
+EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
+c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
+w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
+xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
+A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
+GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
+g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
+5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
+koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
+Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
+Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
+Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
+sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
+dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
+1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
+mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
+utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
+sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
+UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
+7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+ACCVRAIZ1
+=========
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
+SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
+MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
+UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
+jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
+RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
+aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
+0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
+WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
+8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
+5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
+9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
+Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
+Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
+Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
+Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
+QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
+AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
+YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
+AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
+IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
+aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
+dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
+MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
+hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
+R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
+YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
+nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
+TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
+sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
+Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
+3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
+EfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+TWCA Global Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
+CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
+QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
+EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
+Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
+nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
+r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
+Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
+tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
+KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
+sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
+yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
+kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
+zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
+cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
+8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
+/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
+lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
+A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
+i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
+EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
+zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
+-----END CERTIFICATE-----
+
+TeliaSonera Root CA v1
+======================
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
+CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
+MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
+VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
+6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
+3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
+B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
+Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
+oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
+F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
+oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
+gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
+TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
+AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
+DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
+zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
+pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
+G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
+c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
+JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
+qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
+Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
+WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+E-Tugra Certification Authority
+===============================
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
+DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
+ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
+ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
+NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
+QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
+cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
+DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
+hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
+CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
+ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
+BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
+E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
+rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
+jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
+rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
+dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
+/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
+MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
+kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
+XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
+VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
+a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
+dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
+KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
+Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
+8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
+C7TbO6Orb1wdtn7os4I07QZcJA==
+-----END CERTIFICATE-----
+
+T-TeleSec GlobalRoot Class 2
+============================
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
+IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
+cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
+MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
+dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
+ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
+SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
+vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
+2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
+WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
+YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
+r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
+vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
+3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
+-----END CERTIFICATE-----
+
+Atos TrustedRoot 2011
+=====================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
+cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
+MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
+A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
+hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
+54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
+HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
+z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
+l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
+bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
+CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
+k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
+TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
+61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
+3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 1 G3
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
+A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
+b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
+MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
+RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
+PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
+PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
+Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
+ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
+g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
+7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
+9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
+iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
+t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
+hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
+GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
+Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
+3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
+wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
+O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
+FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
+hMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 2 G3
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
+A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
+b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
+MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
+RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
+ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
+NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
+oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
+MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
+V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
+L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
+sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
+6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
+lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
+hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
+pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
+x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
+dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
+U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
+mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
+zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
+JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
+O3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3 G3
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
+A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
+b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
+MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
+RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
+IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
+Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
+6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
+I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
+VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
+5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
+Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
+dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
+rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
+hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
+t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
+TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
+DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
+Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
+hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
+0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
+dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
+PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root G2
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
+IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
+MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
+ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
+35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
+bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
+VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
+YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
+lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
+w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
+0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
+d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
+hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
+jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
+VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
+MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
+RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
+KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
+UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
+YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
+1vUhZscv6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+DigiCert Global Root G2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
+HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
+MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
+dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
+kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
+3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
+BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
+UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
+5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
+F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
+WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
+QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
+iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+DigiCert Global Root G3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
+VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
+MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
+aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
+AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
+YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
+Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
+3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
+VOKa5Vt8sycX
+-----END CERTIFICATE-----
+
+DigiCert Trusted Root G4
+========================
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
+HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
+MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
+pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
+k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
+vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
+QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
+MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
+mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
+f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
+dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
+oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
+ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
+yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
+7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
+ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
+5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
+/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
+5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
+G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
+82Z+
+-----END CERTIFICATE-----
+
+COMODO RSA Certification Authority
+==================================
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
+BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
+A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
+R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
+ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
+dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
+FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
+5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
+x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
+2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
+OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
+sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
+GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
+WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
+rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
+tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
+sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
+pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
+zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
+ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
+7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
+LaZRfyHBNVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+USERTrust RSA Certification Authority
+=====================================
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
+BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
+ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
+BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
+ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
+0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
+Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
+RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
++T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
+/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
+Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
+lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
+yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
+eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
+FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
+7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
+Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
+8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
+FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
+yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
+J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
+sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
+Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+USERTrust ECC Certification Authority
+=====================================
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
+0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
+nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
+HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
+HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
+9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+GlobalSign ECC Root CA - R4
+===========================
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
+OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
+AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
+MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
+JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
+-----END CERTIFICATE-----
+
+GlobalSign ECC Root CA - R5
+===========================
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
+SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
+h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
+uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
+yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA - G3
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
+CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
+TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
+ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
+olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
+x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
+EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
+Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
+mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
+1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
+07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
+FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
+41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
+yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
+U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
+KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
+v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
+8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
+8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
+mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
+1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
+JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
+tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
+-----END CERTIFICATE-----
+
+Staat der Nederlanden EV Root CA
+================================
+-----BEGIN CERTIFICATE-----
+MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
+CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
+MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
+cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
+SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
+O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
+0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
+Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
+XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
+08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
+0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
+74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
+fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
+ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
+eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
+c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
+5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
+b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
+f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
+5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
+WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
+DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
+eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
+-----END CERTIFICATE-----
+
+IdenTrust Commercial Root CA 1
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
+EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
+b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
+MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
+IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
+hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
+mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
+1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
+XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
+3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
+NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
+WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
+xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
+uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
+hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
+ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
+ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
+YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
+feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
+kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
+2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
+Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
+cGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
+
+IdenTrust Public Sector Root CA 1
+=================================
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
+EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
+ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
+UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
+b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
+P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
+Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
+rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
+qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
+mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
+ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
+LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
+iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
+4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
+Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
+DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
+mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
+GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
+m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
+NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
+Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
+ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
+ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
+3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority - G2
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
+BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
+bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
+b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
+HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
+DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
+OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
+/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
+HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
+s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
+TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
+AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
+0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
+iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
+nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
+e4pIb4tF9g==
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority - EC1
+==========================================
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
+YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
+ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
+FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
+LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
+dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
+IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
+AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
+9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
+vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
+kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+CFCA EV ROOT
+============
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
+CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
+IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
+MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
+DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
+BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
+7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
+uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
+ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
+xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
+py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
+gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
+hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
+tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
+BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
+/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
+ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
+4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
+E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
+BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
+aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
+PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
+kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
+ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
+
+Certinomis - Root CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
+Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
+LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
+EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
+ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
+P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
+d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
+z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
+8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
+RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
+6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
+FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
+PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
+i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
+YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
+6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
+AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
+WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
+Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
+lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
+y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
+Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
+DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
+I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
+cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
+hkIGuUE=
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GB CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
+EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
+ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
+MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
+VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
+b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
+scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
+rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
+9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
+Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
+GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
+hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
+dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
+VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
+HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
+
+SZAFIR ROOT CA2
+===============
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
+A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
+BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
+BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
+VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
+qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
+DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
+2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
+ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
+ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
+AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
+AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
+O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
+oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
+4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
+
+Certum Trusted Network CA 2
+===========================
+-----BEGIN CERTIFICATE-----
+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
+BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
+bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
+ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
+TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
+IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
+7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
+CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
+Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
+uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
+GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
+9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
+Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
+hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
+BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
+hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
+Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
+L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
+clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
+pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
+w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
+J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
+ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
+is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
+zAYspsbiDrW5viSP
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions RootCA 2015
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
+BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
+aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
+YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
+MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
+QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
+BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
+MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
+bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
+iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
+6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
+FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
+i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
+GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
+fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
+iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
+hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
+D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
+d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
+d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
+82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
+davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
+Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
+J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
+JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
+p/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions ECC RootCA 2015
+===========================================================
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
+aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
+cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
+aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
+MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
+IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
+VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
+Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
+dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
+Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
+GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
+dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
+
+ISRG Root X1
+============
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
+BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
+EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
+EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
+DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
+Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
+3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
+b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
+Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
+4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
+1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
+hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
+usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
+OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
+A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
+9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
+0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
+hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
+TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
+e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
+JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
+YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
+JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
+m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
+
+AC RAIZ FNMT-RCM
+================
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
+AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
+MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
+TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
+qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
+btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
+j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
+08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
+WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
+tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
+47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
+ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
+i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
+dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
+D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
+j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
+Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
+Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
+8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
+5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
+rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+
+Amazon Root CA 1
+================
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
+VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
+MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
+bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
+FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
+gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
+dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
+VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
+DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
+CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
+8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
+2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
+xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+
+Amazon Root CA 2
+================
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
+VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
+MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
+bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
+kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
+N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
+AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
+fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
+kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
+btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
+Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
+c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
+DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
+A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
+YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
+xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
+gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
+aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
+Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
+KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
+JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
+-----END CERTIFICATE-----
+
+Amazon Root CA 3
+================
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
+EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
+NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
+MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
+f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
+Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
+rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
+eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+
+Amazon Root CA 4
+================
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
+EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
+NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
+MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
+/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
+83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
+MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
+AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+LuxTrust Global Root 2
+======================
+-----BEGIN CERTIFICATE-----
+MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
+A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
+bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
+MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
+Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
+xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
+wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
+1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
+FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
+wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
+a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
+ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
+MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
+/zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
+Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
+FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
+H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
+7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
+ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
+VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
+TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
+/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
+7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
+iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
+-----END CERTIFICATE-----
+
+TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
+D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
+IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
+TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
+ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
+VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
+c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
+bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
+IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
+6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
+wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
+3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
+WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
+ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
+lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
+e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
+q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
+
+GDCA TrustAUTH R5 ROOT
+======================
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
+BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
+DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
+YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
+AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
+OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
+pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
+9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
+xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
+R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
+D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
+oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
+9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
+H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
+6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
+HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
+F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
+8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
+/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
+aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+TrustCor RootCert CA-1
+======================
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP
+MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
+U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
+dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx
+MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu
+YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe
+VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy
+dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq
+jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4
+pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0
+JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h
+gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw
+/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j
+BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5
+mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
+ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C
+qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P
+3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk=
+-----END CERTIFICATE-----
+
+TrustCor RootCert CA-2
+======================
+-----BEGIN CERTIFICATE-----
+MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w
+DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT
+eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0
+eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy
+MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h
+bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
+cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0
+IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb
+ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk
+RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1
+oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb
+XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1
+/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q
+jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP
+eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg
+rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
+8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU
+2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h
+Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp
+kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv
+2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3
+S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw
+PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv
+DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU
+RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE
+xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX
+RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ
+-----END CERTIFICATE-----
+
+TrustCor ECA-1
+==============
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP
+MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
+U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
+dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw
+N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5
+MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y
+IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR
+MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23
+xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc
+p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+
+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj
+YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL
+f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
+AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u
+/ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
+hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs
+J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC
+jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g==
+-----END CERTIFICATE-----
+
+SSL.com Root Certification Authority RSA
+========================================
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
+BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
+MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
+MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
+EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
+LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
+Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
+P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
+oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
+k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
+fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
+gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
+UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
+1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
+bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
+dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
+ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
+u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
+erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
+MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
+vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
+Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
+wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
+WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+SSL.com Root Certification Authority ECC
+========================================
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
+BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
+BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
+MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
+BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
+BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
+hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
+jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
+e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
+5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+
+SSL.com EV Root Certification Authority RSA R2
+==============================================
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
+DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
+MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
+DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
+VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
+hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
+cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
+Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
+B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
+CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
+9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
+RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
+JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
+qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
+++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
+Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
+guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
+OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
+CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
+lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
+rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
+hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
+9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+
+SSL.com EV Root Certification Authority ECC
+===========================================
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
+BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
+BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
+MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
+EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
+LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
+3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
+BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
+5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
+N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
+m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R6
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
+R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
+YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
+U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
+grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
+3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
+vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
+PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
+azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
+WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
+CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
+0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
+b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
+AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
+HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
+lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
+BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
+Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
+3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
+0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
+uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
+oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
+JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GC CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
+SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
+MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
+Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
+ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
+VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
+NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
+AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
+AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
+-----END CERTIFICATE-----
diff --git a/ncat/config.guess b/ncat/config.guess
new file mode 100755
index 0000000..dbfb978
--- /dev/null
+++ b/ncat/config.guess
@@ -0,0 +1,1421 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2015 Free Software Foundation, Inc.
+
+timestamp='2015-01-01'
+
+# This file 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, 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 Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2015 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ cris:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ crisv32:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ frv:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ hexagon:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-${LIBC}
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-${LIBC}
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ exit ;;
+ x86_64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/ncat/config.h.in b/ncat/config.h.in
new file mode 100644
index 0000000..98ec6be
--- /dev/null
+++ b/ncat/config.h.in
@@ -0,0 +1,197 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the `dup2' function. */
+#undef HAVE_DUP2
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 to enable HTTP Digest authentication (requires OpenSSL). */
+#undef HAVE_HTTP_DIGEST
+
+/* 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 `cfg' library (-lcfg). */
+#undef HAVE_LIBCFG
+
+/* Define to 1 if you have the `odm' library (-lodm). */
+#undef HAVE_LIBODM
+
+/* Define to 1 if you have libpcap */
+#undef HAVE_LIBPCAP
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkstemp' function. */
+#undef HAVE_MKSTEMP
+
+/* 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 <net/bpf.h> header file. */
+#undef HAVE_NET_BPF_H
+
+/* Define to 1 if you have OpenSSL. */
+#undef HAVE_OPENSSL
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* 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 `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* 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 `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#undef HAVE_SYS_IOCCOM_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_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/time.h> header file. */
+#undef HAVE_SYS_TIME_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 <sys/un.h> header file. */
+#undef HAVE_SYS_UN_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 <linux/vm_sockets.h> header file. */
+#undef HAVE_LINUX_VM_SOCKETS_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
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* 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 the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+#undef STAT_MACROS_BROKEN
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
+
+/* Defines for locating Lua */
+#undef LUA_INCLUDED
+#undef HAVE_LUA5_4_LUA_H
+#undef HAVE_LUA_5_4_LUA_H
+#undef HAVE_LUA_H
+#undef HAVE_LUA_LUA_H
diff --git a/ncat/config.sub b/ncat/config.sub
new file mode 100755
index 0000000..6d2e94c
--- /dev/null
+++ b/ncat/config.sub
@@ -0,0 +1,1807 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2015 Free Software Foundation, Inc.
+
+timestamp='2015-01-01'
+
+# This file 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, 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 Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2015 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | we32k \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pyramid-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -cnk*|-aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/ncat/config_win.h b/ncat/config_win.h
new file mode 100644
index 0000000..09f037c
--- /dev/null
+++ b/ncat/config_win.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * config_win.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id: ncat.h 16595 2010-01-27 02:51:16Z fyodor $ */
+/* These are preprocessor definitions in effect on Windows, where Autoconf
+ isn't available to create config.h. */
+
+#define HAVE_OPENSSL 1
+#define HAVE_SSL_SET_TLSEXT_HOST_NAME 1
+#define HAVE_HTTP_DIGEST 1
+#define LUA_INCLUDED 1
+#define HAVE_LUA 1
diff --git a/ncat/configure b/ncat/configure
new file mode 100755
index 0000000..b30f0e4
--- /dev/null
+++ b/ncat/configure
@@ -0,0 +1,6596 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="ncat_main.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+LUA_DIST_CLEAN
+LUA_CLEAN
+LUA_BUILD
+LUA_DEPENDS
+LIBLUADIR
+LIBLUA_LIBS
+NOLUA
+LUA_CFLAGS
+PCAP_LIBS
+PCAP_DIST_CLEAN
+PCAP_CLEAN
+PCAP_BUILD
+PCAP_DEPENDS
+libpcapdir
+OPENSSL_LIBS
+HAVE_OPENSSL
+EGREP
+GREP
+CPP
+STRIP
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_openssl
+with_libpcap
+with_liblua
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-openssl=DIR Use optional openssl libs and includes from DIR/lib/ and DIR/include/openssl/
+ --with-libpcap=DIR Look for pcap in DIR/include and DIR/libs.
+ --with-libpcap=included Always use version included with Nmap
+ --with-liblua=DIR Use an existing (compiled) lua lib from DIR/include
+ and DIR/lib.
+ --with-liblua=included Use the liblua version included with Nmap
+ --without-liblua Compile without lua (this will exclude all of NSE
+ from compilation)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+
+
+
+
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+use_openssl="yes"
+specialssldir=""
+
+# Check whether --with-openssl was given.
+if test "${with_openssl+set}" = set; then :
+ withval=$with_openssl; case "$with_openssl" in
+ yes)
+ ;;
+ no)
+ use_openssl="no"
+ ;;
+ *)
+ specialssldir="$with_openssl"
+ LDFLAGS="$LDFLAGS -L$with_openssl/lib"
+ CPPFLAGS="-I$with_openssl/include $CPPFLAGS"
+ ;;
+ esac
+
+fi
+
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test -n "$GCC"; then
+ CFLAGS="$CFLAGS -Wall"
+fi
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $STRIP in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+STRIP=$ac_cv_path_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_STRIP"; then
+ ac_pt_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_STRIP in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_STRIP="$ac_pt_STRIP" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_STRIP="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_STRIP=$ac_cv_path_ac_pt_STRIP
+if test -n "$ac_pt_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_STRIP" >&5
+$as_echo "$ac_pt_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_STRIP" = x; then
+ STRIP="/bin/true"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_pt_STRIP
+ fi
+else
+ STRIP="$ac_cv_path_STRIP"
+fi
+
+
+# Checks for header files.
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
+$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
+if ${ac_cv_header_sys_wait_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+int
+main ()
+{
+ int s;
+ wait (&s);
+ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_sys_wait_h=yes
+else
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
+$as_echo "$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
+
+$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/param.h sys/socket.h sys/time.h unistd.h sys/un.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in linux/vm_sockets.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "linux/vm_sockets.h" "ac_cv_header_linux_vm_sockets_h" "#include <sys/socket.h>
+"
+if test "x$ac_cv_header_linux_vm_sockets_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_VM_SOCKETS_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat file-mode macros are broken" >&5
+$as_echo_n "checking whether stat file-mode macros are broken... " >&6; }
+if ${ac_cv_header_stat_broken+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined S_ISBLK && defined S_IFDIR
+extern char c1[S_ISBLK (S_IFDIR) ? -1 : 1];
+#endif
+
+#if defined S_ISBLK && defined S_IFCHR
+extern char c2[S_ISBLK (S_IFCHR) ? -1 : 1];
+#endif
+
+#if defined S_ISLNK && defined S_IFREG
+extern char c3[S_ISLNK (S_IFREG) ? -1 : 1];
+#endif
+
+#if defined S_ISSOCK && defined S_IFREG
+extern char c4[S_ISSOCK (S_IFREG) ? -1 : 1];
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stat_broken=no
+else
+ ac_cv_header_stat_broken=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stat_broken" >&5
+$as_echo "$ac_cv_header_stat_broken" >&6; }
+if test $ac_cv_header_stat_broken = yes; then
+
+$as_echo "#define STAT_MACROS_BROKEN 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
+if ${ac_cv_c_const+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this sort of thing. */
+ typedef int charset[2];
+ const charset cs = { 0, 0 };
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this sort of thing. */
+ char tx;
+ char *t = &tx;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; } bx;
+ struct s *b = &bx; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_const=yes
+else
+ ac_cv_c_const=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+$as_echo "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+$as_echo "#define const /**/" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
+$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
+if ${ac_cv_header_time+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_time=yes
+else
+ ac_cv_header_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
+$as_echo "$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+fi
+
+
+# Checks for library functions.
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+for ac_header in vfork.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in fork vfork
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_fork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_fork_works=yes
+else
+ ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_vfork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_vfork_works=yes
+else
+ ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+for ac_header in sys/select.h sys/socket.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5
+$as_echo_n "checking types of arguments for select... " >&6; }
+if ${ac_cv_func_select_args+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ for ac_arg234 in 'fd_set *' 'int *' 'void *'; do
+ for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do
+ for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+extern int select ($ac_arg1,
+ $ac_arg234, $ac_arg234, $ac_arg234,
+ $ac_arg5);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ done
+done
+# Provide a safe default value.
+: "${ac_cv_func_select_args=int,int *,struct timeval *}"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5
+$as_echo "$ac_cv_func_select_args" >&6; }
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG1 $1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG234 ($2)
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG5 ($3)
+_ACEOF
+
+rm -f conftest*
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5
+$as_echo_n "checking return type of signal handlers... " >&6; }
+if ${ac_cv_type_signal+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_type_signal=int
+else
+ ac_cv_type_signal=void
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5
+$as_echo "$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+for ac_func in vprintf
+do :
+ ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf"
+if test "x$ac_cv_func_vprintf" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VPRINTF 1
+_ACEOF
+
+ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
+if test "x$ac_cv_func__doprnt" = xyes; then :
+
+$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h
+
+fi
+
+fi
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setsockopt" >&5
+$as_echo_n "checking for library containing setsockopt... " >&6; }
+if ${ac_cv_search_setsockopt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setsockopt ();
+int
+main ()
+{
+return setsockopt ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_setsockopt=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_setsockopt+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_setsockopt+:} false; then :
+
+else
+ ac_cv_search_setsockopt=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setsockopt" >&5
+$as_echo "$ac_cv_search_setsockopt" >&6; }
+ac_res=$ac_cv_search_setsockopt
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+# Ncat does not call gethostbyname directly, but some of the libraries
+# it links to (such as libpcap) do. Instead it calls getaddrinfo. At
+# one point we changed this test to use getaddrinfo rather than
+# gethostbyname, but on a Solaris 9 SPARC box that function could be
+# called without -lnsl, while gethostbyname sitll required -lnsl, so
+# we changed the test back.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
+$as_echo_n "checking for library containing gethostbyname... " >&6; }
+if ${ac_cv_search_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_gethostbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_gethostbyname+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_gethostbyname+:} false; then :
+
+else
+ ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
+$as_echo "$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+# OpenSSL requires dlopen on some platforms
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_dlopen+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+ ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+for ac_func in dup2 gettimeofday inet_ntoa memset mkstemp select socket strcasecmp strchr strdup strerror strncasecmp strtol
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# If they didn't specify it, we try to find it
+if test "$use_openssl" = "yes" -a -z "$specialssldir" ; then
+ ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
+
+else
+ use_openssl="no"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find openssl/ssl.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find openssl/ssl.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&2;}
+fi
+
+
+
+ if test "$use_openssl" = "yes"; then
+ ac_fn_c_check_header_mongrel "$LINENO" "openssl/err.h" "ac_cv_header_openssl_err_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_err_h" = xyes; then :
+
+else
+ use_openssl="no"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find openssl/err.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find openssl/err.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&2;}
+fi
+
+
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ ac_fn_c_check_header_mongrel "$LINENO" "openssl/rand.h" "ac_cv_header_openssl_rand_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_rand_h" = xyes; then :
+
+else
+ use_openssl="no"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find openssl/rand.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find openssl/rand.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&2;}
+fi
+
+
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_int_ctrl in -lcrypto" >&5
+$as_echo_n "checking for BIO_int_ctrl in -lcrypto... " >&6; }
+if ${ac_cv_lib_crypto_BIO_int_ctrl+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char BIO_int_ctrl ();
+int
+main ()
+{
+return BIO_int_ctrl ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_crypto_BIO_int_ctrl=yes
+else
+ ac_cv_lib_crypto_BIO_int_ctrl=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BIO_int_ctrl" >&5
+$as_echo "$ac_cv_lib_crypto_BIO_int_ctrl" >&6; }
+if test "x$ac_cv_lib_crypto_BIO_int_ctrl" = xyes; then :
+ use_openssl="yes"
+else
+ use_openssl="no"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find libcrypto so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find libcrypto so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument" >&2;}
+fi
+
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5
+$as_echo_n "checking for SSL_new in -lssl... " >&6; }
+if ${ac_cv_lib_ssl_SSL_new+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SSL_new ();
+int
+main ()
+{
+return SSL_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ssl_SSL_new=yes
+else
+ ac_cv_lib_ssl_SSL_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new" >&5
+$as_echo "$ac_cv_lib_ssl_SSL_new" >&6; }
+if test "x$ac_cv_lib_ssl_SSL_new" = xyes; then :
+ use_openssl="yes"
+else
+ use_openssl="no"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find libssl so OpenSSL will not be used.
+If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find libssl so OpenSSL will not be used.
+If it is installed you can try the --with-openssl=DIR argument" >&2;}
+fi
+
+ fi
+fi
+
+OPENSSL_LIBS=
+if test "$use_openssl" = "yes"; then
+
+$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_HTTP_DIGEST 1" >>confdefs.h
+
+ OPENSSL_LIBS="-lssl -lcrypto"
+ # Define in Makefile also.
+ HAVE_OPENSSL=yes
+
+fi
+
+
+
+libpcapdir=../libpcap
+
+
+have_libpcap=no
+
+# By default, search for pcap library
+test "${with_libpcap+set}" != "set" && with_libpcap=yes
+
+
+# Check whether --with-libpcap was given.
+if test "${with_libpcap+set}" = set; then :
+ withval=$with_libpcap; case "$with_libpcap" in
+ yes)
+ ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcap_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_create in -lpcap" >&5
+$as_echo_n "checking for pcap_create in -lpcap... " >&6; }
+if ${ac_cv_lib_pcap_pcap_create+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcap_create ();
+int
+main ()
+{
+return pcap_create ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pcap_pcap_create=yes
+else
+ ac_cv_lib_pcap_pcap_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_create" >&5
+$as_echo "$ac_cv_lib_pcap_pcap_create" >&6; }
+if test "x$ac_cv_lib_pcap_pcap_create" = xyes; then :
+ have_libpcap=yes
+fi
+
+fi
+
+
+ ;;
+ included)
+ have_libpcap=no
+ ;;
+ *)
+ _cppflags=$CXXFLAGS
+ _ldflags=$LDFLAGS
+
+ CPPFLAGS="-I$with_libpcap/include $CPPFLAGS"
+ LDFLAGS="-L$with_libpcap/lib $LDFLAGS"
+
+ ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcap_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_create in -lpcap" >&5
+$as_echo_n "checking for pcap_create in -lpcap... " >&6; }
+if ${ac_cv_lib_pcap_pcap_create+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcap_create ();
+int
+main ()
+{
+return pcap_create ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pcap_pcap_create=yes
+else
+ ac_cv_lib_pcap_pcap_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_create" >&5
+$as_echo "$ac_cv_lib_pcap_pcap_create" >&6; }
+if test "x$ac_cv_lib_pcap_pcap_create" = xyes; then :
+ have_libpcap=yes
+ LIBPCAP_INC=$with_libpcap/include
+ LIBPCAP_LIB=$with_libpcap/lib
+fi
+
+fi
+
+
+
+ LDFLAGS=$_ldflags
+ CXXFLAGS=$_cppflags
+ ;;
+ esac
+
+fi
+
+
+if test $have_libpcap = yes; then
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ _cflags=$CXXFLAGS
+ _ldflags=$LDFLAGS
+
+ CPPFLAGS="-I$LIBPCAP_INC $CPPFLAGS"
+ LDFLAGS="-L$LIBPCAP_LIB $LDFLAGS"
+ fi
+
+ # link with -lpcap for the purposes of this test
+ LIBS_OLD="$LIBS"
+ LIBS="$LIBS -lpcap"
+
+ for ac_header in sys/ioccom.h sys/time.h net/bpf.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libpcap is suitable" >&5
+$as_echo_n "checking if libpcap is suitable... " >&6; }
+ if test "$cross_compiling" = yes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling -- assuming yes" >&5
+$as_echo "cross-compiling -- assuming yes" >&6; }; have_libpcap=yes
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <stdio.h>
+extern char pcap_version[];
+int main() {
+ int major, minor1, minor2;
+ sscanf(pcap_version,"%d.%d.%d", &major, &minor1, &minor2);
+ if (major > 0)
+ return 0;
+ if (minor1 < 9)
+ return 1;
+ if (minor2 < 4)
+ return 1;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_NET_BPF_H
+#include <net/bpf.h>
+#endif
+extern char pcap_version[];
+int main() {
+ int major, minor;
+ sscanf(pcap_version,"%d.%d", &major, &minor);
+ if ((major == 1 && minor >= 1) || major > 1)
+ return 0;
+#ifdef BIOCSRTIMEOUT
+#ifdef IOCPARM_LEN
+ if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval))
+ return 1;
+#endif
+#endif
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+ ac_fn_c_check_decl "$LINENO" "pcap_get_selectable_fd" "ac_cv_have_decl_pcap_get_selectable_fd" "#include <pcap.h>
+"
+if test "x$ac_cv_have_decl_pcap_get_selectable_fd" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }; have_libpcap=yes
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- pcap_get_selectable_fd not declared" >&5
+$as_echo "no -- pcap_get_selectable_fd not declared" >&6; }; have_libpcap=no
+fi
+
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- BPF_TIMEOUT BIOCSRTIMEOUT bug (64-bit OS X)" >&5
+$as_echo "no -- BPF_TIMEOUT BIOCSRTIMEOUT bug (64-bit OS X)" >&6; }; have_libpcap=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }; have_libpcap=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+ LIBS="$LIBS_OLD"
+fi
+
+PCAP_LIBS="-lpcap"
+if test $have_libpcap = yes; then
+ PCAP_DEPENDS=""
+ PCAP_BUILD=""
+ PCAP_CLEAN=""
+ PCAP_DIST_CLEAN=""
+
+$as_echo "#define HAVE_LIBPCAP 1" >>confdefs.h
+
+else
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ LDFLAGS="-L$libpcapdir $_ldflags"
+ CPPFLAGS="$CPPFLAGS -I$LIBPCAP_INC"
+ else
+ LDFLAGS="-L$libpcapdir $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS -I$libpcapdir"
+ fi
+ PCAP_DEPENDS='$(LIBPCAPDIR)/libpcap.a'
+ PCAP_BUILD="build-pcap"
+ PCAP_CLEAN="clean-pcap"
+ PCAP_DIST_CLEAN="distclean-pcap"
+fi
+
+
+
+
+
+
+
+# Needed on AIX.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for odm_initialize in -lodm" >&5
+$as_echo_n "checking for odm_initialize in -lodm... " >&6; }
+if ${ac_cv_lib_odm_odm_initialize+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lodm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char odm_initialize ();
+int
+main ()
+{
+return odm_initialize ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_odm_odm_initialize=yes
+else
+ ac_cv_lib_odm_odm_initialize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odm_odm_initialize" >&5
+$as_echo "$ac_cv_lib_odm_odm_initialize" >&6; }
+if test "x$ac_cv_lib_odm_odm_initialize" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBODM 1
+_ACEOF
+
+ LIBS="-lodm $LIBS"
+
+fi
+
+
+# Needed on AIX.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for odm_initialize in -lodm" >&5
+$as_echo_n "checking for odm_initialize in -lodm... " >&6; }
+if ${ac_cv_lib_odm_odm_initialize+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lodm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char odm_initialize ();
+int
+main ()
+{
+return odm_initialize ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_odm_odm_initialize=yes
+else
+ ac_cv_lib_odm_odm_initialize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odm_odm_initialize" >&5
+$as_echo "$ac_cv_lib_odm_odm_initialize" >&6; }
+if test "x$ac_cv_lib_odm_odm_initialize" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBODM 1
+_ACEOF
+
+ LIBS="-lodm $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _system_configuration in -lcfg" >&5
+$as_echo_n "checking for _system_configuration in -lcfg... " >&6; }
+if ${ac_cv_lib_cfg__system_configuration+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcfg $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _system_configuration ();
+int
+main ()
+{
+return _system_configuration ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_cfg__system_configuration=yes
+else
+ ac_cv_lib_cfg__system_configuration=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cfg__system_configuration" >&5
+$as_echo "$ac_cv_lib_cfg__system_configuration" >&6; }
+if test "x$ac_cv_lib_cfg__system_configuration" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCFG 1
+_ACEOF
+
+ LIBS="-lcfg $LIBS"
+
+fi
+
+
+
+
+LIBLUADIR=../liblua
+
+have_lua=no
+requested_included_lua=no
+no_lua=no
+
+# First we test whether they specified liblua explicitly
+
+# Check whether --with-liblua was given.
+if test "${with_liblua+set}" = set; then :
+ withval=$with_liblua; case "$with_liblua" in
+ yes)
+ ;;
+ included)
+ CPPFLAGS="-I\$(top_srcdir)/$LIBLUADIR $CPPFLAGS"
+ LIBLUA_LIBS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_DEPENDS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_BUILD="build-lua"
+ LUA_CLEAN="clean-lua"
+ LUA_DIST_CLEAN="distclean-lua"
+ have_lua="yes"
+
+$as_echo "#define LUA_INCLUDED 1" >>confdefs.h
+
+
+ ;;
+ no)
+ no_lua="yes"
+ ;;
+ *)
+ CPPFLAGS="-I$with_liblua/include $CPPFLAGS"
+ LDFLAGS="-L$with_liblua/lib $LDFLAGS"
+ ;;
+ esac
+
+fi
+
+
+LUA_CFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN"
+
+
+# They don't want lua
+if test "$no_lua" = "yes"; then
+ CPPFLAGS="-DNOLUA $CPPFLAGS"
+ NOLUA="yes"
+ LIBLUA_LIBS=""
+ LUA_DEPENDS=""
+ LUA_BUILD=""
+ LUA_CLEAN=""
+ LUA_DIST_CLEAN=""
+ INSTALLNSE=""
+
+else
+
+ # If they didn't specify it, we try to find it
+ if test $have_lua != yes; then
+ for ac_header in lua5.4/lua.h lua/5.4/lua.h lua.h lua/lua.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ break
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing lua_isyieldable" >&5
+$as_echo_n "checking for library containing lua_isyieldable... " >&6; }
+if ${ac_cv_search_lua_isyieldable+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char lua_isyieldable ();
+int
+main ()
+{
+return lua_isyieldable ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' lua5.4 lua54 lua; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib -lm $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_lua_isyieldable=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_lua_isyieldable+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_lua_isyieldable+:} false; then :
+
+else
+ ac_cv_search_lua_isyieldable=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_lua_isyieldable" >&5
+$as_echo "$ac_cv_search_lua_isyieldable" >&6; }
+ac_res=$ac_cv_search_lua_isyieldable
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ have_lua=yes
+fi
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua version >= 504" >&5
+$as_echo_n "checking for lua version >= 504... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #ifdef HAVE_LUA5_4_LUA_H
+ #include <lua5.4/lua.h>
+ #elif defined HAVE_LUA_5_4_LUA_H
+ #include <lua/5.4/lua.h>
+ #elif defined HAVE_LUA_H || defined LUA_INCLUDED
+ #include <lua.h>
+ #elif defined HAVE_LUA_LUA_H
+ #include <lua/lua.h>
+ #endif
+
+ #if (LUA_VERSION_NUM < 504)
+ #error Incorrect Lua version
+ #endif
+
+int
+main ()
+{
+if(LUA_VERSION_NUM < 504) return 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ have_lua=yes
+else
+ have_lua=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ LUA_DEPENDS=""
+ LUA_BUILD=""
+ LUA_CLEAN=""
+ LUA_DIST_CLEAN=""
+ fi
+
+ # if we didn't find we use our own
+ if test $have_lua != yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CPPFLAGS="-I\$(top_srcdir)/$LIBLUADIR $CPPFLAGS"
+ LIBLUA_LIBS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_DEPENDS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_BUILD="build-lua"
+ LUA_CLEAN="clean-lua"
+ LUA_DIST_CLEAN="distclean-lua"
+
+$as_echo "#define LUA_INCLUDED 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ fi
+
+ INSTALLNSE="install-nse"
+fi
+
+
+
+
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+# NCAT ASCII ART
+if test -f docs/ncat-ascii-art.txt; then
+ cat docs/ncat-ascii-art.txt
+fi
+
+echo "Configuration complete."
diff --git a/ncat/configure.ac b/ncat/configure.ac
new file mode 100644
index 0000000..0f7d3ed
--- /dev/null
+++ b/ncat/configure.ac
@@ -0,0 +1,327 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59)
+AC_INIT(ncat_main.c)
+
+AC_CONFIG_HEADER(config.h)
+
+m4_include([../acinclude.m4])
+
+AC_CANONICAL_HOST
+
+use_openssl="yes"
+specialssldir=""
+AC_ARG_WITH(openssl,[ --with-openssl=DIR Use optional openssl libs and includes from [DIR]/lib/ and [DIR]/include/openssl/],
+[ case "$with_openssl" in
+ yes)
+ ;;
+ no)
+ use_openssl="no"
+ ;;
+ *)
+ specialssldir="$with_openssl"
+ LDFLAGS="$LDFLAGS -L$with_openssl/lib"
+ CPPFLAGS="-I$with_openssl/include $CPPFLAGS"
+ ;;
+ esac]
+)
+
+# Checks for programs.
+AC_PROG_CC
+if test -n "$GCC"; then
+ CFLAGS="$CFLAGS -Wall"
+fi
+AC_PROG_INSTALL
+
+AC_PATH_TOOL([STRIP], [strip], [/bin/true])
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/param.h sys/socket.h sys/time.h unistd.h sys/un.h])
+AC_CHECK_HEADERS([linux/vm_sockets.h], , , [#include <sys/socket.h>])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STAT
+AC_C_CONST
+AC_HEADER_TIME
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_VPRINTF
+AC_SEARCH_LIBS(setsockopt, socket)
+# Ncat does not call gethostbyname directly, but some of the libraries
+# it links to (such as libpcap) do. Instead it calls getaddrinfo. At
+# one point we changed this test to use getaddrinfo rather than
+# gethostbyname, but on a Solaris 9 SPARC box that function could be
+# called without -lnsl, while gethostbyname sitll required -lnsl, so
+# we changed the test back.
+AC_SEARCH_LIBS(gethostbyname, nsl)
+# OpenSSL requires dlopen on some platforms
+AC_SEARCH_LIBS(dlopen, dl)
+AC_CHECK_FUNCS([dup2 gettimeofday inet_ntoa memset mkstemp select socket strcasecmp strchr strdup strerror strncasecmp strtol])
+
+# If they didn't specify it, we try to find it
+if test "$use_openssl" = "yes" -a -z "$specialssldir" ; then
+ AC_CHECK_HEADER(openssl/ssl.h,,
+ [ use_openssl="no"
+ AC_MSG_WARN([Failed to find openssl/ssl.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument]) ])
+
+ if test "$use_openssl" = "yes"; then
+ AC_CHECK_HEADER(openssl/err.h,,
+ [ use_openssl="no"
+ AC_MSG_WARN([Failed to find openssl/err.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument]) ])
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ AC_CHECK_HEADER(openssl/rand.h,,
+ [ use_openssl="no"
+ AC_MSG_WARN([Failed to find openssl/rand.h so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument]) ])
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ AC_CHECK_LIB(crypto, BIO_int_ctrl,
+ [ use_openssl="yes"],
+ [ use_openssl="no"
+ AC_MSG_WARN([Failed to find libcrypto so OpenSSL will not be used.
+ If it is installed you can try the --with-openssl=DIR argument]) ])
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ AC_CHECK_LIB(ssl, SSL_new,
+ [ use_openssl="yes"],
+ [ use_openssl="no"
+ AC_MSG_WARN([Failed to find libssl so OpenSSL will not be used.
+If it is installed you can try the --with-openssl=DIR argument]) ],
+ [ -lcrypto ])
+ fi
+fi
+
+OPENSSL_LIBS=
+if test "$use_openssl" = "yes"; then
+ AC_DEFINE([HAVE_OPENSSL], [1], [Define to 1 if you have OpenSSL.])
+ AC_DEFINE([HAVE_HTTP_DIGEST], [1], [Define to 1 to enable HTTP Digest authentication (requires OpenSSL).])
+ OPENSSL_LIBS="-lssl -lcrypto"
+ # Define in Makefile also.
+ HAVE_OPENSSL=yes
+ AC_SUBST(HAVE_OPENSSL)
+fi
+
+AC_SUBST(OPENSSL_LIBS)
+
+libpcapdir=../libpcap
+AC_SUBST(libpcapdir)
+
+dnl Check whether libpcap is already available
+have_libpcap=no
+
+# By default, search for pcap library
+test "${with_libpcap+set}" != "set" && with_libpcap=yes
+
+AC_ARG_WITH(libpcap,
+AC_HELP_STRING([--with-libpcap=DIR], [Look for pcap in DIR/include and DIR/libs.])
+AC_HELP_STRING([--with-libpcap=included], [Always use version included with Nmap]),
+[ case "$with_libpcap" in
+ yes)
+ AC_CHECK_HEADER(pcap.h,[
+ AC_CHECK_LIB(pcap, pcap_create,
+ [have_libpcap=yes ])])
+ ;;
+ included)
+ have_libpcap=no
+ ;;
+ *)
+ _cppflags=$CXXFLAGS
+ _ldflags=$LDFLAGS
+
+ CPPFLAGS="-I$with_libpcap/include $CPPFLAGS"
+ LDFLAGS="-L$with_libpcap/lib $LDFLAGS"
+
+ AC_CHECK_HEADER(pcap.h,[
+ AC_CHECK_LIB(pcap, pcap_create,
+ [have_libpcap=yes
+ LIBPCAP_INC=$with_libpcap/include
+ LIBPCAP_LIB=$with_libpcap/lib])])
+
+ LDFLAGS=$_ldflags
+ CXXFLAGS=$_cppflags
+ ;;
+ esac]
+)
+
+if test $have_libpcap = yes; then
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ _cflags=$CXXFLAGS
+ _ldflags=$LDFLAGS
+
+ CPPFLAGS="-I$LIBPCAP_INC $CPPFLAGS"
+ LDFLAGS="-L$LIBPCAP_LIB $LDFLAGS"
+ fi
+
+ # link with -lpcap for the purposes of this test
+ LIBS_OLD="$LIBS"
+ LIBS="$LIBS -lpcap"
+ PCAP_IS_SUITABLE([have_libpcap=yes], [have_libpcap=no], [have_libpcap=yes])
+ LIBS="$LIBS_OLD"
+fi
+
+PCAP_LIBS="-lpcap"
+if test $have_libpcap = yes; then
+ PCAP_DEPENDS=""
+ PCAP_BUILD=""
+ PCAP_CLEAN=""
+ PCAP_DIST_CLEAN=""
+ AC_DEFINE([HAVE_LIBPCAP], [1], [Define to 1 if you have libpcap])
+else
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ LDFLAGS="-L$libpcapdir $_ldflags"
+ CPPFLAGS="$CPPFLAGS -I$LIBPCAP_INC"
+ else
+ LDFLAGS="-L$libpcapdir $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS -I$libpcapdir"
+ fi
+ PCAP_DEPENDS='$(LIBPCAPDIR)/libpcap.a'
+ PCAP_BUILD="build-pcap"
+ PCAP_CLEAN="clean-pcap"
+ PCAP_DIST_CLEAN="distclean-pcap"
+fi
+
+AC_SUBST(PCAP_DEPENDS)
+AC_SUBST(PCAP_BUILD)
+AC_SUBST(PCAP_CLEAN)
+AC_SUBST(PCAP_DIST_CLEAN)
+AC_SUBST(PCAP_LIBS)
+
+# Needed on AIX.
+AC_CHECK_LIB(odm, odm_initialize)
+
+# Needed on AIX.
+AC_CHECK_LIB(odm, odm_initialize)
+AC_CHECK_LIB(cfg, _system_configuration)
+
+
+
+LIBLUADIR=../liblua
+
+have_lua=no
+requested_included_lua=no
+no_lua=no
+
+# First we test whether they specified liblua explicitly
+AC_ARG_WITH(liblua,
+AC_HELP_STRING([--with-liblua=DIR], [Use an existing (compiled) lua lib from DIR/include and DIR/lib.])
+AC_HELP_STRING([--with-liblua=included], [Use the liblua version included with Nmap])
+AC_HELP_STRING([--without-liblua], [Compile without lua (this will exclude all of NSE from compilation)]),
+[ case "$with_liblua" in
+ yes)
+ ;;
+ included)
+ CPPFLAGS="-I\$(top_srcdir)/$LIBLUADIR $CPPFLAGS"
+ LIBLUA_LIBS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_DEPENDS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_BUILD="build-lua"
+ LUA_CLEAN="clean-lua"
+ LUA_DIST_CLEAN="distclean-lua"
+ have_lua="yes"
+ AC_DEFINE([LUA_INCLUDED], [1], [Using included liblua])
+
+ ;;
+ no)
+ no_lua="yes"
+ ;;
+ *)
+ CPPFLAGS="-I$with_liblua/include $CPPFLAGS"
+ LDFLAGS="-L$with_liblua/lib $LDFLAGS"
+ ;;
+ esac]
+)
+
+LUA_CFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN"
+AC_SUBST(LUA_CFLAGS)
+
+# They don't want lua
+if test "$no_lua" = "yes"; then
+ CPPFLAGS="-DNOLUA $CPPFLAGS"
+ NOLUA="yes"
+ LIBLUA_LIBS=""
+ LUA_DEPENDS=""
+ LUA_BUILD=""
+ LUA_CLEAN=""
+ LUA_DIST_CLEAN=""
+ INSTALLNSE=""
+
+else
+
+ # If they didn't specify it, we try to find it
+ if test $have_lua != yes; then
+ AC_CHECK_HEADERS([lua5.4/lua.h lua/5.4/lua.h lua.h lua/lua.h], [break])
+ AC_SEARCH_LIBS(lua_isyieldable, [lua5.4 lua54 lua], [have_lua=yes],, [-lm])
+ AC_LANG_PUSH(C)
+ AC_MSG_CHECKING([for lua version >= 504])
+ AC_PREPROC_IFELSE([ AC_LANG_PROGRAM(
+ [[
+ #ifdef HAVE_LUA5_4_LUA_H
+ #include <lua5.4/lua.h>
+ #elif defined HAVE_LUA_5_4_LUA_H
+ #include <lua/5.4/lua.h>
+ #elif defined HAVE_LUA_H || defined LUA_INCLUDED
+ #include <lua.h>
+ #elif defined HAVE_LUA_LUA_H
+ #include <lua/lua.h>
+ #endif
+
+ #if (LUA_VERSION_NUM < 504)
+ #error Incorrect Lua version
+ #endif
+ ]],
+ [[if(LUA_VERSION_NUM < 504) return 1;]])],
+ [have_lua=yes], [have_lua=no])
+ AC_LANG_POP(C)
+
+ LUA_DEPENDS=""
+ LUA_BUILD=""
+ LUA_CLEAN=""
+ LUA_DIST_CLEAN=""
+ fi
+
+ # if we didn't find we use our own
+ if test $have_lua != yes; then
+ AC_MSG_RESULT(no)
+ CPPFLAGS="-I\$(top_srcdir)/$LIBLUADIR $CPPFLAGS"
+ LIBLUA_LIBS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_DEPENDS="\$(top_srcdir)/$LIBLUADIR/liblua.a"
+ LUA_BUILD="build-lua"
+ LUA_CLEAN="clean-lua"
+ LUA_DIST_CLEAN="distclean-lua"
+ AC_DEFINE([LUA_INCLUDED], [1], [Using included liblua])
+ else
+ AC_MSG_RESULT(yes)
+ fi
+
+ INSTALLNSE="install-nse"
+fi
+
+AC_SUBST(NOLUA)
+AC_SUBST(LIBLUA_LIBS)
+AC_SUBST(LIBLUADIR)
+AC_SUBST(LUA_DEPENDS)
+AC_SUBST(LUA_BUILD)
+AC_SUBST(LUA_CLEAN)
+AC_SUBST(LUA_DIST_CLEAN)
+
+
+
+AC_CONFIG_FILES(Makefile)
+AC_OUTPUT
+# NCAT ASCII ART
+if test -f docs/ncat-ascii-art.txt; then
+ cat docs/ncat-ascii-art.txt
+fi
+
+echo "Configuration complete."
diff --git a/ncat/docs/AUTHORS b/ncat/docs/AUTHORS
new file mode 100644
index 0000000..c0232c8
--- /dev/null
+++ b/ncat/docs/AUTHORS
@@ -0,0 +1,28 @@
+Ncat AUTHORS
+============
+
+Ncat is based in concept (but not code) on the original "Netcat"
+written by Hobbit circa 1994. Ncat combines the original Netcat
+feature set as well as various other ideas from other Netcat-like
+products, such as CryptCat, Socat, GNU Netcat, etc.
+
+Ncat was originally written from the ground up by Chris Gibson
+(chris@linuxops.net) and was funded by the Google Summer of Code Program
+2005.
+
+Development, bug fixes, security auditing, improvements by Sean
+(infamous42md@hotpop.com).
+
+Starting with the Google Summer of Code 2008, Ncat development was
+picked back up by Mixter and Kris Katterjohn. This included many bug
+fixes, new features and code cleanups.
+
+The Ncat requirements, ideas and general support and help were given by
+Fyodor.
+
+Many helpful comments, suggestions and other useful information was
+taken from the nmap-dev list (@insecure.org) as well as other
+contributors via email.
+
+Ncat shares the Nmap infrastructure libraries (Nsock and Nbase) which
+were originally written by Fyodor.
diff --git a/ncat/docs/README b/ncat/docs/README
new file mode 100644
index 0000000..77000fb
--- /dev/null
+++ b/ncat/docs/README
@@ -0,0 +1,146 @@
+ . .
+ \`-"'"-'/
+ } 6 6 {
+ ==. Y ,==
+ /^^^\ .
+ / \ )
+ ( )-( )/ _
+ -""---""--- /
+ / Ncat \_/
+ ( ____
+ \_.=|____E
+
+
+README for Ncat
+---------------
+
+Ncat is a reimplementation of the currently splintered and reasonably
+unmaintained Netcat family. Ncat will do pretty much everything that
+all the other Netcat's do, all in one place. Plus it has the added
+benefit of spanky new features and ongoing development.
+
+Ncat was designed with the original Netcat interface in mind. Rather
+than replacing the old Netcat interface with a brand new (and thus more
+convoluted) set of options, the Ncat interface was intentionally kept
+clean and simple to use, just like the original product.
+
+Ncat provides most of the features present in the original Netcat but with
+a complete overhaul and rewrite, along with completely new features and a
+combination of other well received features of other Netcat products, such
+as IPv6 and SSL support.
+
+The port scanning support has been entirely removed from Ncat. The
+reason for this is fairly obvious: there is a better port scanner out
+there already... :)
+
+Ncat can act as either a client or server, using TCP or UDP over IPv4 or
+IPv6. SSL support is provided for both the client and server mode.
+
+There is also a new "connection brokering" feature which enables two or
+more hosts to connect that previously were unable to directly communicate
+with each other.
+
+For example: "Host A" can connect to "Host B" but not "Host C"
+ "Host C" can connect to "Host B" but not "Host A"
+
+It is clear, then, that if you could connect to "Host B" then "Host A"
+and "Host C" could directly communicate...
+
+[HostA] <------> [HostB-with-Ncat-Broker] <------> [HostC]
+
+Ncat's connection brokering will allow you to connect between Host A and
+Host C via Host B without the trouble of having to have SOCKS support,
+etc. This is still somewhat experimental behaviour.
+
+Ncat has support for HTTP "CONNECT" via an HTTP proxy server such as Squid.
+It can also connect via a SOCKS4 server and is very flexible in terms of
+how it shuffles your data around.
+
+Ncat can also spawn its own HTTP CONNECT proxy server for your
+own relaying requirements.
+
+Ncat has the ability to execute a program and handle the I/O for its data
+over the socket. In other words, Ncat can "add" networking support to
+applications that currently have none.
+
+For example, you could:
+
+ncat --exec "/bin/bash" -l 5000
+
+NOTE: This is exceptionally dangerous behaviour, as it leaves an open shell
+sitting directly accessible to anyone who is able to connect to port 5000.
+See the allow and deny options below for securing your Ncat processes.
+
+Ncat has a TCP and UDP "redir"-style redirection feature to allow the user
+to redirect traffic from one host to another.
+
+For example:
+
+ncat --exec "/usr/local/bin/ncat www.example.com 80" -l 8888
+
+This command binds Ncat to the local machine on port 8888 and redirects
+connections to www.example.com. You may also find uses for this as a "host
+hiding" system. Similar to SOCKS4 but without any of the hassle of having
+to have SOCKS support in the application.
+
+This also begs the question of, "What would happen if you decided you wanted
+to pass the --udp flag in to the above command somewhere?"
+
+In this case, you would have a TCP to UDP "gender changer".
+
+If you have an application that only makes only TCP connections, for example,
+you could spawn a Ncat process to listen on a the applications TCP port and
+then redirect the TCP connection out to the final destination, only over UDP.
+
+The --allow and --deny options are provided to prevent unauthorized access to
+any Ncat process that is listening on a port. These options are also paired
+with the --allowfile and --denyfile options, similar in behaviour to Nmap.
+
+The allow and deny options accept a number of different IP address formats
+for maximum flexibility:
+
+A single IP address, of the format:
+
+ ip.ip.ip.ip
+
+EG: 192.168.10.1
+
+A CIDR-style IP address range, of the format:
+
+ ip.ip.ip.ip/cidr
+
+EG: 192.168.10.0/24
+
+An IP and full netmask, of the format:
+
+ ip.ip.ip.ip:nm.nm.nm.nm
+
+EG: 192.168.10.4:255.255.255.255
+
+An IP address with wildcards:
+
+ ip.ip.ip.*
+ ip.ip.*.*
+ ip.*.*.*
+
+These rules may also be used in a flat file, delimited by newlines. An
+example of a full ACL is included in docs/examples/ labelled 'iplist'. Also
+note that comments start with a # and are perfectly acceptable for use in
+the ACL's.
+
+For example, the file "ipaccess" might look like:
+
+# Abuse from ADSL user.
+88.223.14.1/32
+
+# This guy is scanning us for SOCKS4 servers to abuse, block his /24
+194.213.167.*
+
+To implement this IP address ACL simply run:
+
+ncat --denyfile /path/to/file/ipaccess -l 7000
+
+For further documentation, please see the man page.
+
+--Chris Gibson and Kris Katterjohn
+
diff --git a/ncat/docs/THANKS b/ncat/docs/THANKS
new file mode 100644
index 0000000..d8d1bc0
--- /dev/null
+++ b/ncat/docs/THANKS
@@ -0,0 +1,29 @@
+Ncat Acknowledgements
+=====================
+
+This file is a short rambling of various "thank-you"'s to all
+the very generous support and advice received from various
+parties.
+
+First and foremost: Thanks go out to Fyodor for all the support
+and great ideas throughout the course of development and no doubt
+also in the future.
+
+Thanks to Google and the Summer of Code team. The points of
+contact with Google being Chris DiBona, Natalie and Jude. Thanks to
+you all for making this possible. Without whom I wouldn't even
+be writing this.
+
+Also, thank you to all the folks from #c on Undernet who kicked
+me in the right direction when things were at their most broken.
+
+Thanks to Jan for all her support and, well, general tolerance. :)
+
+Thanks to all the people who've submitted bug reports, given me
+ideas, helped me test Ncat or just given me general encouragement
+over the previous years. It is most appreciated.
+
+Finally, thanks to Hobbit for writing the original Netcat; it still
+rocks.
+
+--Chris Gibson, <chris@linuxops.net>
diff --git a/ncat/docs/examples/README b/ncat/docs/examples/README
new file mode 100644
index 0000000..7e253fc
--- /dev/null
+++ b/ncat/docs/examples/README
@@ -0,0 +1,15 @@
+/examples/scripts
+~~~~~~~~~~~~~~~~~
+These are a set of small scripts to further demonstrate some
+uses for Ncat. You *will* have to change some values yourself,
+such as in "http-proxy", if your proxy server requires authorization,
+you'll have to add your own authorization information.
+
+
+/examples/logs/
+~~~~~~~~~~~~~~~
+These are a set of output logfiles generated by Ncat to briefly
+demonstrate Ncat's logging abilities.
+
+
+--Chris Gibson, <chris@linuxops.net>
diff --git a/ncat/docs/examples/ipaccess b/ncat/docs/examples/ipaccess
new file mode 100644
index 0000000..356bea1
--- /dev/null
+++ b/ncat/docs/examples/ipaccess
@@ -0,0 +1,23 @@
+#
+# This is a sample IP access list that
+# could potentially be used with Ncat
+# to allow or deny specific users from
+# connecting to an Ncat process, such as
+# a standard listen operation to being
+# able to access your newly spawned SOCKS4
+# server.
+#
+# Obviously, these IP addresses are pretty
+# useless to most people. It is an example
+# afterall. :)
+#
+# Chris Gibson, <chris@linuxops.net>
+
+# lo interface.
+127.0.0.1/8
+
+# eth0 internal network.
+192.168.0.0/24
+
+# eth1 to outside world.
+55.20.30.1/32
diff --git a/ncat/docs/examples/logs/ascii-output b/ncat/docs/examples/logs/ascii-output
new file mode 100644
index 0000000..324f2a1
--- /dev/null
+++ b/ncat/docs/examples/logs/ascii-output
@@ -0,0 +1,3 @@
+HELO xxx.xxx.xxx
+220 smtp.google.com ESMTP
+250 smtp.google.com Hello xxx.xxx.xxx [xxx.xxx.xxx.xxx], pleased to meet you
diff --git a/ncat/docs/examples/logs/hex-output b/ncat/docs/examples/logs/hex-output
new file mode 100644
index 0000000..0114db5
--- /dev/null
+++ b/ncat/docs/examples/logs/hex-output
@@ -0,0 +1,47 @@
+[0000] 47 45 54 20 2F 69 6E 64 65 78 2E 68 74 6D 6C 20 GET..ind ex.html.
+[0010] 48 54 54 50 2F 31 2E 30 0A HTTP.1.0 .
+[0000] 55 73 65 72 2D 41 67 65 6E 74 3A 20 4E 63 61 74 User.Age nt..Ncat
+[0010] 0A .
+[0000] 48 6F 73 74 3A 20 77 77 77 2E 67 6F 6F 67 6C 65 Host..ww w.google
+[0010] 2E 63 6F 6D 0A .com.
+[0000] 0A .
+[0000] 48 54 54 50 2F 31 2E 30 20 33 30 32 20 46 6F 75 HTTP.1.0 .302.Fou
+[0010] 6E 64 0D 0A 4C 6F 63 61 74 69 6F 6E 3A 20 68 74 nd..Loca tion..ht
+[0020] 74 70 3A 2F 2F 77 77 77 2E 67 6F 6F 67 6C 65 2E tp...www .google.
+[0030] 63 6F 2E 75 6B 2F 63 78 66 65 72 3F 63 3D 50 52 co.uk.cx fer.c.PR
+[0040] 45 46 25 33 44 3A 54 4D 25 33 44 31 31 32 34 37 EF.3D.TM .3D11247
+[0050] 35 35 38 30 32 3A 53 25 33 44 48 75 52 73 51 62 55802.S. 3DHuRsQb
+[0060] 51 69 43 59 52 71 4A 6E 5A 32 26 70 72 65 76 3D QiCYRqJn Z2.prev.
+[0070] 2F 69 6E 64 65 78 2E 68 74 6D 6C 0D 0A 53 65 74 .index.h tml..Set
+[0080] 2D 43 6F 6F 6B 69 65 3A 20 50 52 45 46 3D 49 44 .Cookie. .PREF.ID
+[0090] 3D 31 63 31 31 36 32 63 66 36 63 63 33 65 35 63 .1c1162c f6cc3e5c
+[00a0] 64 3A 43 52 3D 31 3A 54 4D 3D 31 31 32 34 37 35 d.CR.1.T M.112475
+[00b0] 35 38 30 32 3A 4C 4D 3D 31 31 32 34 37 35 35 38 5802.LM. 11247558
+[00c0] 30 32 3A 53 3D 5F 38 33 69 47 45 53 67 6F 7A 6E 02.S..83 iGESgozn
+[00d0] 33 49 4F 6D 34 3B 20 65 78 70 69 72 65 73 3D 53 3IOm4..e xpires.S
+[00e0] 75 6E 2C 20 31 37 2D 4A 61 6E 2D 32 30 33 38 20 un..17.J an.2038.
+[00f0] 31 39 3A 31 34 3A 30 37 20 47 4D 54 3B 20 70 61 19.14.07 .GMT..pa
+[0100] 74 68 3D 2F 3B 20 64 6F 6D 61 69 6E 3D 2E 67 6F th....do main..go
+[0110] 6F 67 6C 65 2E 63 6F 6D 0D 0A 43 6F 6E 74 65 6E ogle.com ..Conten
+[0120] 74 2D 54 79 70 65 3A 20 74 65 78 74 2F 68 74 6D t.Type.. text.htm
+[0130] 6C 0D 0A 53 65 72 76 65 72 3A 20 47 57 53 2F 32 l..Serve r..GWS.2
+[0140] 2E 31 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67 .1..Cont ent.Leng
+[0150] 74 68 3A 20 32 32 37 0D 0A 44 61 74 65 3A 20 54 th..227. .Date..T
+[0160] 75 65 2C 20 32 33 20 41 75 67 20 32 30 30 35 20 ue..23.A ug.2005.
+[0170] 30 30 3A 31 30 3A 30 32 20 47 4D 54 0D 0A 43 6F 00.10.02 .GMT..Co
+[0180] 6E 6E 65 63 74 69 6F 6E 3A 20 4B 65 65 70 2D 41 nnection ..Keep.A
+[0190] 6C 69 76 65 0D 0A 0D 0A 3C 48 54 4D 4C 3E 3C 48 live.... .HTML..H
+[01a0] 45 41 44 3E 3C 54 49 54 4C 45 3E 33 30 32 20 4D EAD..TIT LE.302.M
+[01b0] 6F 76 65 64 3C 2F 54 49 54 4C 45 3E 3C 2F 48 45 oved..TI TLE...HE
+[01c0] 41 44 3E 3C 42 4F 44 59 3E 0A 3C 48 31 3E 33 30 AD..BODY ...H1.30
+[01d0] 32 20 4D 6F 76 65 64 3C 2F 48 31 3E 0A 54 68 65 2.Moved. .H1..The
+[01e0] 20 64 6F 63 75 6D 65 6E 74 20 68 61 73 20 6D 6F .documen t.has.mo
+[01f0] 76 65 64 0A 3C 41 20 48 52 45 46 3D 22 68 74 74 ved..A.H REF..htt
+[0200] 70 3A 2F 2F 77 77 77 2E 67 6F 6F 67 6C 65 2E 63 p...www. google.c
+[0210] 6F 2E 75 6B 2F 63 78 66 65 72 3F 63 3D 50 52 45 o.uk.cxf er.c.PRE
+[0220] 46 25 33 44 3A 54 4D 25 33 44 31 31 32 34 37 35 F.3D.TM. 3D112475
+[0230] 35 38 30 32 3A 53 25 33 44 48 75 52 73 51 62 51 5802.S.3 DHuRsQbQ
+[0240] 69 43 59 52 71 4A 6E 5A 32 26 61 6D 70 3B 70 72 iCYRqJnZ 2.amp.pr
+[0250] 65 76 3D 2F 69 6E 64 65 78 2E 68 74 6D 6C 22 3E ev..inde x.html..
+[0260] 68 65 72 65 3C 2F 41 3E 2E 0D 0A 3C 2F 42 4F 44 here..A. .....BOD
+[0270] 59 3E 3C 2F 48 54 4D 4C 3E 0D 0A Y...HTML ...
diff --git a/ncat/docs/examples/scripts/README b/ncat/docs/examples/scripts/README
new file mode 100644
index 0000000..e50372f
--- /dev/null
+++ b/ncat/docs/examples/scripts/README
@@ -0,0 +1,6 @@
+These are various scripts that demonstrate some
+potential usage for Ncat.
+
+If you find a neat usage for Ncat and possibly
+write a few lines of code to automate something,
+then please email them over to Chris Gibson (chris@linuxops.net)
diff --git a/ncat/docs/examples/scripts/http-proxy b/ncat/docs/examples/scripts/http-proxy
new file mode 100755
index 0000000..904c20f
--- /dev/null
+++ b/ncat/docs/examples/scripts/http-proxy
@@ -0,0 +1,5 @@
+NCAT_PATH=../../..
+PROXY_HOST=www.cnn.com:80
+PROXY_AUTH=user:pass
+
+$NCAT_PATH/ncat --http-proxy "$PROXY_HOST" --proxy-auth "$PROXY_AUTH" localhost 3128
diff --git a/ncat/docs/examples/scripts/http-scan/README b/ncat/docs/examples/scripts/http-scan/README
new file mode 100644
index 0000000..bb5c8be
--- /dev/null
+++ b/ncat/docs/examples/scripts/http-scan/README
@@ -0,0 +1,14 @@
+HTTP-SCAN with Ncat
+~~~~~~~~~~~~~~~~~~~
+
+This is a simple exercise that uses a small amount of
+scripted automation that will throw out the banner
+information of n number of hosts listed in the file "iplist".
+
+Ncat uses the "get.request" HTTP header to get the newly
+connected webserver to tell you about itself.
+
+Usage: ./scan-example
+
+Variables to change: None, but you may want to change "iplist"
+ to other more informative hosts.
diff --git a/ncat/docs/examples/scripts/http-scan/get.request b/ncat/docs/examples/scripts/http-scan/get.request
new file mode 100644
index 0000000..778a569
--- /dev/null
+++ b/ncat/docs/examples/scripts/http-scan/get.request
@@ -0,0 +1,3 @@
+HEAD / HTTP/1.0
+
+
diff --git a/ncat/docs/examples/scripts/http-scan/iplist b/ncat/docs/examples/scripts/http-scan/iplist
new file mode 100644
index 0000000..f0417e9
--- /dev/null
+++ b/ncat/docs/examples/scripts/http-scan/iplist
@@ -0,0 +1,5 @@
+www.google.com
+www.microsoft.com
+www.apache.org
+www.freebsd.org
+www.apple.com
diff --git a/ncat/docs/examples/scripts/http-scan/scan-example b/ncat/docs/examples/scripts/http-scan/scan-example
new file mode 100755
index 0000000..1fe7f75
--- /dev/null
+++ b/ncat/docs/examples/scripts/http-scan/scan-example
@@ -0,0 +1,7 @@
+NCAT_PATH=../../../..
+if [ -a "$NCAT_PATH/ncat" ]
+ then
+ for addr in `cat iplist`; do $NCAT_PATH/ncat --disable-eof-exit $addr 80 < get.request; done;
+else
+ echo "Ncat is not buit. Please build Ncat before you use these scripts";
+fi
diff --git a/ncat/docs/examples/scripts/http-scan/scanner-output b/ncat/docs/examples/scripts/http-scan/scanner-output
new file mode 100644
index 0000000..5c69d59
--- /dev/null
+++ b/ncat/docs/examples/scripts/http-scan/scanner-output
@@ -0,0 +1,57 @@
+Connected to 66.102.9.147:80
+HTTP/1.0 302 Found
+Location: http://www.google.co.uk/
+Set-Cookie: PREF=ID=b6262fee80b28ffc:TM=1137945347:LM=1137945347:S=s7TLf6mcMNGW-33R; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
+Content-Type: text/html
+Server: GWS/2.1
+Content-Length: 224
+Date: Sun, 22 Jan 2006 15:55:47 GMT
+Connection: Keep-Alive
+
+Connected to 207.46.198.30:80
+HTTP/1.1 200 OK
+Connection: close
+Date: Sun, 22 Jan 2006 15:55:48 GMT
+Server: Microsoft-IIS/6.0
+P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
+X-Powered-By: ASP.NET
+X-AspNet-Version: 2.0.50727
+Cache-Control: private
+Content-Type: text/html; charset=utf-8
+Content-Length: 21061
+
+Connected to 209.237.227.195:80
+HTTP/1.1 200 OK
+Date: Sun, 22 Jan 2006 15:55:48 GMT
+Server: Apache/2.2.0 (Unix)
+Last-Modified: Wed, 18 Jan 2006 03:00:54 GMT
+ETag: "997bf1-2d93-419e2580"
+Accept-Ranges: bytes
+Content-Length: 11667
+Cache-Control: max-age=86400
+Expires: Mon, 23 Jan 2006 15:55:48 GMT
+Connection: close
+Content-Type: text/html; charset=ISO-8859-1
+
+Connected to 216.136.204.117:80
+HTTP/1.1 200 OK
+Date: Sun, 22 Jan 2006 15:55:49 GMT
+Server: Apache/1.3.x LaHonda (Unix)
+Last-Modified: Fri, 20 Jan 2006 21:24:33 GMT
+ETag: "26f8f7-9839-43d15511"
+Accept-Ranges: bytes
+Content-Length: 38969
+Connection: close
+Content-Type: text/html
+X-Pad: avoid browser bug
+
+Connected to 17.112.152.32:80
+HTTP/1.0 200 OK
+Age: 328
+Date: Sun, 22 Jan 2006 15:50:20 GMT
+Content-Length: 26131
+Content-Type: text/html
+Expires: Sun, 22 Jan 2006 16:10:20 GMT
+Cache-Control: max-age=1200
+Server: Apache/1.3.29 (Darwin) PHP/4.3.1
+
diff --git a/ncat/docs/ncat-ascii-art.txt b/ncat/docs/ncat-ascii-art.txt
new file mode 100644
index 0000000..1621079
--- /dev/null
+++ b/ncat/docs/ncat-ascii-art.txt
@@ -0,0 +1,11 @@
+ . .
+ \`-"'"-'/
+ } 6 6 {
+ ==. Y ,==
+ /^^^\ .
+ / \ ) Ncat: A modern interpretation of classic Netcat
+ ( )-( )/
+ -""---""--- /
+ / Ncat \_/
+ ( ____
+ \_.=|____E
diff --git a/ncat/docs/ncat.1 b/ncat/docs/ncat.1
new file mode 100644
index 0000000..7fbc5b5
--- /dev/null
+++ b/ncat/docs/ncat.1
@@ -0,0 +1,787 @@
+'\" t
+.\" Title: Ncat
+.\" Author: [see the "Authors" section]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\" Date: 05/17/2023
+.\" Manual: Ncat Reference Guide
+.\" Source: Ncat
+.\" Language: English
+.\"
+.TH "NCAT" "1" "05/17/2023" "Ncat" "Ncat Reference Guide"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+ncat \- Concatenate and redirect sockets
+.SH "SYNOPSIS"
+.HP \w'\fBncat\fR\ 'u
+\fBncat\fR [\fIOPTIONS\fR...] [\fIhostname\fR] [\fIport\fR]
+.SH "DESCRIPTION"
+.PP
+Ncat is a feature\-packed networking utility which reads and writes data across networks from the command line\&. Ncat was written for the Nmap Project and is the culmination of the currently splintered family of Netcat incarnations\&. It is designed to be a reliable back\-end tool to instantly provide network connectivity to other applications and users\&. Ncat will not only work with IPv4 and IPv6 but provides the user with a virtually limitless number of potential uses\&.
+.PP
+Among Ncat\*(Aqs vast number of features there is the ability to chain Ncats together; redirection of TCP, UDP, and SCTP ports to other sites; SSL support; and proxy connections via SOCKS4, SOCKS5 or HTTP proxies (with optional proxy authentication as well)\&. Some general principles apply to most applications and thus give you the capability of instantly adding networking support to software that would normally never support it\&.
+.SH "OPTIONS SUMMARY"
+.PP
+.if n \{\
+.RS 4
+.\}
+.nf
+Ncat 7\&.94 ( https://nmap\&.org/ncat )
+Usage: ncat [options] [hostname] [port]
+
+Options taking a time assume seconds\&. Append \*(Aqms\*(Aq for milliseconds,
+\*(Aqs\*(Aq for seconds, \*(Aqm\*(Aq for minutes, or \*(Aqh\*(Aq for hours (e\&.g\&. 500ms)\&.
+ \-4 Use IPv4 only
+ \-6 Use IPv6 only
+ \-U, \-\-unixsock Use Unix domain sockets only
+ \-\-vsock Use vsock sockets only
+ \-C, \-\-crlf Use CRLF for EOL sequence
+ \-c, \-\-sh\-exec <command> Executes the given command via /bin/sh
+ \-e, \-\-exec <command> Executes the given command
+ \-\-lua\-exec <filename> Executes the given Lua script
+ \-g hop1[,hop2,\&.\&.\&.] Loose source routing hop points (8 max)
+ \-G <n> Loose source routing hop pointer (4, 8, 12, \&.\&.\&.)
+ \-m, \-\-max\-conns <n> Maximum <n> simultaneous connections
+ \-h, \-\-help Display this help screen
+ \-d, \-\-delay <time> Wait between read/writes
+ \-o, \-\-output <filename> Dump session data to a file
+ \-x, \-\-hex\-dump <filename> Dump session data as hex to a file
+ \-i, \-\-idle\-timeout <time> Idle read/write timeout
+ \-p, \-\-source\-port port Specify source port to use
+ \-s, \-\-source addr Specify source address to use (doesn\*(Aqt affect \-l)
+ \-l, \-\-listen Bind and listen for incoming connections
+ \-k, \-\-keep\-open Accept multiple connections in listen mode
+ \-n, \-\-nodns Do not resolve hostnames via DNS
+ \-t, \-\-telnet Answer Telnet negotiations
+ \-u, \-\-udp Use UDP instead of default TCP
+ \-\-sctp Use SCTP instead of default TCP
+ \-v, \-\-verbose Set verbosity level (can be used several times)
+ \-w, \-\-wait <time> Connect timeout
+ \-z Zero\-I/O mode, report connection status only
+ \-\-append\-output Append rather than clobber specified output files
+ \-\-send\-only Only send data, ignoring received; quit on EOF
+ \-\-recv\-only Only receive data, never send anything
+ \-\-no\-shutdown Continue half\-duplex when receiving EOF on stdin
+ \-\-allow Allow only given hosts to connect to Ncat
+ \-\-allowfile A file of hosts allowed to connect to Ncat
+ \-\-deny Deny given hosts from connecting to Ncat
+ \-\-denyfile A file of hosts denied from connecting to Ncat
+ \-\-broker Enable Ncat\*(Aqs connection brokering mode
+ \-\-chat Start a simple Ncat chat server
+ \-\-proxy <addr[:port]> Specify address of host to proxy through
+ \-\-proxy\-type <type> Specify proxy type ("http", "socks4", "socks5")
+ \-\-proxy\-auth <auth> Authenticate with HTTP or SOCKS proxy server
+ \-\-proxy\-dns <type> Specify where to resolve proxy destination
+ \-\-ssl Connect or listen with SSL
+ \-\-ssl\-cert Specify SSL certificate file (PEM) for listening
+ \-\-ssl\-key Specify SSL private key (PEM) for listening
+ \-\-ssl\-verify Verify trust and domain name of certificates
+ \-\-ssl\-trustfile PEM file containing trusted SSL certificates
+ \-\-ssl\-ciphers Cipherlist containing SSL ciphers to use
+ \-\-ssl\-servername Request distinct server name (SNI)
+ \-\-ssl\-alpn ALPN protocol list to use
+ \-\-version Display Ncat\*(Aqs version information and exit
+
+See the ncat(1) manpage for full options, descriptions and usage examples
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.SH "CONNECT MODE AND LISTEN MODE"
+.PP
+Ncat operates in one of two primary modes: connect mode and listen mode\&. Other modes, such as the HTTP proxy server, act as special cases of these two\&. In connect mode, Ncat works as a client\&. In listen mode it is a server\&.
+.PP
+In connect mode, the
+\fB\fIhostname\fR\fR
+and
+\fB\fIport\fR\fR
+arguments tell what to connect to\&.
+\fB\fIhostname\fR\fR
+is required, and may be a hostname or IP address\&. If
+\fB\fIport\fR\fR
+is supplied, it must be a decimal port number\&. If omitted, it defaults to 31337\&.
+.PP
+In listen mode,
+\fB\fIhostname\fR\fR
+and
+\fB\fIport\fR\fR
+control the address the server will bind to\&. Both arguments are optional in listen mode\&. If
+\fB\fIhostname\fR\fR
+is omitted, it defaults to listening on all available addresses over IPv4 and IPv6\&. If
+\fB\fIport\fR\fR
+is omitted, it defaults to 31337\&.
+.SH "PROTOCOL OPTIONS"
+.PP
+\fB\-4\fR (IPv4 only)
+.RS 4
+Force the use of IPv4 only\&.
+.RE
+.PP
+\fB\-6\fR (IPv6 only)
+.RS 4
+Force the use of IPv6 only\&.
+.RE
+.PP
+\fB\-U\fR, \fB\-\-unixsock\fR (Use Unix domain sockets)
+.RS 4
+Use Unix domain sockets rather than network sockets\&. This option may be used on its own for stream sockets, or combined with
+\fB\-\-udp\fR
+for datagram sockets\&. A description of
+\fB\-U\fR
+mode is in
+the section called \(lqUNIX DOMAIN SOCKETS\(rq\&.
+.RE
+.PP
+\fB\-u\fR, \fB\-\-udp\fR (Use UDP)
+.RS 4
+Use UDP for the connection (the default is TCP)\&.
+.RE
+.PP
+\fB\-\-sctp\fR (Use SCTP)
+.RS 4
+Use SCTP for the connection (the default is TCP)\&. SCTP support is implemented in TCP\-compatible mode\&.
+.RE
+.PP
+\fB\-\-vsock\fR (Use AF_VSOCK sockets)
+.RS 4
+Use AF_VSOCK sockets rather than the default TCP sockets (Linux only)\&. This option may be used on its own for stream sockets or combined with
+\fB\-\-udp\fR
+for datagram sockets\&. A description of
+\fB\-\-vsock\fR
+mode is in
+the section called \(lqAF_VSOCK SOCKETS\(rq\&.
+.RE
+.SH "CONNECT MODE OPTIONS"
+.PP
+\fB\-g \fR\fB\fIhop1\fR\fR\fB[,\fIhop2\fR,\&.\&.\&.]\fR (Loose source routing)
+.RS 4
+Sets hops for IPv4 loose source routing\&. You can use
+\fB\-g\fR
+once with a comma\-separated list of hops, use
+\fB\-g\fR
+multiple times with single hops to build the list, or combine the two\&. Hops can be given as IP addresses or hostnames\&.
+.RE
+.PP
+\fB\-G \fR\fB\fIptr\fR\fR (Set source routing pointer)
+.RS 4
+Sets the IPv4 source route
+\(lqpointer\(rq
+for use with
+\fB\-g\fR\&. The argument must be a multiple of 4 and no more than 28\&. Not all operating systems support setting this pointer to anything other than four\&.
+.RE
+.PP
+\fB\-p \fR\fB\fIport\fR\fR, \fB\-\-source\-port \fR\fB\fIport\fR\fR (Specify source port)
+.RS 4
+Set the port number for Ncat to bind to\&.
+.RE
+.PP
+\fB\-s \fR\fB\fIhost\fR\fR, \fB\-\-source \fR\fB\fIhost\fR\fR (Specify source address)
+.RS 4
+Set the address for Ncat to bind to\&.
+.RE
+.SH "LISTEN MODE OPTIONS"
+.PP
+See
+the section called \(lqACCESS CONTROL OPTIONS\(rq
+for information on limiting the hosts that may connect to the listening Ncat process\&.
+.PP
+\fB\-l\fR, \fB\-\-listen\fR (Listen for connections)
+.RS 4
+Listen for connections rather than connecting to a remote machine
+.RE
+.PP
+\fB\-m \fR\fB\fInumconns\fR\fR, \fB\-\-max\-conns \fR\fB\fInumconns\fR\fR (Specify maximum number of connections)
+.RS 4
+The maximum number of simultaneous connections accepted by an Ncat instance\&. 100 is the default (60 on Windows)\&.
+.RE
+.PP
+\fB\-k\fR, \fB\-\-keep\-open\fR (Accept multiple connections)
+.RS 4
+Normally a listening server accepts only one connection and then quits when the connection is closed\&. This option makes it accept multiple simultaneous connections and wait for more connections after they have all been closed\&. It must be combined with
+\fB\-\-listen\fR\&. In this mode there is no way for Ncat to know when its network input is finished, so it will keep running until interrupted\&. This also means that it will never close its output stream, so any program reading from Ncat and looking for end\-of\-file will also hang\&.
+.RE
+.PP
+\fB\-\-broker\fR (Connection brokering)
+.RS 4
+Allow multiple parties to connect to a centralised Ncat server and communicate with each other\&. Ncat can broker communication between systems that are behind a NAT or otherwise unable to directly connect\&. This option is used in conjunction with
+\fB\-\-listen\fR, which causes the
+\fB\-\-listen\fR
+port to have broker mode enabled\&.
+.RE
+.PP
+\fB\-\-chat\fR (Ad\-hoc \(lqchat server\(rq)
+.RS 4
+The
+\fB\-\-chat\fR
+option enables chat mode, intended for the exchange of text between several users\&. In chat mode, connection brokering is turned on\&. Ncat prefixes each message received with an ID before relaying it to the other connections\&. The ID is unique for each connected client\&. This helps distinguish who sent what\&. Additionally, non\-printing characters such as control characters are escaped to keep them from doing damage to a terminal\&.
+.RE
+.SH "SSL OPTIONS"
+.PP
+\fB\-\-ssl\fR (Use SSL)
+.RS 4
+In connect mode, this option transparently negotiates an SSL session with an SSL server to securely encrypt the connection\&. This is particularly handy for talking to SSL enabled HTTP servers, etc\&.
+.sp
+In server mode, this option listens for incoming SSL connections, rather than plain untunneled traffic\&.
+.sp
+In UDP mode, this option enables Datagram TLS (DTLS)\&.
+.RE
+.PP
+\fB\-\-ssl\-verify\fR (Verify server certificates)
+.RS 4
+In client mode,
+\fB\-\-ssl\-verify\fR
+is like
+\fB\-\-ssl\fR
+except that it also requires verification of the server certificate\&. Ncat comes with a default set of trusted certificates in the file
+ca\-bundle\&.crt\&.
+Some operating systems provide a default list of trusted certificates; these will also be used if available\&. Use
+\fB\-\-ssl\-trustfile\fR
+to give a custom list\&. Use
+\fB\-v\fR
+one or more times to get details about verification failures\&.
+Ncat does not check for revoked certificates\&.
+.sp
+This option has no effect in server mode\&.
+.RE
+.PP
+\fB\-\-ssl\-cert \fR\fB\fIcertfile\&.pem\fR\fR (Specify SSL certificate)
+.RS 4
+This option gives the location of a PEM\-encoded certificate files used to authenticate the server (in listen mode) or the client (in connect mode)\&. Use it in combination with
+\fB\-\-ssl\-key\fR\&.
+.RE
+.PP
+\fB\-\-ssl\-key \fR\fB\fIkeyfile\&.pem\fR\fR (Specify SSL private key)
+.RS 4
+This option gives the location of the PEM\-encoded private key file that goes with the certificate named with
+\fB\-\-ssl\-cert\fR\&.
+.RE
+.PP
+\fB\-\-ssl\-trustfile \fR\fB\fIcert\&.pem\fR\fR (List trusted certificates)
+.RS 4
+This option sets a list of certificates that are trusted for purposes of certificate verification\&. It has no effect unless combined with
+\fB\-\-ssl\-verify\fR\&. The argument to this option is the name of a PEM
+file containing trusted certificates\&. Typically, the file will contain certificates of certification authorities, though it may also contain server certificates directly\&. When this option is used, Ncat does not use its default certificates\&.
+.RE
+.PP
+\fB\-\-ssl\-ciphers \fR\fB\fIcipherlist\fR\fR (Specify SSL ciphersuites)
+.RS 4
+This option sets the list of ciphersuites that Ncat will use when connecting to servers or when accepting SSL connections from clients\&. The syntax is described in the OpenSSL ciphers(1) man page, and defaults to
+ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!MD5:@STRENGTH
+.RE
+.PP
+\fB\-\-ssl\-servername \fR\fB\fIname\fR\fR (Request distinct server name)
+.RS 4
+In client mode, this option sets the TLS SNI (Server Name Indication) extension, which tells the server the name of the logical server Ncat is contacting\&. This is important when the target server hosts multiple virtual servers at a single underlying network address\&. If the option is not provided, the TLS SNI extension will be populated with the target server hostname\&.
+.RE
+.PP
+\fB\-\-ssl\-alpn \fR\fB\fIALPN list\fR\fR (Specify ALPN protocol list)
+.RS 4
+This option allows you to specify a comma\-separated list of protocols to send via the Application\-Layer Protocol Negotiation (ALPN) TLS extension\&. Not supported by all versions of OpenSSL\&.
+.RE
+.SH "PROXY OPTIONS"
+.PP
+\fB\-\-proxy \fR\fB\fIhost\fR\fR\fB[:\fIport\fR]\fR (Specify proxy address)
+.RS 4
+Requests proxying through
+\fIhost\fR:\fIport\fR, using the protocol specified by
+\fB\-\-proxy\-type\fR\&.
+.sp
+If no port is specified, the proxy protocol\*(Aqs well\-known port is used (1080 for SOCKS and 3128 for HTTP)\&. When specifying an IPv6 HTTP proxy server using the IP address rather than the hostname, the square\-bracket notation (for example [2001:db8::1]:8080) MUST be used to separate the port from the IPv6 address\&. If the proxy requires authentication, use
+\fB\-\-proxy\-auth\fR\&.
+.RE
+.PP
+\fB\-\-proxy\-type \fR\fB\fIproto\fR\fR (Specify proxy protocol)
+.RS 4
+In connect mode, this option requests the protocol
+\fIproto\fR
+to connect through the proxy host specified by
+\fB\-\-proxy\fR\&. In listen mode, this option has Ncat act as a proxy server using the specified protocol\&.
+.sp
+The currently available protocols in connect mode are
+http
+(CONNECT),
+socks4
+(SOCKSv4), and
+socks5
+(SOCKSv5)\&. The only server currently supported is
+http\&. If this option is not used, the default protocol is
+http\&.
+.RE
+.PP
+\fB\-\-proxy\-auth \fR\fB\fIuser\fR\fR\fB[:\fIpass\fR]\fR (Specify proxy credentials)
+.RS 4
+In connect mode, gives the credentials that will be used to connect to the proxy server\&. In listen mode, gives the credentials that will be required of connecting clients\&. For use with
+\fB\-\-proxy\-type http\fR
+or
+\fB\-\-proxy\-type socks5\fR, the form should be username:password\&. For
+\fB\-\-proxy\-type socks4\fR, it should be a username only\&.
+.sp
+These credentials can be alternatively passed onto Ncat by setting environment variable
+\fBNCAT_PROXY_AUTH\fR, which reduces the risk of the credentials being captured in process logs\&. (Option
+\fB\-\-proxy\-auth\fR
+takes precedence\&.)
+.RE
+.PP
+\fB\-\-proxy\-dns \fR\fB\fItype\fR\fR (Specify where to resolve proxy destination)
+.RS 4
+In connect mode, it provides control over whether proxy destination hostnames are resolved by the remote proxy server or locally, by Ncat itself\&. Possible values for
+\fItype\fR
+are:
+.sp
+local
+\- Hostnames are resolved locally on the Ncat host\&. Ncat exits with error if the hostname cannot be resolved\&.
+.sp
+remote
+\- Hostnames are passed directly onto the remote proxy server\&. This is the default behavior\&.
+.sp
+both
+\- Hostname resolution is first attempted on the Ncat host\&. Unresolvable hostnames are passed onto the remote proxy server\&.
+.sp
+none
+\- Hostname resolution is completely disabled\&. Only a literal IPv4 or IPv6 address can be used as the proxy destination\&.
+.sp
+Local hostname resolution generally respects IP version specified with options
+\fB\-4\fR
+or
+\fB\-6\fR, except for SOCKS4, which is incompatible with IPv6\&.
+.RE
+.SH "COMMAND EXECUTION OPTIONS"
+.PP
+\fB\-e \fR\fB\fIcommand\fR\fR, \fB\-\-exec \fR\fB\fIcommand\fR\fR (Execute command)
+.RS 4
+Execute the specified command after a connection has been established\&. The command must be specified as a full pathname\&. All input from the remote client will be sent to the application and responses sent back to the remote client over the socket, thus making your command\-line application interactive over a socket\&. Combined with
+\fB\-\-keep\-open\fR, Ncat will handle multiple simultaneous connections to your specified port/application like inetd\&. Ncat will only accept a maximum, definable, number of simultaneous connections controlled by the
+\fB\-m\fR
+option\&. By default this is set to 100 (60 on Windows)\&.
+.RE
+.PP
+\fB\-c \fR\fB\fIcommand\fR\fR, \fB\-\-sh\-exec \fR\fB\fIcommand\fR\fR (Execute command via sh)
+.RS 4
+Same as
+\fB\-e\fR, except it tries to execute the command via
+/bin/sh\&. This means you don\*(Aqt have to specify the full path for the command, and shell facilities like environment variables are available\&.
+.RE
+.PP
+\fB\-\-lua\-exec \fR\fB\fIfile\fR\fR (Execute a \&.lua script)
+.RS 4
+Runs the specified file as a Lua script after a connection has been established, using a built\-in interpreter\&. Both the script\*(Aqs standard input and the standard output are redirected to the connection data streams\&.
+.RE
+.PP
+All exec options add the following variables to the child\*(Aqs environment:
+.PP
+\fBNCAT_REMOTE_ADDR\fR, \fBNCAT_REMOTE_PORT\fR
+.RS 4
+The IP address and port number of the remote host\&. In connect mode, it\*(Aqs the target\*(Aqs address; in listen mode, it\*(Aqs the client\*(Aqs address\&.
+.RE
+.PP
+\fBNCAT_LOCAL_ADDR\fR, \fBNCAT_LOCAL_PORT\fR
+.RS 4
+The IP address and port number of the local end of the connection\&.
+.RE
+.PP
+\fBNCAT_PROTO\fR
+.RS 4
+The protocol in use: one of
+TCP,
+UDP, and
+SCTP\&.
+.RE
+.SH "ACCESS CONTROL OPTIONS"
+.PP
+\fB\-\-allow \fR\fB\fIhost\fR\fR\fB[,\fIhost\fR,\&.\&.\&.]\fR (Allow connections)
+.RS 4
+The list of hosts specified will be the only hosts allowed to connect to the Ncat process\&. All other connection attempts will be disconnected\&. In case of a conflict between
+\fB\-\-allow\fR
+and
+\fB\-\-deny\fR,
+\fB\-\-allow\fR
+takes precedence\&. Host specifications follow the same syntax used by Nmap\&.
+.RE
+.PP
+\fB\-\-allowfile \fR\fB\fIfile\fR\fR (Allow connections from file)
+.RS 4
+This has the same functionality as
+\fB\-\-allow\fR, except that the allowed hosts are provided in a new\-line delimited allow file, rather than directly on the command line\&.
+.RE
+.PP
+\fB\-\-deny \fR\fB\fIhost\fR\fR\fB[,\fIhost\fR,\&.\&.\&.]\fR (Deny connections)
+.RS 4
+Issue Ncat with a list of hosts that will not be allowed to connect to the listening Ncat process\&. Specified hosts will have their session silently terminated if they try to connect\&. In case of a conflict between
+\fB\-\-allow\fR
+and
+\fB\-\-deny\fR,
+\fB\-\-allow\fR
+takes precedence\&. Host specifications follow the same syntax used by Nmap\&.
+.RE
+.PP
+\fB\-\-denyfile \fR\fB\fIfile\fR\fR (Deny connections from file)
+.RS 4
+This is the same functionality as
+\fB\-\-deny\fR, except that excluded hosts are provided in a new\-line delimited deny file, rather than directly on the command line\&.
+.RE
+.SH "TIMING OPTIONS"
+.PP
+These options accept a
+time
+parameter\&. This is specified in seconds by default, though you can append
+ms,
+s,
+m, or
+h
+to the value to specify milliseconds, seconds, minutes, or hours\&.
+.PP
+\fB\-d \fR\fB\fItime\fR\fR, \fB\-\-delay \fR\fB\fItime\fR\fR (Specify line delay)
+.RS 4
+Set the delay interval for lines sent\&. This effectively limits the number of lines that Ncat will send in the specified period\&. This may be useful for low\-bandwidth sites, or have other uses such as coping with annoying
+\fBiptables \-\-limit\fR
+options\&.
+.RE
+.PP
+\fB\-i \fR\fB\fItime\fR\fR, \fB\-\-idle\-timeout \fR\fB\fItime\fR\fR (Specify idle timeout)
+.RS 4
+Set a fixed timeout for idle connections\&. If the idle timeout is reached, the connection is terminated\&.
+.RE
+.PP
+\fB\-w \fR\fB\fItime\fR\fR, \fB\-\-wait \fR\fB\fItime\fR\fR (Specify connect timeout)
+.RS 4
+Set a fixed timeout for connection attempts\&.
+.RE
+.SH "OUTPUT OPTIONS"
+.PP
+\fB\-o \fR\fB\fIfile\fR\fR, \fB\-\-output \fR\fB\fIfile\fR\fR (Save session data)
+.RS 4
+Dump session data to a file
+.RE
+.PP
+\fB\-x \fR\fB\fIfile\fR\fR, \fB\-\-hex\-dump \fR\fB\fIfile\fR\fR (Save session data in hex)
+.RS 4
+Dump session data in hex to a file\&.
+.RE
+.PP
+\fB\-\-append\-output\fR (Append output)
+.RS 4
+Issue Ncat with
+\fB\-\-append\-ouput\fR
+along with
+\fB\-o\fR
+and/or
+\fB\-x\fR
+and it will append the resulted output rather than truncating the specified output files\&.
+.RE
+.PP
+\fB\-v\fR, \fB\-\-verbose\fR (Be verbose)
+.RS 4
+Issue Ncat with
+\fB\-v\fR
+and it will be verbose and display all kinds of useful connection based information\&. Use more than once (\fB\-vv\fR,
+\fB\-vvv\fR\&.\&.\&.) for greater verbosity\&.
+.RE
+.SH "MISC OPTIONS"
+.PP
+\fB\-C\fR, \fB\-\-crlf\fR (Use CRLF as EOL)
+.RS 4
+This option tells Ncat to convert LF
+line endings to CRLF
+when taking input from standard input\&.
+This is useful for talking to some stringent servers directly from a terminal in one of the many common plain\-text protocols that use CRLF for end\-of\-line\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-help\fR (Help screen)
+.RS 4
+Displays a short help screen with common options and parameters, and then exits\&.
+.RE
+.PP
+\fB\-\-recv\-only\fR (Only receive data)
+.RS 4
+If this option is passed, Ncat will only receive data and will not try to send anything\&.
+.RE
+.PP
+\fB\-\-send\-only\fR (Only send data)
+.RS 4
+If this option is passed, then Ncat will only send data and will ignore anything received\&. This option also causes Ncat to close the network connection and terminate after EOF is received on standard input\&.
+.RE
+.PP
+\fB\-\-no\-shutdown\fR (Do not shutdown into half\-duplex mode)
+.RS 4
+If this option is passed, Ncat will not invoke shutdown on a socket after seeing EOF on stdin\&. This is provided for backward\-compatibility with OpenBSD netcat, which exhibits this behavior when executed with its \*(Aq\-d\*(Aq option\&.
+.RE
+.PP
+\fB\-n\fR, \fB\-\-nodns\fR (Do not resolve hostnames)
+.RS 4
+Completely disable hostname resolution across all Ncat options, such as the destination, source address, source routing hops, and the proxy\&. All addresses must be specified numerically\&. (Note that resolution of proxy destinations is controlled separately via option
+\fB\-\-proxy\-dns\fR\&.)
+.RE
+.PP
+\fB\-t\fR, \fB\-\-telnet\fR (Answer Telnet negotiations)
+.RS 4
+Handle DO/DONT WILL/WONT Telnet negotiations\&. This makes it possible to script Telnet sessions with Ncat\&.
+.RE
+.PP
+\fB\-\-version\fR (Display version)
+.RS 4
+Displays the Ncat version number and exits\&.
+.RE
+.SH "UNIX DOMAIN SOCKETS"
+.PP
+The
+\fB\-U\fR
+option (same as
+\fB\-\-unixsock\fR) causes Ncat to use Unix domain sockets rather than network sockets\&. Unix domain sockets exist as an entry in the filesystem\&. You must give the name of a socket to connect to or to listen on\&. For example, to make a connection,
+.PP
+\fBncat \-U ~/unixsock\fR
+.PP
+To listen on a socket:
+.PP
+\fBncat \-l \-U ~/unixsock\fR
+.PP
+Listen mode will create the socket if it doesn\*(Aqt exist\&. The socket will continue to exist after the program ends\&.
+.PP
+Both stream and datagram domain sockets are supported\&. Use
+\fB\-U\fR
+on its own for stream sockets, or combine it with
+\fB\-\-udp\fR
+for datagram sockets\&. Datagram sockets require a source socket to connect from\&. By default, a source socket with a random filename will be created as needed, and deleted when the program ends\&. Use the
+\fB\-\-source\fR
+with a path to use a source socket with a specific name\&.
+.SH "AF_VSOCK SOCKETS"
+.PP
+The
+\fB\-\-vsock\fR
+option causes Ncat to use AF_VSOCK sockets rather than network sockets\&. A CID must be given instead of a hostname or IP address\&. For example, to make a connection to the host,
+.PP
+\fBncat \-\-vsock 2 1234\fR
+.PP
+To listen on a socket:
+.PP
+\fBncat \-l \-\-vsock 1234\fR
+.PP
+Both stream and datagram domain sockets are supported, but socket type availability depends on the hypervisor\&. Use
+\fB\-\-vsock\fR
+on its own for stream sockets, or combine it with
+\fB\-\-udp\fR
+for datagram sockets\&.
+.SH "EXAMPLES"
+.PP
+Connect to example\&.org on TCP port 8080\&.
+.RS 4
+\fBncat example\&.org 8080\fR
+.RE
+.PP
+Listen for connections on TCP port 8080\&.
+.RS 4
+\fBncat \-l 8080\fR
+.RE
+.PP
+Redirect TCP port 8080 on the local machine to host on port 80\&.
+.RS 4
+\fBncat \-\-sh\-exec "ncat example\&.org 80" \-l 8080 \-\-keep\-open\fR
+.RE
+.PP
+Bind to TCP port 8081 and attach /bin/bash for the world to access freely\&.
+.RS 4
+\fBncat \-\-exec "/bin/bash" \-l 8081 \-\-keep\-open\fR
+.RE
+.PP
+Bind a shell to TCP port 8081, limit access to hosts on a local network, and limit the maximum number of simultaneous connections to 3\&.
+.RS 4
+\fBncat \-\-exec "/bin/bash" \-\-max\-conns 3 \-\-allow 192\&.168\&.0\&.0/24 \-l 8081 \-\-keep\-open\fR
+.RE
+.PP
+Connect to smtphost:25 through a SOCKS4 server on port 1080\&.
+.RS 4
+\fBncat \-\-proxy socks4host \-\-proxy\-type socks4 \-\-proxy\-auth joe smtphost 25\fR
+.RE
+.PP
+Connect to smtphost:25 through a SOCKS5 server on port 1080\&.
+.RS 4
+\fBncat \-\-proxy socks5host \-\-proxy\-type socks5 \-\-proxy\-auth joe:secret smtphost 25\fR
+.RE
+.PP
+Create an HTTP proxy server on localhost port 8888\&.
+.RS 4
+\fBncat \-l \-\-proxy\-type http localhost 8888\fR
+.RE
+.PP
+Send a file over TCP port 9899 from host2 (client) to host1 (server)\&.
+.RS 4
+HOST1$
+\fBncat \-l 9899 > outputfile\fR
+.sp
+HOST2$
+\fBncat HOST1 9899 < inputfile\fR
+.RE
+.PP
+Transfer in the other direction, turning Ncat into a \(lqone file\(rq server\&.
+.RS 4
+HOST1$
+\fBncat \-l 9899 < inputfile\fR
+.sp
+HOST2$
+\fBncat HOST1 9899 > outputfile\fR
+.RE
+.SH "EXIT CODE"
+.PP
+The exit code reflects whether a connection was made and completed successfully\&. 0 means there was no error\&. 1 means there was a network error of some kind, for example
+\(lqConnection refused\(rq
+or
+\(lqConnection reset\(rq\&. 2 is reserved for all other errors, like an invalid option or a nonexistent file\&.
+.SH "BUGS"
+.PP
+Like its authors, Ncat isn\*(Aqt perfect\&. But you can help make it better by sending bug reports or even writing patches\&. If Ncat doesn\*(Aqt behave the way you expect, first upgrade to the latest version available from
+\m[blue]\fB\%https://nmap.org\fR\m[]\&. If the problem persists, do some research to determine whether it has already been discovered and addressed\&. Try Googling the error message or browsing the
+nmap\-dev
+archives at
+\m[blue]\fB\%https://seclists.org/\fR\m[]\&.
+
+Read this full manual page as well\&. If nothing comes of this, mail a bug report to
+<dev@nmap\&.org>\&. Please include everything you have learned about the problem, as well as what version of Ncat you are running and what operating system version it is running on\&. Problem reports and Ncat usage questions sent to dev@nmap\&.org are far more likely to be answered than those sent to Fyodor directly\&.
+.PP
+Code patches to fix bugs are even better than bug reports\&. Basic instructions for creating patch files with your changes are available at
+\m[blue]\fB\%https://svn.nmap.org/nmap/HACKING\fR\m[]\&. Patches may be sent to
+nmap\-dev
+(recommended) or to Fyodor directly\&.
+.SH "AUTHORS"
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Chris Gibson
+<chris@linuxops\&.net>
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Gordon Lyon (Fyodor)<fyodor@nmap\&.org>
+(\m[blue]\fB\%http://insecure.org\fR\m[])
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Kris Katterjohn
+<katterjohn@gmail\&.com>
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Mixter
+<mixter@gmail\&.com>
+.RE
+.PP
+The original Netcat was written by *Hobbit*
+<hobbit@avian\&.org>\&. While Ncat isn\*(Aqt built on any code from the
+\(lqtraditional\(rq
+Netcat (or any other implementation), Ncat is most definitely based on Netcat in spirit and functionality\&.
+.SH "LEGAL NOTICES"
+.SS "Ncat Copyright and Licensing"
+.PP
+Ncat is (C) 2005\(en2022 Nmap Software LLC\&. It is distributed as free and open source software under the same license terms as our Nmap software\&. Precise terms and further details are available
+from \m[blue]\fB\%https://nmap.org/man/man-legal.html\fR\m[]\&.
+.SS "Creative Commons License for this Ncat Guide"
+.PP
+This
+Ncat Reference Guide
+is (C) 2005\(en2022 Nmap Software LLC\&. It is hereby placed under version 3\&.0 of the
+\m[blue]\fBCreative Commons Attribution License\fR\m[]\&\s-2\u[1]\d\s+2\&. This allows you redistribute and modify the work as you desire, as long as you credit the original source\&. Alternatively, you may choose to treat this document as falling under the same license as Ncat itself (discussed previously)\&.
+.SS "Source Code Availability and Community Contributions"
+.PP
+Source is provided to this software because we believe users have a right to know exactly what a program is going to do before they run it\&. This also allows you to audit the software for security holes (none have been found so far)\&.
+.PP
+Source code also allows you to port Nmap (which includes Ncat) to new platforms, fix bugs, and add new features\&. You are highly encouraged to send your changes to
+<dev@nmap\&.org>
+for possible incorporation into the main distribution\&. By sending these changes to Fyodor or one of the Insecure\&.Org development mailing lists, it is assumed that you are offering the Nmap Project (Nmap Software LLC) the unlimited, non\-exclusive right to reuse, modify, and relicense the code\&. Nmap will always be available open source,
+but this is important because the inability to relicense code has caused devastating problems for other Free Software projects (such as KDE and NASM)\&. We also occasionally relicense the code to third parties as discussed in the Nmap man page\&. If you wish to specify special license conditions of your contributions, just say so when you send them\&.
+.SS "No Warranty"
+.PP
+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 Nmap Public Source License for more details at
+\m[blue]\fB\%https://nmap.org/npsl/\fR\m[], or in the
+LICENSE
+file included with Nmap\&.
+.SS "Inappropriate Usage"
+.PP
+Ncat should never be installed with special privileges (e\&.g\&. suid root)\&.
+That would open up a major security vulnerability as other users on the system (or attackers) could use it for privilege escalation\&.
+.SS "Third\-Party Software"
+.PP
+This product includes software developed by the
+\m[blue]\fBApache Software Foundation\fR\m[]\&\s-2\u[2]\d\s+2\&. A modified version of the
+\m[blue]\fBLibpcap portable packet capture library\fR\m[]\&\s-2\u[3]\d\s+2
+is distributed along with Ncat\&. The Windows version of Ncat utilized the Libpcap\-derived
+\m[blue]\fBNpcap library\fR\m[]\&\s-2\u[4]\d\s+2
+instead\&. Certain raw networking functions use the
+\m[blue]\fBLibdnet\fR\m[]\&\s-2\u[5]\d\s+2
+networking library, which was written by Dug Song\&.
+A modified version is distributed with Ncat\&. Ncat can optionally link with the
+\m[blue]\fBOpenSSL cryptography toolkit\fR\m[]\&\s-2\u[6]\d\s+2
+for SSL version detection support\&. All of the third\-party software described in this paragraph is freely redistributable under BSD\-style software licenses\&.
+.SH "NOTES"
+.IP " 1." 4
+Creative Commons Attribution License
+.RS 4
+\%http://creativecommons.org/licenses/by/3.0/
+.RE
+.IP " 2." 4
+Apache Software Foundation
+.RS 4
+\%http://www.apache.org
+.RE
+.IP " 3." 4
+Libpcap portable packet capture library
+.RS 4
+\%http://www.tcpdump.org
+.RE
+.IP " 4." 4
+Npcap library
+.RS 4
+\%https://npcap.com
+.RE
+.IP " 5." 4
+Libdnet
+.RS 4
+\%http://libdnet.sourceforge.net
+.RE
+.IP " 6." 4
+OpenSSL cryptography toolkit
+.RS 4
+\%http://www.openssl.org
+.RE
diff --git a/ncat/docs/ncat.usage.txt b/ncat/docs/ncat.usage.txt
new file mode 100644
index 0000000..d965963
--- /dev/null
+++ b/ncat/docs/ncat.usage.txt
@@ -0,0 +1,57 @@
+Ncat 7.94SVN ( https://nmap.org/ncat )
+Usage: ncat [options] [hostname] [port]
+
+Options taking a time assume seconds. Append 'ms' for milliseconds,
+'s' for seconds, 'm' for minutes, or 'h' for hours (e.g. 500ms).
+ -4 Use IPv4 only
+ -6 Use IPv6 only
+ -U, --unixsock Use Unix domain sockets only
+ --vsock Use vsock sockets only
+ -C, --crlf Use CRLF for EOL sequence
+ -c, --sh-exec <command> Executes the given command via /bin/sh
+ -e, --exec <command> Executes the given command
+ --lua-exec <filename> Executes the given Lua script
+ -g hop1[,hop2,...] Loose source routing hop points (8 max)
+ -G <n> Loose source routing hop pointer (4, 8, 12, ...)
+ -m, --max-conns <n> Maximum <n> simultaneous connections
+ -h, --help Display this help screen
+ -d, --delay <time> Wait between read/writes
+ -o, --output <filename> Dump session data to a file
+ -x, --hex-dump <filename> Dump session data as hex to a file
+ -i, --idle-timeout <time> Idle read/write timeout
+ -p, --source-port port Specify source port to use
+ -s, --source addr Specify source address to use (doesn't affect -l)
+ -l, --listen Bind and listen for incoming connections
+ -k, --keep-open Accept multiple connections in listen mode
+ -n, --nodns Do not resolve hostnames via DNS
+ -t, --telnet Answer Telnet negotiations
+ -u, --udp Use UDP instead of default TCP
+ --sctp Use SCTP instead of default TCP
+ -v, --verbose Set verbosity level (can be used several times)
+ -w, --wait <time> Connect timeout
+ -z Zero-I/O mode, report connection status only
+ --append-output Append rather than clobber specified output files
+ --send-only Only send data, ignoring received; quit on EOF
+ --recv-only Only receive data, never send anything
+ --no-shutdown Continue half-duplex when receiving EOF on stdin
+ --allow Allow only given hosts to connect to Ncat
+ --allowfile A file of hosts allowed to connect to Ncat
+ --deny Deny given hosts from connecting to Ncat
+ --denyfile A file of hosts denied from connecting to Ncat
+ --broker Enable Ncat's connection brokering mode
+ --chat Start a simple Ncat chat server
+ --proxy <addr[:port]> Specify address of host to proxy through
+ --proxy-type <type> Specify proxy type ("http", "socks4", "socks5")
+ --proxy-auth <auth> Authenticate with HTTP or SOCKS proxy server
+ --proxy-dns <type> Specify where to resolve proxy destination
+ --ssl Connect or listen with SSL
+ --ssl-cert Specify SSL certificate file (PEM) for listening
+ --ssl-key Specify SSL private key (PEM) for listening
+ --ssl-verify Verify trust and domain name of certificates
+ --ssl-trustfile PEM file containing trusted SSL certificates
+ --ssl-ciphers Cipherlist containing SSL ciphers to use
+ --ssl-servername Request distinct server name (SNI)
+ --ssl-alpn ALPN protocol list to use
+ --version Display Ncat's version information and exit
+
+See the ncat(1) manpage for full options, descriptions and usage examples
diff --git a/ncat/docs/ncat.xml b/ncat/docs/ncat.xml
new file mode 100644
index 0000000..d202843
--- /dev/null
+++ b/ncat/docs/ncat.xml
@@ -0,0 +1,1225 @@
+<refentry id="ncatman">
+ <refmeta>
+ <refentrytitle>Ncat</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo class="source">Ncat</refmiscinfo>
+ <refmiscinfo class="manual">Ncat Reference Guide</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id="ncat-man-name">
+ <refname>ncat</refname>
+ <refpurpose>Concatenate and redirect sockets</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv id="ncat-man-synopsis">
+ <cmdsynopsis>
+ <command>ncat</command>
+ <arg choice="opt" rep="repeat">
+ <replaceable>OPTIONS</replaceable>
+ </arg>
+ <arg choice="opt">
+ <replaceable>hostname</replaceable>
+ </arg>
+ <arg choice="opt">
+ <replaceable>port</replaceable>
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="ncat-man-description">
+ <title>Description</title>
+
+ <para>Ncat is a feature-packed networking utility which reads and writes
+ data across networks from the command line. Ncat was written for the Nmap
+ Project and is the culmination of the currently splintered family of Netcat
+ incarnations. It is designed to
+ be a reliable back-end tool to instantly provide network connectivity to other
+ applications and users. Ncat will not only work with IPv4 and IPv6 but provides
+ the user with a virtually limitless number of potential uses.</para>
+
+ <para>Among Ncat's vast number of features there is the ability to chain Ncats
+ together; redirection of TCP, UDP, and SCTP ports to other sites; SSL support; and proxy
+ connections via SOCKS4, SOCKS5 or HTTP proxies (with optional proxy
+ authentication as well). Some general principles apply to most applications
+ and thus give you the capability of instantly adding networking support to
+ software that would normally never support it.</para>
+ </refsect1>
+
+ <refsect1 id="ncat-man-options-summary">
+ <title>Options Summary</title>
+
+ <para>
+<screen><xi:include href="ncat.usage.txt" parse="text" xmlns:xi="http://www.w3.org/2001/XInclude" /></screen>
+ </para>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-modes">
+ <indexterm><primary>connect mode (Ncat)</primary></indexterm>
+ <indexterm><primary>client mode (Ncat)</primary><see>connect mode</see></indexterm>
+ <indexterm><primary>listen mode (Ncat)</primary></indexterm>
+ <indexterm><primary>server mode (Ncat)</primary><see>listen mode</see></indexterm>
+ <title>Connect Mode and Listen Mode</title>
+
+ <para>
+ Ncat operates in one of two primary modes: connect mode and listen
+ mode. Other modes, such as the HTTP proxy server, act as special
+ cases of these two. In connect mode, Ncat works as a client. In
+ listen mode it is a server.
+ </para>
+
+ <para>
+ In connect mode, the <option><replaceable>hostname</replaceable></option>
+ and <option><replaceable>port</replaceable></option> arguments tell
+ what to connect to.
+ <option><replaceable>hostname</replaceable></option> is required,
+ and may be a hostname or IP address. If
+ <option><replaceable>port</replaceable></option> is supplied, it
+ must be a decimal port number. If omitted, it defaults to
+ 31337.<indexterm><primary>default port of Ncat</primary></indexterm><indexterm><primary>31337</primary><see>default port of Ncat</see></indexterm>
+ </para>
+
+ <para>
+ In listen mode, <option><replaceable>hostname</replaceable></option>
+ and <option><replaceable>port</replaceable></option> control the
+ address the server will bind to. Both arguments are optional in
+ listen mode. If <option><replaceable>hostname</replaceable></option>
+ is omitted, it defaults to listening on all available addresses over
+ IPv4 and IPv6. If <option><replaceable>port</replaceable></option> is
+ omitted, it defaults to 31337.
+ </para>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-proto-options">
+ <title>Protocol Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>-4</option> (IPv4 only)
+ <indexterm><primary><option>-4</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Force the use of IPv4 only.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-6</option> (IPv6 only)
+ <indexterm><primary><option>-6</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Force the use of IPv6 only.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-U</option>,
+ <option>--unixsock</option> (Use Unix domain sockets)
+ <indexterm><primary><option>--unixsock</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-U</option> (Ncat option)</primary><see><option>--unixsock</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Use Unix domain sockets rather than network sockets.
+ This option may be used on its own for stream sockets, or
+ combined with <option>--udp</option> for datagram sockets.
+ A description of <option>-U</option> mode is in
+ <xref linkend="ncat-man-unixsock"/>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-u</option>,
+ <option>--udp</option> (Use UDP)
+ <indexterm><primary><option>--udp</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-u</option> (Ncat option)</primary><see><option>--udp</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Use UDP for the connection (the default is TCP).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--sctp</option> (Use SCTP)
+ <indexterm><primary><option>--sctp</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Use SCTP for the connection (the default is TCP).
+ SCTP support is implemented in TCP-compatible mode.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--vsock</option> (Use AF_VSOCK sockets)
+ <indexterm><primary><option>--vsock</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Use AF_VSOCK sockets rather than the default TCP sockets (Linux only).
+ This option may be used on its own for stream sockets or combined with <option>--udp</option> for datagram sockets.
+ A description of <option>--vsock</option> mode is in
+ <xref linkend="ncat-man-vsock"/>.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-connect-options">
+ <title>Connect Mode Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>-g <replaceable>hop1</replaceable><optional>,<replaceable>hop2</replaceable>,...</optional></option> (Loose source routing)
+ <indexterm><primary><option>-g</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Sets hops for IPv4 loose source routing. You can use <option>-g</option>
+ once with a comma-separated list of hops, use <option>-g</option> multiple
+ times with single hops to build the list, or combine the two. Hops can be
+ given as IP addresses or hostnames.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-G <replaceable>ptr</replaceable></option> (Set source routing pointer)
+ <indexterm><primary><option>-G</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Sets the IPv4 source route <quote>pointer</quote> for use with <option>-g</option>.
+ The argument must be a multiple of 4 and no more than 28. Not all operating
+ systems support setting this pointer to anything other than four.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-p <replaceable>port</replaceable></option>,
+ <option>--source-port <replaceable>port</replaceable></option> (Specify source port)
+ <indexterm><primary><option>--source-port</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-p</option> (Ncat option)</primary><see><option>--source-port</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Set the port number for Ncat to bind to.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-s <replaceable>host</replaceable></option>,
+ <option>--source <replaceable>host</replaceable></option> (Specify source address)
+ <indexterm><primary><option>--source</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-s</option> (Ncat option)</primary><see><option>--source</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Set the address for Ncat to bind to.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-listen-options">
+ <title>Listen Mode Options</title>
+
+ <para>See <xref linkend="ncat-man-access-options"/> for information on limiting the
+ hosts that may connect to the listening Ncat process.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>-l</option>,
+ <option>--listen</option> (Listen for connections)
+ <indexterm><primary><option>--listen</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-l</option> (Ncat option)</primary><see><option>--listen</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Listen for connections rather than connecting to a remote
+ machine</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-m <replaceable>numconns</replaceable></option>,
+ <option>--max-conns <replaceable>numconns</replaceable></option> (Specify maximum number of connections)
+ <indexterm><primary><option>--max-conns</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-m</option> (Ncat option)</primary><see><option>--max-conns</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>The maximum number of simultaneous connections accepted by an Ncat
+ instance. 100 is the default (60 on Windows).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-k</option>,
+ <option>--keep-open</option> (Accept multiple connections)
+ <indexterm><primary><option>--keep-open</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-k</option> (Ncat option)</primary><see><option>--keep-open</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Normally a listening server accepts only one connection and
+ then quits when the connection is closed. This option makes it accept
+ multiple simultaneous connections and wait for more connections after
+ they have all been closed. It must be combined with
+ <option>--listen</option>. In this mode there is no way for Ncat to
+ know when its network input is finished, so it will keep running
+ until interrupted. This also means that it will never close its
+ output stream, so any program reading from Ncat and looking for
+ end-of-file will also hang.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--broker</option> (Connection brokering)
+ <indexterm><primary><option>--broker</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Allow multiple parties to connect to a centralised Ncat server
+ and communicate with each other. Ncat can broker communication between
+ systems that are behind a NAT or otherwise unable to directly connect.
+ This option is used in conjunction with <option>--listen</option>, which
+ causes the <option>--listen</option> port to have broker mode enabled.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--chat</option> (Ad-hoc <quote>chat server</quote>)
+ <indexterm><primary><option>--chat</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>The <option>--chat</option> option enables chat mode, intended
+ for the exchange of text between several users. In chat mode,
+ connection brokering is turned on. Ncat prefixes each message received
+ with an ID before relaying it to the other connections. The ID is
+ unique for each connected client. This helps distinguish who sent
+ what. Additionally, non-printing characters such as control characters
+ are escaped to keep them from doing damage to a terminal.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-ssl-options">
+ <title>SSL Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>--ssl</option> (Use SSL)
+ <indexterm><primary><option>--ssl</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>In connect mode, this option transparently negotiates an SSL
+ session with an SSL server to securely encrypt the connection. This is
+ particularly handy for talking to SSL enabled HTTP servers, etc.</para>
+ <para>In server mode, this option listens for incoming SSL connections,
+ rather than plain untunneled traffic.</para>
+ <para>In UDP mode, this option enables Datagram TLS (DTLS).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ssl-verify</option> (Verify server certificates)
+ <indexterm><primary><option>--ssl-verify</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>In client mode, <option>--ssl-verify</option> is like
+ <option>--ssl</option> except that it also requires verification of
+ the server certificate. Ncat comes with a default set of trusted
+ certificates in the file
+ <filename>ca-bundle.crt</filename>.<indexterm><primary><filename>ca-bundle.crt</filename></primary></indexterm>
+ Some operating systems provide a default list of
+ trusted certificates; these will also be used if available. Use
+ <option>--ssl-trustfile</option> to give a custom list. Use
+ <option>-v</option> one or more times to get details about
+ verification failures.</para>
+ <indexterm><primary>revoked certificates</primary><see>certificate revocation</see></indexterm>
+ <para>Ncat does not check for revoked
+ certificates.<indexterm><primary>certification revocation</primary></indexterm></para>
+ <para>This option has no effect in server mode.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ssl-cert <replaceable>certfile.pem</replaceable></option> (Specify SSL certificate)
+ <indexterm><primary><option>--ssl-cert</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>This option gives the location of a PEM-encoded
+ certificate files used to authenticate the server (in listen
+ mode) or the client (in connect mode). Use it in combination
+ with <option>--ssl-key</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ssl-key <replaceable>keyfile.pem</replaceable></option> (Specify SSL private key)
+ <indexterm><primary><option>--ssl-key</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>This option gives the location of the PEM-encoded
+ private key file that goes with the certificate named with
+ <option>--ssl-cert</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ssl-trustfile <replaceable>cert.pem</replaceable></option> (List trusted certificates)
+ <indexterm><primary><option>--ssl-trustfile</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>This option sets a list of certificates that are trusted for
+ purposes of certificate verification. It has no effect unless combined
+ with <option>--ssl-verify</option>. The argument to this option is the
+ name of a PEM<indexterm><primary>PEM (Privacy Enhanced Mail)</primary></indexterm>
+ file containing trusted certificates. Typically, the file will contain
+ certificates of certification authorities, though it may also contain
+ server certificates directly. When this option is used, Ncat does not
+ use its default certificates.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ssl-ciphers <replaceable>cipherlist</replaceable></option> (Specify SSL ciphersuites)
+ <indexterm><primary><option>--ssl-ciphers</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>This option sets the list of ciphersuites that Ncat will use
+ when connecting to servers or when accepting SSL connections from
+ clients. The syntax is described in the OpenSSL ciphers(1) man
+ page, and defaults to
+ <literal>ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!MD5:@STRENGTH</literal></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ssl-servername <replaceable>name</replaceable></option> (Request distinct server name)
+ <indexterm><primary><option>--ssl-servername</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>In client mode, this option sets the TLS SNI (Server Name
+ Indication) extension, which tells the server the name of the
+ logical server Ncat is contacting. This is important when the
+ target server hosts multiple virtual servers at a single underlying
+ network address. If the option is not provided, the TLS SNI
+ extension will be populated with the target server hostname.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ssl-alpn <replaceable>ALPN list</replaceable></option> (Specify ALPN protocol list)
+ <indexterm><primary><option>--ssl-alpn</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>This option allows you to specify a comma-separated list of
+ protocols to send via the Application-Layer Protocol Negotiation
+ (ALPN) TLS extension. Not supported by all versions of OpenSSL.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-proxy-options">
+ <title>Proxy Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>--proxy <replaceable>host</replaceable><optional>:<replaceable>port</replaceable></optional></option> (Specify proxy address)
+ <indexterm><primary><option>--proxy</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Requests proxying through <replaceable>host</replaceable>:<replaceable>port</replaceable>,
+ using the protocol specified by <option>--proxy-type</option>.</para>
+
+ <para>If no port is specified, the proxy protocol's well-known port is used (1080 for
+ SOCKS and 3128 for HTTP). When specifying an IPv6 HTTP proxy server
+ using the IP address rather than the hostname, the square-bracket
+ notation (for example [2001:db8::1]:8080) MUST be used to separate
+ the port from the IPv6 address.
+ If the proxy requires authentication, use <option>--proxy-auth</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--proxy-type <replaceable>proto</replaceable></option> (Specify proxy protocol)
+ <indexterm><primary><option>--proxy-type</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>In connect mode, this option requests the protocol <replaceable>proto</replaceable>
+ to connect through the proxy host specified by <option>--proxy</option>. In listen mode,
+ this option has Ncat act as a proxy server using the specified protocol.</para>
+
+ <para>The currently available protocols in connect mode are <literal>http</literal>
+ (CONNECT), <literal>socks4</literal> (SOCKSv4), and
+ <literal>socks5</literal> (SOCKSv5).
+ The only server currently supported is <literal>http</literal>.
+ If this option is not used, the default protocol is <literal>http</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--proxy-auth <replaceable>user</replaceable><optional>:<replaceable>pass</replaceable></optional></option> (Specify proxy credentials)
+ <indexterm><primary><option>--proxy-auth</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>In connect mode, gives the credentials that will be used to
+ connect to the proxy server. In listen mode, gives the credentials
+ that will be required of connecting clients. For use with
+ <option>--proxy-type http</option> or
+ <option>--proxy-type socks5</option>, the form should be
+ username:password. For
+ <option>--proxy-type socks4</option>, it should be a username only.</para>
+ <para>These credentials can be alternatively passed onto Ncat by
+ setting environment variable
+ <envar>NCAT_PROXY_AUTH</envar><indexterm><primary><envar>NCAT_PROXY_AUTH</envar> environment variable</primary></indexterm>,
+ which reduces the risk of the credentials being captured in process
+ logs. (Option <option>--proxy-auth</option> takes precedence.)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--proxy-dns <replaceable>type</replaceable></option> (Specify where to resolve proxy destination)
+ <indexterm><primary><option>--proxy-dns</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>In connect mode, it provides control over whether proxy
+ destination hostnames are resolved by the remote proxy server or
+ locally, by Ncat itself.
+ Possible values for <replaceable>type</replaceable> are:</para>
+
+ <para><literal>local</literal> - Hostnames are resolved locally on
+ the Ncat host. Ncat exits with error if the hostname cannot be
+ resolved.</para>
+
+ <para><literal>remote</literal> - Hostnames are passed directly onto
+ the remote proxy server. This is the default behavior.</para>
+
+ <para><literal>both</literal> - Hostname resolution is first
+ attempted on the Ncat host. Unresolvable hostnames are passed onto
+ the remote proxy server.</para>
+
+ <para><literal>none</literal> - Hostname resolution is completely
+ disabled. Only a literal IPv4 or IPv6 address can be used as
+ the proxy destination.</para>
+
+ <para>Local hostname resolution generally respects IP version
+ specified with options <option>-4</option> or <option>-6</option>,
+ except for SOCKS4, which is incompatible with IPv6.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-command-options">
+ <title>Command Execution Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>-e <replaceable>command</replaceable></option>,
+ <option>--exec <replaceable>command</replaceable></option> (Execute command)
+ <indexterm><primary><option>--exec</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-e</option> (Ncat option)</primary><see><option>--exec</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Execute the specified command after a connection has been
+ established. The command must be specified as a full pathname. All
+ input from the remote client will be sent to the application and
+ responses sent back to the remote client over the socket, thus
+ making your command-line application interactive over a
+ socket. Combined with <option>--keep-open</option>,
+ Ncat will handle multiple simultaneous connections to your
+ specified port/application like inetd. Ncat will only
+ accept a maximum, definable, number of simultaneous connections
+ controlled by the <option>-m</option> option. By default this is set
+ to 100 (60 on Windows).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-c <replaceable>command</replaceable></option>,
+ <option>--sh-exec <replaceable>command</replaceable></option> (Execute command via sh)
+ <indexterm><primary><option>--sh-exec</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-c</option> (Ncat option)</primary><see><option>--sh-exec</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Same as <option>-e</option>, except it tries to execute
+ the command via <filename>/bin/sh</filename>. This means you don't
+ have to specify the full path for the command, and shell facilities
+ like environment variables are available.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--lua-exec <replaceable>file</replaceable></option> (Execute a .lua script)
+ <indexterm><primary><option>--lua-exec</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Runs the specified file as a Lua script after a connection has been
+ established, using a built-in interpreter. Both the script's standard input and
+ the standard output are redirected to the connection data streams.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>All exec options add the following variables to the child's environment:</para>
+ <variablelist>
+ <varlistentry>
+ <term><envar>NCAT_REMOTE_ADDR</envar></term><indexterm><primary><envar>NCAT_REMOTE_ADDR></envar> environment variable</primary></indexterm>
+ <term><envar>NCAT_REMOTE_PORT</envar></term><indexterm><primary><envar>NCAT_REMOTE_PORT></envar> environment variable</primary></indexterm>
+ <listitem>
+ <para>
+ The IP address and port number of the remote host. In connect mode, it's
+ the target's address; in listen mode, it's the client's address.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><envar>NCAT_LOCAL_ADDR</envar></term><indexterm><primary><envar>NCAT_LOCAL_ADDR></envar> environment variable</primary></indexterm>
+ <term><envar>NCAT_LOCAL_PORT</envar></term><indexterm><primary><envar>NCAT_LOCAL_PORT></envar> environment variable</primary></indexterm>
+ <listitem>
+ <para>
+ The IP address and port number of the local end of the connection.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><envar>NCAT_PROTO</envar></term><indexterm><primary><envar>NCAT_PROTO></envar> environment variable</primary></indexterm>
+ <listitem>
+ <para>
+ The protocol in use: one of <code>TCP</code>, <code>UDP</code>, and <code>SCTP</code>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="ncat-man-access-options">
+ <title>Access Control Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>--allow <replaceable>host</replaceable><optional>,<replaceable>host</replaceable>,...</optional></option> (Allow connections)
+ <indexterm><primary><option>--allow</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>The list of hosts specified will be the only hosts allowed
+ to connect to the Ncat process. All other connection attempts will
+ be disconnected. In case of a conflict between
+ <option>--allow</option> and <option>--deny</option>,
+ <option>--allow</option> takes precedence. Host
+ specifications follow the same syntax used
+ by Nmap.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--allowfile <replaceable>file</replaceable></option> (Allow connections from file)
+ <indexterm><primary><option>--allowfile</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>This has the same functionality as <option>--allow</option>,
+ except that the allowed hosts are provided in a new-line delimited allow
+ file, rather than directly on the command line.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--deny <replaceable>host</replaceable><optional>,<replaceable>host</replaceable>,...</optional></option> (Deny connections)
+ <indexterm><primary><option>--deny</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Issue Ncat with a list of hosts that will not be allowed to connect
+ to the listening Ncat process. Specified hosts will have their session
+ silently terminated if they try to connect.
+ In case of a conflict between
+ <option>--allow</option> and <option>--deny</option>,
+ <option>--allow</option> takes precedence. Host
+ specifications follow the same syntax used by Nmap.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--denyfile <replaceable>file</replaceable></option> (Deny connections from file)
+ <indexterm><primary><option>--denyfile</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>This is the same functionality as <option>--deny</option>,
+ except that excluded hosts are provided in a new-line delimited deny
+ file, rather than directly on the command line.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-timing-options">
+ <title>Timing Options</title>
+
+ <para>These options accept a <literal>time</literal> parameter. This is specified
+ in seconds by default, though you can append <literal>ms</literal>, <literal>s</literal>, <literal>m</literal>,
+ or <literal>h</literal> to the value to specify milliseconds, seconds, minutes, or hours.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>-d <replaceable>time</replaceable></option>,
+ <option>--delay <replaceable>time</replaceable></option> (Specify line delay)
+ <indexterm><primary><option>--delay</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-d</option> (Ncat option)</primary><see><option>--delay</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Set the delay interval for lines sent. This effectively limits
+ the number of lines that Ncat will send in the specified period. This
+ may be useful for low-bandwidth sites, or have other uses such as
+ coping with
+ annoying <command>iptables --limit</command> options.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-i <replaceable>time</replaceable></option>,
+ <option>--idle-timeout <replaceable>time</replaceable></option> (Specify idle timeout)
+ <indexterm><primary><option>--idle-timeout</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-i</option> (Ncat option)</primary><see><option>--idle-timeout</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Set a fixed timeout for idle connections. If the idle timeout
+ is reached, the connection is terminated.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-w <replaceable>time</replaceable></option>,
+ <option>--wait <replaceable>time</replaceable></option> (Specify connect timeout)
+ <indexterm><primary><option>--wait</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-w</option> (Ncat option)</primary><see><option>--wait</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Set a fixed timeout for connection attempts.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-output-options">
+ <title>Output Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>-o <replaceable>file</replaceable></option>,
+ <option>--output <replaceable>file</replaceable></option> (Save session data)
+ <indexterm><primary><option>--output</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-o</option> (Ncat option)</primary><see><option>--output</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Dump session data to a file</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-x <replaceable>file</replaceable></option>,
+ <option>--hex-dump <replaceable>file</replaceable></option> (Save session data in hex)
+ <indexterm><primary><option>--hex-dump</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-x</option> (Ncat option)</primary><see><option>--hex-dump</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Dump session data in hex to a file.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--append-output</option> (Append output)
+ <indexterm><primary><option>--append-output</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Issue Ncat with <option>--append-ouput</option> along with
+ <option>-o</option> and/or <option>-x</option> and it will append
+ the resulted output rather than truncating the specified output files.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-v</option>,
+ <option>--verbose</option> (Be verbose)
+ <indexterm><primary><option>--verbose</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-v</option> (Ncat option)</primary><see><option>--verbose</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Issue Ncat with <option>-v</option> and it will be verbose and
+ display all kinds of useful connection based information. Use more
+ than once (<option>-vv</option>, <option>-vvv</option>...) for greater
+ verbosity.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-misc-options">
+ <title>Misc Options</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>-C</option>,
+ <option>--crlf</option> (Use CRLF as EOL)
+ <indexterm><primary><option>--crlf</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-C</option> (Ncat option)</primary><see><option>--crlf</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>This option tells Ncat to convert
+ LF<indexterm><primary>LF line ending</primary></indexterm>
+ line endings to
+ CRLF<indexterm><primary>CRLF line ending</primary></indexterm>
+ when taking input from
+ standard input.<indexterm><primary>standard input</primary></indexterm>
+ This is useful for talking to some stringent
+ servers directly from a terminal in one of the many common plain-text
+ protocols that use CRLF for end-of-line.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-h</option>,
+ <option>--help</option> (Help screen)
+ <indexterm><primary><option>--help</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-h</option> (Ncat option)</primary><see><option>--help</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Displays a short help screen with common options and parameters,
+ and then exits.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--recv-only</option> (Only receive data)
+ <indexterm><primary><option>--recv-only</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>If this option is passed, Ncat will only receive data and will
+ not try to send anything.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--send-only</option> (Only send data)
+ <indexterm><primary><option>--send-only</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>If this option is passed, then Ncat will only send data and will
+ ignore anything received. This option also causes Ncat to close the
+ network connection and terminate after EOF is received on standard
+ input.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--no-shutdown</option> (Do not shutdown into half-duplex mode)
+ <indexterm><primary><option>--no-shutdown</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>If this option is passed, Ncat will not invoke shutdown on a
+ socket after seeing EOF on stdin. This is provided for
+ backward-compatibility with OpenBSD netcat, which exhibits this
+ behavior when executed with its '-d' option.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-n</option>,
+ <option>--nodns</option> (Do not resolve hostnames)
+ <indexterm><primary><option>--nodns</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-n</option> (Ncat option)</primary><see><option>--nodns</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Completely disable hostname resolution across all Ncat options,
+ such as the destination, source address, source routing hops, and
+ the proxy. All addresses must be specified numerically.
+ (Note that resolution of proxy destinations is controlled separately
+ via option <option>--proxy-dns</option>.)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-t</option>,
+ <option>--telnet</option> (Answer Telnet negotiations)
+ <indexterm><primary><option>--telnet</option> (Ncat option)</primary></indexterm>
+ <indexterm><primary><option>-t</option> (Ncat option)</primary><see><option>--telnet</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>Handle DO/DONT WILL/WONT Telnet negotiations. This makes it
+ possible to script Telnet sessions with Ncat.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--version</option> (Display version)
+ <indexterm><primary><option>--version</option> (Ncat option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Displays the Ncat version number and exits.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="ncat-man-unixsock">
+ <title>Unix Domain Sockets</title>
+
+ <para>
+ The <option>-U</option> option (same as <option>--unixsock</option>)
+ causes Ncat to use Unix domain sockets rather than network sockets.
+ Unix domain sockets exist as an entry in the filesystem. You must
+ give the name of a socket to connect to or to listen on. For
+ example, to make a connection,
+ </para>
+ <para><command>ncat -U ~/unixsock</command></para>
+ <para>
+ To listen on a socket:
+ </para>
+ <para><command>ncat -l -U ~/unixsock</command></para>
+ <para>
+ Listen mode will create the socket if it doesn't exist. The socket
+ will continue to exist after the program ends.
+ </para>
+
+ <para>
+ Both stream and datagram domain sockets are supported. Use
+ <option>-U</option> on its own for stream sockets, or
+ combine it with <option>--udp</option> for datagram sockets.
+ Datagram sockets require a source socket to connect from. By
+ default, a source socket with a random filename will be created as
+ needed, and deleted when the program ends. Use the
+ <option>--source</option> with a path to use a source socket with a
+ specific name.
+ </para>
+
+ </refsect1>
+
+ <refsect1 id="ncat-man-vsock">
+ <title>AF_VSOCK Sockets</title>
+
+ <para>
+ The <option>--vsock</option> option causes Ncat to use AF_VSOCK
+ sockets rather than network sockets. A CID must be given instead of a
+ hostname or IP address. For example, to make a connection to the host,
+ </para>
+ <para><command>ncat --vsock 2 1234</command></para>
+ <para>
+ To listen on a socket:
+ </para>
+ <para><command>ncat -l --vsock 1234</command></para>
+ <para>
+ Both stream and datagram domain sockets are supported, but socket type
+ availability depends on the hypervisor. Use
+ <option>--vsock</option> on its own for stream sockets, or
+ combine it with <option>--udp</option> for datagram sockets.
+ </para>
+ </refsect1>
+ <refsect1 id="ncat-man-examples">
+ <title>Examples</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ Connect to example.org on TCP port 8080.
+ </term>
+ <listitem>
+ <para><command>ncat example.org 8080</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Listen for connections on TCP port 8080.
+ </term>
+ <listitem>
+ <para><command>ncat -l 8080</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Redirect TCP port 8080 on the local machine to host on port 80.
+ </term>
+ <listitem>
+ <para><command>ncat --sh-exec "ncat example.org 80" -l 8080 --keep-open</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Bind to TCP port 8081 and attach <filename>/bin/bash</filename>
+ for the world to access freely.
+ </term>
+ <listitem>
+ <para><command>ncat --exec "/bin/bash" -l 8081 --keep-open</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Bind a shell to TCP port 8081, limit access to hosts on a local
+ network, and limit the maximum number of simultaneous connections to 3.
+ </term>
+ <listitem>
+ <para><command>ncat --exec "/bin/bash" --max-conns 3 --allow 192.168.0.0/24 -l 8081 --keep-open</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Connect to smtphost:25 through a SOCKS4 server on port 1080.
+ </term>
+ <listitem>
+ <para><command>ncat --proxy socks4host --proxy-type socks4 --proxy-auth joe smtphost 25</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Connect to smtphost:25 through a SOCKS5 server on port 1080.
+ </term>
+ <listitem>
+ <para><command>ncat --proxy socks5host --proxy-type socks5 --proxy-auth joe:secret smtphost 25</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Create an HTTP proxy server on localhost port 8888.
+ </term>
+ <listitem>
+ <para><command>ncat -l --proxy-type http localhost 8888</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Send a file over TCP port 9899 from host2 (client) to host1
+ (server).
+ </term>
+ <listitem>
+<para>HOST1$ <command>ncat -l 9899 &gt; outputfile</command></para>
+<para>HOST2$ <command>ncat HOST1 9899 &lt; inputfile</command></para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Transfer in the other direction, turning Ncat into a <quote>one
+ file</quote> server.
+ </term>
+ <listitem>
+<para>HOST1$ <command>ncat -l 9899 &lt; inputfile</command></para>
+<para>HOST2$ <command>ncat HOST1 9899 &gt; outputfile</command></para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="ncat-man-exit-code">
+ <title>Exit Code</title>
+
+ <para>The exit code reflects whether a connection was made and
+ completed successfully. 0 means there was no error. 1 means there
+ was a network error of some kind, for example <quote>Connection
+ refused</quote> or <quote>Connection reset</quote>. 2 is reserved
+ for all other errors, like an invalid option or a nonexistent
+ file.</para>
+ </refsect1>
+
+ <refsect1 id="ncat-man-bugs">
+ <title>Bugs</title>
+
+ <para>Like its authors, Ncat isn't perfect. But you can help make
+ it better by sending bug reports or even writing patches. If Ncat
+ doesn't behave the way you expect, first upgrade to the latest
+ version available from <ulink
+ url="https://nmap.org"/>. If the problem persists,
+ do some research to determine whether it has already been
+ discovered and addressed. Try Googling the error message or
+ browsing the <citetitle>nmap-dev</citetitle> archives at <ulink
+ url="https://seclists.org/" />.
+ <indexterm><primary><citetitle>nmap-dev</citetitle> mailing list</primary></indexterm>
+ Read this full manual page as
+ well. If nothing comes of this, mail a bug report to
+ <email>dev@nmap.org</email>. Please include everything
+ you have learned about the problem, as well as what version of
+ Ncat you are running and what operating system version it is
+ running on. Problem reports and Ncat usage questions sent to
+ dev@nmap.org are far more likely to be answered than
+ those sent to Fyodor directly.</para>
+
+ <para>Code patches to fix bugs are even better than bug reports.
+ Basic instructions for creating patch files with your changes are
+ available at <ulink
+ url="https://svn.nmap.org/nmap/HACKING" />. Patches may
+ be sent to <citetitle>nmap-dev</citetitle> (recommended) or to Fyodor directly.</para>
+ </refsect1>
+
+ <refsect1 id="ncat-man-author">
+ <title>Authors</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>Chris Gibson <email>chris@linuxops.net</email></para>
+ </listitem>
+ <listitem>
+ <para>Gordon Lyon (Fyodor)<email>fyodor@nmap.org</email>
+ (<ulink url="http://insecure.org" />)</para>
+ </listitem>
+ <listitem>
+ <para>Kris Katterjohn <email>katterjohn@gmail.com</email></para>
+ </listitem>
+ <listitem>
+ <para>Mixter <email>mixter@gmail.com</email></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The original Netcat was written by *Hobbit* <email>hobbit@avian.org</email>.
+ While Ncat isn't built on any code from the <quote>traditional</quote> Netcat (or any
+ other implementation), Ncat is most definitely based on Netcat in spirit
+ and functionality.</para>
+ </refsect1>
+
+ <refsect1 id='ncat-man-legal'>
+ <title>Legal Notices</title>
+
+<refsect2 id="ncat-copyright">
+ <title>Ncat Copyright and Licensing</title>
+ <indexterm><primary>copyright</primary></indexterm>
+
+ <para>Ncat is (C) 2005&ndash;2022 Nmap Software LLC. It is distributed
+ as free and open source software under the same license terms as our
+ Nmap software. Precise terms and further details are available
+ <man>from <ulink url="https://nmap.org/man/man-legal.html"/>.</man>
+ <notman>in <xref linkend="nmap-copyright"/>.</notman></para>
+</refsect2>
+
+<refsect2 id="ncat-man-copyright">
+ <title>Creative Commons License for this Ncat Guide</title>
+ <para>This <citetitle>Ncat Reference Guide</citetitle> is (C)
+ 2005&ndash;2022 Nmap Software LLC. It is
+ hereby placed under version 3.0 of the <ulink
+ url="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+ Attribution License</ulink>. This allows you redistribute and modify
+ the work as you desire, as long as you credit the original source.
+ Alternatively, you may choose to treat this document as falling under
+ the same license as Ncat itself (discussed previously).</para>
+</refsect2>
+
+<refsect2 id="ncat-source-contrib">
+ <title>Source Code Availability and Community Contributions</title>
+
+<para>Source is provided to this software because we believe users
+have a right to know exactly what a program is going to do before they
+run it. This also allows you to audit the software for security holes
+(none have been found so far).</para>
+
+<para>Source code also allows you to port Nmap (which includes Ncat)
+to new platforms, fix bugs, and add new features. You are highly
+encouraged to send your changes to
+<email>dev@nmap.org</email> for possible incorporation into
+the main distribution. By sending these changes to Fyodor or one of
+the Insecure.Org development mailing lists, it is assumed that you are
+offering the Nmap Project (Nmap Software LLC) the unlimited,
+non-exclusive right to reuse, modify, and relicense the code. Nmap
+will always be available open source,<indexterm><primary>open
+source</primary></indexterm> but this is important because the
+inability to relicense code has caused devastating problems for other
+Free Software projects (such as KDE and NASM). We also occasionally
+relicense the code to third parties as discussed in the Nmap man page.
+If you wish to specify special license conditions of your
+contributions, just say so when you send them.</para>
+
+</refsect2>
+
+<refsect2 id="ncat-no-warranty"><title>No Warranty<indexterm><primary>warranty (lack of)</primary></indexterm></title>
+
+<para>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 Nmap Public Source
+License for more details at <ulink url="https://nmap.org/npsl/" />,
+or in the <filename>LICENSE</filename> file
+included with Nmap.</para>
+</refsect2>
+
+<refsect2 id="ncat-inappropriate-usage"><title>Inappropriate Usage</title>
+<para>Ncat should never be installed with special privileges
+(e.g. suid root).<indexterm><primary>suid</primary><see>setuid</see></indexterm>
+That would open up a major security vulnerability as other users on the
+system (or attackers) could use it for privilege escalation.
+</para>
+</refsect2>
+
+<refsect2 id="ncat-third-party-soft"><title>Third-Party Software</title>
+
+<para>This product includes software developed by
+the <ulink role="hidepdf" url="http://www.apache.org">Apache Software
+Foundation</ulink>. A modified version of the <ulink role="hidepdf"
+url="http://www.tcpdump.org">Libpcap portable packet capture
+library</ulink><indexterm><primary>libpcap</primary></indexterm>
+is distributed along with Ncat.
+The Windows version of Ncat utilized the Libpcap-derived
+<ulink role="hidepdf" url="https://npcap.com">Npcap library</ulink><indexterm><primary>Npcap</primary></indexterm>
+instead.
+Certain raw networking functions use the
+<ulink role="hidepdf" url="http://libdnet.sourceforge.net">Libdnet</ulink><indexterm><primary>libdnet</primary></indexterm>
+networking library, which was written by Dug Song.<indexterm><primary>Song, Dug</primary></indexterm>
+A modified version is distributed with Ncat.
+Ncat can optionally link with the
+<ulink role="hidepdf" url="http://www.openssl.org">OpenSSL
+cryptography toolkit</ulink><indexterm><primary>OpenSSL</primary></indexterm>
+for SSL version detection support.
+All of the third-party software described in this paragraph is freely
+redistributable under BSD-style software licenses.</para>
+</refsect2>
+</refsect1>
+
+</refentry>
+
diff --git a/ncat/docs/ncatguide.xml b/ncat/docs/ncatguide.xml
new file mode 100644
index 0000000..a1010d4
--- /dev/null
+++ b/ncat/docs/ncatguide.xml
@@ -0,0 +1,2008 @@
+<indexterm significance="preferred" class="startofrange" id="ncat-indexterm"><primary>Ncat</primary></indexterm>
+
+<sect1 id="ncat-overview">
+ <title>Ncat: Your General-Purpose Network Connector</title>
+
+ <para>
+ Ncat is a general-purpose command-line tool for reading, writing,
+ redirecting, and encrypting data across a network. It aims to be
+ your network <ulink role="hidepdf"
+ url="http://en.wikipedia.org/wiki/Swiss_Army_knife">Swiss Army
+ knife</ulink>, handling a wide variety of security testing and
+ administration tasks. Ncat is suitable for interactive use or as a
+ network-connected back end for other tools. Ncat can:
+ </para>
+
+ <itemizedlist>
+
+ <listitem><para>Act as a simple TCP/UDP/SCTP/SSL client for interacting
+ with web servers, telnet servers, mail servers, and other TCP/IP
+ network services. Often the best way to understand a service (for
+ fixing problems, finding security flaws, or testing custom commands)
+ is to interact with it using Ncat. This lets you you control every character
+ sent and view the raw, unfiltered responses.</para></listitem>
+
+ <listitem><para>Act as a simple TCP/UDP/SCTP/SSL server for offering
+ services to clients, or simply to understand what existing clients
+ are up to by capturing every byte they send.</para></listitem>
+
+ <listitem><para>Redirect or proxy TCP/UDP/SCTP traffic to other ports or
+ hosts. This can be done using simple redirection (everything sent
+ to a port is automatically relayed somewhere else you specify in
+ advance) or by acting as a SOCKS or HTTP proxy so clients
+ specify their own destinations. In client mode, Ncat can
+ connect to destinations through a chain of anonymous or
+ authenticated proxies.</para></listitem>
+
+ <listitem><para>Run on all major operating systems. We distribute
+ Linux, Windows, and Mac OS X binaries, and Ncat compiles on most
+ other systems. A trusted tool must be available
+ whenever you need it, no matter what computer you're
+ using.</para></listitem>
+
+ <listitem><para>Encrypt communication with SSL, and transport it over IPv4 or IPv6.</para></listitem>
+
+ <listitem><para>Act as a network gateway for execution of system
+ commands, with I/O redirected to the network. It was designed to work
+ like the Unix utility <command>cat</command>, but for the
+ network.</para></listitem>
+
+ <listitem><para>Act as a connection broker, allowing two (or far
+ more) clients to connect to each other through a third (brokering)
+ server. This enables multiple machines hidden behind NAT gateways
+ to communicate with each other, and also enables the simple Ncat
+ chat mode.</para></listitem>
+ </itemizedlist>
+
+ <para>These capabilities become even more powerful and versatile
+ when combined.</para>
+
+ <para>
+ Ncat is our modern reinvention of the venerable Netcat (nc) tool released by Hobbit in 1996. While Ncat is similar to Netcat in spirit, they don't share any source code. Instead, Ncat makes use of Nmap's well optimized and tested networking
+ libraries. Compatibility with the original Netcat and some well known variants is maintained
+ where it doesn't conflict with Ncat's enhancements or cause
+ usability problems. Ncat adds many capabilities not found in
+ Hobbit's original nc, including SSL support, proxy connections,
+ IPv6, and connection brokering.
+ The original nc contained a simple port
+ scanner, but we omitted that from Ncat because we have a preferred
+ tool for that function.
+ </para>
+
+ <para>
+ This guide starts with examples of basic Ncat usage, then moves on to more advanced features. Those are followed by practical sections which use examples to demonstrate how Ncat can solve common real-world problems. A few neat Ncat tricks are covered as well.
+ </para>
+</sect1>
+
+<!-- Need a discussion of shell syntax, as it's such a big part of using
+the tool? Many of these examples suppose a Unix environment. -->
+
+<sect1 id="ncat-usage">
+ <title>Basic usage</title>
+
+ <para>
+ Ncat always operates in one of two basic modes:
+ <firstterm>connect mode</firstterm><indexterm><primary>connect mode</primary></indexterm> and
+ <firstterm>listen mode</firstterm>.<indexterm><primary>listen mode</primary></indexterm>
+ In connect mode, Ncat initiates a connection (or sends UDP data) to a service that is
+ listening somewhere. For those familiar with socket programming,
+ connect mode is like using the <function>connect</function> function.
+ In listen mode, Ncat waits for an incoming connection (or data receipt), like using the
+ <function>bind</function> and <function>listen</function> functions.
+ You can think of connect mode as <quote>client</quote> mode and listen
+ mode as <quote>server</quote> mode.
+ </para>
+
+ <para>
+ To use Ncat in connect mode, run
+ <informalexample>
+<literallayout>
+<command>ncat <replaceable>host</replaceable> <optional><replaceable>port</replaceable></optional></command>
+</literallayout>
+ </informalexample>
+ <replaceable>host</replaceable> may be a hostname or IP
+ address, and
+ <replaceable>port</replaceable> is a port number. Listen mode is the
+ same, with the addition of the
+ <option>--listen</option><indexterm><primary><option>--listen</option>
+ (Ncat option></primary></indexterm> option (or
+ its <option>-l</option><indexterm><primary><option>-l</option> (Ncat
+ option)</primary><see><option>--listen</option></see></indexterm>
+ alias):
+ <informalexample>
+
+<literallayout>
+<command>ncat --listen <optional><replaceable>host</replaceable></optional> <optional><replaceable>port</replaceable></optional></command>
+<command>ncat -l <optional><replaceable>host</replaceable></optional> <optional><replaceable>port</replaceable></optional></command>
+</literallayout>
+ </informalexample>
+ In listen mode, <replaceable>host</replaceable> controls the address
+ on which Ncat listens; if you omit it, Ncat will bind to all local interfaces (INADDR_ANY). If the port number is omitted, Ncat uses its
+ default port
+ 31337.<indexterm><primary>default port of Ncat</primary></indexterm>
+ Typically only privileged
+ (root)<indexterm><primary>privileged users</primary></indexterm>
+ users may bind to a port number lower than
+ 1024.<indexterm><primary>ports</primary><secondary>reserved</secondary></indexterm><indexterm><primary>reserved ports</primary></indexterm>
+ A listening TCP server normally accepts only one connection and will
+ exit after the client disconnects. Combined with the
+ <option>--keep-open</option><indexterm><primary><option>--keep-open</option> (Ncat option)</primary></indexterm>
+ option, Ncat accepts multiple concurrent connections up
+ to the connection limit. With <option>--keep-open</option> (or
+ <option>-k</option> for short), the server receives everything sent by
+ any of its clients, and anything the server sends is sent to all of
+ them.
+ </para>
+
+ <para>
+ By default, Ncat uses TCP. The option
+ <option>--udp</option><indexterm><primary><option>--udp</option> (Ncat option)</primary></indexterm>
+ or
+ <option>-u</option><indexterm><primary><option>-u</option> (Ncat option)</primary><see><option>--udp</option></see></indexterm>
+ enables UDP instead,
+ and
+ <option>--sctp</option><indexterm><primary><option>--sctp</option> (Ncat option)</primary></indexterm>
+ enables SCTP.<indexterm><primary>SCTP</primary><secondary>in Ncat</secondary></indexterm>
+ Ncat listens on both IPv4 and IPv6, and connects to either address family as well. The
+ <option>-6</option><indexterm><primary><option>-6</option> (Ncat option)</primary></indexterm>
+ option forces IPv6-only, and
+ <option>-4</option><indexterm><primary><option>-4</option> (Ncat option)</primary></indexterm>
+ forces IPv4-only. See <xref linkend="ncat-protocols"/> for more details.
+ The rest of this guide documents all the Ncat options through
+ descriptions and examples. For a quick summary of options at any time,
+ run
+ <command>ncat --help</command><indexterm><primary><option>--help</option> (Ncat option)</primary></indexterm>
+ or <command>man ncat</command>.
+ </para>
+
+ <sect2 id="ncat-connect">
+ <title>A Connect Mode Example</title>
+
+ <para>
+
+ A good way to start learning about Ncat (and network protocols in
+ general) is to connect to a network service and talk with it. In
+ this case we use Ncat to manually retrieve a web page from an HTTP
+ server, just as web browsers do in the background when you visit a
+ web site.
+ <xref linkend="ncat-ex-http" xrefstyle="select: label nopage"/>
+ shows a (truncated) sample session. Try it yourself!
+ Text in bold is what you type; everything else is what comes
+ back. The blank line after the <userinput>GET</userinput> line is
+ required&mdash;just hit <keycap>enter</keycap> twice.
+ </para>
+
+ <example id="ncat-ex-http">
+ <title>Ncat as a web browser</title>
+ <indexterm><primary>GET HTTP method</primary></indexterm>
+ <indexterm><primary><option>-C</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<screen>
+$ <userinput>ncat -C scanme.nmap.org 80</userinput>
+<userinput>GET / HTTP/1.0
+
+</userinput>HTTP/1.1 200 OK
+Date: Thu, 05 Feb 2009 15:31:40 GMT
+Server: Apache/2.2.2 (Fedora)
+Last-Modified: Mon, 19 May 2008 04:49:49 GMT
+ETag: "fc8c91-2e3-44d8e17edd540"
+Accept-Ranges: bytes
+Content-Length: 739
+Connection: close
+Content-Type: text/html; charset=UTF-8
+
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Go ahead and ScanMe!&lt;/title&gt;
+&lt;/head&gt;
+</screen>
+ </example>
+
+ <para>
+ Here we have instructed Ncat to connect to the host
+ scanme.nmap.org<indexterm><primary>scanme.nmap.org</primary></indexterm>
+ on port 80, the port for HTTP. The <option>-C</option> option turns
+ on CRLF<indexterm><primary>CRLF</primary></indexterm> replacement,
+ which replaces any line endings you type with CRLF. CRLF line
+ endings are required by many protocols, including HTTP, though many servers will accept a plain newline (LF) character.
+ </para>
+
+ <para>
+ <userinput>GET / HTTP/1.0</userinput> requests the root document of
+ the server; we are retrieving the same document named by the URL
+ http://scanme.nmap.org:80/. The web server responds with a status code
+ (<computeroutput>HTTP/1.1 200 OK</computeroutput>), followed by the
+ HTTP header and the text of the web page. If you try this with other
+ web servers, note that many of them are actually virtual hosts and you
+ will need to send the <literal>Host</literal> header field. See
+ RFC&nbsp;2616<indexterm><primary>RFC 2616</primary></indexterm> for
+ more information about HTTP.
+ </para>
+ </sect2>
+
+ <sect2 id="ncat-listen">
+ <title>A Listen Mode Example</title>
+
+ <para>
+ So much for using Ncat as a web browser. What about a web server?
+ That's possible too; it just takes a bit of preparation. The first
+ step is to create the document to serve. Create a text file called
+ <filename>hello.http</filename> with these contents:
+<screen>
+<![CDATA[HTTP/1.0 200 OK
+
+<html>
+ <body>
+ <h1>Hello, world!</h1>
+ </body>
+</html>]]>
+</screen>
+ Now run the command
+ <command>ncat -l localhost 8080 &lt; hello.http</command>. This
+ instructs Ncat to listen on the local port 8080 and read
+ <filename>hello.http</filename> on its input. Ncat is now primed to
+ send the contents of the file as soon as it receives a connection.
+ Now open a web browser and type in the address
+ <userinput>http://localhost:8080/</userinput>.
+ <xref linkend="ncat-fig-hello" xrefstyle="select: label nopage"/>
+ shows a sample of what will appear.
+ </para>
+
+ <figure id="ncat-fig-hello">
+ <title>Web page served by Ncat</title>
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="../../book/images/ncat-fig-hello.png"/>
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+ </figure>
+
+ <para>
+ In the terminal where you ran Ncat, you will see everything the web
+ browser sent to request the page. You should see a
+ <computeroutput>GET</computeroutput><indexterm><primary>GET HTTP method</primary></indexterm>
+ line like the one you sent in
+ the connect mode example. This shows that Ncat by default both sends
+ and receives.
+ </para>
+
+ <para>
+ If you try to refresh the page, it won't work. That's because Ncat
+ ran out of input; it won't re-send what has already been sent. For
+ more information on making a server that continually responds to
+ requests, see the examples in
+ <xref linkend="ncat-simple-services"/>. More HTTP server tricks can
+ be found here in <xref linkend="ncat-httpserv"/>.
+ </para>
+
+ </sect2>
+</sect1>
+
+<sect1 id="ncat-protocols">
+ <title>Protocols</title>
+
+ <indexterm><primary>TLS</primary><see>SSL</see></indexterm>
+ <indexterm><primary>Transport Layer Security (TLS)</primary><see>SSL</see></indexterm>
+
+ <para>
+ Ncat can use TCP, UDP, SCTP, SSL, IPv4, IPv6, and various combinations
+ of these. TCP over IPv4 is the default.
+ </para>
+
+ <para>
+ TCP,<indexterm significance="preferred"><primary>TCP</primary><secondary>in Ncat</secondary></indexterm>
+ the Transmission Control Protocol, is the reliable protocol that
+ underlies a great deal of Internet traffic. Ncat makes TCP connections
+ by default. TCP may be combined with SSL.
+ </para>
+
+ <para>
+ UDP,<indexterm significance="preferred"><primary>UDP</primary><secondary>in Ncat</secondary></indexterm>
+ the User Datagram Protocol, is an unreliable protocol often used by
+ applications that can't afford the overhead of TCP. Use the
+ <option>--udp</option><indexterm><primary><option>--udp</option> (Ncat option)</primary></indexterm>
+ option to make Ncat use UDP.
+ UDP may be secured using the <option>--ssl</option> option, which enables
+ Datagram TLS (DTLS)<indexterm><primary>DTLS</primary><secondary>Datagram TLS</secondary></indexterm>.
+ </para>
+
+ <para>
+ SCTP,<indexterm significance="preferred"><primary>SCTP</primary><secondary>in Ncat</secondary></indexterm>
+ the Stream Control Transmission Protocol, is a newer reliable
+ protocol. It is selected with the
+ <option>--sctp</option><indexterm><primary><option>--sctp</option> (Ncat option)</primary></indexterm>
+ option. Ncat uses a TCP-compatible subset of SCTP features, not
+ including multiple streams per connection or message boundaries. SCTP
+ may be combined with SSL.
+ </para>
+
+ <para>
+ SSL<indexterm significance="preferred"><primary>SSL</primary><secondary>in Ncat</secondary></indexterm>
+ (Secure Sockets Layer) or
+ TLS (Transport Layer Security) provides security to network traffic
+ when used properly. Use the
+ <option>--ssl</option><indexterm><primary><option>--ssl</option> (Ncat option)</primary></indexterm>
+ to turn SSL on; it works with TCP or SCTP. See <xref
+ linkend="ncat-ssl"/> for instructions and caveats.
+ </para>
+
+ <para>
+ IPv4,<indexterm significance="preferred"><primary>IPv4</primary><secondary>in Ncat</secondary></indexterm>
+ the Internet Protocol version 4, is the most popular version of the
+ Internet Protocol in use. Using the
+ <option>-4</option><indexterm><primary><option>-4 (Ncat option)</option></primary></indexterm>
+ puts Ncat into IPv4-only mode; only IPv4 addresses will be used even
+ if, for example, as hostname resolves to IPv6 addresses as well.
+ </para>
+
+ <para>
+ IPv6<indexterm significance="preferred"><primary>IPv6</primary><secondary>in Ncat</secondary></indexterm>
+ is the lesser-used successor to IPv4. Use
+ <option>-6</option><indexterm><primary><option>-6</option> (Ncat option)</primary></indexterm>
+ to put Ncat into IPv6-only mode.
+ By default, Ncat will listen on both IPv4 and IPv6, and will connect to
+ resolved addresses in the order they are returned by the operating system.
+ </para>
+</sect1>
+
+<sect1 id="ncat-broker">
+ <title>Connection Brokering</title>
+
+ <para>
+ One of Ncat's most useful and unique abilities is called
+ connection brokering. A listening Ncat in broker mode accepts
+ connections from multiple clients. Anything received from one of
+ the clients is sent back out to all the others. In this way an
+ Ncat broker acts like a network hub, broadcasting all traffic to
+ everyone connected.
+ </para>
+
+ <para>
+ Activate broker mode with the <option>--broker</option> option, which
+ must be combined with
+ <option>--listen</option>. It wouldn't make sense for a client to be
+ a broker. See <xref linkend="ncat-file-transfer"/> for details on using brokering to transfer files through restrictive firewalls,
+ and <xref linkend="ncat-chat"/> for using brokering to set up multi-user chat rooms.
+ </para>
+</sect1>
+
+<sect1 id="ncat-ssl">
+ <title>SSL</title>
+
+ <para>
+ Ncat can encrypt its traffic using SSL. In connect mode, simply add the
+ <option>--ssl</option><indexterm><primary><option>--ssl</option> (Ncat option)</primary></indexterm>
+ option. <option>--ssl</option> works with TCP (the default) and
+ SCTP<indexterm><primary>SCTP</primary><secondary>in Ncat</secondary></indexterm>
+ (<option>--sctp</option><indexterm><primary><option>--sctp</option> (Ncat option)</primary></indexterm>
+ option). Here is the syntax for connecting to
+ an HTTPS server:
+ <informalexample>
+<literallayout>
+<command>ncat -C --ssl <replaceable>server</replaceable> 443</command>
+</literallayout>
+ </informalexample>
+ </para>
+
+ <para>
+ Sometimes an SSL server will require a client certificate for
+ authentication. When this is the case, use the
+ <option>--ssl-cert</option><indexterm><primary><option>--ssl-cert</option> (Ncat option)</primary></indexterm>
+ and
+ <option>--ssl-key</option><indexterm><primary><option>--ssl-key</option> (Ncat option)</primary></indexterm>
+ options to give the locations of PEM-encoded files containing the
+ certificate and private key, respectively. The certificate and key may
+ be in the same file.
+ </para>
+
+ <para>
+ <indexterm><primary>certificate verification</primary></indexterm>
+ <indexterm><primary>trust</primary><see>certificate verification</see></indexterm>
+ By default the client will not do any server certificate verification, so it
+ will not be detected if the server has the wrong certificate or no
+ certificate at all. Use the <option>--ssl-verify</option> option to
+ require verification of the certificate and matching of the domain
+ name.
+ <indexterm><primary><option>--ssl-verify</option> (Ncat option)</primary></indexterm>
+<literallayout>
+<command>ncat -C --ssl-verify <replaceable>server</replaceable> 443</command>
+</literallayout>
+ Verification is done using the
+ <filename>ca-bundle.crt</filename><indexterm><primary><filename>ca-bundle.crt</filename></primary></indexterm>
+ certificate bundle shipped with Ncat, plus whatever trusted
+ certificates the operating system may provide. If you want to verify a
+ connection to a server whose certificate isn't signed by one of the
+ default certification authorities, use the
+ <option>--ssl-trustfile</option> to name a file containing
+ certificates you trust. The file must be in PEM format.
+ <indexterm><primary><option>--ssl-trustfile</option> (Ncat option)</primary></indexterm>
+<literallayout>
+<command>ncat -C --ssl-verify --ssl-trustfile <replaceable><filename>custom-certs.pem</filename></replaceable> <replaceable>server</replaceable> 443</command>
+</literallayout>
+ Verification should be done whenever it is feasible. Even with
+ encryption, an unverified connection is vulnerable to a
+ man-in-the-middle attack. Ncat does not do certificate
+ revocation<indexterm><primary>certificate revocation</primary></indexterm><indexterm><primary>CRL</primary><see>certificate revocation</see></indexterm>
+ checking.
+ </para>
+
+ <para>
+ <indexterm><primary>SSL ciphers</primary><secondary>in Ncat</secondary></indexterm>
+ SSL connections depend on the client and server agreeing on a common
+ ciphersuite: a combination of key exchange, symmetric cipher, and message
+ integrity mechanism. The choice of which ciphersuites to offer (as a
+ client) or accept (as a server) is a matter of choice between the greatest
+ compatibility and the greatest security. The default set, expressed as an
+ OpenSSL cipherlist, is
+ <literal>ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!MD5:@STRENGTH</literal>, a reasonable balance
+ between the two ends of the spectrum. To set a different priority or
+ initial choice, use the <option>--ssl-ciphers</option> option.
+ <indexterm><primary><option>--ssl-ciphers</option> (Ncat option)</primary></indexterm>
+ <literallayout>
+ <command>ncat --ssl-ciphers <replaceable>HIGH:!aNULL:!eNULL</replaceable> <replaceable>server</replaceable> 443</command>
+ </literallayout>
+ </para>
+ <indexterm><primary><option>--ssl-ciphers</option> (Ncat option)</primary></indexterm>
+
+ <indexterm><primary>SSL</primary><secondary>in Ncat</secondary></indexterm>
+ <indexterm><primary>certificate</primary><secondary>automatic generation of</secondary></indexterm>
+ <indexterm><primary>certificate</primary><seealso><option>--ssl-cert</option></seealso></indexterm>
+ <indexterm><primary>keys, cryptographic</primary><seealso><option>--ssl-key</option></seealso></indexterm>
+ <para>
+ Ncat can act as an SSL server as well. The server must provide a
+ certificate that clients can verify if they choose. If you start an
+ SSL server without using the <option>--ssl-cert</option> and
+ <option>--ssl-key</option> options, Ncat will automatically generate a
+ certificate and 2,048-bit RSA key. The certificate will of course not
+ be trusted by any application doing certificate verification. In
+ verbose mode, the key's fingerprint will be printed so you can do
+ manual verification if desired.
+ <xref linkend="ncat-ex-ssl-gen" xrefstyle="select: label nopage"/>
+ shows sample output.
+ </para>
+
+ <example id="ncat-ex-ssl-gen">
+ <title>Automatic certificate generation</title>
+ <indexterm><primary><option>--ssl</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<screen>
+$ <userinput>ncat -v --listen --ssl</userinput>
+Ncat ( https://nmap.org/ncat )
+Generating a temporary 2048-bit RSA key. Use --ssl-key and --ssl-cert to use a <continuation/>permanent one.
+SHA-1 fingerprint: F0:13:BF:FB:2D:AA:76:88:22:60:3E:17:93:29:3E:0E:6B:92:C0:2F
+</screen>
+ </example>
+
+ <para>
+ Using an existing certificate and key is recommended whenever possible
+ because it allows for robust server authentication. Use the
+ <option>--ssl-cert</option> and <option>--ssl-key</option> options to
+ pass in PEM-encoded files.
+ For testing purposes you can generate a self-signed certificate and
+ private key. If you have OpenSSL<indexterm><primary>OpenSSL</primary></indexterm>
+ installed, use this command:
+ <informalexample>
+<literallayout>
+<command>openssl req -new -x509 -keyout test-key.pem -out test-cert.pem</command>.
+</literallayout>
+ </informalexample>
+ For purposes of certificate verification, the
+ <varname>commonName</varname><indexterm><primary><varname>commonName</varname></primary></indexterm>
+ in the certificate should match the fully qualified domain
+ name<indexterm><primary>fully qualified domain name</primary></indexterm>
+ of the host that will run the server. After generating the files,
+ start the server:
+ <informalexample>
+<literallayout>
+<command>ncat --listen --ssl --ssl-cert test-cert.pem --ssl-key test-key.pem</command>.
+</literallayout>
+ </informalexample>
+ To make a verified client connection, copy the
+ <filename>test-cert.pem</filename> file somewhere where the client can
+ access it, then run
+ <informalexample>
+<literallayout>
+<command>ncat --ssl-verify --ssl-trustfile test-cert.pem</command>.
+</literallayout>
+ </informalexample>
+ </para>
+</sect1>
+
+<sect1 id="ncat-exec">
+ <title>Command Execution</title>
+
+ <para>
+ Ncat can execute an external command after establishing a
+ connection. The command's standard input and output<indexterm><primary>standard input</primary></indexterm><indexterm><primary>standard output</primary></indexterm>
+ streams are redirected to use Ncat's network connection. Anything received over
+ the connection is given to the command's stdin, and anything the
+ command writes to stdout is sent back out over the connection. This feature makes
+ almost any terminal application accessible over a network (with some
+ caveats).
+ </para>
+
+ <para>
+ There are three ways of running a command:
+ <itemizedlist spacing="compact">
+ <listitem>
+ <option>--exec</option><indexterm><primary><option>--exec</option> (Ncat option)</primary></indexterm>
+ runs a command without shell interpretation.
+ </listitem>
+ <listitem>
+ <option>--sh-exec</option><indexterm><primary><option>--sh-exec</option> (Ncat option)</primary></indexterm>
+ runs a command by passing a string to a system shell.
+ </listitem>
+ <listitem>
+ <option>--lua-exec</option><indexterm><primary><option>--lua-exec</option> (Ncat option)</primary></indexterm>
+ runs a Lua program using Ncat's built-in Lua interpreter.<indexterm><primary>Lua</primary><secondary>in Ncat</secondary></indexterm>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ The
+ <option>--exec</option><indexterm><primary><option>--exec</option> (Ncat option)</primary></indexterm>
+ option (alias
+ <option>-e</option>)<indexterm><primary><option>-e</option> (Ncat option)</primary><see><option>--exec</option></see></indexterm>
+ takes the full pathname of a command to execute, along with its
+ arguments. The command is executed directly; Ncat does not interpret
+ the given string beyond splitting the command and its arguments.
+ <xref linkend="ncat-ex-exec" xrefstyle="select: label nopage"/>
+ shows an example of usage.
+ </para>
+
+ <example id="ncat-ex-exec">
+ <title>Running a command with <option>--exec</option></title>
+<literallayout><command>ncat -l --exec "/bin/echo Hello."</command></literallayout>
+ </example>
+
+ <para>
+ The
+ <option>--sh-exec</option><indexterm><primary><option>--sh-exec</option> (Ncat option)</primary></indexterm>
+ option
+ (<option>-c</option>)<indexterm><primary><option>-c</option> (Ncat option)</primary><see><option>--sh-exec</option></see></indexterm>
+ works the same as <option>--exec</option>, except that it
+ executes the command by passing it to <command>/bin/sh -c</command>
+ on Unix or <command>cmd.exe /C</command> on Windows.
+ You don't have to use the full pathname of the command if the
+ command is in the
+ <envar>PATH</envar>.<indexterm><primary><envar>PATH</envar></primary></indexterm>
+ Additionally you have access to shell facilities such as pipelines
+ and environment variable expansion.
+ <xref linkend="ncat-ex-sh-exec" xrefstyle="select: label nopage"/>
+ shows a command run with <option>--sh-exec</option>. This server,
+ when connected to, sends back the name of its working directory.
+ </para>
+
+ <example id="ncat-ex-sh-exec">
+ <title>Running a command with <option>--sh-exec</option></title>
+<literallayout><command>ncat -l --sh-exec "echo `pwd`"</command></literallayout>
+ </example>
+
+ <para>
+ The
+ <option>--lua-exec</option><indexterm significance="preferred"><primary><option>--lua-exec</option> (Ncat option)</primary></indexterm>
+ option takes the filename of a Lua program to run. Ncat runs the
+ program using its built-in interpreter and redirects its input and
+ output streams. Anything the program writes to standard output (for
+ example with <code>print</code> or <code>io.write</code>) is written
+ to the connection, and any reads from standard input come from the
+ connection. A nice thing about running programs written in Lua is that
+ the same interpreter is used on all platforms, in comparison with
+ shells that operate differently.
+ </para>
+
+ <para>
+ That means that the default Ncat build
+ is all you need to run a simple network service. To write a program, the
+ standard text editor (even a Windows "notepad") is enough; to learn how
+ to create programs in Lua, have a look at "Programming in Lua" book
+ available for free at
+ <ulink role="hidepdf" url="http://www.lua.org/pil/contents.html">Lua.org</ulink>
+ website.
+ <xref linkend="ncat-ex-lua-exec" xrefstyle="select: label nopage"/>
+ shows how to run a program stored in a file called
+ <filename>hello-luaexec.lua</filename>. You can find this script - and
+ some other ones - in Nmap's source code package, in
+ <literal>ncat/scripts</literal> directory - the latest versions of the
+ scripts can be found in the
+ <ulink role="hidepdf" url="https://svn.nmap.org/nmap/ncat/scripts/">Nmap project public SVN repository</ulink>.
+ Here are the contents of the hello-luaexec.lua file, if you would prefer
+ to create the file yourself:
+ </para>
+
+<programlisting>
+--This is a --lua-exec "Hello world" example. In order to send to a client,
+--all you need to do is output it to the standard output.
+
+print("Hello, world!")
+</programlisting>
+
+ <example id="ncat-ex-lua-exec">
+ <title>Running a command with <option>--lua-exec</option></title>
+<literallayout><command>ncat -l --lua-exec hello-luaexec.lua</command></literallayout>
+ </example>
+
+ <para>
+ Now, anyone that connects to our server will see the "Hello, world"
+ message. For a script with a bit more capabilities, have a look at
+<ulink role="hidepdf" url="https://svn.nmap.org/nmap/ncat/scripts/conditional.lua">conditional.lua</ulink>.
+ It shows how to create a simple menu, receive some data from the user
+ repeatedly and react according to her decisions. You might want to start
+ off your experiments with Lua by making changes to this script. Also see
+ <xref linkend="ncat-httpserv"/> for information on how to run a simple
+ HTTP server in Lua.
+ </para>
+
+ <para>
+ The exec options can be used in connect mode and listen mode. In
+ listen mode, Ncat accepts one connection, runs the command, and then
+ quits, just like listen mode without exec. But when listen mode is
+ combined with
+ <option>--keep-open</option>,<indexterm><primary><option>--keep-open (Ncat option)</option></primary><secondary>with <option>--exec</option></secondary></indexterm>
+ Ncat will accept multiple connections, forking off a new handler for
+ each.
+ The server will keep running until you press
+ <keycombo><keycap>ctrl</keycap><keycap>C</keycap></keycombo> or
+ otherwise terminate it externally. In this way Ncat can work much like
+ inetd.<indexterm><primary>inetd</primary></indexterm>
+ Many examples of the use of <option>--exec</option> and
+ <option>--sh-exec</option> in listen mode are found in
+ <xref linkend="ncat-simple-services"/>.
+ </para>
+
+ <example id="ncat-ex-sh-exec-persistent">
+ <title>Running an inetd-like server</title>
+<literallayout><command>ncat -l --keep-open --exec "/bin/echo Hello."</command></literallayout>
+ </example>
+
+ <para>
+ Whatever the exec mode, Ncat sets environment variables in the spawned
+ program's environment that describe the connection.
+
+ <variablelist>
+ <varlistentry>
+ <term><envar>NCAT_REMOTE_ADDR</envar></term><indexterm><primary><envar>NCAT_REMOTE_ADDR></envar> environment variable</primary></indexterm>
+ <term><envar>NCAT_REMOTE_PORT</envar></term><indexterm><primary><envar>NCAT_REMOTE_PORT></envar> environment variable</primary></indexterm>
+ <listitem>
+ <para>
+ The IP address and port number of the remote host. In connect mode, it's
+ the target's address; in listen mode, it's the client's address.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><envar>NCAT_LOCAL_ADDR</envar></term><indexterm><primary><envar>NCAT_LOCAL_ADDR></envar> environment variable</primary></indexterm>
+ <term><envar>NCAT_LOCAL_PORT</envar></term><indexterm><primary><envar>NCAT_LOCAL_PORT></envar> environment variable</primary></indexterm>
+ <listitem>
+ <para>
+ The IP address and port number of the local end of the connection.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><envar>NCAT_PROTO</envar></term><indexterm><primary><envar>NCAT_PROTO></envar> environment variable</primary></indexterm>
+ <listitem>
+ <para>
+ The protocol in use: one of <code>TCP</code>, <code>UDP</code>, and <code>SCTP</code>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <xref linkend="ncat-ex-exec-env" xrefstyle="select: label nopage"/>
+ shows the output of a Lua program that reads these variables.
+ You can see these environment variables in action by running this
+
+ </para>
+
+ <example id="ncat-ex-exec-env">
+ <title>Exec environment variables</title>
+ <para>The contents of the program <filename>env.lua</filename>:
+<programlisting>function env(v)
+ print(string.format("%s %q", v, os.getenv(v)))
+end
+env("NCAT_REMOTE_ADDR")
+env("NCAT_REMOTE_PORT")
+env("NCAT_LOCAL_ADDR")
+env("NCAT_LOCAL_PORT")
+env("NCAT_PROTO")</programlisting>
+ </para>
+ <para>The output of running the program:
+<screen>
+$ <userinput>ncat -l --lua-exec env.lua &amp;</userinput>
+$ <userinput>ncat localhost</userinput>
+NCAT_REMOTE_ADDR "127.0.0.1"
+NCAT_REMOTE_PORT "60179"
+NCAT_LOCAL_ADDR "127.0.0.1"
+NCAT_LOCAL_PORT "31337"
+NCAT_PROTO "TCP"
+</screen>
+ </para>
+ </example>
+
+ <indexterm><primary>--lua-exec portability</primary></indexterm>
+ <warning><para>
+ When writing your own --lua-exec script, keep in mind that while Lua is
+ very portable, there is a caveat related to running your Lua scripts
+ written on Windows to Unix systems. For technical reasons, --lua-exec
+ on Windows reloads the script every time it is run. Do not rely on this
+ behavior on other systems though - on POSIX-compatible systems, the
+ script is only loaded once and any modifications to its code will not
+ be visible until you restart Ncat.
+ </para></warning>
+
+ <para>
+ Any program that takes input and produces output can be executed by
+ Ncat, but not all programs are suited to this kind of interaction.
+ Many programs buffer their input and output,<indexterm><primary>buffering</primary><secondary>effect on Ncat of</secondary></indexterm>
+ so if they receive some bytes, they many not process those bytes and
+ write output until their input buffer is full, or the output may be
+ deferred until the output buffer is full. If another program sends a
+ few bytes and then waits for a response, it may hang indefinitely.
+ Buffers are flushed when input or output ends, so even those
+ programs that don't work interactively will work when run on an
+ entire file at a time.
+ </para>
+
+ <para>
+ Be careful when using the various exec
+ options. It can be dangerous to connect a
+ new application to a network, especially one that wasn't written
+ with potentially hostile input in mind. Any local vulnerabilities in
+ an application may become remote vulnerabilities when you execute
+ it through Ncat.
+ </para>
+</sect1>
+
+<sect1 id="ncat-output">
+ <title>Output Options</title>
+
+ <indexterm><primary>verbosity</primary><secondary>of Ncat</secondary></indexterm>
+ <para>
+ Like any proper pipeline utility, Ncat reads from
+ standard input<indexterm><primary>standard input</primary></indexterm>
+ and writes to
+ standard output<indexterm><primary>standard output</primary></indexterm>
+ so you can redirect I/O to or from any program or file. The only
+ exception is when Ncat is run with the <option>--exec</option> or
+ <option>--sh-exec</option> options, in which case it communicates with
+ the subprocess instead. Nothing in the streams is added, removed, or
+ altered, unless you specifically ask for it with an option such as
+ <option>-C</option><indexterm><primary><option>-C</option> (Ncat option)</primary></indexterm>
+ (CRLF processing) or
+ <option>--telnet</option><indexterm><primary><option>-telnet</option> (Ncat option)</primary></indexterm>
+ (Telnet negotiation). If Ncat prints any diagnostic messages, they are
+ sent to
+ standard error<indexterm><primary>standard error</primary></indexterm>
+ so as not to interfere with the data stream. By default Ncat does not
+ print any such messages, but you can enable them with the
+ <option>--verbose</option><indexterm><primary><option>--verbose</option> (Ncat option)</primary></indexterm>
+ (<option>-v</option>)<indexterm><primary><option>-v</option> (Ncat option)</primary><see><option>--verbose</option></see></indexterm>
+ option. Use <option>-v</option> more than once for even more output.
+ </para>
+
+ <indexterm><primary>hex dump</primary></indexterm>
+ <indexterm><primary>transcript</primary></indexterm>
+ <indexterm><primary>log file</primary><secondary>of Ncat</secondary></indexterm>
+ <para>
+ Use the
+ <option>--output</option><indexterm><primary><option>--output</option> (Ncat option)</primary></indexterm>
+ option or its alias
+ <option>-o</option><indexterm><primary><option>-o</option> (Ncat option)</primary><see><option>--output</option></see></indexterm>
+ to record a transcript of everything sent and received to a file:
+ <informalexample>
+<literallayout>
+<command>ncat -C --output smtp-debug.log mail.example.com 25</command>
+</literallayout>
+ </informalexample>
+ The log contains everything sent and received without differentiation.
+ Sometimes a hex dump is more useful than a plain text log; for that
+ use
+ <option>--hex-dump</option><indexterm><primary><option>--hex-dump</option> (Ncat option)</primary></indexterm>
+ or
+ <option>-x</option>.<indexterm><primary><option>-x</option> (Ncat option)</primary><see><option>--hex-dump</option></see></indexterm>
+ Let's see what happens if we accidentally speak SMTP to an SSH server:
+<screen>
+$ <userinput>ncat -C --hex-dump ssh-hex.log scanme.nmap.org 22</userinput>
+SSH-2.0-OpenSSH_4.3
+<userinput>HELO example.com</userinput>
+Protocol mismatch.
+</screen>
+ The <option>--hex-dump</option> log file for this session:
+<screen>
+[0000] 53 53 48 2D 32 2E 30 2D 4F 70 65 6E 53 53 48 5F SSH-2.0- OpenSSH_
+[0010] 34 2E 33 0A 4.3.
+[0000] 48 45 4C 4F 20 65 78 61 6D 70 6C 65 2E 63 6F 6D HELO exa mple.com
+[0010] 0D 0A ..
+[0000] 50 72 6F 74 6F 63 6F 6C 20 6D 69 73 6D 61 74 63 Protocol mismatc
+[0010] 68 2E 0A h..
+</screen>
+ Each transmission is dumped separately. There is a break and the
+ counter at the left starts over each time there is a new send.
+ </para>
+</sect1>
+
+<sect1 id="ncat-access">
+ <indexterm><primary>access control</primary></indexterm>
+ <title>Access Control</title>
+
+ <para>
+ A listening Ncat may control which hosts connect to it with the
+ <option>--allow</option><indexterm><primary><option>--allow</option> (Ncat option)</primary></indexterm>
+ and
+ <option>--deny</option><indexterm><primary><option>--deny</option> (Ncat option)</primary></indexterm>
+ options. Each of these takes a comma-separated list of host
+ specifications. The syntax is almost identical to that recognized by Nmap for
+ targets
+ (see <ulink url="https://nmap.org/book/man-target-specification.html">the section called <quote>Target Specification</quote></ulink>).
+ <!-- (see <xref linkend="host-discovery-specify-targets"/>). -->
+ This includes IPv4 and IPv6 addresses, hostnames, IPv4 octet ranges,
+ and CIDR netmasks. In Ncat (unlike Nmap), CIDR netmasks are supported for IPv6
+ addresses.
+ </para>
+
+ <para>
+ With <option>--allow</option>, any hosts matching one of the listed specifiers
+ are allowed and all others are denied. With <option>--deny</option>,
+ those hosts matching the list are denied and all others are accepted.
+ If a host matches both the <option>--allow</option> and
+ <option>--deny</option> lists, it is denied.
+ </para>
+
+ <para>
+ Use
+ <option>--allowfile</option><indexterm><primary><option>--allowfile</option> (Ncat option)</primary></indexterm>
+ and
+ <option>--denyfile</option><indexterm><primary><option>--denyfile</option> (Ncat option)</primary></indexterm>
+ to allow or deny a list of host/network specifiers stored in a file. Each line of the
+ file contains a specification in one of the forms listed above. Any
+ file acceptable to Nmap's
+ <option>-iL</option><indexterm><primary><option>-iL</option></primary></indexterm>
+ and
+ <option>--excludefile</option><indexterm><primary><option>--excludefile</option></primary></indexterm>
+ options is suitable for <option>--allowfile</option> and
+ <option>--denyfile</option>.
+ </para>
+
+ <para>
+ The following example commands demonstrate various kinds of access control.
+ </para>
+
+ <!-- 2001:db8::/32 is an IPv6 prefix reserved for documentation, RFC 3849. -->
+ <variablelist>
+ <varlistentry>
+ <term>Allow one host, deny all others</term>
+ <listitem>
+<literallayout>
+<command>ncat -l --allow 192.168.0.125</command>
+<command>ncat -l --allow 2001:db8::7d</command>
+<command>ncat -l --allow trusted.example.com</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Deny one host, allow all others</term>
+ <listitem>
+<literallayout>
+<command>ncat -l --deny 192.168.0.200</command>
+<command>ncat -l --deny 2001:db8::c8</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Allow hosts on a local network, deny all others</term>
+ <listitem>
+<literallayout>
+<command>ncat -l --allow 192.168.0.0/24</command>
+<command>ncat -l --allow 192.168.0.0-255</command>
+<command>ncat -l --allow 2001:db8::/32</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Allow or deny hosts from a file</term>
+ <listitem>
+<literallayout>
+<command>ncat -l --allowfile trusted-hosts.txt</command>
+<command>ncat -l --denyfile external-hosts.txt</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Be aware that host-based access control is susceptible to spoofing attacks and various other possible failures. These mechanisms should not be relied on for complete security.
+ </para>
+
+ <para>
+ Another kind of access control is simply limiting the maximum number
+ of connections a listening Ncat will accept. Use the
+ <option>--max-conns</option><indexterm><primary><option>--max-conns</option> (Ncat option)</primary></indexterm>
+ option or its
+ <option>-m</option><indexterm><primary><option>-m</option></primary><see><option>--max-conns</option></see></indexterm>
+ alias to do that. The default maximum number of connections is 100, or 60 on Windows.
+ <informalexample>
+<literallayout>
+<command>ncat -l --max-conns 5</command>
+</literallayout>
+ </informalexample>
+ </para>
+</sect1>
+
+<sect1 id="ncat-proxy">
+ <title>Proxying</title>
+
+ <indexterm><primary>HTTP proxy</primary><see>proxy</see></indexterm>
+ <indexterm><primary>proxy</primary><secondary>Ncat as</secondary></indexterm>
+ <para>
+ Ncat can route its connections through a
+ SOCKS&nbsp;4<indexterm><primary>SOCKS proxy</primary></indexterm>, SOCKS&nbsp;5
+ or HTTP<indexterm><primary>HTTP proxy</primary></indexterm> proxy. A basic
+ connection looks like
+ <informalexample>
+<indexterm><primary><option>--proxy</option> (Ncat option)</primary></indexterm>
+<indexterm><primary><option>--proxy-type</option> (Ncat option)</primary></indexterm>
+<literallayout>
+<command>ncat --proxy <replaceable>proxyhost</replaceable><optional>:<replaceable>proxyport</replaceable></optional> --proxy-type <group choice="req"><arg choice="plain">http</arg><arg choice="plain">socks4</arg><arg choice="plain">socks5</arg></group> <replaceable>host</replaceable> <optional><replaceable>port</replaceable></optional></command>
+</literallayout>
+ </informalexample>
+ <option>--proxy-type</option> may be omitted; it defaults to
+ <literal>http</literal>. If <replaceable>proxyport</replaceable> is
+ omitted, it defaults to the well-known port for the chosen proxy type:
+ 1080 for SOCKS and 3128 for HTTP. An exception to this rule is when
+ the proxy host is given by a IPv6 address; in this case the port is
+ required because otherwise it would be ambiguous whether the digits
+ after the last colon are the port number or part of the address.
+ </para>
+
+ <para>
+ If the proxy server requires authentication, use the
+ <option>--proxy-auth</option><indexterm><primary><option>--proxy-auth</option> (Ncat option)</primary></indexterm>
+ option. Use
+ <command>--proxy-auth <replaceable>username</replaceable>:<replaceable>password</replaceable></command>
+ for HTTP and SOCKS5 proxies and
+ <command>--proxy-auth <replaceable>username</replaceable></command>
+ for SOCKS4 proxies.
+ </para>
+
+ <para>
+ Ncat can act as a proxy server itself in listen mode. The only proxy
+ type supported in this case is <literal>http</literal>.
+ <informalexample>
+<literallayout>
+<command>ncat -l 3128 --proxy-type http</command>
+<command>ncat -l 3128 --proxy-type http --proxy-auth <replaceable>user</replaceable>:<replaceable>pass</replaceable></command>
+</literallayout>
+ </informalexample>
+ In listen mode the proxy port number is not automatically set and will
+ be the default of 31337 unless specified. The proxy supports the
+ GET,<indexterm><primary>GET HTTP method</primary></indexterm>
+ HEAD,<indexterm><primary>HEAD HTTP method</primary></indexterm>
+ and POST<indexterm><primary>POST HTTP method</primary></indexterm>
+ methods used in web browsing, as well as the
+ CONNECT<indexterm><primary>CONNECT HTTP method</primary></indexterm>
+ method that allows tunneling arbitrary TCP connections. (When Ncat
+ connects as a client, it uses CONNECT.) Use
+ <option>--proxy-auth</option> to make the server require
+ authentication with a specific username and password.
+ </para>
+
+ <para>
+ For HTTP, both the Basic<indexterm><primary>Basic authentication (HTTP)</primary></indexterm>
+ and Digest<indexterm><primary>Digest authentication (HTTP)</primary></indexterm>
+ authentication schemes are supported, as both a client and a server.
+ Digest is more secure, so the Ncat client will use that in preference
+ to Basic when it is available. The server offers both schemes to its
+ clients. See
+ RFC&nbsp;2617,<indexterm><primary>RFC 2617</primary></indexterm>
+ section 4 for security considerations of HTTP authentication. Basic
+ sends credentials in the clear and Digest does not. Ncat's
+ implementation of Digest authentication allows replay attacks for up
+ to 10 seconds (replay and other attacks are always possible with
+ Basic).
+ </para>
+
+ <indexterm><primary>open proxy</primary></indexterm>
+ <warning><para>
+ Ncat's HTTP proxy is designed to stay out of your way and help you
+ make temporary network connections. It shouldn't be used as an
+ everyday proxy exposed to the Internet. You can limit who connects
+ using <option>--allow</option>,<indexterm><primary><option>--allow</option></primary></indexterm>
+ <option>--deny</option>,<indexterm><primary><option>--deny</option></primary></indexterm> and
+ <option>--proxy-auth</option>, but these are not strong forms of
+ authentication. An unauthenticated proxy is dangerous because it may
+ enable others to perform attacks or help them evade detection. The
+ CONNECT<indexterm><primary>CONNECT HTTP method</primary><secondary>danger of</secondary></indexterm>
+ capability is especially dangerous because it enables any kind
+ of traffic, not just HTTP.
+ </para></warning>
+</sect1>
+
+<sect1 id="ncat-other-options">
+ <title>Other Options</title>
+
+ <para>
+ This section contains descriptions of all options that haven't been
+ discussed so far.
+ </para>
+
+ <para>
+ The
+ <option>--nodns</option><indexterm><primary><option>--nodns</option> (Ncat option)</primary></indexterm>
+ option (and its short form
+ <option>-n</option>)<indexterm><primary><option>-n</option> (Ncat option)</primary><see><option>--nodns</option></see></indexterm>
+ instructs Ncat never to resolve names into addresses. All hosts must
+ appear as IPv4 or IPv6 addresses.
+ </para>
+
+ <para>
+ Ncat can be used as a Telnet client or server with the
+ <option>--telnet</option><indexterm><primary><option>--telnet</option> (Ncat option)</primary></indexterm>
+ option
+ (<option>-t</option>).<indexterm><primary><option>-t</option> (Ncat option)</primary><see><option>--telnet</option></see></indexterm>
+ This simply causes Ncat to respond negatively to any questions asked
+ by the other host in the binary Telnet protocol, removing such
+ negotiations from the stream seen by the user. The primary use of this
+ option is to allow running canned Telnet scripts.
+ </para>
+
+ <para>
+ The
+ <option>--send-only</option><indexterm><primary><option>--send-only</option> (Ncat option)</primary></indexterm>
+ and
+ <option>--recv-only</option><indexterm><primary><option>--send-only</option> (Ncat option)</primary></indexterm>
+ options do what their names imply, turning Ncat into a one-way
+ communications channel instead of its default two-way channel. A usage example is gathering data from a server
+ without the possibility of accidentally sending something typed at the
+ keyboard. <option>--send-only</option> in both connect and listen
+ modes causes Ncat to quit when its input runs out. Normally it will
+ not quit until the network connection is closed because the remote
+ side may still send something, but in the case of
+ <option>--send-only</option> there's no reason to receive anything
+ more.
+ </para>
+
+ <sect2 id="ncat-source">
+ <title>Source Options</title>
+
+ <para>
+ In connect mode, you may set the source address and port used for
+ the connection with the
+ <option>--source</option><indexterm><primary><option>--source</option> (Ncat option)</primary></indexterm>
+ (<option>-s</option>)<indexterm><primary><option>-s</option> (Ncat option)</primary><see><option>--source</option></see></indexterm>
+ and
+ <option>--source-port</option><indexterm><primary><option>--source-port</option> (Ncat option)</primary></indexterm>
+ (<option>-p</option>).<indexterm><primary><option>-p</option> (Ncat option)</primary><see><option>--source-port</option></see></indexterm>
+ The <option>-s</option> option only works for locally configured
+ addresses; it doesn't work like Nmap's
+ <option>-S</option><indexterm><primary><option>-S</option></primary></indexterm>
+ option. The value of <option>-p</option> is that sometimes firewalls
+ will allow traffic that comes from certain source ports (such as 20 or 53).
+ <!-- See <xref linkend="defeating-firewalls-source-port"/>. -->
+ </para>
+
+ <indexterm><primary>source routing</primary><secondary>in Ncat</secondary></indexterm>
+ <para>
+ The
+ <option>-g</option><indexterm><primary><option>-g</option> (Ncat option)</primary></indexterm>
+ option allows hops selection for IPv4 loose source routing. List the
+ hops in order by giving <option>-g</option> multiple times or by
+ separating the hops with commas. By default the source routing
+ pointer is 4 in the packets sent, indicating the first hop in the
+ list. You may set the pointer to another value with the
+ <option>-G</option><indexterm><primary><option>-G</option> (Ncat option)</primary></indexterm>
+ option. The pointer value must be a multiple of 4 between 4 and 28,
+ but some operating systems only support 4.
+ </para>
+ </sect2>
+
+ <sect2 id="ncat-timing">
+ <title>Timing</title>
+
+ <para>
+ Ncat offers various options to control timing. Each of them take an
+ argument that is assumed to be in seconds, unless followed by
+ <quote>ms</quote> for milliseconds,
+ <quote>s</quote> for seconds, <quote>m</quote> for minutes, or
+ <quote>h</quote> for hours. <quote>30s</quote> means 30 seconds. This format should already be familiar to Nmap users.
+ </para>
+
+ <para>
+ The
+ <option>--delay</option><indexterm><primary><option>--delay</option> (Ncat option)</primary></indexterm>
+ option and its short form
+ <option>-d</option><indexterm><primary><option>-d</option> (Ncat option)</primary><see><option>--delay</option></see></indexterm>
+ make Ncat wait the given amount of time between each discrete read
+ or write operation. For example, <command>--delay 500ms</command>
+ enforces a delay of half a second.
+ </para>
+
+ <para>
+ The
+ <option>--idle-timeout</option><indexterm><primary><option>--idle-timeout</option> (Ncat option)</primary></indexterm>
+ option and it synonym
+ <option>-i</option><indexterm><primary><option>-i</option> (Ncat option)</primary><see><option>--idle-timeout</option></see></indexterm>
+ allow setting a timeout for reads and writes in connect mode. If the
+ client fails to read or write for the given time period, the
+ connection is dropped. These options do not work in listen mode.
+ </para>
+
+ <para>The
+ <option>--wait</option><indexterm><primary><option>--wait</option></primary></indexterm> (or <option>-w</option> for short)<indexterm><primary><option>-w</option> (Ncat option)</primary><see><option>--wait</option></see></indexterm>
+ option sets how long Ncat will wait for a connection to be established in
+ connect mode. The default is 10 seconds.
+ </para>
+ </sect2>
+</sect1>
+
+<sect1 id="ncat-file-transfer">
+ <title>File Transfer</title>
+ <indexterm><primary>file transfer with Ncat</primary></indexterm>
+
+ <para>
+ There is no shortage of ways to transfer a file over a network. Most
+ file transfers are ably handled by email, network file systems, HTTP,
+ SFTP, or other protocols. What do you do, though, when that file is
+ too big to email, the transfer is between two machines not connected
+ to the Internet, or you just need to do one quick file transfer
+ without having to set up and tear down a file server? In these and
+ other situations Ncat can be the right tool for the job. Some tricky
+ file transfer scenarios can really make you appreciate the flexibility
+ of a raw network pipe.
+ </para>
+
+ <para>
+ As you know, Ncat by default sends all its traffic without encryption,
+ so it is possible for someone to intercept files in transit. See
+ <xref linkend="ncat-ssl"/> for one method of encrypting traffic.
+ </para>
+
+ <para>
+ By default, Ncat doesn't close its connection until it is closed by
+ the remote end, even after it has exhausted its input. That is because
+ (as far as Ncat knows) the remote server may still have data to send
+ back. The
+ <option>--send-only</option><indexterm><primary><option>--send-only</option> (Ncat option)</primary></indexterm>
+ option, when applicable, changes this behavior to close the connection
+ and quit at the end of input. This is normally what you want when
+ doing a one-way file transfer.
+ </para>
+
+ <para>
+ A basic file transfer is very simple: Start Ncat in listen mode on one
+ end, start Ncat in connect mode on the other end, and pipe the file
+ over the connection. There are two ways to do this that differ only in
+ which end listens, the sender or the receiver. Sometimes you can't
+ create a listening socket on one end of the transfer because of a lack
+ or permissions, NAT, or filtering. As long as you can listen on at
+ least one end, though, you can use this technique.
+ </para>
+
+ <para>
+ These examples show how to transfer <filename>inputfile</filename> on
+ host1 to <filename>outputfile</filename> on host2. Here no port number
+ was specified so Ncat will use its default
+ port<indexterm><primary>default port of Ncat</primary></indexterm> of
+ 31337. To use a different port just list it on the command line.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Transfer a file, receiver listens</term>
+ <listitem>
+<indexterm><primary><option>--listen</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<indexterm><primary><option>-l</option> (Ncat option)</primary><see><option>--listen</option></see></indexterm>
+<literallayout>
+host2$ <userinput>ncat -l &gt; outputfile</userinput>
+host1$ <userinput>ncat --send-only host2 &lt; inputfile</userinput>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Transfer a file, sender listens</term>
+ <listitem>
+<literallayout>
+host1$ <userinput>ncat -l --send-only &lt; inputfile</userinput>
+host2$ <userinput>ncat host1 &gt; outputfile</userinput>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Note the order of the commands. The listener must be started first,
+ regardless of the direction of transfer, or else the client will not
+ have anything to connect to.
+ </para>
+
+ <para>
+ The above technique works fine for sending a single file. One way to
+ send multiple files is to bundle them up with <command>tar</command>
+ or <command>zip</command> and send the archive file. But there's an
+ even easier way. Just pipe the output of <command>tar</command>
+ directly into Ncat on the sending side, and pipe Ncat's output into
+ <command>tar</command> on the receiving side. This is especially
+ useful when the sending computer doesn't have enough free disk space
+ to hold the archive file. Here's how to transfer
+ <replaceable>files</replaceable> using the <quote>receiver
+ listens</quote> method, though of course the <quote>sender
+ listens</quote> method works just as well.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Transfer a bundle of files</term>
+ <listitem>
+<literallayout>
+host2$ <userinput>ncat -l | tar xzv</userinput>
+host1$ <userinput>tar czv <replaceable>files</replaceable> | ncat --send-only host2</userinput>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Not only tar files but any stream of bytes can be transferred in this
+ way. Here is an example of transferring an entire disk image from host1
+ to host2. Naturally, the disk should be unmounted or mounted
+ read-only.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Transfer a disk image</term>
+ <listitem>
+<literallayout>
+host2$ <userinput>ncat -l &gt; host1-hda.image</userinput>
+host1$ <userinput>ncat --send-only host2 &lt; /dev/hda</userinput>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Disk images are typically large files that take a long time to
+ transfer. You can compress the image on the fly while sending and
+ decompress it on the other end. Whether this makes an improvement
+ depends on the speed of the network and the compression program.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Transfer a disk image with compression</term>
+ <listitem>
+<literallayout>
+host2$ <userinput>ncat -l | bzip2 -d &gt; host1-hda.image</userinput>
+host1$ <userinput>cat /dev/hda | bzip2 | ncat --send-only host2</userinput>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ The basic file transmission technique described at the beginning of
+ this section fails if neither participating host is capable of
+ listening, or the two hosts can't communicate directly. This situation
+ has become common with the prevalence of network address translation.
+ A way to work around it is to use a third host as an intermediary. The
+ intermediate host listens in connection brokering mode and the other
+ two hosts connect to it. Recall from <xref linkend="ncat-broker"/>
+ that in connection brokering mode any input received on one socket is
+ copied and sent out to all other sockets. With just two hosts
+ connected this is especially simple: anything coming from one host
+ gets forwarded to the other. This example shows host1 sending
+ <filename>inputfile</filename> to <filename>outputfile</filename> on
+ host2, using host3 as an intermediary.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Transfer a file through an intermediary</term>
+ <listitem>
+<indexterm><primary><option>--broker</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+host3$ <userinput>ncat -l --broker</userinput>
+host2$ <userinput>ncat host3 &gt; outputfile</userinput>
+host1$ <userinput>ncat --send-only host3 &lt; inputfile</userinput>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Note that it's important for host2 (the receiving host) to connect to
+ the broker before host1 (the sending host) does. The broker does not
+ buffer received data to send to hosts that connect later. After the
+ file is transferred, it is necessary to forcibly disconnect the Ncat
+ on host2 with
+ <keycombo><keycap>ctrl</keycap><keycap>C</keycap></keycombo>. The
+ broker never disconnects any of its clients.
+ </para>
+</sect1>
+
+<sect1 id="ncat-chat">
+ <title>Chatting</title>
+
+ <para>
+ In its most basic form, Ncat simply moves bits from one place to
+ another. This is all that is needed to set up a simple chat system. By
+ default, Ncat reads from
+ standard input<indexterm><primary>standard input</primary></indexterm>
+ and writes to
+ standard output,<indexterm><primary>standard output</primary></indexterm>
+ meaning that it will send whatever is typed at the keyboard and will
+ show on the screen whatever is received.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Two-user chat</term>
+ <listitem>
+<literallayout>
+host1$ <userinput>ncat -l</userinput>
+host2$ <userinput>ncat host1</userinput>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ With this setup, two users can communicate with each other. Whatever
+ one types will appear on the screen of the other. Be aware that
+ standard input is probably line-buffered so it may be necessary to press
+ <keycap>enter</keycap> before a line is sent. Which side listens
+ and which side connects is not important in this situation, except that the listener must start ncat first.
+ </para>
+
+ <para>
+ The above technique is limited to one-on-one conversations. If more
+ users connect to the server, each one will effectively create a new
+ chat channel with the server; none of the connecting users will hear
+ each other. Multi-user chatting is easily supported using connection
+ brokering with the <option>--broker</option> option (see
+ <xref linkend="ncat-broker"/>). In broker mode, anything received on
+ one connection is sent out to all other connections, so everyone can
+ talk with everyone else.
+ </para>
+
+ <indexterm><primary>chat mode (Ncat)</primary></indexterm>
+ <para>
+ When many users are chatting through a connection broker, it can be
+ hard to know who is saying what. For these cases Ncat provides a simple
+ hack to tell users apart. When the
+ <option>--chat</option><indexterm><primary><option>--chat</option> (Ncat option)</primary></indexterm>
+ option is given, connection brokering is automatically enabled. Each
+ message received is prefixed with an ID before being relayed to all
+ other clients. The ID is unique for each client connection, and
+ therefore functions something like a username. Also, in chat mode any
+ control characters are escaped so they won't mess up your terminal.
+ The server is started with
+<literallayout>
+server$ <userinput>ncat -l --chat</userinput>
+</literallayout>
+ </para>
+
+ <para>
+ Once the server is started, this is how the chat appears to one of the
+ connected users. The lines that begin with
+ <literal>&lt;user<replaceable>n</replaceable>&gt;</literal> are from
+ other connected users. The line beginning with
+ <literal>&lt;user0&gt;</literal> was sent by the listening broker.
+ </para>
+
+<screen>
+client$ <userinput>ncat server</userinput>
+&lt;user6&gt; Is anyone there?
+<userinput>I'm here.</userinput>
+&lt;user5&gt; Me too.
+&lt;user0&gt; Go away, all of you.
+</screen>
+
+ <para>
+ The user IDs generated by Ncat are based on the file descriptor for
+ each connection, and must be considered arbitrary. There is no way to
+ choose a particular ID or make one persist across sessions.
+ Nevertheless, <option>--chat</option> can come in handy for those
+ quick multi-user conversations.
+ </para>
+</sect1>
+
+<sect1 id="ncat-tricks">
+ <title>Neat Tricks</title>
+
+ <sect2 id="ncat-smtp">
+ <title>Send Mail</title>
+
+ <para>
+ It is great fun to interact with text-based network protocols with
+ nothing more than Ncat and a keyboard. Here's a short example
+ showing how to send email by talking to an SMTP server. SMTP is
+ described in
+ RFC&nbsp;5321,<indexterm><primary>RFC 5321</primary></indexterm>
+ but you don't need to know much about the protocol to send a simple
+ message. The service's assigned port number is 25, and we use
+ <option>-C</option> because it requires CRLF line endings.
+ <xref linkend="ncat-ex-smtp" xrefstyle="select: label nopage"/>
+ contains a transcript of a session.
+ </para>
+
+ <example id="ncat-ex-smtp">
+ <title>Ncat as mail client</title>
+<indexterm><primary><option>--crlf</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<screen>
+$ <userinput>ncat -C mail.example.com 25</userinput>
+220 mail.example.com ESMTP
+<userinput>HELO client.example.com</userinput>
+250 mail.example.com Hello client.example.com
+<userinput>MAIL FROM:a@example.com</userinput>
+250 OK
+<userinput>RCPT TO:b@example.com</userinput>
+250 Accepted
+<userinput>DATA</userinput>
+354 Enter message, ending with "." on a line by itself
+<userinput>From: a@example.com
+To: b@example.com
+Subject: Greetings from Ncat
+
+Hello. This short message is being sent by Ncat.
+.</userinput>
+250 OK
+<userinput>QUIT</userinput>
+221 mail.example.com closing connection
+</screen>
+ </example>
+
+ <para>
+ To make this example work for you, change
+ <literal>mail.example.com</literal> to your SMTP server and
+ <literal>client.example.com</literal> to your domain
+ name. Naturally you'll want to change the email addresses and
+ message too. It will likely only work when using your normal mail
+ server with your real email address, or when using the recipient's
+ mail server (look up the MX record for the domain name in their
+ email address).
+ </para>
+
+ <para>
+ Obviously this technique can be used for more than just sending
+ mail. Ncat is a great interactive debugging tool for any text-based
+ protocol. Such debugging is sometimes done with the
+ <command>telnet</command> command, because it provides something
+ like a raw text stream. Ncat offers a few advantages over
+ <command>telnet</command>, though. Ncat doesn't print anything
+ except what is sent by the remote host. Telnet isn't suitable for
+ arbitrary binary data because it reserves some bytes as control
+ characters. The <command>telnet</command> command quits when its
+ input runs out, so you may not see what the other end sends. And
+ finally, <command>telnet</command> doesn't do UDP.
+ </para>
+ </sect2>
+
+ <sect2 id="ncat-httpserv">
+ <title>Turn Ncat into a simple web server</title>
+
+ <para>
+ Continuing the example from <xref linkend="ncat-listen"/>, we can
+ create a simple HTTP server that serves the
+ <literal>index.html</literal> file using the following command:
+ </para>
+
+<literallayout>
+<command>ncat -lk -p 8080 --sh-exec "echo -e 'HTTP/1.1 200 OK\r\n'; cat index.html"</command>
+</literallayout>
+
+ <para>
+ Or, if you're a Windows user:
+ </para>
+
+<literallayout>
+<command>ncat -lk -p 8080 --sh-exec "echo HTTP/1.1 200 OK&amp; echo(&amp;type index.html"</command>
+</literallayout>
+
+ <para>
+ This will start the HTTP server, serving the <literal>index.html</literal>
+ file from your current working directory. To try it out, visit
+ <userinput>http://localhost:8080/</userinput> using
+ your web browser. You can also skip <literal>:8080</literal> from the
+ URL if you specified <literal>-p 80</literal> instead of
+ <literal>-p 8080</literal> in the command above. Note that it will send
+ this file regardless of the entered URL - to change the file being sent,
+ you need to change the Ncat command or use the httpd.lua script (see
+ below).
+ </para>
+
+ <para>
+ Since Ncat v6.40, it is possible to use --lua-exec feature to run a Lua
+ script turning Ncat into a web server. In order to do that, need the
+ httpd.lua script which is bundled with the Ncat source in the
+ <literal>ncat/scripts/</literal> directory. With the httpd.lua script in
+ your working directory, run Ncat in listening mode:</para>
+
+<literallayout>
+<command>ncat --lua-exec httpd.lua --listen 8080 --keep-open</command>
+</literallayout>
+
+ <para>
+ This will spawn a HTTP server on TCP port 8080. Unlike the previous
+ example though, the httpd.lua script works without modification on all
+ POSIX-compatible systems and also on Windows. Moreover, you can specify
+ in the URL any other file from the current directory or one of its
+ subdirectories and it will be sent to the user, unlike the
+ <literal>--sh-exec</literal> example.
+ </para>
+
+ <indexterm><primary>Ncat HTTP server on production</primary></indexterm>
+ <warning><para>
+ The Ncat HTTP server examples shown above are very simple and may be not
+ as powerful as complete HTTP servers, such as Apache HTTPD. It is not
+ advised to use them in production environments (such as public website
+ hosting). It might be useful, though, if you need to quickly spawn a HTTP
+ server to copy some files or for educational purposes.
+ </para></warning>
+
+ </sect2>
+
+ <sect2 id="ncat-chain">
+ <title>Chain Ncats Together</title>
+
+ <para>
+ Ncat is designed to work within a pipeline, so naturally the output
+ of one instance of Ncat can be fed into the input of another. Here
+ is one way to send a log file from host1 to host3 by way of host2:
+<screen>
+host3$ <userinput>ncat -l &gt; log.txt</userinput>
+host2$ <userinput>ncat -l | ncat host3</userinput>
+host1$ <userinput>ncat --send-only host2 &lt; log.txt</userinput>
+</screen>
+ </para>
+
+ <para>
+ A possible problem with this technique is that it is one-way: host1 can
+ send to host3 but there is no way for host3 to send anything back to
+ host1. In this case it doesn't matter, but it can be done with a
+ small change. Consider this:
+<screen>
+host3$ <userinput>ncat -l &gt; log.txt</userinput>
+host2$ <userinput>ncat -l --sh-exec "ncat host3"</userinput>
+host1$ <userinput>ncat --send-only host2 &lt; log.txt</userinput>
+</screen>
+ The Ncat listening on host2, upon receiving a connection, creates a
+ new Ncat to speak to host3 and connects the inputs and outputs of
+ the programs running on host1 and host3 together. The same trick can
+ be used on the local host too. This example forwards the local port
+ 8080 to the web server on example.org:
+ <informalexample>
+<literallayout>
+<command>ncat -l localhost 8080 --sh-exec "ncat example.org 80"</command>
+</literallayout>
+ </informalexample>
+ </para>
+ </sect2>
+
+ <sect2 id="ncat-unwrap-ssl">
+ <title>Unwrap SSL</title>
+
+ <!-- This trick was suggested by Brandon Enright.
+ https://seclists.org/nmap-dev/2009/q1/379 -->
+ <para>
+ Suppose you need to connect to an
+ IMAP<indexterm><primary>IMAP</primary></indexterm> server that
+ requires SSL, but your mail reader doesn't support SSL. Ncat can act
+ as the encrypted bridge to connect the client and server. You will
+ connect the mail client to a local port and Ncat will forward the
+ traffic, encrypted, to the server. Here's how to connect IMAP (port
+ 143) on the local host to
+ IMAP over SSL (port 993)<indexterm><primary>IMAPS</primary></indexterm>
+ on <literal>imap.example.com</literal>.
+<literallayout>
+<command>ncat -l localhost 143 --sh-exec "ncat --ssl imap.example.com 993"</command>
+</literallayout>
+ Once this is in place, instruct the mail client to connect to the
+ IMAP server on localhost.
+ </para>
+
+ <para>
+ This trick works for protocols that pass traffic strictly between
+ two hosts. It doesn't work well for
+ HTTP<indexterm><primary>HTTP</primary></indexterm>
+ because HTTP is usually aware of hostnames and often involves
+ multiple hosts.
+ </para>
+ </sect2>
+
+ <sect2 id="ncat-ssh-tunnel">
+ <title>Use SSH Through an Ncat Tunnel</title>
+
+ <!-- This trick was suggested by Greg Darke.
+ https://seclists.org/nmap-dev/2009/q1/403 -->
+ <para>
+ With Ncat and OpenSSH<indexterm><primary>OpenSSH</primary></indexterm>
+ you can SSH to a host behind a NAT<indexterm><primary>network address translation</primary></indexterm>
+ router without having to forward ports on the router. The router
+ must have Ncat installed. Here is how to SSH to
+ <filename><replaceable>host</replaceable></filename> through
+ <filename><replaceable>router</replaceable></filename>:
+<literallayout>
+<command>ssh -o ProxyCommand="ssh -q <replaceable>router</replaceable> ncat %h %p" <replaceable>host</replaceable></command>
+</literallayout>
+ </para>
+ <para>
+ The <varname>ProxyCommand</varname> option of <command>ssh</command>
+ tells how to open the SSH connection to
+ <filename><replaceable>host</replaceable></filename>. It does this
+ by opening another SSH session to
+ <filename><replaceable>router</replaceable></filename> and
+ connecting it to
+ <filename><replaceable>host</replaceable></filename> with Ncat.
+ </para>
+
+ <para>
+ If your SSH server administrator did not disable tunneling (which is
+ enabled in most default configurations), you can use the proxy server
+ built into SSH. Use the following command to spawn a proxy server on
+ TCP port 8080 of your local machine that tunnels the traffic through
+ the SSH connection:
+ </para>
+
+<literallayout>
+<command>ssh router -D 8080</command>
+</literallayout>
+
+ <para>
+ Now you can make connections inside the network using Ncat's proxy client
+ capabilities. For example, to connect to host with IP address
+ 192.168.1.123 that is behind the router, you can use the following
+ command if you spawned the tunnel:
+ </para>
+
+<literallayout>
+<command>ncat --proxy localhost:8080 --proxy-type socks4 192.168.1.123</command>
+</literallayout>
+
+ </sect2>
+
+ <sect2 id="ncat-nmap-version">
+ <title>Watch What Nmap's Version Detection is Doing</title>
+
+ <para>
+ <!-- <xref linkend="vscan"/> tells all about Nmap's version detection
+ system. --> Ncat can show you at a low level what's going on when Nmap
+ version-scans a service. We'll make a service that only listens and
+ instruct Nmap to use every version probe in the book. Set up Ncat to
+ listen and record a hex dump log. The
+ <option>--keep-open</option><indexterm><primary><option>--keep-open</option> (Ncat option)</primary></indexterm>
+ option will make Ncat keep listening and accepting more connections
+ after the first one is finished, contrary to the normal listen mode
+ behavior of quitting when the first connection ends. Some version
+ probes are binary so redirect standard output to
+ <filename>/dev/null</filename><indexterm><primary><filename>/dev/null</filename></primary></indexterm>
+ to avoid writing them to the screen.
+ <informalexample>
+<indexterm><primary><option>--hex-dump</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<indexterm><primary><option>--keep-open</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<command>ncat -l --keep-open 5200 --hex-dump vscan.log &gt; /dev/null</command>
+</literallayout>
+ </informalexample>
+ Now scan the open port you made:
+ <informalexample>
+<indexterm><primary><option>--version-all</option></primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>nmap -d -sV --version-all localhost -p 5200</command>
+</literallayout>
+ </informalexample>
+ An except of the hex dump is shown in
+ <xref linkend="ncat-ex-nmap-version" xrefstyle="select: label nopage"/>.
+ </para>
+
+ <example id="ncat-ex-nmap-version">
+ <title>Hex dump of Nmap version detection</title>
+<screen><![CDATA[[0000] 0D 0A 0D 0A ....
+[0000] 47 45 54 20 2F 20 48 54 54 50 2F 31 2E 30 0D 0A GET / HT TP/1.0..
+[0010] 0D 0A ..
+[0000] 4F 50 54 49 4F 4E 53 20 2F 20 48 54 54 50 2F 31 OPTIONS / HTTP/1
+[0010] 2E 30 0D 0A 0D 0A .0....
+[0000] 4F 50 54 49 4F 4E 53 20 2F 20 52 54 53 50 2F 31 OPTIONS / RTSP/1
+[0010] 2E 30 0D 0A 0D 0A .0....
+[0000] 80 00 00 28 72 FE 1D 13 00 00 00 00 00 00 00 02 ...(r... ........
+[0010] 00 01 86 A0 00 01 97 7C 00 00 00 00 00 00 00 00 .......| ........
+[0020] 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
+[0000] 00 1E 00 06 01 00 00 01 00 00 00 00 00 00 07 76 ........ .......v
+[0010] 65 72 73 69 6F 6E 04 62 69 6E 64 00 00 10 00 03 ersion.b ind.....
+[0000] 00 0C 00 00 10 00 00 00 00 00 00 00 00 00 ........ ......
+[0000] 45 48 4C 4F 0D 0A EHLO..
+[0000] 48 45 4C 50 0D 0A HELP..]]></screen>
+ </example>
+
+ <para>
+ At the beginning, Nmap would have sent its
+ NULL probe<indexterm><primary>NULL probe</primary></indexterm>,
+ which isn't shown in the log file because the NULL probe doesn't
+ send anything<!-- (see <xref linkend="vscan-technique"/>)-->. At the top of
+ the log is the GenericLines probe
+ (<computeroutput>0D&nbsp;0A&nbsp;0D&nbsp;0A</computeroutput>, or
+ <computeroutput>\r\n\r\n</computeroutput>). After that is our old
+ friend the HTTP GET<indexterm><primary>GET HTTP method</primary></indexterm>
+ request. Then come all the other probes in the
+ <filename>nmap-service-probes</filename><indexterm><primary><filename>nmap-service-probes</filename></primary></indexterm>
+ file. In this excerpt are shown probes designed to get a response
+ from RPC, DNS, and SMTP.
+ </para>
+
+ </sect2>
+</sect1>
+
+<sect1 id="ncat-simple-services">
+ <title>Emulating Diagnostic Services</title>
+
+ <para>
+ There are a number of simple Internet protocols intended for testing
+ and measurement purposes. Because they deal with simple, fundamental
+ network operations they are a good match for Ncat's capabilities. This
+ section shows how to to emulate services of increasing complexity:
+ discard, echo, daytime, qotd, and chargen. These particular commands assume you are on a UNIX system such as Linux or Mac OS X, and using a <filename>/bin/sh</filename> compatible shell, such as Bash.
+ </para>
+
+ <para>
+ The discard service,<indexterm><primary>discard service</primary></indexterm>
+ defined in
+ RFC&nbsp;863,<indexterm><primary>RFC 863</primary></indexterm> simply
+ ignores anything sent to it. It runs on TCP or UDP port&nbsp;9. By
+ default, Ncat doesn't send any information unless instructed to, so
+ nothing special is needed to emulate discard. Send Ncat's output to
+ <filename>/dev/null</filename><indexterm><primary><filename>/dev/null</filename></primary></indexterm>
+ to avoid filling the screen with characters received, or just let it
+ write to the terminal if you're curious to see what's there. Use the
+ <option>--recv-only</option><indexterm><primary><option>--recv-only</option> (Ncat)</primary></indexterm>
+ option to prohibit sending any characters that might be entered at the
+ terminal.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>TCP discard server</term>
+ <listitem>
+<indexterm><primary><option>--recv-only</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<indexterm><primary><option>--keep-open</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>ncat -l --keep-open 9 --recv-only > /dev/null</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>UDP discard server</term>
+ <listitem>
+<literallayout>
+<command>ncat --udp -l --keep-open 9 --recv-only > /dev/null</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Ncat in UDP mode uses all the same options as TCP. The caveat here is that
+ connections can't be closed, only timed out, so you will eventually run out
+ of sockets if you do not use a timeout. Currently, none of the timeout
+ options do the appropriate thing in this instance.
+ </para>
+
+ <para>
+ The echo service<indexterm><primary>echo service</primary></indexterm>
+ is defined in
+ RFC&nbsp;862.<indexterm><primary>RFC 862</primary></indexterm> It runs
+ on TCP or UDP port&nbsp;7. One step more advanced than discard, it
+ sends back any data received until the connection is closed. How do
+ you instruct Ncat to return what it receives? One easy way is to run
+ everything through <filename>/bin/cat</filename>.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>TCP echo server</term>
+ <listitem>
+<indexterm><primary><option>--exec</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>ncat -l 7 --keep-open --exec "/bin/cat"</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>UDP echo server</term>
+ <listitem>
+<indexterm><primary><option>--udp</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>ncat -l 7 --keep-open --udp --exec "/bin/cat"</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ The daytime service,<indexterm><primary>daytime service</primary></indexterm>
+ defined in
+ RFC&nbsp;867,<indexterm><primary>RFC 867</primary></indexterm>
+ sends a human-readable date and time string over TCP or UDP
+ port&nbsp;13. It ignores any input. The format of the date and time
+ string is left unspecified, so we are free to use the output of
+ <filename>/bin/date</filename>. Because we are not interested in
+ anything sent by the client we use the
+ <option>--send-only</option><indexterm><primary><option>--send-only</option> (Ncat option)</primary></indexterm>
+ option.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>TCP daytime server</term>
+ <listitem>
+<indexterm><primary><option>--send-only</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<indexterm><primary><option>--exec</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>ncat -l 13 --keep-open --send-only --exec "/bin/date"</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>UDP daytime server</term>
+ <listitem>
+<indexterm><primary><option>--udp</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>ncat -l 13 --keep-open --udp --send-only --exec "/bin/date"</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Nmap comes with a
+ <filename>daytime.nse</filename><indexterm><primary><filename>daytime.nse</filename> script</primary></indexterm>
+ script that works with the daytime service. Here is its output running
+ against Ncat daytime servers on TCP and UDP.
+ </para>
+
+ <example id="ncat-ex-daytime">
+ <title><filename>daytime.nse</filename> against an Ncat daytime server</title>
+ <indexterm><primary><option>--script</option></primary><secondary>example of</secondary></indexterm>
+<screen>
+# <userinput>nmap -sSU -p 13 --script=daytime localhost</userinput>
+Starting Nmap ( https://nmap.org )
+
+Nmap scan report for localhost (127.0.0.1)
+PORT STATE SERVICE
+13/tcp open daytime
+|_daytime: Mon Jan 19 17:43:18 MST 2009
+13/udp open daytime
+|_daytime: Mon Jan 19 17:43:18 MST 2009
+
+Nmap done: 1 IP address (1 host up) scanned in 0.31 seconds
+</screen>
+ </example>
+
+ <para>
+ The qotd<indexterm><primary>qotd service</primary></indexterm>
+ (quote of the day) service is defined in
+ RFC&nbsp;865.<indexterm><primary>RFC 865</primary></indexterm> When a
+ connection is made to TCP or UDP port 17, it sends back a short
+ message, ignoring any input. Ncat can do this by invoking a program
+ that generates messages. A traditional choice is
+ <filename>/usr/games/fortune</filename>, though there are many
+ possibilities. <filename>/usr/bin/uptime</filename>, for example,
+ could be useful.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>TCP qotd server</term>
+ <listitem>
+<indexterm><primary><option>--exec</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>ncat -l 17 --keep-open --send-only --exec "/usr/games/fortune"</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>UDP qotd server</term>
+ <listitem>
+<indexterm><primary><option>--udp</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<literallayout>
+<command>do ncat -l 17 --keep-open --udp --send-only --exec "/usr/games/fortune"</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ In this example it's instructive to consider the difference between
+ <command>ncat -l 17 --exec "/usr/games/fortune"</command> and
+ <command>/usr/games/fortune | ncat -l 17</command>. Think about why the
+ second command stops working after the first connection.
+ </para>
+
+ <para>
+ The chargen service<indexterm><primary>chargen service</primary></indexterm>
+ from
+ RFC&nbsp;864<indexterm><primary>RFC 864</primary></indexterm> rounds
+ out our tour of diagnostic services. It runs on TCP and UDP port 19.
+ With TCP, chargen ignores any input and sends a never-ending stream of
+ data. Never-ending, that is, until the connection is closed by the
+ user, who the RFC suggests may have <quote>had enough</quote>. There
+ are many ways of generating the characters; reading from
+ <filename>/dev/zero</filename><indexterm><primary><filename>/dev/zero</filename></primary></indexterm>
+ and running <command>yes</command> come to mind.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>TCP chargen server</term>
+ <listitem>
+<literallayout>
+<command>yes "chargenchargenchargen" | ncat -l --keep-open 19 --send-only</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Notice that in this case the program pipes its output into
+ <command>ncat</command> rather than being invoked with
+ <option>--exec</option>. For chargen either method would work,
+ because the output of <command>yes</command> never changes.
+ Using a pipe requires only one process other than
+ <command>ncat</command>, but all users connected simultaneously will
+ see the same output stream in synchrony. If the contents must be
+ independent for each stream, then use the <option>--exec</option>
+ method, with the understanding that a new process will be started for
+ each connection.
+ </para>
+
+ <para>
+ The UDP chargen protocol is a little different. When a datagram is
+ received, it sends back one datagram containing a random number of
+ characters. Implementing this is starting to get away from Ncat, but
+ one way it could be done with the
+ Bash shell<indexterm><primary>Bash shell</primary></indexterm>
+ is this:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>UDP chargen server</term>
+ <listitem>
+<indexterm><primary><option>--udp</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<indexterm><primary><option>--sh-exec</option> (Ncat option)</primary><secondary>example of</secondary></indexterm>
+<indexterm><primary><option>-c</option> (Ncat option)</primary><see><option>--sh-exec</option></see></indexterm>
+<literallayout>
+<command>ncat -l 19 --keep-open --udp --send-only --sh-exec \
+ "yes chargenchargenchargen | dd count=1 bs=$(($RANDOM % 512)) 2> /dev/null"</command>
+</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Notice the use of
+ <option>--sh-exec</option><indexterm><primary><option>--sh-exec</option> (Ncat option)</primary></indexterm>
+ rather than
+ <option>--exec</option><indexterm><primary><option>--exec</option> (Ncat option)</primary></indexterm>
+ to allow the use of the shell's environment variables and arithmetic
+ evaluation. Standard
+ error<indexterm><primary>standard error</primary><secondary>in Ncat subprocesses</secondary></indexterm>
+ is redirected to
+ <filename>/dev/null</filename><indexterm><primary><filename>/dev/null</filename></primary></indexterm>
+ to avoid including <command>dd</command>'s summary lines
+ (<computeroutput>1+0 records out</computeroutput>), which would
+ otherwise be included by Ncat.
+ </para>
+
+ <para>
+ This completes the tour of simple diagnostic services. These have been
+ easy to implement with Ncat because (with the exception of UDP
+ chargen) they all map directly onto a familiar command-line program.
+ As services become more complex it gets harder to do everything in the
+ shell. For complicated services it's better to write a separate
+ program and have Ncat exec it directly.
+ </para>
+
+</sect1>
+
+<indexterm class="endofrange" startref="ncat-indexterm"/>
diff --git a/ncat/docs/ncatguidehtml.xml b/ncat/docs/ncatguidehtml.xml
new file mode 100644
index 0000000..f761d0e
--- /dev/null
+++ b/ncat/docs/ncatguidehtml.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
+[
+<!ENTITY ncat SYSTEM "ncatguide.xml">
+]>
+
+<article id="ncat">
+<artheader>
+ <title>Ncat Users' Guide</title>
+</artheader>
+&ncat;
+</article>
diff --git a/ncat/docs/ncatmanhtml.xml b/ncat/docs/ncatmanhtml.xml
new file mode 100644
index 0000000..260b030
--- /dev/null
+++ b/ncat/docs/ncatmanhtml.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
+[
+<!ENTITY refguide SYSTEM "ncat.xml">
+]>
+<article id="ncatman">
+<artheader>
+<title>Ncat Reference Guide (Man Page)</title>
+</artheader>
+&refguide;
+</article>
diff --git a/ncat/http.c b/ncat/http.c
new file mode 100644
index 0000000..1a25988
--- /dev/null
+++ b/ncat/http.c
@@ -0,0 +1,1633 @@
+/***************************************************************************
+ * http.c -- HTTP network interaction, parsing, and construction. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include <string.h>
+
+#include "base64.h"
+#include "ncat.h"
+#include "http.h"
+
+/* Limit the size of in-memory data structures to avoid certain denial of
+ service attacks (those trying to consume all available memory). */
+static const int MAX_REQUEST_LINE_LENGTH = 1024;
+static const int MAX_STATUS_LINE_LENGTH = 1024;
+static const int MAX_HEADER_LENGTH = 1024 * 10;
+
+void socket_buffer_init(struct socket_buffer *buf, int sd)
+{
+ buf->fdn.fd = sd;
+#ifdef HAVE_OPENSSL
+ buf->fdn.ssl = NULL;
+#endif
+ buf->p = buf->buffer;
+ buf->end = buf->p;
+}
+
+/* Read from a stateful socket buffer. If there is any data in the buffer it is
+ returned, otherwise data is read with recv. Return value is as for recv. */
+int socket_buffer_read(struct socket_buffer *buf, char *out, size_t size)
+{
+ int i;
+
+ /* Refill the buffer if necessary. */
+ if (buf->p >= buf->end) {
+ buf->p = buf->buffer;
+ do {
+ errno = 0;
+ i = fdinfo_recv(&buf->fdn, buf->buffer, sizeof(buf->buffer));
+ } while (i == -1 && errno == EINTR);
+ if (i <= 0)
+ return i;
+ buf->end = buf->buffer + i;
+ }
+ i = buf->end - buf->p;
+ if (i > size)
+ i = size;
+ memcpy(out, buf->p, i);
+ buf->p += i;
+
+ return i;
+}
+
+/* Read a line thorough a stateful socket buffer. The line, including its '\n',
+ is returned in a dynamically allocated buffer. The length of the line is
+ returned in *n. If the length of the line exceeds maxlen, then NULL is
+ returned and *n is greater than or equal to maxlen. On error, NULL is
+ returned and *n is less than maxlen. The returned buffer is always
+ null-terminated if the return value is not NULL. */
+char *socket_buffer_readline(struct socket_buffer *buf, size_t *n, size_t maxlen)
+{
+ char *line;
+ char *newline;
+ size_t count;
+
+ line = NULL;
+ *n = 0;
+
+ do {
+ /* Refill the buffer if necessary. */
+ if (buf->p >= buf->end) {
+ int i;
+
+ buf->p = buf->buffer;
+ do {
+ errno = 0;
+ i = fdinfo_recv(&buf->fdn, buf->buffer, sizeof(buf->buffer));
+ } while (i == -1 && errno == EINTR);
+ if (i <= 0) {
+ free(line);
+ return NULL;
+ }
+ buf->end = buf->buffer + i;
+ }
+
+ newline = (char *) memchr(buf->p, '\n', buf->end - buf->p);
+ if (newline == NULL)
+ count = buf->end - buf->p;
+ else
+ count = newline + 1 - buf->p;
+
+ if (*n + count >= maxlen) {
+ /* Line exceeds our maximum length. */
+ free(line);
+ *n += count;
+ return NULL;
+ }
+
+ line = (char *) safe_realloc(line, *n + count + 1);
+ memcpy(line + *n, buf->p, count);
+ *n += count;
+ buf->p += count;
+ } while (newline == NULL);
+
+ line[*n] = '\0';
+
+ return line;
+}
+
+/* This is like socket_buffer_read, except that it blocks until it can read all
+ size bytes. If fewer than size bytes are available, it reads them and returns
+ -1. */
+int socket_buffer_readcount(struct socket_buffer *buf, char *out, size_t size)
+{
+ size_t n = 0;
+ int i;
+
+ while (n < size) {
+ /* Refill the buffer if necessary. */
+ if (buf->p >= buf->end) {
+ buf->p = buf->buffer;
+ do {
+ errno = 0;
+ i = fdinfo_recv(&buf->fdn, buf->buffer, sizeof(buf->buffer));
+ } while (i == -1 && errno == EINTR);
+ if (i <= 0)
+ return -1;
+ buf->end = buf->buffer + i;
+ }
+ i = buf->end - buf->p;
+ if (i < size - n) {
+ memcpy(out + n, buf->p, i);
+ buf->p += i;
+ n += i;
+ } else {
+ memcpy(out + n, buf->p, size - n);
+ buf->p += size - n;
+ n += size - n;
+ }
+ }
+
+ return n;
+}
+
+/* Get whatever is left in the buffer. */
+char *socket_buffer_remainder(struct socket_buffer *buf, size_t *len)
+{
+ if (len != NULL)
+ *len = buf->end - buf->p;
+
+ return buf->p;
+}
+
+/* The URI functions have a test program in test/test-uri.c. Run the test after
+ making any changes and add tests for any new functions. */
+
+void uri_init(struct uri *uri)
+{
+ uri->scheme = NULL;
+ uri->host = NULL;
+ uri->port = -1;
+ uri->path = NULL;
+}
+
+void uri_free(struct uri *uri)
+{
+ free(uri->scheme);
+ free(uri->host);
+ free(uri->path);
+}
+
+static int hex_digit_value(char digit)
+{
+ const char *DIGITS = "0123456789abcdef";
+ const char *p;
+
+ if ((unsigned char) digit == '\0')
+ return -1;
+ p = strchr(DIGITS, tolower((int) (unsigned char) digit));
+ if (p == NULL)
+ return -1;
+
+ return p - DIGITS;
+}
+
+/* Case-insensitive string comparison. */
+static int str_cmp_i(const char *a, const char *b)
+{
+ while (*a != '\0' && *b != '\0') {
+ int ca, cb;
+
+ ca = tolower((int) (unsigned char) *a);
+ cb = tolower((int) (unsigned char) *b);
+ if (ca != cb)
+ return ca - cb;
+ a++;
+ b++;
+ }
+
+ if (*a == '\0' && *b == '\0')
+ return 0;
+ else if (*a == '\0')
+ return -1;
+ else
+ return 1;
+}
+
+static int str_equal_i(const char *a, const char *b)
+{
+ return str_cmp_i(a, b) == 0;
+}
+
+static int lowercase(char *s)
+{
+ char *p;
+
+ for (p = s; *p != '\0'; p++)
+ *p = tolower((int) (unsigned char) *p);
+
+ return p - s;
+}
+
+/* In-place percent decoding. */
+static int percent_decode(char *s)
+{
+ char *p, *q;
+
+ /* Skip to the first '%'. If there are no percent escapes, this lets us
+ return without doing any copying. */
+ q = s;
+ while (*q != '\0' && *q != '%')
+ q++;
+
+ p = q;
+ while (*q != '\0') {
+ if (*q == '%') {
+ int c, d;
+
+ q++;
+ c = hex_digit_value(*q);
+ if (c == -1)
+ return -1;
+ q++;
+ d = hex_digit_value(*q);
+ if (d == -1)
+ return -1;
+
+ *p++ = c * 16 + d;
+ q++;
+ } else {
+ *p++ = *q++;
+ }
+ }
+ *p = '\0';
+
+ return p - s;
+}
+
+/* Use these functions because isalpha and isdigit can change their meaning
+ based on the locale. */
+static int is_alpha_char(int c)
+{
+ return c != '\0' && strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", c) != NULL;
+}
+
+static int is_digit_char(int c)
+{
+ return c != '\0' && strchr("0123456789", c) != NULL;
+}
+
+/* Get the default port for the given URI scheme, or -1 if unrecognized. */
+static int scheme_default_port(const char *scheme)
+{
+ if (str_equal_i(scheme, "http"))
+ return 80;
+
+ return -1;
+}
+
+/* Parse a URI string into a struct URI. Any parts of the URI that are absent
+ will become NULL entries in the structure, except for the port which will be
+ -1. Returns NULL on error. See RFC 3986, section 3 for syntax. */
+struct uri *uri_parse(struct uri *uri, const char *uri_s)
+{
+ const char *p, *q;
+
+ uri_init(uri);
+
+ /* Scheme, section 3.1. */
+ p = uri_s;
+ if (!is_alpha_char(*p))
+ goto fail;
+ for (q = p; is_alpha_char(*q) || is_digit_char(*q) || *q == '+' || *q == '-' || *q == '.'; q++)
+ ;
+ if (*q != ':')
+ goto fail;
+ uri->scheme = mkstr(p, q);
+ /* "An implementation should accept uppercase letters as equivalent to
+ lowercase in scheme names (e.g., allow "HTTP" as well as "http") for the
+ sake of robustness..." */
+ lowercase(uri->scheme);
+
+ /* Authority, section 3.2. */
+ p = q + 1;
+ if (*p == '/' && *(p + 1) == '/') {
+ char *authority = NULL;
+
+ p += 2;
+ for (q = p; !(*q == '/' || *q == '?' || *q == '#' || *q == '\0'); q++)
+ ;
+ authority = mkstr(p, q);
+ if (uri_parse_authority(uri, authority) == NULL) {
+ free(authority);
+ goto fail;
+ }
+ free(authority);
+
+ p = q;
+ }
+ if (uri->port == -1)
+ uri->port = scheme_default_port(uri->scheme);
+
+ /* Path, section 3.3. We include the query and fragment in the path. The
+ path is also not percent-decoded because we just pass it on to the origin
+ server. */
+ q = strchr(p, '\0');
+ uri->path = mkstr(p, q);
+
+ return uri;
+
+fail:
+ uri_free(uri);
+ return NULL;
+}
+
+/* Parse the authority part of a URI. userinfo (user name and password) are not
+ supported and will cause an error if present. See RFC 3986, section 3.2.
+ Returns NULL on error. */
+struct uri *uri_parse_authority(struct uri *uri, const char *authority)
+{
+ const char *portsep;
+ const char *host_start, *host_end;
+ const char *tail;
+
+ /* We do not support "user:pass@" userinfo. The proxy has no use for it. */
+ if (strchr(authority, '@') != NULL)
+ return NULL;
+
+ /* Find the beginning and end of the host. */
+ host_start = authority;
+ if (*host_start == '[') {
+ /* IPv6 address in brackets. */
+ host_start++;
+ host_end = strchr(host_start, ']');
+ if (host_end == NULL)
+ return NULL;
+ portsep = host_end + 1;
+ if (!(*portsep == ':' || *portsep == '\0'))
+ return NULL;
+ } else {
+ portsep = strrchr(authority, ':');
+ if (portsep == NULL)
+ portsep = strchr(authority, '\0');
+ host_end = portsep;
+ }
+
+ /* Get the port number. */
+ if (*portsep == ':' && *(portsep + 1) != '\0') {
+ long n;
+
+ errno = 0;
+ n = parse_long(portsep + 1, &tail);
+ if (errno != 0 || *tail != '\0' || tail == portsep + 1 || n < 1 || n > 65535)
+ return NULL;
+ uri->port = n;
+ } else {
+ uri->port = -1;
+ }
+
+ /* Get the host. */
+ uri->host = mkstr(host_start, host_end);
+ if (percent_decode(uri->host) < 0) {
+ free(uri->host);
+ uri->host = NULL;
+ return NULL;
+ }
+
+ return uri;
+}
+
+static void http_header_node_free(struct http_header *node)
+{
+ free(node->name);
+ free(node->value);
+ free(node);
+}
+
+void http_header_free(struct http_header *header)
+{
+ struct http_header *p, *next;
+
+ for (p = header; p != NULL; p = next) {
+ next = p->next;
+ http_header_node_free(p);
+ }
+}
+
+/* RFC 2616, section 2.2; see LWS. */
+static int is_space_char(int c)
+{
+ return c == ' ' || c == '\t';
+}
+
+/* RFC 2616, section 2.2. */
+static int is_ctl_char(int c)
+{
+ return (c >= 0 && c <= 31) || c == 127;
+}
+
+/* RFC 2616, section 2.2. */
+static int is_sep_char(int c)
+{
+ return c != '\0' && strchr("()<>@,;:\\\"/[]?={} \t", c) != NULL;
+}
+
+/* RFC 2616, section 2.2. */
+static int is_token_char(char c)
+{
+ return !iscntrl((int) (unsigned char) c) && !is_sep_char((int) (unsigned char) c);
+}
+
+static int is_crlf(const char *s)
+{
+ return *s == '\n' || (*s == '\r' && *(s + 1) == '\n');
+}
+
+static const char *skip_crlf(const char *s)
+{
+ if (*s == '\n')
+ return s + 1;
+ else if (*s == '\r' && *(s + 1) == '\n')
+ return s + 2;
+
+ ncat_assert(0);
+ return NULL;
+}
+
+static int field_name_equal(const char *a, const char *b)
+{
+ return str_equal_i(a, b);
+}
+
+/* Get the value of every header with the given name, separated by commas. If
+ you only want the first value for header fields that should not be
+ concatenated in this way, use http_header_get_first. The returned string
+ must be freed. */
+char *http_header_get(const struct http_header *header, const char *name)
+{
+ const struct http_header *p;
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+ int count;
+
+ count = 0;
+ for (p = header; p != NULL; p = p->next) {
+ /* RFC 2616, section 4.2: "Multiple message-header fields with the same
+ field-name MAY be present in a message if and only if the entire
+ field-value for that header field is defined as a comma-separated
+ list [i.e., #(values)]. It MUST be possible to combine the multiple
+ header fields into one "field-name: field-value" pair, without
+ changing the semantics of the message, by appending each subsequent
+ field-value to the first, each separated by a comma." */
+ if (field_name_equal(p->name, name)) {
+ if (count > 0)
+ strbuf_append_str(&buf, &size, &offset, ", ");
+ strbuf_append_str(&buf, &size, &offset, p->value);
+ count++;
+ }
+ }
+
+ return buf;
+}
+
+const struct http_header *http_header_next(const struct http_header *header,
+ const struct http_header *p, const char *name)
+{
+ if (p == NULL)
+ p = header;
+ else
+ p = p->next;
+
+ for (; p != NULL; p = p->next) {
+ if (field_name_equal(p->name, name))
+ return p;
+ }
+
+ return NULL;
+}
+
+/* Get the value of the first header with the given name. The returned string
+ must be freed. */
+char *http_header_get_first(const struct http_header *header, const char *name)
+{
+ const struct http_header *p;
+
+ p = http_header_next(header, NULL, name);
+ if (p != NULL)
+ return Strdup(p->value);
+
+ return NULL;
+}
+
+struct http_header *http_header_set(struct http_header *header, const char *name, const char *value)
+{
+ struct http_header *node, **prev;
+
+ header = http_header_remove(header, name);
+
+ node = (struct http_header *) safe_malloc(sizeof(*node));
+ node->name = Strdup(name);
+ node->value = Strdup(value);
+ node->next = NULL;
+
+ /* Link it to the end of the list. */
+ for (prev = &header; *prev != NULL; prev = &(*prev)->next)
+ ;
+ *prev = node;
+
+ return header;
+}
+
+/* Read a token from a space-separated string. This only recognizes space as a
+ separator, so the string must already have had LWS normalized.
+ http_header_parse does this normalization. */
+static const char *read_token(const char *s, char **token)
+{
+ const char *t;
+
+ while (*s == ' ')
+ s++;
+ t = s;
+ while (is_token_char(*t))
+ t++;
+ if (s == t)
+ return NULL;
+
+ *token = mkstr(s, t);
+
+ return t;
+}
+
+static const char *read_quoted_string(const char *s, char **quoted_string)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+ const char *t;
+
+ while (is_space_char(*s))
+ s++;
+ if (*s != '"')
+ return NULL;
+ s++;
+ t = s;
+ while (*s != '"') {
+ /* Get a block of normal characters. */
+ while (*t != '"' && *t != '\\') {
+ /* This is qdtext, which is TEXT except for CTL. */
+ if (is_ctl_char(*t)) {
+ free(buf);
+ return NULL;
+ }
+ t++;
+ }
+ strbuf_append(&buf, &size, &offset, s, t - s);
+ /* Now possibly handle an escape. */
+ if (*t == '\\') {
+ t++;
+ /* You can only escape a CHAR, octets 0-127. But we disallow 0. */
+ if (*t <= 0) {
+ free(buf);
+ return NULL;
+ }
+ strbuf_append(&buf, &size, &offset, t, 1);
+ t++;
+ }
+ s = t;
+ }
+ s++;
+
+ *quoted_string = buf;
+ return s;
+}
+
+static const char *read_token_or_quoted_string(const char *s, char **token)
+{
+ while (is_space_char(*s))
+ s++;
+ if (*s == '"')
+ return read_quoted_string(s, token);
+ else
+ return read_token(s, token);
+}
+
+static const char *read_token_list(const char *s, char **tokens[], size_t *n)
+{
+ char *token;
+
+ *tokens = NULL;
+ *n = 0;
+
+ for (;;) {
+ s = read_token(s, &token);
+ if (s == NULL) {
+ int i;
+
+ for (i = 0; i < *n; i++)
+ free((*tokens)[i]);
+ free(*tokens);
+
+ return NULL;
+ }
+
+ *tokens = (char **) safe_realloc(*tokens, (*n + 1) * sizeof((*tokens)[0]));
+ (*tokens)[(*n)++] = token;
+ if (*s != ',')
+ break;
+ s++;
+ }
+
+ return s;
+}
+
+struct http_header *http_header_remove(struct http_header *header, const char *name)
+{
+ struct http_header *p, *next, **prev;
+
+ prev = &header;
+ for (p = header; p != NULL; p = next) {
+ next = p->next;
+ if (field_name_equal(p->name, name)) {
+ *prev = next;
+ http_header_node_free(p);
+ continue;
+ }
+ prev = &p->next;
+ }
+
+ return header;
+}
+
+/* Removes hop-by-hop headers listed in section 13.5.1 of RFC 2616, and
+ additionally removes any headers listed in the Connection header as described
+ in section 14.10. */
+int http_header_remove_hop_by_hop(struct http_header **header)
+{
+ static const char *HOP_BY_HOP_HEADERS[] = {
+ "Connection",
+ "Keep-Alive",
+ "Proxy-Authenticate",
+ "Proxy-Authorization",
+ "TE",
+ "Trailers",
+ "Transfer-Encoding",
+ "Upgrade",
+ };
+ char *connection;
+ char **connection_tokens;
+ size_t num_connection_tokens;
+ unsigned int i;
+
+ connection = http_header_get(*header, "Connection");
+ if (connection != NULL) {
+ const char *p;
+
+ p = read_token_list(connection, &connection_tokens, &num_connection_tokens);
+ if (p == NULL) {
+ free(connection);
+ return 400;
+ }
+ if (*p != '\0') {
+ free(connection);
+ for (i = 0; i < num_connection_tokens; i++)
+ free(connection_tokens[i]);
+ free(connection_tokens);
+ return 400;
+ }
+ free(connection);
+ } else {
+ connection_tokens = NULL;
+ num_connection_tokens = 0;
+ }
+
+ for (i = 0; i < sizeof(HOP_BY_HOP_HEADERS) / sizeof(HOP_BY_HOP_HEADERS[0]); i++)
+ *header = http_header_remove(*header, HOP_BY_HOP_HEADERS[i]);
+ for (i = 0; i < num_connection_tokens; i++)
+ *header = http_header_remove(*header, connection_tokens[i]);
+
+ for (i = 0; i < num_connection_tokens; i++)
+ free(connection_tokens[i]);
+ free(connection_tokens);
+
+ return 0;
+}
+
+char *http_header_to_string(const struct http_header *header, size_t *n)
+{
+ const struct http_header *p;
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+
+ strbuf_append_str(&buf, &size, &offset, "");
+
+ for (p = header; p != NULL; p = p->next)
+ strbuf_sprintf(&buf, &size, &offset, "%s: %s\r\n", p->name, p->value);
+
+ if (n != NULL)
+ *n = offset;
+
+ return buf;
+}
+
+void http_request_init(struct http_request *request)
+{
+ request->method = NULL;
+ uri_init(&request->uri);
+ request->version = HTTP_UNKNOWN;
+ request->header = NULL;
+ request->content_length_set = 0;
+ request->content_length = 0;
+ request->bytes_transferred = 0;
+}
+
+void http_request_free(struct http_request *request)
+{
+ free(request->method);
+ uri_free(&request->uri);
+ http_header_free(request->header);
+}
+
+char *http_request_to_string(const struct http_request *request, size_t *n)
+{
+ const char *path;
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+
+ /* RFC 2616, section 5.1.2: "the absolute path cannot be empty; if none is
+ present in the original URI, it MUST be given as "/" (the server
+ root)." */
+ path = request->uri.path;
+ if (path[0] == '\0')
+ path = "/";
+
+ if (request->version == HTTP_09) {
+ /* HTTP/0.9 doesn't have headers. See
+ http://www.w3.org/Protocols/HTTP/AsImplemented.html. */
+ strbuf_sprintf(&buf, &size, &offset, "%s %s\r\n", request->method, path);
+ } else {
+ const char *version;
+ char *header_str;
+
+ if (request->version == HTTP_10)
+ version = " HTTP/1.0";
+ else
+ version = " HTTP/1.1";
+
+ header_str = http_header_to_string(request->header, NULL);
+ strbuf_sprintf(&buf, &size, &offset, "%s %s%s\r\n%s\r\n",
+ request->method, path, version, header_str);
+ free(header_str);
+ }
+
+ if (n != NULL)
+ *n = offset;
+
+ return buf;
+}
+
+void http_response_init(struct http_response *response)
+{
+ response->version = HTTP_UNKNOWN;
+ response->code = 0;
+ response->phrase = NULL;
+ response->header = NULL;
+ response->content_length_set = 0;
+ response->content_length = 0;
+ response->bytes_transferred = 0;
+}
+
+void http_response_free(struct http_response *response)
+{
+ free(response->phrase);
+ http_header_free(response->header);
+}
+
+char *http_response_to_string(const struct http_response *response, size_t *n)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+
+ if (response->version == HTTP_09) {
+ /* HTTP/0.9 doesn't have a Status-Line or headers. See
+ http://www.w3.org/Protocols/HTTP/AsImplemented.html. */
+ return Strdup("");
+ } else {
+ const char *version;
+ char *header_str;
+
+ if (response->version == HTTP_10)
+ version = "HTTP/1.0";
+ else
+ version = "HTTP/1.1";
+
+ header_str = http_header_to_string(response->header, NULL);
+ strbuf_sprintf(&buf, &size, &offset, "%s %d %s\r\n%s\r\n",
+ version, response->code, response->phrase, header_str);
+ free(header_str);
+ }
+
+ if (n != NULL)
+ *n = offset;
+
+ return buf;
+}
+
+int http_read_header(struct socket_buffer *buf, char **result)
+{
+ char *line = NULL;
+ char *header;
+ size_t n = 0;
+ size_t count;
+ int blank;
+
+ header = NULL;
+
+ do {
+ line = socket_buffer_readline(buf, &count, MAX_HEADER_LENGTH);
+ if (line == NULL) {
+ free(header);
+ if (count >= MAX_HEADER_LENGTH)
+ /* Request Entity Too Large. */
+ return 413;
+ else
+ return 400;
+ }
+ blank = is_crlf(line);
+
+ if (n + count >= MAX_HEADER_LENGTH) {
+ free(line);
+ free(header);
+ /* Request Entity Too Large. */
+ return 413;
+ }
+
+ header = (char *) safe_realloc(header, n + count + 1);
+ memcpy(header + n, line, count);
+ n += count;
+ free(line);
+ } while (!blank);
+ header[n] = '\0';
+
+ *result = header;
+
+ return 0;
+}
+
+static const char *skip_lws(const char *s)
+{
+ for (;;) {
+ while (is_space_char(*s))
+ s++;
+
+ if (*s == '\n' && is_space_char(*(s + 1)))
+ s += 1;
+ else if (*s == '\r' && *(s + 1) == '\n' && is_space_char(*(s + 2)))
+ s += 2;
+ else
+ break;
+ }
+
+ return s;
+}
+
+/* See section 4.2 of RFC 2616 for header format. */
+int http_parse_header(struct http_header **result, const char *header)
+{
+ const char *p, *q;
+ size_t value_len, value_offset;
+ struct http_header *node, **prev;
+
+ *result = NULL;
+ prev = result;
+
+ p = header;
+ while (*p != '\0' && !is_crlf(p)) {
+ /* Get the field name. */
+ q = p;
+ while (*q != '\0' && is_token_char(*q))
+ q++;
+ if (*q != ':') {
+ http_header_free(*result);
+ return 400;
+ }
+
+ node = (struct http_header *) safe_malloc(sizeof(*node));
+ node->name = mkstr(p, q);
+ node->value = NULL;
+ node->next = NULL;
+ value_len = 0;
+ value_offset = 0;
+
+ /* Copy the header field value until we hit a CRLF. */
+ p = q + 1;
+ p = skip_lws(p);
+ for (;;) {
+ q = p;
+ while (*q != '\0' && !is_space_char(*q) && !is_crlf(q)) {
+ /* Section 2.2 of RFC 2616 disallows control characters. */
+ if (iscntrl((int) (unsigned char) *q)) {
+ http_header_node_free(node);
+ return 400;
+ }
+ q++;
+ }
+ strbuf_append(&node->value, &value_len, &value_offset, p, q - p);
+ p = skip_lws(q);
+ if (is_crlf(p))
+ break;
+ /* Replace LWS with a single space. */
+ strbuf_append_str(&node->value, &value_len, &value_offset, " ");
+ }
+ *prev = node;
+ prev = &node->next;
+
+ p = skip_crlf(p);
+ }
+
+ return 0;
+}
+
+static int http_header_get_content_length(const struct http_header *header, int *content_length_set, unsigned long *content_length)
+{
+ char *content_length_s;
+ const char *tail;
+ int code;
+
+ content_length_s = http_header_get_first(header, "Content-Length");
+ if (content_length_s == NULL) {
+ *content_length_set = 0;
+ *content_length = 0;
+ return 0;
+ }
+
+ code = 0;
+
+ errno = 0;
+ *content_length_set = 1;
+ *content_length = parse_long(content_length_s, &tail);
+ if (errno != 0 || *tail != '\0' || tail == content_length_s)
+ code = 400;
+ free(content_length_s);
+
+ return code;
+}
+
+/* Parse a header and fill in any relevant fields in the request structure. */
+int http_request_parse_header(struct http_request *request, const char *header)
+{
+ int code;
+
+ code = http_parse_header(&request->header, header);
+ if (code != 0)
+ return code;
+ code = http_header_get_content_length(request->header, &request->content_length_set, &request->content_length);
+ if (code != 0)
+ return code;
+
+ return 0;
+}
+
+/* Parse a header and fill in any relevant fields in the response structure. */
+int http_response_parse_header(struct http_response *response, const char *header)
+{
+ int code;
+
+ code = http_parse_header(&response->header, header);
+ if (code != 0)
+ return code;
+ code = http_header_get_content_length(response->header, &response->content_length_set, &response->content_length);
+ if (code != 0)
+ return code;
+
+ return 0;
+}
+
+int http_read_request_line(struct socket_buffer *buf, char **line)
+{
+ size_t n;
+
+ *line = NULL;
+
+ /* Section 4.1 of RFC 2616 says "servers SHOULD ignore any empty line(s)
+ received where a Request-Line is expected." */
+ do {
+ free(*line);
+ *line = socket_buffer_readline(buf, &n, MAX_REQUEST_LINE_LENGTH);
+ if (*line == NULL) {
+ if (n >= MAX_REQUEST_LINE_LENGTH)
+ /* Request Entity Too Large. */
+ return 413;
+ else
+ return 400;
+ }
+ } while (is_crlf(*line));
+
+ return 0;
+}
+
+/* Returns the character pointer after the HTTP version, or s if there was a
+ parse error. */
+static const char *parse_http_version(const char *s, enum http_version *version)
+{
+ const char *PREFIX = "HTTP/";
+ const char *p, *q;
+ long major, minor;
+
+ *version = HTTP_UNKNOWN;
+
+ p = s;
+ if (memcmp(p, PREFIX, strlen(PREFIX)) != 0)
+ return s;
+ p += strlen(PREFIX);
+
+ /* Major version. */
+ errno = 0;
+ major = parse_long(p, &q);
+ if (errno != 0 || q == p)
+ return s;
+
+ p = q;
+ if (*p != '.')
+ return s;
+ p++;
+
+ /* Minor version. */
+ errno = 0;
+ minor = parse_long(p, &q);
+ if (errno != 0 || q == p)
+ return s;
+
+ if (major == 1 && minor == 0)
+ *version = HTTP_10;
+ else if (major == 1 && minor == 1)
+ *version = HTTP_11;
+
+ return q;
+}
+
+int http_parse_request_line(const char *line, struct http_request *request)
+{
+ const char *p, *q;
+ struct uri *uri;
+ char *uri_s;
+
+ http_request_init(request);
+
+ p = line;
+ while (*p == ' ')
+ p++;
+
+ /* Method (CONNECT, GET, etc.). */
+ q = p;
+ while (is_token_char(*q))
+ q++;
+ if (p == q)
+ goto badreq;
+ request->method = mkstr(p, q);
+
+ /* URI. */
+ p = q;
+ while (*p == ' ')
+ p++;
+ q = p;
+ while (*q != '\0' && *q != ' ')
+ q++;
+ if (p == q)
+ goto badreq;
+ uri_s = mkstr(p, q);
+
+ /* RFC 2616, section 5.1.1: The method is case-sensitive.
+ RFC 2616, section 5.1.2:
+ Request-URI = "*" | absoluteURI | abs_path | authority
+ The absoluteURI form is REQUIRED when the request is being made to a
+ proxy... The authority form is only used by the CONNECT method. */
+ if (strcmp(request->method, "CONNECT") == 0) {
+ uri = uri_parse_authority(&request->uri, uri_s);
+ } else {
+ uri = uri_parse(&request->uri, uri_s);
+ }
+ free(uri_s);
+ if (uri == NULL)
+ /* The URI parsing failed. */
+ goto badreq;
+
+ /* Version number. */
+ p = q;
+ while (*p == ' ')
+ p++;
+ if (*p == '\0') {
+ /* No HTTP/X.X version number indicates version 0.9. */
+ request->version = HTTP_09;
+ } else {
+ q = parse_http_version(p, &request->version);
+ if (p == q)
+ goto badreq;
+ }
+
+ return 0;
+
+badreq:
+ http_request_free(request);
+ return 400;
+}
+
+int http_read_status_line(struct socket_buffer *buf, char **line)
+{
+ size_t n;
+
+ /* RFC 2616, section 6.1: "The first line of a Response message is the
+ Status-Line... No CR or LF is allowed except in the final CRLF sequence."
+ Contrast that with Request-Line, which allows leading blank lines. */
+ *line = socket_buffer_readline(buf, &n, MAX_STATUS_LINE_LENGTH);
+ if (*line == NULL) {
+ if (n >= MAX_STATUS_LINE_LENGTH)
+ /* Request Entity Too Large. */
+ return 413;
+ else
+ return 400;
+ }
+
+ return 0;
+}
+
+/* Returns 0 on success and nonzero on failure. */
+int http_parse_status_line(const char *line, struct http_response *response)
+{
+ const char *p, *q;
+
+ http_response_init(response);
+
+ /* Version. */
+ p = parse_http_version(line, &response->version);
+ if (p == line)
+ return -1;
+ while (*p == ' ')
+ p++;
+
+ /* Status code. */
+ errno = 0;
+ response->code = parse_long(p, &q);
+ if (errno != 0 || q == p)
+ return -1;
+ p = q;
+
+ /* Reason phrase. */
+ while (*p == ' ')
+ p++;
+ q = p;
+ while (!is_crlf(q))
+ q++;
+ /* We expect that the CRLF ends the string. */
+ if (*skip_crlf(q) != '\0')
+ return -1;
+ response->phrase = mkstr(p, q);
+
+ return 0;
+}
+
+/* This is a convenience wrapper around http_parse_status_line that only returns
+ the status code. Returns the status code on success or -1 on failure. */
+int http_parse_status_line_code(const char *line)
+{
+ struct http_response resp;
+ int code;
+
+ if (http_parse_status_line(line, &resp) != 0)
+ return -1;
+ code = resp.code;
+ http_response_free(&resp);
+
+ return code;
+}
+
+static const char *http_read_challenge(const char *s, struct http_challenge *challenge)
+{
+ const char *p;
+ char *scheme;
+
+ http_challenge_init(challenge);
+
+ scheme = NULL;
+ s = read_token(s, &scheme);
+ if (s == NULL)
+ goto bail;
+ if (str_equal_i(scheme, "Basic")) {
+ challenge->scheme = AUTH_BASIC;
+ } else if (str_equal_i(scheme, "Digest")) {
+ challenge->scheme = AUTH_DIGEST;
+ } else {
+ challenge->scheme = AUTH_UNKNOWN;
+ }
+ free(scheme);
+ scheme = NULL;
+
+ /* RFC 2617, section 1.2, requires at least one auth-param:
+ challenge = auth-scheme 1*SP 1#auth-param
+ But there are some schemes (NTLM and Negotiate) that can be without
+ auth-params, so we allow that here. A comma indicates the end of this
+ challenge and the beginning of the next (see the comment in the loop
+ below). */
+ while (is_space_char(*s))
+ s++;
+ if (*s == ',') {
+ s++;
+ while (is_space_char(*s))
+ s++;
+ if (*s == '\0')
+ goto bail;
+ return s;
+ }
+
+ while (*s != '\0') {
+ char *name, *value;
+
+ p = read_token(s, &name);
+ if (p == NULL)
+ goto bail;
+ while (is_space_char(*p))
+ p++;
+ /* It's possible that we've hit the end of one challenge and the
+ beginning of another. Section 14.33 says that the header value can be
+ 1#challenge, in other words several challenges separated by commas.
+ Because the auth-params are also separated by commas, the only way we
+ can tell is if we find a token not followed by an equals sign. */
+ if (*p != '=')
+ break;
+ p++;
+ while (is_space_char(*p))
+ p++;
+ p = read_token_or_quoted_string(p, &value);
+ if (p == NULL) {
+ free(name);
+ goto bail;
+ }
+ if (str_equal_i(name, "realm"))
+ challenge->realm = Strdup(value);
+ else if (challenge->scheme == AUTH_DIGEST) {
+ if (str_equal_i(name, "nonce")) {
+ if (challenge->digest.nonce != NULL)
+ goto bail;
+ challenge->digest.nonce = Strdup(value);
+ } else if (str_equal_i(name, "opaque")) {
+ if (challenge->digest.opaque != NULL)
+ goto bail;
+ challenge->digest.opaque = Strdup(value);
+ } else if (str_equal_i(name, "algorithm")) {
+ if (str_equal_i(value, "MD5"))
+ challenge->digest.algorithm = ALGORITHM_MD5;
+ else
+ challenge->digest.algorithm = ALGORITHM_UNKNOWN;
+ } else if (str_equal_i(name, "qop")) {
+ char **tokens;
+ size_t n;
+ int i;
+ const char *tmp;
+
+ tmp = read_token_list(value, &tokens, &n);
+ if (tmp == NULL) {
+ free(name);
+ free(value);
+ goto bail;
+ }
+ for (i = 0; i < n; i++) {
+ if (str_equal_i(tokens[i], "auth"))
+ challenge->digest.qop |= QOP_AUTH;
+ else if (str_equal_i(tokens[i], "auth-int"))
+ challenge->digest.qop |= QOP_AUTH_INT;
+ }
+ for (i = 0; i < n; i++)
+ free(tokens[i]);
+ free(tokens);
+ if (*tmp != '\0') {
+ free(name);
+ free(value);
+ goto bail;
+ }
+ }
+ }
+ free(name);
+ free(value);
+ while (is_space_char(*p))
+ p++;
+ if (*p == ',') {
+ p++;
+ while (is_space_char(*p))
+ p++;
+ if (*p == '\0')
+ goto bail;
+ }
+ s = p;
+ }
+
+ return s;
+
+bail:
+ if (scheme != NULL)
+ free(scheme);
+ http_challenge_free(challenge);
+
+ return NULL;
+}
+
+static const char *http_read_credentials(const char *s,
+ struct http_credentials *credentials)
+{
+ const char *p;
+ char *scheme;
+
+ credentials->scheme = AUTH_UNKNOWN;
+
+ s = read_token(s, &scheme);
+ if (s == NULL)
+ return NULL;
+ if (str_equal_i(scheme, "Basic")) {
+ http_credentials_init_basic(credentials);
+ } else if (str_equal_i(scheme, "Digest")) {
+ http_credentials_init_digest(credentials);
+ } else {
+ free(scheme);
+ return NULL;
+ }
+ free(scheme);
+
+ while (is_space_char(*s))
+ s++;
+ if (credentials->scheme == AUTH_BASIC) {
+ p = s;
+ /* Read base64. */
+ while (is_alpha_char(*p) || is_digit_char(*p) || *p == '+' || *p == '/' || *p == '=')
+ p++;
+ credentials->u.basic = mkstr(s, p);
+ while (is_space_char(*p))
+ p++;
+ s = p;
+ } else if (credentials->scheme == AUTH_DIGEST) {
+ char *name, *value;
+
+ while (*s != '\0') {
+ p = read_token(s, &name);
+ if (p == NULL)
+ goto bail;
+ while (is_space_char(*p))
+ p++;
+ /* It's not legal to combine multiple Authorization or
+ Proxy-Authorization values. The productions are
+ "Authorization" ":" credentials (section 14.8)
+ "Proxy-Authorization" ":" credentials (section 14.34)
+ Contrast this with WWW-Authenticate and Proxy-Authenticate and
+ their handling in http_read_challenge. */
+ if (*p != '=')
+ goto bail;
+ p++;
+ while (is_space_char(*p))
+ p++;
+ p = read_token_or_quoted_string(p, &value);
+ if (p == NULL) {
+ free(name);
+ goto bail;
+ }
+ if (str_equal_i(name, "username")) {
+ if (credentials->u.digest.username != NULL)
+ goto bail;
+ credentials->u.digest.username = Strdup(value);
+ } else if (str_equal_i(name, "realm")) {
+ if (credentials->u.digest.realm != NULL)
+ goto bail;
+ credentials->u.digest.realm = Strdup(value);
+ } else if (str_equal_i(name, "nonce")) {
+ if (credentials->u.digest.nonce != NULL)
+ goto bail;
+ credentials->u.digest.nonce = Strdup(value);
+ } else if (str_equal_i(name, "uri")) {
+ if (credentials->u.digest.uri != NULL)
+ goto bail;
+ credentials->u.digest.uri = Strdup(value);
+ } else if (str_equal_i(name, "response")) {
+ if (credentials->u.digest.response != NULL)
+ goto bail;
+ credentials->u.digest.response = Strdup(value);
+ } else if (str_equal_i(name, "algorithm")) {
+ if (str_equal_i(value, "MD5"))
+ credentials->u.digest.algorithm = ALGORITHM_MD5;
+ else
+ credentials->u.digest.algorithm = ALGORITHM_UNKNOWN;
+ } else if (str_equal_i(name, "qop")) {
+ if (str_equal_i(value, "auth"))
+ credentials->u.digest.qop = QOP_AUTH;
+ else if (str_equal_i(value, "auth-int"))
+ credentials->u.digest.qop = QOP_AUTH_INT;
+ else
+ credentials->u.digest.qop = QOP_NONE;
+ } else if (str_equal_i(name, "cnonce")) {
+ if (credentials->u.digest.cnonce != NULL)
+ goto bail;
+ credentials->u.digest.cnonce = Strdup(value);
+ } else if (str_equal_i(name, "nc")) {
+ if (credentials->u.digest.nc != NULL)
+ goto bail;
+ credentials->u.digest.nc = Strdup(value);
+ }
+ free(name);
+ free(value);
+ while (is_space_char(*p))
+ p++;
+ if (*p == ',') {
+ p++;
+ while (is_space_char(*p))
+ p++;
+ if (*p == '\0')
+ goto bail;
+ }
+ s = p;
+ }
+ }
+
+ return s;
+
+bail:
+ http_credentials_free(credentials);
+
+ return NULL;
+}
+
+/* Is scheme a preferred over scheme b? We prefer Digest to Basic when Digest is
+ supported. */
+static int auth_scheme_is_better(enum http_auth_scheme a,
+ enum http_auth_scheme b)
+{
+#if HAVE_HTTP_DIGEST
+ if (b == AUTH_DIGEST)
+ return 0;
+ if (b == AUTH_BASIC)
+ return a == AUTH_DIGEST;
+ if (b == AUTH_UNKNOWN)
+ return a == AUTH_BASIC || a == AUTH_DIGEST;
+#else
+ if (b == AUTH_BASIC)
+ return 0;
+ if (b == AUTH_UNKNOWN)
+ return a == AUTH_BASIC;
+#endif
+
+ return 0;
+}
+
+struct http_challenge *http_header_get_proxy_challenge(const struct http_header *header, struct http_challenge *challenge)
+{
+ const struct http_header *p;
+
+ http_challenge_init(challenge);
+
+ p = NULL;
+ while ((p = http_header_next(header, p, "Proxy-Authenticate")) != NULL) {
+ const char *tmp;
+
+ tmp = p->value;
+ while (*tmp != '\0') {
+ struct http_challenge tmp_info;
+
+ tmp = http_read_challenge(tmp, &tmp_info);
+ if (tmp == NULL) {
+ http_challenge_free(challenge);
+ return NULL;
+ }
+ if (auth_scheme_is_better(tmp_info.scheme, challenge->scheme)) {
+ http_challenge_free(challenge);
+ *challenge = tmp_info;
+ } else {
+ http_challenge_free(&tmp_info);
+ }
+ }
+ }
+
+ return challenge;
+}
+
+struct http_credentials *http_header_get_proxy_credentials(const struct http_header *header, struct http_credentials *credentials)
+{
+ const struct http_header *p;
+
+ credentials->scheme = AUTH_UNKNOWN;
+
+ p = NULL;
+ while ((p = http_header_next(header, p, "Proxy-Authorization")) != NULL) {
+ const char *tmp;
+
+ tmp = p->value;
+ while (*tmp != '\0') {
+ struct http_credentials tmp_info;
+
+ tmp = http_read_credentials(tmp, &tmp_info);
+ if (tmp == NULL) {
+ http_credentials_free(credentials);
+ return NULL;
+ }
+ if (auth_scheme_is_better(tmp_info.scheme, credentials->scheme)) {
+ http_credentials_free(credentials);
+ *credentials = tmp_info;
+ } else {
+ http_credentials_free(&tmp_info);
+ }
+ }
+ }
+
+ return credentials;
+}
+
+void http_challenge_init(struct http_challenge *challenge)
+{
+ challenge->scheme = AUTH_UNKNOWN;
+ challenge->realm = NULL;
+ challenge->digest.nonce = NULL;
+ challenge->digest.opaque = NULL;
+ challenge->digest.algorithm = ALGORITHM_MD5;
+ challenge->digest.qop = 0;
+}
+
+void http_challenge_free(struct http_challenge *challenge)
+{
+ free(challenge->realm);
+ if (challenge->scheme == AUTH_DIGEST) {
+ free(challenge->digest.nonce);
+ free(challenge->digest.opaque);
+ }
+}
+
+void http_credentials_init_basic(struct http_credentials *credentials)
+{
+ credentials->scheme = AUTH_BASIC;
+ credentials->u.basic = NULL;
+}
+
+void http_credentials_init_digest(struct http_credentials *credentials)
+{
+ credentials->scheme = AUTH_DIGEST;
+ credentials->u.digest.username = NULL;
+ credentials->u.digest.realm = NULL;
+ credentials->u.digest.nonce = NULL;
+ credentials->u.digest.uri = NULL;
+ credentials->u.digest.response = NULL;
+ credentials->u.digest.algorithm = ALGORITHM_MD5;
+ credentials->u.digest.qop = QOP_NONE;
+ credentials->u.digest.nc = NULL;
+ credentials->u.digest.cnonce = NULL;
+}
+
+void http_credentials_free(struct http_credentials *credentials)
+{
+ if (credentials->scheme == AUTH_BASIC) {
+ free(credentials->u.basic);
+ } else if (credentials->scheme == AUTH_DIGEST) {
+ free(credentials->u.digest.username);
+ free(credentials->u.digest.realm);
+ free(credentials->u.digest.nonce);
+ free(credentials->u.digest.uri);
+ free(credentials->u.digest.response);
+ free(credentials->u.digest.nc);
+ free(credentials->u.digest.cnonce);
+ }
+}
diff --git a/ncat/http.h b/ncat/http.h
new file mode 100644
index 0000000..763490f
--- /dev/null
+++ b/ncat/http.h
@@ -0,0 +1,225 @@
+/***************************************************************************
+ * http.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef _HTTP_H
+#define _HTTP_H
+
+#include "ncat_config.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* This is an abstraction over a socket (really a struct fdinfo) that provides
+ rudimentary buffering. It is useful for the line-oriented parts of HTTP. */
+struct socket_buffer {
+ struct fdinfo fdn;
+ char buffer[BUFSIZ];
+ char *p;
+ char *end;
+};
+
+void socket_buffer_init(struct socket_buffer *buf, int sd);
+
+int socket_buffer_read(struct socket_buffer *buf, char *out, size_t size);
+
+char *socket_buffer_readline(struct socket_buffer *buf, size_t *n, size_t maxlen);
+
+int socket_buffer_readcount(struct socket_buffer *buf, char *out, size_t size);
+
+char *socket_buffer_remainder(struct socket_buffer *buf, size_t *len);
+
+/* A broken-down URI as defined in RFC 3986, except that the query and fragment
+ parts are included in the path. */
+struct uri {
+ char *scheme;
+ char *host;
+ int port;
+ char *path;
+};
+
+void uri_init(struct uri *uri);
+
+void uri_free(struct uri *uri);
+
+struct uri *uri_parse(struct uri *uri, const char *uri_s);
+
+struct uri *uri_parse_authority(struct uri *uri, const char *authority);
+
+enum http_version {
+ HTTP_09,
+ HTTP_10,
+ HTTP_11,
+ HTTP_UNKNOWN,
+};
+
+struct http_header {
+ char *name;
+ char *value;
+ struct http_header *next;
+};
+
+struct http_request {
+ char *method;
+ struct uri uri;
+ enum http_version version;
+ struct http_header *header;
+ int content_length_set;
+ unsigned long content_length;
+ unsigned long bytes_transferred;
+};
+
+struct http_response {
+ enum http_version version;
+ int code;
+ char *phrase;
+ struct http_header *header;
+ int content_length_set;
+ unsigned long content_length;
+ unsigned long bytes_transferred;
+};
+
+void http_header_free(struct http_header *header);
+char *http_header_get(const struct http_header *header, const char *name);
+const struct http_header *http_header_next(const struct http_header *header, const struct http_header *p, const char *name);
+char *http_header_get_first(const struct http_header *header, const char *name);
+struct http_header *http_header_set(struct http_header *header, const char *name, const char *value);
+struct http_header *http_header_remove(struct http_header *header, const char *name);
+int http_header_remove_hop_by_hop(struct http_header **header);
+char *http_header_to_string(const struct http_header *header, size_t *n);
+
+void http_request_init(struct http_request *request);
+void http_request_free(struct http_request *request);
+char *http_request_to_string(const struct http_request *request, size_t *n);
+
+void http_response_init(struct http_response *response);
+void http_response_free(struct http_response *response);
+char *http_response_to_string(const struct http_response *response, size_t *n);
+
+int http_read_header(struct socket_buffer *buf, char **result);
+int http_parse_header(struct http_header **result, const char *header);
+int http_request_parse_header(struct http_request *request, const char *header);
+int http_response_parse_header(struct http_response *response, const char *header);
+
+int http_read_request_line(struct socket_buffer *buf, char **line);
+int http_parse_request_line(const char *line, struct http_request *request);
+
+int http_read_status_line(struct socket_buffer *buf, char **line);
+int http_parse_status_line(const char *line, struct http_response *response);
+int http_parse_status_line_code(const char *line);
+
+enum http_auth_scheme { AUTH_UNKNOWN, AUTH_BASIC, AUTH_DIGEST };
+enum http_digest_algorithm { ALGORITHM_MD5, ALGORITHM_UNKNOWN };
+enum http_digest_qop { QOP_NONE = 0, QOP_AUTH = 1 << 0, QOP_AUTH_INT = 1 << 1 };
+
+struct http_challenge {
+ enum http_auth_scheme scheme;
+ char *realm;
+ struct {
+ char *nonce;
+ char *opaque;
+ enum http_digest_algorithm algorithm;
+ /* A bit mask of supported qop values ("auth", "auth-int", etc.). */
+ unsigned char qop;
+ } digest;
+};
+
+struct http_credentials {
+ enum http_auth_scheme scheme;
+ union {
+ char *basic;
+ struct {
+ char *username;
+ char *realm;
+ char *nonce;
+ char *uri;
+ char *response;
+ enum http_digest_algorithm algorithm;
+ enum http_digest_qop qop;
+ char *nc;
+ char *cnonce;
+ } digest;
+ } u;
+};
+
+void http_challenge_init(struct http_challenge *challenge);
+void http_challenge_free(struct http_challenge *challenge);
+struct http_challenge *http_header_get_proxy_challenge(const struct http_header *header, struct http_challenge *challenge);
+
+void http_credentials_init_basic(struct http_credentials *credentials);
+void http_credentials_init_digest(struct http_credentials *credentials);
+void http_credentials_free(struct http_credentials *credentials);
+struct http_credentials *http_header_get_proxy_credentials(const struct http_header *header, struct http_credentials *credentials);
+
+#if HAVE_HTTP_DIGEST
+/* Initialize the server secret used in generating nonces. */
+int http_digest_init_secret(void);
+int http_digest_nonce_time(const char *nonce, struct timeval *tv);
+/* Return a Proxy-Authenticate header. */
+char *http_digest_proxy_authenticate(const char *realm, int stale);
+/* Return a Proxy-Authorization header answering the given challenge. */
+char *http_digest_proxy_authorization(const struct http_challenge *challenge,
+ const char *username, const char *password,
+ const char *method, const char *uri);
+int http_digest_check_credentials(const char *username, const char *realm,
+ const char *password, const char *method,
+ const struct http_credentials *credentials);
+#endif
+
+#endif
diff --git a/ncat/http_digest.c b/ncat/http_digest.c
new file mode 100644
index 0000000..f6a636b
--- /dev/null
+++ b/ncat/http_digest.c
@@ -0,0 +1,376 @@
+/***************************************************************************
+ * ncat_digest.c -- HTTP Digest authentication handling. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+/* Nonces returned by make_nonce have the form
+ timestamp-MD5(secret:timestamp)
+ using representative values, this may look like
+ 1263929285.015273-a8e75fae174fc0e6a5df47bf9900beb6
+ Sending a timestamp in the clear allows us to compute how long ago the nonce
+ was issued without local state. Including microseconds reduces the chance
+ that the same nonce will be issued for two different requests. When a nonce
+ is received from a client, the time is extracted and then the nonce is
+ recalculated locally to make sure they match. This is similar to the strategy
+ recommended in section 3.2.1 of RFC 2617.
+
+ When Ncat does Digest authentication as a client, it only does so to make a
+ single CONNECT request to a proxy server. Therefore we don't use a differing
+ nc (nonce count) but always the constant 00000001. */
+
+#include "ncat.h"
+#include "http.h"
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+/* What's a good length for this? I think it exists only to prevent us from
+ hashing known plaintext from the server. */
+#define CNONCE_LENGTH 8
+
+#define SECRET_LENGTH 16
+
+static unsigned char secret[SECRET_LENGTH];
+static int secret_initialized = 0;
+
+static int append_quoted_string(char **buf, size_t *size, size_t *offset, const char *s)
+{
+ const char *t;
+
+ strbuf_append_str(buf, size, offset, "\"");
+ for (;;) {
+ t = s;
+ while (!((*t >= 0 && *t <= 31) || *t == 127 || *t == '\\'))
+ t++;
+ strbuf_append(buf, size, offset, s, t - s);
+ if (*t == '\0')
+ break;
+ strbuf_sprintf(buf, size, offset, "\\%c", *t);
+ s = t + 1;
+ }
+ strbuf_append_str(buf, size, offset, "\"");
+
+ return *size;
+}
+
+/* n is the size of src. dest must have at least n * 2 + 1 allocated bytes. */
+static char *enhex(char *dest, const unsigned char *src, size_t n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ Snprintf(dest + i * 2, 3, "%02x", src[i]);
+
+ return dest;
+}
+
+/* Initialize the server secret used in generating nonces. Return -1 on
+ failure. */
+int http_digest_init_secret(void)
+{
+ if (!RAND_status())
+ return -1;
+ if (RAND_bytes(secret, sizeof(secret)) != 1)
+ return -1;
+ secret_initialized = 1;
+
+ return 0;
+}
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+#endif
+static char *make_nonce(const struct timeval *tv)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+ EVP_MD_CTX *md5;
+ unsigned char hashbuf[EVP_MAX_MD_SIZE];
+ char hash_hex[EVP_MAX_MD_SIZE * 2 + 1];
+ char time_buf[32];
+ unsigned int hash_size = 0;
+
+ /* Crash if someone forgot to call http_digest_init_secret. */
+ if (!secret_initialized)
+ bye("Server secret not initialized for Digest authentication. Call http_digest_init_secret.");
+
+ Snprintf(time_buf, sizeof(time_buf), "%lu.%06lu",
+ (long unsigned) tv->tv_sec, (long unsigned) tv->tv_usec);
+ md5 = EVP_MD_CTX_new();
+ EVP_DigestInit_ex(md5, EVP_md5(), NULL);
+ EVP_DigestUpdate(md5, secret, sizeof(secret));
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, time_buf, strlen(time_buf));
+ EVP_DigestFinal_ex(md5, hashbuf, &hash_size);
+ enhex(hash_hex, hashbuf, hash_size);
+
+ strbuf_sprintf(&buf, &size, &offset, "%s-%s", time_buf, hash_hex);
+ EVP_MD_CTX_free(md5);
+
+ return buf;
+}
+
+/* Arguments are assumed to be non-NULL, with the exception of nc and cnonce,
+ which may be garbage only if qop == QOP_NONE. */
+static void make_response(char buf[EVP_MAX_MD_SIZE * 2 + 1],
+ const char *username, const char *realm, const char *password,
+ const char *method, const char *uri, const char *nonce,
+ enum http_digest_qop qop, const char *nc, const char *cnonce)
+{
+ char HA1_hex[EVP_MAX_MD_SIZE * 2 + 1], HA2_hex[EVP_MAX_MD_SIZE * 2 + 1];
+ unsigned char hashbuf[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX *md5;
+ unsigned int hash_size = 0;
+ const EVP_MD *md = EVP_md5();
+
+ /* Calculate H(A1). */
+ md5 = EVP_MD_CTX_new();
+ EVP_DigestInit_ex(md5, md, NULL);
+ EVP_DigestUpdate(md5, username, strlen(username));
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, realm, strlen(realm));
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, password, strlen(password));
+ EVP_DigestFinal_ex(md5, hashbuf, &hash_size);
+ enhex(HA1_hex, hashbuf, hash_size);
+
+ /* Calculate H(A2). */
+ EVP_DigestInit_ex(md5, md, NULL);
+ EVP_DigestUpdate(md5, method, strlen(method));
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, uri, strlen(uri));
+ EVP_DigestFinal_ex(md5, hashbuf, &hash_size);
+ enhex(HA2_hex, hashbuf, hash_size);
+
+ /* Calculate response. */
+ EVP_DigestInit_ex(md5, md, NULL);
+ EVP_DigestUpdate(md5, HA1_hex, strlen(HA1_hex));
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, nonce, strlen(nonce));
+ if (qop == QOP_AUTH) {
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, nc, strlen(nc));
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, cnonce, strlen(cnonce));
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, "auth", strlen("auth"));
+ }
+ EVP_DigestUpdate(md5, ":", 1);
+ EVP_DigestUpdate(md5, HA2_hex, strlen(HA2_hex));
+ EVP_DigestFinal_ex(md5, hashbuf, &hash_size);
+
+ enhex(buf, hashbuf, hash_size);
+ EVP_MD_CTX_free(md5);
+}
+
+/* Extract the issuance time from a nonce (without checking other aspects of
+ validity. If the time can't be extracted, returns -1, 0 otherwise. */
+int http_digest_nonce_time(const char *nonce, struct timeval *tv)
+{
+ unsigned long sec, usec;
+
+ if (sscanf(nonce, "%lu.%lu", &sec, &usec) != 2)
+ return -1;
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+
+ return 0;
+}
+
+char *http_digest_proxy_authenticate(const char *realm, int stale)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+ struct timeval tv;
+ char *nonce;
+
+ if (gettimeofday(&tv, NULL) == -1)
+ return NULL;
+
+ strbuf_append_str(&buf, &size, &offset, "Digest realm=");
+ append_quoted_string(&buf, &size, &offset, realm);
+
+ nonce = make_nonce(&tv);
+ strbuf_append_str(&buf, &size, &offset, ", nonce=");
+ append_quoted_string(&buf, &size, &offset, nonce);
+ free(nonce);
+ strbuf_append_str(&buf, &size, &offset, ", qop=\"auth\"");
+
+ if (stale)
+ strbuf_append_str(&buf, &size, &offset, ", stale=true");
+
+ return buf;
+}
+
+char *http_digest_proxy_authorization(const struct http_challenge *challenge,
+ const char *username, const char *password,
+ const char *method, const char *uri)
+{
+ /* For now we authenticate successfully at most once, so we don't need a
+ varying client nonce count. */
+ static const u32 nc = 0x00000001;
+
+ char response_hex[EVP_MAX_MD_SIZE * 2 + 1];
+ unsigned char cnonce[CNONCE_LENGTH];
+ char cnonce_buf[CNONCE_LENGTH * 2 + 1];
+ char nc_buf[8 + 1];
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+ enum http_digest_qop qop;
+
+ if (challenge->scheme != AUTH_DIGEST
+ || challenge->realm == NULL
+ || challenge->digest.nonce == NULL
+ || challenge->digest.algorithm != ALGORITHM_MD5)
+ return NULL;
+
+ if (challenge->digest.qop & QOP_AUTH) {
+ Snprintf(nc_buf, sizeof(nc_buf), "%08x", nc);
+ if (!RAND_status())
+ return NULL;
+ if (RAND_bytes(cnonce, sizeof(cnonce)) != 1)
+ return NULL;
+ enhex(cnonce_buf, cnonce, sizeof(cnonce));
+ qop = QOP_AUTH;
+ } else {
+ qop = QOP_NONE;
+ }
+
+ strbuf_append_str(&buf, &size, &offset, " Digest");
+ strbuf_append_str(&buf, &size, &offset, " username=");
+ append_quoted_string(&buf, &size, &offset, username);
+ strbuf_append_str(&buf, &size, &offset, ", realm=");
+ append_quoted_string(&buf, &size, &offset, challenge->realm);
+ strbuf_append_str(&buf, &size, &offset, ", nonce=");
+ append_quoted_string(&buf, &size, &offset, challenge->digest.nonce);
+ strbuf_append_str(&buf, &size, &offset, ", uri=");
+ append_quoted_string(&buf, &size, &offset, uri);
+
+ if (qop == QOP_AUTH) {
+ strbuf_append_str(&buf, &size, &offset, ", qop=auth");
+ strbuf_append_str(&buf, &size, &offset, ", cnonce=");
+ append_quoted_string(&buf, &size, &offset, cnonce_buf);
+ strbuf_sprintf(&buf, &size, &offset, ", nc=%s", nc_buf);
+ }
+
+ make_response(response_hex, username, challenge->realm, password,
+ method, uri, challenge->digest.nonce, qop, nc_buf, cnonce_buf);
+ strbuf_append_str(&buf, &size, &offset, ", response=");
+ append_quoted_string(&buf, &size, &offset, response_hex);
+
+ if (challenge->digest.opaque != NULL) {
+ strbuf_append_str(&buf, &size, &offset, ", opaque=");
+ append_quoted_string(&buf, &size, &offset, challenge->digest.opaque);
+ }
+
+ strbuf_append_str(&buf, &size, &offset, "\r\n");
+
+ return buf;
+}
+
+/* Check that a nonce is one that we issued, and that the response is what is
+ expected. This doesn't do any checking against the lifetime of the nonce. */
+int http_digest_check_credentials(const char *username, const char *realm,
+ const char *password, const char *method,
+ const struct http_credentials *credentials)
+{
+ char response_hex[EVP_MAX_MD_SIZE * 2 + 1];
+ struct timeval tv;
+ char *nonce;
+
+ if (credentials->scheme != AUTH_DIGEST
+ || credentials->u.digest.username == NULL
+ || credentials->u.digest.realm == NULL
+ || credentials->u.digest.nonce == NULL
+ || credentials->u.digest.uri == NULL
+ || credentials->u.digest.response == NULL
+ || credentials->u.digest.algorithm != ALGORITHM_MD5) {
+ return 0;
+ }
+ if (credentials->u.digest.qop != QOP_NONE && credentials->u.digest.qop != QOP_AUTH)
+ return 0;
+ if (credentials->u.digest.qop == QOP_AUTH
+ && (credentials->u.digest.nc == NULL
+ || credentials->u.digest.cnonce == NULL)) {
+ return 0;
+ }
+
+ if (strcmp(username, credentials->u.digest.username) != 0)
+ return 0;
+ if (strcmp(realm, credentials->u.digest.realm) != 0)
+ return 0;
+
+ if (http_digest_nonce_time(credentials->u.digest.nonce, &tv) == -1)
+ return 0;
+
+ nonce = make_nonce(&tv);
+ if (strcmp(nonce, credentials->u.digest.nonce) != 0) {
+ /* We could not have handed out this nonce. */
+ free(nonce);
+ return 0;
+ }
+ free(nonce);
+
+ make_response(response_hex, credentials->u.digest.username, realm,
+ password, method, credentials->u.digest.uri,
+ credentials->u.digest.nonce, credentials->u.digest.qop,
+ credentials->u.digest.nc, credentials->u.digest.cnonce);
+
+ return strcmp(response_hex, credentials->u.digest.response) == 0;
+}
diff --git a/ncat/missing b/ncat/missing
new file mode 100755
index 0000000..22e101a
--- /dev/null
+++ b/ncat/missing
@@ -0,0 +1,198 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997, 2001, 2002 Free Software Foundation, Inc.
+# Franc,ois 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.in; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`$configure_ac'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`$configure_ac'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`$configure_ac'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' $configure_ac`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`$configure_ac'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/ncat/mkinstalldirs b/ncat/mkinstalldirs
new file mode 100755
index 0000000..46abf3b
--- /dev/null
+++ b/ncat/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1.1.1 2006/01/21 16:58:25 evii Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/ncat/ncat.h b/ncat/ncat.h
new file mode 100644
index 0000000..9f876ae
--- /dev/null
+++ b/ncat/ncat.h
@@ -0,0 +1,218 @@
+/***************************************************************************
+ * ncat.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef NCAT_H_
+#define NCAT_H_
+
+#include "ncat_config.h"
+
+#include <nbase.h>
+
+#include "nsock.h"
+#include "util.h"
+#include "sys_wrap.h"
+
+#include "ncat_connect.h"
+#include "ncat_core.h"
+#include "ncat_exec.h"
+#include "ncat_listen.h"
+#include "ncat_proxy.h"
+#include "ncat_ssl.h"
+
+/* Ncat information for output, etc. */
+#define NCAT_NAME "Ncat"
+#define NCAT_URL "https://nmap.org/ncat"
+#define NCAT_VERSION "7.94SVN"
+
+#ifndef __GNUC__
+#ifndef __attribute__
+#define __attribute__(x)
+#endif
+#endif
+
+#define SOCKS_BUFF_SIZE 512
+
+/* structs */
+
+#ifdef WIN32
+#pragma pack(1)
+#endif
+struct socks4_data {
+ char version;
+ char type;
+ unsigned short port;
+ uint32_t address;
+ char data[SOCKS_BUFF_SIZE]; // this has to be able to hold FQDN and username
+} __attribute__((packed));
+
+struct socks5_connect {
+ char ver;
+ unsigned char nmethods;
+ char methods[3];
+} __attribute__((packed));
+
+struct socks5_auth {
+ char ver; // must be always 1
+ unsigned char data[SOCKS_BUFF_SIZE];
+} __attribute__((packed));
+
+struct socks5_request {
+ char ver;
+ char cmd;
+ char rsv;
+ char atyp;
+ unsigned char dst[SOCKS_BUFF_SIZE]; // addr/name and port info
+} __attribute__((packed));
+#ifdef WIN32
+#pragma pack()
+#endif
+
+/* defines */
+
+/* Client-mode timeout for reads, infinite */
+#define DEFAULT_READ_TIMEOUT -1
+
+/* Client-mode timeout for writes, in msecs */
+#define DEFAULT_WRITE_TIMEOUT 2000
+
+/* Client-mode timeout for connection establishment, in msecs */
+#define DEFAULT_CONNECT_TIMEOUT 10000
+
+/* The default length of Ncat buffers */
+#define DEFAULT_BUF_LEN (1024)
+#define DEFAULT_TCP_BUF_LEN (1024 * 8)
+#define DEFAULT_UDP_BUF_LEN (1024 * 128)
+
+/* Default Ncat port */
+#define DEFAULT_NCAT_PORT 31337
+
+/* Default port for SOCKS4 */
+#define DEFAULT_SOCKS4_PORT 1080
+
+/* Default port for SOCKS5 */
+#define DEFAULT_SOCKS5_PORT 1080
+
+
+/* The default port Ncat will connect to when trying to connect to an HTTP
+ * proxy server. The current setting is the default for squid and probably
+ * other HTTP proxies. But it may also be 8080, 8888, etc.
+ */
+#define DEFAULT_PROXY_PORT 3128
+
+/* Listen() backlog */
+#define BACKLOG 10
+
+/* The default maximum number of simultaneous connections Ncat will accept to
+ * a listening port. You may want to increase or decrease this value depending
+ * on your specific needs.
+ */
+#ifdef WIN32
+/* Windows is commonly limited to 64 sockets, so keep the default somewhat below
+ that. http://www.tangentsoft.net/wskfaq/advanced.html#64sockets */
+#define DEFAULT_MAX_CONNS 60
+#else
+#define DEFAULT_MAX_CONNS 100
+#endif
+
+/* SOCKS4 protocol responses */
+#define SOCKS4_VERSION 4
+#define SOCKS_CONNECT 1
+#define SOCKS_BIND 2
+#define SOCKS4_CONN_ACC 90 /* woot */
+#define SOCKS4_CONN_REF 91
+#define SOCKS4_CONN_IDENT 92
+#define SOCKS4_CONN_IDENTDIFF 93
+
+/* SOCKS5 protocol */
+#define SOCKS5_VERSION 5
+#define SOCKS5_AUTH_NONE 0
+#define SOCKS5_AUTH_GSSAPI 1
+#define SOCKS5_AUTH_USERPASS 2
+#define SOCKS5_AUTH_FAILED 255
+#define SOCKS5_ATYP_IPv4 1
+#define SOCKS5_ATYP_NAME 3
+#define SOCKS5_ATYP_IPv6 4
+
+#define SOCKS5_USR_MAXLEN 255
+#define SOCKS5_PWD_MAXLEN 255
+#define SOCKS5_DST_MAXLEN 255
+
+#if SOCKS_BUFF_SIZE < (1 + SOCKS5_USR_MAXLEN) + (1 + SOCKS5_PWD_MAXLEN)
+#error SOCKS_BUFF_SIZE is defined too small to handle SOCKS5 authentication
+#endif
+
+#if SOCKS_BUFF_SIZE < (1 + SOCKS5_DST_MAXLEN) + 2
+#error SOCKS_BUFF_SIZE is defined too small to handle SOCKS5 destination
+#endif
+
+/* Length of IPv6 address */
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+
+/* Dummy WNOHANG for Windows */
+#ifndef WNOHANG
+#define WNOHANG 0
+#endif
+
+#endif
diff --git a/ncat/ncat.vcxproj b/ncat/ncat.vcxproj
new file mode 100644
index 0000000..38f50b8
--- /dev/null
+++ b/ncat/ncat.vcxproj
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Static|Win32">
+ <Configuration>Static</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C1E04411-E021-468B-83F1-CB624BBA7589}</ProjectGuid>
+ <RootNamespace>ncat</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Static|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Static|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">.\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">.\Release\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">true</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <TypeLibraryName>.\Debug/ncat.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..;../nbase;..\nsock\include;..\..\nmap-mswin32-aux\Npcap\Include;..\..\nmap-mswin32-aux\OpenSSL\include;..\liblua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderOutputFile>.\Debug/ncat.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+ <ObjectFileName>.\Debug/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+ <WarningLevel>Level2</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <ResourceOutputFileName>
+ </ResourceOutputFileName>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>nbase.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;nsock.lib;advapi32.lib;libcrypto.lib;libssl.lib;liblua.lib</AdditionalDependencies>
+ <OutputFile>.\Debug\ncat.exe</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>..\..\nmap-mswin32-aux\Npcap\Lib;..\nsock;..\nbase;..\..\nmap-mswin32-aux\OpenSSL\lib;..\liblua;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <DelayLoadDLLs>wpcap.dll</DelayLoadDLLs>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>.\Debug/ncat.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy "..\..\nmap-mswin32-aux\OpenSSL\bin\*.dll" "$(Configuration)\" /y</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <TypeLibraryName>.\Release/ncat.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>.;..;../nbase;..\nsock\include;..\..\nmap-mswin32-aux\Npcap\Include;..\..\nmap-mswin32-aux\OpenSSL\include;..\liblua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderOutputFile>.\Release/ncat.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+ <ObjectFileName>.\Release/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+ <WarningLevel>Level2</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>nsock.lib;nbase.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;advapi32.lib;libcrypto.lib;libssl.lib</AdditionalDependencies>
+ <OutputFile>.\Release/ncat.exe</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>..\..\nmap-mswin32-aux\Npcap\Lib;..\nsock;..\nbase;..\..\nmap-mswin32-aux\OpenSSL\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <DelayLoadDLLs>wpcap.dll</DelayLoadDLLs>
+ <ProgramDatabaseFile>.\Release/ncat.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <RandomizedBaseAddress>true</RandomizedBaseAddress>
+ <DataExecutionPrevention>true</DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <OptimizeReferences>true</OptimizeReferences>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy "..\..\nmap-mswin32-aux\OpenSSL\bin\*.dll" "$(Configuration)\" /y</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">
+ <Midl>
+ <TypeLibraryName>.\Release/ncat.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>.;..;../nbase;..\nsock\include;..\..\nmap-mswin32-aux\Npcap\Include;..\..\nmap-mswin32-aux\OpenSSL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderOutputFile>.\Release/ncat.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+ <ObjectFileName>.\Release/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+ <WarningLevel>Level2</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>nsock.lib;nbase.lib;ws2_32.lib;IPHlpAPI.Lib;advapi32.lib;libcrypto.lib;libssl.lib;user32.lib;gdi32.lib</AdditionalDependencies>
+ <OutputFile>.\Release/ncat.exe</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>..\..\nmap-mswin32-aux\Npcap\Lib;..\nsock;..\nbase;..\..\nmap-mswin32-aux\OpenSSL\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ProgramDatabaseFile>.\Release/ncat.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <RandomizedBaseAddress>true</RandomizedBaseAddress>
+ <DataExecutionPrevention>true</DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="base64.c" />
+ <ClCompile Include="http.c" />
+ <ClCompile Include="http_digest.c" />
+ <ClCompile Include="ncat_connect.c" />
+ <ClCompile Include="ncat_core.c" />
+ <ClCompile Include="ncat_exec_win.c" />
+ <ClCompile Include="ncat_listen.c" />
+ <ClCompile Include="ncat_lua.c" />
+ <ClCompile Include="ncat_main.c" />
+ <ClCompile Include="ncat_proxy.c" />
+ <ClCompile Include="ncat_ssl.c" />
+ <ClCompile Include="ncat_win.c" />
+ <ClCompile Include="sys_wrap.c" />
+ <ClCompile Include="util.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="base64.h" />
+ <ClInclude Include="http.h" />
+ <ClInclude Include="ncat.h" />
+ <ClInclude Include="ncat_connect.h" />
+ <ClInclude Include="ncat_core.h" />
+ <ClInclude Include="ncat_exec.h" />
+ <ClInclude Include="ncat_listen.h" />
+ <ClInclude Include="ncat_lua.h" />
+ <ClInclude Include="ncat_proxy.h" />
+ <ClInclude Include="ncat_ssl.h" />
+ <ClInclude Include="..\mswin32\resource.h" />
+ <ClInclude Include="sockaddr_u.h" />
+ <ClInclude Include="sys_wrap.h" />
+ <ClInclude Include="util.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="certs\ca-bundle.crt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Copying %(Filename).crt to output directory...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy /y "%(FullPath)" "$(TargetDir)%(Filename).crt" &gt; nul
+</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)%(Filename).crt;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Copying %(Filename).crt to output directory...</Message>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">Copying %(Filename).crt to output directory...</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy /y "%(FullPath)" "$(TargetDir)%(Filename).crt" &gt; nul
+</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">copy /y "%(FullPath)" "$(TargetDir)%(Filename).crt" &gt; nul
+</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)%(Filename).crt;%(Outputs)</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">$(TargetDir)%(Filename).crt;%(Outputs)</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\liblua\liblua.vcxproj">
+ <Project>{31fb0767-a71f-4575-8379-002d72b8af86}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\nbase\nbase.vcxproj">
+ <Project>{b630c8f7-3138-43e8-89ed-78742fa2ac5f}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="..\nsock\nsock.vcxproj">
+ <Project>{f8d6d1e3-d4ea-402c-98aa-168e5309baf4}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/ncat/ncat_config.h b/ncat/ncat_config.h
new file mode 100644
index 0000000..d0606a9
--- /dev/null
+++ b/ncat/ncat_config.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * ncat_config.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+#ifndef NCAT_CONFIG_H
+#define NCAT_CONFIG_H
+
+/* This is a wrapper that selects config.h or config_win.h depending on whether
+ we're using Autoconf or a static Windows configuration file. */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#elif WIN32
+#include "config_win.h"
+#else
+#error "No config.h, and not WIN32"
+#endif
+
+#endif
diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c
new file mode 100644
index 0000000..dda5183
--- /dev/null
+++ b/ncat/ncat_connect.c
@@ -0,0 +1,1425 @@
+/***************************************************************************
+ * ncat_connect.c -- Ncat connect mode. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "base64.h"
+#include "nsock.h"
+#include "ncat.h"
+#include "util.h"
+#include "sys_wrap.h"
+
+#include "nbase.h"
+#include "http.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#include <netdb.h>
+#endif
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+/* Deprecated in OpenSSL 3.0 */
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+# define SSL_get_peer_certificate SSL_get1_peer_certificate
+#endif
+#endif
+
+#ifdef WIN32
+/* Define missing constant for shutdown(2).
+ * See:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740481%28v=vs.85%29.aspx
+ */
+#define SHUT_WR SD_SEND
+#endif
+
+struct conn_state {
+ nsock_iod sock_nsi;
+ nsock_iod stdin_nsi;
+ nsock_event_id idle_timer_event_id;
+ int crlf_state;
+};
+
+static struct conn_state cs = {
+ NULL,
+ NULL,
+ 0,
+ 0
+};
+
+static void try_nsock_connect(nsock_pool nsp, struct sockaddr_list *conn_addr);
+static void connect_handler(nsock_pool nsp, nsock_event evt, void *data);
+static void post_connect(nsock_pool nsp, nsock_iod iod);
+static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data);
+static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data);
+static void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data);
+static void idle_timer_handler(nsock_pool nsp, nsock_event evt, void *data);
+static void refresh_idle_timer(nsock_pool nsp);
+
+#ifdef HAVE_OPENSSL
+/* This callback is called for every certificate in a chain. ok is true if
+ OpenSSL's internal verification has verified the certificate. We don't change
+ anything about the verification, we only need access to the certificates to
+ provide diagnostics. */
+static int verify_callback(int ok, X509_STORE_CTX *store)
+{
+ X509 *cert = X509_STORE_CTX_get_current_cert(store);
+ int err = X509_STORE_CTX_get_error(store);
+
+ /* Print the subject, issuer, and fingerprint depending on the verbosity
+ level. */
+ if ((!ok && o.verbose) || o.debug > 1) {
+ char digest_buf[SHA1_STRING_LENGTH + 1];
+ char *fp;
+
+ loguser("Subject: ");
+ X509_NAME_print_ex_fp(stderr, X509_get_subject_name(cert), 0, XN_FLAG_COMPAT);
+ loguser_noprefix("\n");
+ loguser("Issuer: ");
+ X509_NAME_print_ex_fp(stderr, X509_get_issuer_name(cert), 0, XN_FLAG_COMPAT);
+ loguser_noprefix("\n");
+
+ fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf));
+ ncat_assert(fp == digest_buf);
+ loguser("SHA-1 fingerprint: %s\n", digest_buf);
+ }
+
+ if (!ok && o.verbose) {
+ loguser("Certificate verification failed (%s).\n",
+ X509_verify_cert_error_string(err));
+ }
+
+ return ok;
+}
+
+static void set_ssl_ctx_options(SSL_CTX *ctx)
+{
+ if (o.ssltrustfile == NULL) {
+ ssl_load_default_ca_certs(ctx);
+ } else {
+ if (o.debug)
+ logdebug("Using trusted CA certificates from %s.\n", o.ssltrustfile);
+ if (SSL_CTX_load_verify_locations(ctx, o.ssltrustfile, NULL) != 1) {
+ bye("Could not load trusted certificates from %s.\n%s",
+ o.ssltrustfile, ERR_error_string(ERR_get_error(), NULL));
+ }
+ }
+
+ if (o.sslverify) {
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
+ } else {
+ /* Still check verification status and report it */
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
+ if (o.ssl && o.debug)
+ logdebug("Not doing certificate verification.\n");
+ }
+
+ if (o.sslcert != NULL && o.sslkey != NULL) {
+ if (SSL_CTX_use_certificate_file(ctx, o.sslcert, SSL_FILETYPE_PEM) != 1)
+ bye("SSL_CTX_use_certificate_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ if (SSL_CTX_use_PrivateKey_file(ctx, o.sslkey, SSL_FILETYPE_PEM) != 1)
+ bye("SSL_CTX_use_Privatekey_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ } else {
+ if ((o.sslcert == NULL) != (o.sslkey == NULL))
+ bye("The --ssl-key and --ssl-cert options must be used together.");
+ }
+ if (o.sslciphers == NULL) {
+ if (!SSL_CTX_set_cipher_list(ctx, "ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!MD5:@STRENGTH"))
+ bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL));
+ }
+ else {
+ printf("setting ciphers: %s\n", o.sslciphers);
+ if (!SSL_CTX_set_cipher_list(ctx, o.sslciphers))
+ bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL));
+ }
+
+#ifdef HAVE_ALPN_SUPPORT
+
+ if (o.sslalpn) {
+ size_t alpn_len;
+ unsigned char *alpn = next_protos_parse(&alpn_len, o.sslalpn);
+
+ if (alpn == NULL)
+ bye("Could not parse ALPN string");
+
+ if (o.debug)
+ logdebug("Using ALPN String %s\n", o.sslalpn);
+
+ /* SSL_CTX_set_alpn_protos returns 0 on success */
+ if (SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len) != 0){
+ free(alpn);
+ bye("SSL_CTX_set_alpn_protos: %s.", ERR_error_string(ERR_get_error(), NULL));
+ }
+
+ free(alpn);
+ }
+
+#endif
+
+}
+#endif
+
+/* Depending on verbosity, print a message that a connection was established. */
+static void connect_report(nsock_iod nsi)
+{
+ union sockaddr_u peer;
+ zmem(&peer, sizeof(peer.storage));
+
+ nsock_iod_get_communication_info(nsi, NULL, NULL, NULL, &peer.sockaddr,
+ sizeof(peer.storage));
+ if (o.verbose) {
+ char peer_str[INET6_ADDRSTRLEN + sizeof(union sockaddr_u)] = {0};
+ if (o.proxytype) {
+ Snprintf(peer_str, sizeof(peer_str), "%s:%u", o.target, o.portno);
+ }
+ else {
+ Strncpy(peer_str, socktop(&peer, 0), sizeof(peer_str));
+ }
+#ifdef HAVE_OPENSSL
+ if (nsock_iod_check_ssl(nsi)) {
+ X509 *cert;
+ X509_NAME *subject;
+ char digest_buf[SHA1_STRING_LENGTH + 1];
+ char *fp;
+
+ loguser("SSL connection to %s.", peer_str);
+
+ cert = SSL_get_peer_certificate((SSL *)nsock_iod_get_ssl(nsi));
+ ncat_assert(cert != NULL);
+
+ subject = X509_get_subject_name(cert);
+ if (subject != NULL) {
+ char buf[256];
+ int n;
+
+ n = X509_NAME_get_text_by_NID(subject, NID_organizationName, buf, sizeof(buf));
+ if (n >= 0 && n <= sizeof(buf) - 1)
+ loguser_noprefix(" %s", buf);
+ }
+
+ loguser_noprefix("\n");
+
+ fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf));
+ ncat_assert(fp == digest_buf);
+ loguser("SHA-1 fingerprint: %s\n", digest_buf);
+ } else
+#endif
+ {
+ loguser("Connected to %s.\n", peer_str);
+ }
+ }
+}
+
+/* Just like inet_socktop, but it puts IPv6 addresses in square brackets. */
+static const char *sock_to_url(char *host_str, unsigned short port)
+{
+ static char buf[512];
+
+ switch(getaddrfamily(host_str)) {
+ case -1:
+ case 1:
+ Snprintf(buf, sizeof(buf), "%s:%hu", host_str, port);
+ break;
+ case 2:
+ Snprintf(buf, sizeof(buf), "[%s]:%hu", host_str, port);
+ }
+
+ return buf;
+}
+
+static int append_connect_request_line(char **buf, size_t *size, size_t *offset,
+ char* host_str,unsigned short port)
+{
+ return strbuf_sprintf(buf, size, offset, "CONNECT %s HTTP/1.0\r\n",
+ sock_to_url(host_str,port));
+}
+
+static char *http_connect_request(char* host_str, unsigned short port, int *n)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+
+ append_connect_request_line(&buf, &size, &offset, host_str, port);
+ strbuf_append_str(&buf, &size, &offset, "\r\n");
+ *n = offset;
+
+ return buf;
+}
+
+static char *http_connect_request_auth(char* host_str, unsigned short port, int *n,
+ struct http_challenge *challenge)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+
+ append_connect_request_line(&buf, &size, &offset, host_str, port);
+ strbuf_append_str(&buf, &size, &offset, "Proxy-Authorization:");
+ if (challenge->scheme == AUTH_BASIC) {
+ char *auth_str;
+
+ auth_str = b64enc((unsigned char *) o.proxy_auth, strlen(o.proxy_auth));
+ strbuf_sprintf(&buf, &size, &offset, " Basic %s\r\n", auth_str);
+ free(auth_str);
+#if HAVE_HTTP_DIGEST
+ } else if (challenge->scheme == AUTH_DIGEST) {
+ char *proxy_auth;
+ char *username, *password;
+ char *response_hdr;
+
+ /* Split up the proxy auth argument. */
+ proxy_auth = Strdup(o.proxy_auth);
+ username = proxy_auth;
+ password = strchr(proxy_auth, ':');
+ if (password == NULL) {
+ free(proxy_auth);
+ return NULL;
+ }
+ *password++ = '\0';
+ response_hdr = http_digest_proxy_authorization(challenge,
+ username, password, "CONNECT", sock_to_url(o.target,o.portno));
+ if (response_hdr == NULL) {
+ free(proxy_auth);
+ return NULL;
+ }
+ strbuf_append_str(&buf, &size, &offset, response_hdr);
+ free(proxy_auth);
+ free(response_hdr);
+#endif
+ } else {
+ bye("Unknown authentication type.");
+ }
+ strbuf_append_str(&buf, &size, &offset, "\r\n");
+ *n = offset;
+
+ return buf;
+}
+
+/* Return a usable socket descriptor after proxy negotiation, or -1 on any
+ error. If any bytes are received through the proxy after negotiation, they
+ are written to stdout. */
+static int do_proxy_http(void)
+{
+ struct socket_buffer sockbuf;
+ char *request;
+ char *status_line, *header;
+ char *remainder;
+ size_t len;
+ int sd, code;
+ int n;
+ char *target;
+ union sockaddr_u addr;
+ size_t sslen;
+ char addrstr[INET6_ADDRSTRLEN];
+
+ request = NULL;
+ status_line = NULL;
+ header = NULL;
+
+ sd = do_connect(SOCK_STREAM);
+ if (sd == -1) {
+ loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno()));
+ return -1;
+ }
+
+ if (proxyresolve(o.target, 0, &addr.storage, &sslen, o.af)) {
+ /* target resolution has failed, possibly because it is disabled */
+ if (!(o.proxydns & PROXYDNS_REMOTE)) {
+ loguser("Error: Failed to resolve host %s locally.\n", o.target);
+ goto bail;
+ }
+ if (o.verbose)
+ loguser("Host %s will be resolved by the proxy.\n", o.target);
+ target = o.target;
+ } else {
+ /* addr is now populated with either sockaddr_in or sockaddr_in6 */
+ Strncpy(addrstr, inet_socktop(&addr), sizeof(addrstr));
+ target = addrstr;
+ if (o.verbose && getaddrfamily(o.target) == -1)
+ loguser("Host %s locally resolved to %s.\n", o.target, target);
+ }
+
+ /* First try a request with no authentication. */
+ request = http_connect_request(target, o.portno, &n);
+ if (send(sd, request, n, 0) < 0) {
+ loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
+ goto bail;
+ }
+ free(request);
+ request = NULL;
+
+ socket_buffer_init(&sockbuf, sd);
+
+ if (http_read_status_line(&sockbuf, &status_line) != 0) {
+ loguser("Error reading proxy response Status-Line.\n");
+ goto bail;
+ }
+ code = http_parse_status_line_code(status_line);
+ if (o.debug)
+ logdebug("Proxy returned status code %d.\n", code);
+ free(status_line);
+ status_line = NULL;
+ if (http_read_header(&sockbuf, &header) != 0) {
+ loguser("Error reading proxy response header.\n");
+ goto bail;
+ }
+
+ if (code == 407 && o.proxy_auth != NULL) {
+ struct http_header *h;
+ struct http_challenge challenge;
+
+ close(sd);
+ sd = -1;
+
+ if (http_parse_header(&h, header) != 0) {
+ loguser("Error parsing proxy response header.\n");
+ goto bail;
+ }
+ free(header);
+ header = NULL;
+
+ if (http_header_get_proxy_challenge(h, &challenge) == NULL) {
+ loguser("Error getting Proxy-Authenticate challenge.\n");
+ http_header_free(h);
+ goto bail;
+ }
+ http_header_free(h);
+
+ sd = do_connect(SOCK_STREAM);
+ if (sd == -1) {
+ loguser("Proxy reconnection failed: %s.\n", socket_strerror(socket_errno()));
+ goto bail;
+ }
+
+ request = http_connect_request_auth(target, o.portno, &n, &challenge);
+ if (request == NULL) {
+ loguser("Error building Proxy-Authorization header.\n");
+ http_challenge_free(&challenge);
+ goto bail;
+ }
+ if (o.debug)
+ logdebug("Reconnection header:\n%s", request);
+ if (send(sd, request, n, 0) < 0) {
+ loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
+ http_challenge_free(&challenge);
+ goto bail;
+ }
+ free(request);
+ request = NULL;
+ http_challenge_free(&challenge);
+
+ socket_buffer_init(&sockbuf, sd);
+
+ if (http_read_status_line(&sockbuf, &status_line) != 0) {
+ loguser("Error reading proxy response Status-Line.\n");
+ goto bail;
+ }
+ code = http_parse_status_line_code(status_line);
+ if (o.debug)
+ logdebug("Proxy returned status code %d.\n", code);
+ free(status_line);
+ status_line = NULL;
+ if (http_read_header(&sockbuf, &header) != 0) {
+ loguser("Error reading proxy response header.\n");
+ goto bail;
+ }
+ }
+
+ if (code != 200) {
+ loguser("Proxy returned status code %d.\n", code);
+ goto bail;
+ }
+
+ free(header);
+ header = NULL;
+
+ remainder = socket_buffer_remainder(&sockbuf, &len);
+ Write(STDOUT_FILENO, remainder, len);
+
+ return sd;
+
+bail:
+ if (sd != -1)
+ close(sd);
+ if (request != NULL)
+ free(request);
+ if (status_line != NULL)
+ free(status_line);
+ if (header != NULL)
+ free(header);
+
+ return -1;
+}
+
+
+/* SOCKS4a support
+ * Return a usable socket descriptor after
+ * proxy negotiation, or -1 on any error.
+ */
+static int do_proxy_socks4(void)
+{
+ char socksbuf[8];
+ struct socks4_data socks4msg;
+ size_t datalen;
+ char *username = o.proxy_auth != NULL ? o.proxy_auth : "";
+ union sockaddr_u addr;
+ size_t sslen;
+ int sd;
+
+ if (getaddrfamily(o.target) == 2) {
+ loguser("Error: IPv6 addresses are not supported with Socks4.\n");
+ return -1;
+ }
+
+ sd = do_connect(SOCK_STREAM);
+ if (sd == -1) {
+ loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno()));
+ return sd;
+ }
+
+ if (o.verbose) {
+ loguser("Connected to proxy %s:%hu\n", inet_socktop(&targetaddrs->addr),
+ inet_port(&targetaddrs->addr));
+ }
+
+ /* Fill the socks4_data struct */
+ zmem(&socks4msg, sizeof(socks4msg));
+ socks4msg.version = SOCKS4_VERSION;
+ socks4msg.type = SOCKS_CONNECT;
+ socks4msg.port = htons(o.portno);
+
+ if (strlen(username) >= sizeof(socks4msg.data)) {
+ loguser("Error: username is too long.\n");
+ close(sd);
+ return -1;
+ }
+ strcpy(socks4msg.data, username);
+ datalen = strlen(username) + 1;
+
+ if (proxyresolve(o.target, 0, &addr.storage, &sslen, AF_INET)) {
+ /* target resolution has failed, possibly because it is disabled */
+ if (!(o.proxydns & PROXYDNS_REMOTE)) {
+ loguser("Error: Failed to resolve host %s locally.\n", o.target);
+ close(sd);
+ return -1;
+ }
+ if (o.verbose)
+ loguser("Host %s will be resolved by the proxy.\n", o.target);
+ socks4msg.address = inet_addr("0.0.0.1");
+ if (datalen + strlen(o.target) >= sizeof(socks4msg.data)) {
+ loguser("Error: host name is too long.\n");
+ close(sd);
+ return -1;
+ }
+ strcpy(socks4msg.data + datalen, o.target);
+ datalen += strlen(o.target) + 1;
+ } else {
+ /* addr is now populated with sockaddr_in */
+ socks4msg.address = addr.in.sin_addr.s_addr;
+ if (o.verbose && getaddrfamily(o.target) == -1)
+ loguser("Host %s locally resolved to %s.\n", o.target,
+ inet_socktop(&addr));
+ }
+
+ if (send(sd, (char *)&socks4msg, offsetof(struct socks4_data, data) + datalen, 0) < 0) {
+ loguser("Error: sending proxy request: %s.\n", socket_strerror(socket_errno()));
+ close(sd);
+ return -1;
+ }
+
+ /* The size of the socks4 response is 8 bytes. So read exactly
+ 8 bytes from the buffer */
+ if (recv(sd, socksbuf, 8, 0) < 0) {
+ loguser("Error: short response from proxy.\n");
+ close(sd);
+ return -1;
+ }
+
+ if (sd != -1 && socksbuf[1] != SOCKS4_CONN_ACC) {
+ loguser("Proxy connection failed.\n");
+ close(sd);
+ return -1;
+ }
+
+ return sd;
+}
+
+/* SOCKS5 support
+ * Return a usable socket descriptor after
+ * proxy negotiation, or -1 on any error.
+ */
+static int do_proxy_socks5(void)
+{
+ struct socks5_connect socks5msg;
+ uint16_t proxyport = htons(o.portno);
+ char socksbuf[4];
+ int sd;
+ size_t dstlen, targetlen;
+ struct socks5_request socks5msg2;
+ struct socks5_auth socks5auth;
+ char *uptr, *pptr;
+ size_t authlen, ulen, plen;
+ union sockaddr_u addr;
+ size_t sslen;
+ void *addrbuf;
+ size_t addrlen;
+ size_t bndaddrlen;
+ char bndaddr[SOCKS5_DST_MAXLEN + 2]; /* IPv4/IPv6/hostname and port */
+
+ sd = do_connect(SOCK_STREAM);
+ if (sd == -1) {
+ loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno()));
+ return sd;
+ }
+
+ if (o.verbose) {
+ loguser("Connected to proxy %s:%hu\n", inet_socktop(&targetaddrs->addr),
+ inet_port(&targetaddrs->addr));
+ }
+
+ zmem(&socks5msg,sizeof(socks5msg));
+ socks5msg.ver = SOCKS5_VERSION;
+ socks5msg.nmethods = 0;
+ socks5msg.methods[socks5msg.nmethods++] = SOCKS5_AUTH_NONE;
+
+ if (o.proxy_auth)
+ socks5msg.methods[socks5msg.nmethods++] = SOCKS5_AUTH_USERPASS;
+
+ if (send(sd, (char *)&socks5msg, offsetof(struct socks5_connect, methods) + socks5msg.nmethods, 0) < 0) {
+ loguser("Error: proxy request: %s.\n", socket_strerror(socket_errno()));
+ close(sd);
+ return -1;
+ }
+
+ /* connect response just two bytes, version and auth method */
+ if (recv(sd, socksbuf, 2, 0) < 0) {
+ loguser("Error: malformed connect response from proxy.\n");
+ close(sd);
+ return -1;
+ }
+
+ if (socksbuf[0] != SOCKS5_VERSION) {
+ loguser("Error: wrong SOCKS version in connect response.\n");
+ close(sd);
+ return -1;
+ }
+
+ switch((unsigned char)socksbuf[1]) {
+ case SOCKS5_AUTH_NONE:
+ if (o.verbose)
+ loguser("No authentication needed.\n");
+ break;
+
+ case SOCKS5_AUTH_USERPASS:
+ if (o.verbose)
+ loguser("Doing username and password authentication.\n");
+
+ if(!o.proxy_auth){
+ /* Proxy must not select a method not offered by the client */
+ loguser("Error: proxy selected invalid authentication method.\n");
+ close(sd);
+ return -1;
+ }
+
+ /* Split up the proxy auth argument. */
+ uptr = o.proxy_auth;
+ pptr = strchr(o.proxy_auth, ':');
+ if (pptr == NULL) {
+ loguser("Error: invalid username:password combo.\n");
+ close(sd);
+ return -1;
+ }
+
+ ulen = (pptr++) - uptr;
+ plen = strlen(pptr);
+ if (ulen > SOCKS5_USR_MAXLEN) {
+ loguser("Error: username length exceeds %d.\n", SOCKS5_USR_MAXLEN);
+ close(sd);
+ return -1;
+ }
+ if (plen > SOCKS5_PWD_MAXLEN) {
+ loguser("Error: password length exceeds %d.\n", SOCKS5_PWD_MAXLEN);
+ close(sd);
+ return -1;
+ }
+
+ /*
+ * For username/password authentication the client's authentication request is
+ * field 1: version number, 1 byte (must be 0x01 -- version of subnegotiation)
+ * field 2: username length, 1 byte
+ * field 3: username
+ * field 4: password length, 1 byte
+ * field 5: password
+ *
+ * Server response for username/password authentication:
+ * field 1: version, 1 byte
+ * field 2: status code, 1 byte.
+ * 0x00 = success
+ * any other value = failure, connection must be closed
+ */
+
+ socks5auth.ver = 1;
+ authlen = 0;
+ socks5auth.data[authlen++] = ulen;
+ memcpy(socks5auth.data + authlen, uptr, ulen);
+ authlen += ulen;
+
+ socks5auth.data[authlen++] = plen;
+ memcpy(socks5auth.data + authlen, pptr, plen);
+ authlen += plen;
+
+ if (send(sd, (char *) &socks5auth, offsetof(struct socks5_auth, data) + authlen, 0) < 0) {
+ loguser("Error: sending proxy authentication.\n");
+ close(sd);
+ return -1;
+ }
+
+ if (recv(sd, socksbuf, 2, 0) < 0) {
+ loguser("Error: malformed proxy authentication response.\n");
+ close(sd);
+ return -1;
+ }
+
+ if (socksbuf[0] != 1 || socksbuf[1] != 0) {
+ loguser("Error: authentication failed.\n");
+ close(sd);
+ return -1;
+ }
+
+ break;
+
+ case SOCKS5_AUTH_FAILED:
+ loguser("Error: no acceptable authentication method proposed.\n");
+ close(sd);
+ return -1;
+
+ default:
+ /* Proxy must not select a method not offered by the client */
+ loguser("Error: proxy selected invalid authentication method.\n");
+ close(sd);
+ return -1;
+ }
+
+ zmem(&socks5msg2,sizeof(socks5msg2));
+ socks5msg2.ver = SOCKS5_VERSION;
+ socks5msg2.cmd = SOCKS_CONNECT;
+ socks5msg2.rsv = 0;
+
+ if (proxyresolve(o.target, 0, &addr.storage, &sslen, o.af)) {
+ /* target resolution has failed, possibly because it is disabled */
+ if (!(o.proxydns & PROXYDNS_REMOTE)) {
+ loguser("Error: Failed to resolve host %s locally.\n", o.target);
+ close(sd);
+ return -1;
+ }
+ if (o.verbose)
+ loguser("Host %s will be resolved by the proxy.\n", o.target);
+ socks5msg2.atyp = SOCKS5_ATYP_NAME;
+ targetlen = strlen(o.target);
+ if (targetlen > SOCKS5_DST_MAXLEN){
+ loguser("Error: hostname length exceeds %d.\n", SOCKS5_DST_MAXLEN);
+ close(sd);
+ return -1;
+ }
+ dstlen = 0;
+ socks5msg2.dst[dstlen++] = targetlen;
+ memcpy(socks5msg2.dst + dstlen, o.target, targetlen);
+ dstlen += targetlen;
+ } else {
+ /* addr is now populated with either sockaddr_in or sockaddr_in6 */
+ switch (addr.sockaddr.sa_family) {
+ case AF_INET:
+ socks5msg2.atyp = SOCKS5_ATYP_IPv4;
+ addrbuf = &addr.in.sin_addr;
+ addrlen = 4;
+ break;
+ case AF_INET6:
+ socks5msg2.atyp = SOCKS5_ATYP_IPv6;
+ addrbuf = &addr.in6.sin6_addr;
+ addrlen = 16;
+ break;
+ default:
+ ncat_assert(0);
+ }
+ memcpy(socks5msg2.dst, addrbuf, addrlen);
+ dstlen = addrlen;
+ if (o.verbose && getaddrfamily(o.target) == -1)
+ loguser("Host %s locally resolved to %s.\n", o.target,
+ inet_socktop(&addr));
+ }
+
+ memcpy(socks5msg2.dst + dstlen, &proxyport, 2);
+ dstlen += 2;
+
+ if (send(sd, (char *) &socks5msg2, offsetof(struct socks5_request , dst) + dstlen, 0) < 0) {
+ loguser("Error: sending proxy request: %s.\n", socket_strerror(socket_errno()));
+ close(sd);
+ return -1;
+ }
+
+ if (recv(sd, socksbuf, 4, 0) < 0) {
+ loguser("Error: malformed request response from proxy.\n");
+ close(sd);
+ return -1;
+ }
+
+ if (socksbuf[0] != SOCKS5_VERSION) {
+ loguser("Error: wrong SOCKS version in request response.\n");
+ close(sd);
+ return -1;
+ }
+
+ switch(socksbuf[1]) {
+ case 0:
+ if (o.verbose)
+ loguser("connection succeeded.\n");
+ break;
+ case 1:
+ loguser("Error: general SOCKS server failure.\n");
+ close(sd);
+ return -1;
+ case 2:
+ loguser("Error: connection not allowed by ruleset.\n");
+ close(sd);
+ return -1;
+ case 3:
+ loguser("Error: Network unreachable.\n");
+ close(sd);
+ return -1;
+ case 4:
+ loguser("Error: Host unreachable.\n");
+ close(sd);
+ return -1;
+ case 5:
+ loguser("Error: Connection refused.\n");
+ close(sd);
+ return -1;
+ case 6:
+ loguser("Error: TTL expired.\n");
+ close(sd);
+ return -1;
+ case 7:
+ loguser("Error: Command not supported.\n");
+ close(sd);
+ return -1;
+ case 8:
+ loguser("Error: Address type not supported.\n");
+ close(sd);
+ return -1;
+ default:
+ loguser("Error: unassigned value in the reply.\n");
+ close(sd);
+ return -1;
+ }
+
+ switch (socksbuf[3]) {
+ case SOCKS5_ATYP_IPv4:
+ bndaddrlen = 4 + 2;
+ break;
+ case SOCKS5_ATYP_IPv6:
+ bndaddrlen = 16 + 2;
+ break;
+ case SOCKS5_ATYP_NAME:
+ if (recv(sd, socksbuf, 1, 0) < 0) {
+ loguser("Error: malformed request response from proxy.\n");
+ close(sd);
+ return -1;
+ }
+ bndaddrlen = (unsigned char)socksbuf[0] + 2;
+ break;
+ default:
+ loguser("Error: invalid proxy bind address type.\n");
+ close(sd);
+ return -1;
+ }
+
+ if (recv(sd, bndaddr, bndaddrlen, 0) < 0) {
+ loguser("Error: malformed request response from proxy.\n");
+ close(sd);
+ return -1;
+ }
+
+ return(sd);
+}
+
+static nsock_iod new_iod(nsock_pool mypool) {
+ nsock_iod nsi = nsock_iod_new(mypool, NULL);
+ if (nsi == NULL)
+ bye("Failed to create nsock_iod.");
+ if (nsock_iod_set_hostname(nsi, o.sslservername) == -1)
+ bye("Failed to set hostname on iod.");
+
+ switch (srcaddr.storage.ss_family) {
+ case AF_UNSPEC:
+ break;
+ case AF_INET:
+ nsock_iod_set_localaddr(nsi, &srcaddr.storage,
+ sizeof(srcaddr.in));
+ break;
+#ifdef AF_INET6
+ case AF_INET6:
+ nsock_iod_set_localaddr(nsi, &srcaddr.storage,
+ sizeof(srcaddr.in6));
+ break;
+#endif
+#if HAVE_SYS_UN_H
+ case AF_UNIX:
+ nsock_iod_set_localaddr(nsi, &srcaddr.storage,
+ SUN_LEN((struct sockaddr_un *)&srcaddr.storage));
+ break;
+#endif
+ default:
+ nsock_iod_set_localaddr(nsi, &srcaddr.storage,
+ sizeof(srcaddr.storage));
+ break;
+ }
+
+ if (o.numsrcrtes) {
+ unsigned char *ipopts = NULL;
+ size_t ipoptslen = 0;
+
+ if (o.af != AF_INET)
+ bye("Sorry, -g can only currently be used with IPv4.");
+ ipopts = buildsrcrte(targetaddrs->addr.in.sin_addr, o.srcrtes, o.numsrcrtes, o.srcrteptr, &ipoptslen);
+
+ nsock_iod_set_ipoptions(nsi, ipopts, ipoptslen);
+ free(ipopts); /* Nsock has its own copy */
+ }
+ return nsi;
+}
+
+int ncat_connect(void)
+{
+ nsock_pool mypool;
+ int rc;
+
+ /* Unless explicitly asked not to do so, ncat uses the
+ * fallback nsock engine to maximize compatibility between
+ * operating systems and the different use cases.
+ */
+ if (!o.nsock_engine)
+ nsock_set_default_engine("select");
+
+ /* Create an nsock pool */
+ if ((mypool = nsock_pool_new(NULL)) == NULL)
+ bye("Failed to create nsock_pool.");
+
+ if (o.debug >= 6)
+ nsock_set_loglevel(NSOCK_LOG_DBG_ALL);
+ else if (o.debug >= 3)
+ nsock_set_loglevel(NSOCK_LOG_DBG);
+ else if (o.debug >= 1)
+ nsock_set_loglevel(NSOCK_LOG_INFO);
+ else
+ nsock_set_loglevel(NSOCK_LOG_ERROR);
+
+ /* Allow connections to broadcast addresses. */
+ nsock_pool_set_broadcast(mypool, 1);
+
+#ifdef HAVE_OPENSSL
+#ifdef HAVE_DTLS_CLIENT_METHOD
+ if(o.proto == IPPROTO_UDP)
+ set_ssl_ctx_options((SSL_CTX *) nsock_pool_dtls_init(mypool, 0));
+ else
+#endif
+ set_ssl_ctx_options((SSL_CTX *) nsock_pool_ssl_init(mypool, 0));
+#endif
+
+ if (!o.proxytype) {
+#if HAVE_SYS_UN_H
+ /* For DGRAM UNIX socket we have to use source socket */
+ if (o.af == AF_UNIX && o.proto == IPPROTO_UDP)
+ {
+ if (srcaddr.storage.ss_family != AF_UNIX) {
+ char *tmp_name = NULL;
+#if HAVE_MKSTEMP
+ char *tmpdir = getenv("TMPDIR");
+ size_t size=0, offset=0;
+ strbuf_sprintf(&tmp_name, &size, &offset, "%s/ncat.XXXXXX",
+ tmpdir ? tmpdir : "/tmp");
+ if (mkstemp(tmp_name) == -1) {
+ bye("Failed to create name for temporary DGRAM source Unix domain socket (mkstemp).");
+ }
+ unlink(tmp_name);
+#else
+ /* If no source socket was specified, we have to create temporary one. */
+ if ((tmp_name = tempnam(NULL, "ncat.")) == NULL)
+ bye("Failed to create name for temporary DGRAM source Unix domain socket (tempnam).");
+#endif
+
+ NCAT_INIT_SUN(&srcaddr, tmp_name);
+ free (tmp_name);
+ }
+
+ if (o.verbose)
+ loguser("[%s] used as source DGRAM Unix domain socket.\n", srcaddr.un.sun_path);
+ }
+#endif
+ /* A non-proxy connection. Create an iod for a new socket. */
+ cs.sock_nsi = new_iod(mypool);
+
+#if HAVE_SYS_UN_H
+ if (o.af == AF_UNIX) {
+ if (o.proto == IPPROTO_UDP) {
+ nsock_connect_unixsock_datagram(mypool, cs.sock_nsi, connect_handler, NULL,
+ &targetaddrs->addr.sockaddr,
+ SUN_LEN((struct sockaddr_un *)&targetaddrs->addr.sockaddr));
+ } else {
+ nsock_connect_unixsock_stream(mypool, cs.sock_nsi, connect_handler, o.conntimeout,
+ NULL, &targetaddrs->addr.sockaddr,
+ SUN_LEN((struct sockaddr_un *)&targetaddrs->addr.sockaddr));
+ }
+ } else
+#endif
+ {
+ /* Add connection to first resolved address. */
+ try_nsock_connect(mypool, targetaddrs);
+ }
+ } else {
+ /* A proxy connection. */
+ static int connect_socket;
+
+ if (strcmp(o.proxytype, "http") == 0) {
+ connect_socket = do_proxy_http();
+ } else if (strcmp(o.proxytype, "socks4") == 0) {
+ connect_socket = do_proxy_socks4();
+ } else if (strcmp(o.proxytype, "socks5") == 0) {
+ connect_socket = do_proxy_socks5();
+ }
+
+ if (connect_socket == -1)
+ {
+ nsock_pool_delete(mypool);
+ return 1;
+ }
+
+ /* Once the proxy negotiation is done, Nsock takes control of the
+ socket. */
+ cs.sock_nsi = nsock_iod_new2(mypool, connect_socket, NULL);
+ if (nsock_iod_set_hostname(cs.sock_nsi, o.sslservername) == -1)
+ bye("Failed to set hostname on iod.");
+ if (o.ssl)
+ {
+ /* connect_handler creates stdin_nsi and calls post_connect */
+ nsock_reconnect_ssl(mypool, cs.sock_nsi, connect_handler, o.conntimeout, NULL, NULL);
+ }
+ else
+ {
+ /* Create IOD for nsp->stdin */
+ if ((cs.stdin_nsi = nsock_iod_new2(mypool, 0, NULL)) == NULL)
+ bye("Failed to create stdin nsiod.");
+
+ post_connect(mypool, cs.sock_nsi);
+ }
+ }
+
+ /* connect */
+ rc = nsock_loop(mypool, -1);
+
+ free_sockaddr_list(targetaddrs);
+
+ if (o.verbose) {
+ struct timeval end_time;
+ double time;
+ gettimeofday(&end_time, NULL);
+ time = TIMEVAL_MSEC_SUBTRACT(end_time, start_time) / 1000.0;
+ loguser("%lu bytes sent, %lu bytes received in %.2f seconds.\n",
+ nsock_iod_get_write_count(cs.sock_nsi),
+ nsock_iod_get_read_count(cs.sock_nsi), time);
+ }
+
+#if HAVE_SYS_UN_H
+ if (o.af == AF_UNIX && o.proto == IPPROTO_UDP) {
+ if (o.verbose)
+ loguser("Deleting source DGRAM Unix domain socket. [%s]\n", srcaddr.un.sun_path);
+ unlink(srcaddr.un.sun_path);
+ }
+#endif
+
+ nsock_pool_delete(mypool);
+
+ return rc == NSOCK_LOOP_ERROR ? 1 : 0;
+}
+
+static void try_nsock_connect(nsock_pool nsp, struct sockaddr_list *conn_addr)
+{
+#ifdef HAVE_OPENSSL
+ if (o.ssl) {
+ nsock_connect_ssl(nsp, cs.sock_nsi, connect_handler,
+ o.conntimeout, (void *)conn_addr->next,
+ &conn_addr->addr.sockaddr, conn_addr->addrlen,
+ o.proto, inet_port(&conn_addr->addr),
+ NULL);
+ }
+ else
+#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ if (o.af == AF_VSOCK) {
+ if (o.proto == IPPROTO_UDP) {
+ nsock_connect_vsock_datagram(nsp, cs.sock_nsi, connect_handler,
+ (void *)conn_addr->next, &conn_addr->addr.sockaddr,
+ conn_addr->addrlen, conn_addr->addr.vm.svm_port);
+ } else {
+ nsock_connect_vsock_stream(nsp, cs.sock_nsi, connect_handler,
+ o.conntimeout, (void *)conn_addr->next,
+ &conn_addr->addr.sockaddr, conn_addr->addrlen,
+ conn_addr->addr.vm.svm_port);
+ }
+ }
+ else
+#endif
+ if (o.proto == IPPROTO_UDP) {
+ nsock_connect_udp(nsp, cs.sock_nsi, connect_handler, (void *)conn_addr->next,
+ &conn_addr->addr.sockaddr, conn_addr->addrlen,
+ inet_port(&conn_addr->addr));
+ }
+ else if (o.proto == IPPROTO_SCTP) {
+ nsock_connect_sctp(nsp, cs.sock_nsi, connect_handler,
+ o.conntimeout, (void *)conn_addr->next,
+ &conn_addr->addr.sockaddr, conn_addr->addrlen,
+ inet_port(&conn_addr->addr));
+ }
+ else {
+ nsock_connect_tcp(nsp, cs.sock_nsi, connect_handler,
+ o.conntimeout, (void *)conn_addr->next,
+ &conn_addr->addr.sockaddr, conn_addr->addrlen,
+ inet_port(&conn_addr->addr));
+ }
+}
+
+static void send_udp_null(nsock_pool nsp)
+{
+ char *NULL_PROBE = "\0";
+ int length = 1;
+ nsock_write(nsp, cs.sock_nsi, write_socket_handler, -1, NULL, NULL_PROBE, length);
+}
+
+static void connect_handler(nsock_pool nsp, nsock_event evt, void *data)
+{
+ enum nse_status status = nse_status(evt);
+ enum nse_type type = nse_type(evt);
+ struct sockaddr_list *next_addr = (struct sockaddr_list *)data;
+
+ ncat_assert(type == NSE_TYPE_CONNECT || type == NSE_TYPE_CONNECT_SSL);
+
+ if (status == NSE_STATUS_ERROR || status == NSE_STATUS_TIMEOUT) {
+ /* If there are more resolved addresses, try connecting to next one */
+ if (next_addr != NULL) {
+ if (o.verbose) {
+ union sockaddr_u peer;
+ zmem(&peer, sizeof(peer.storage));
+ nsock_iod_get_communication_info(cs.sock_nsi, NULL, NULL, NULL,
+ &peer.sockaddr, sizeof(peer.storage));
+ loguser("Connection to %s failed: %s.\n", inet_socktop(&peer),
+ (status == NSE_STATUS_TIMEOUT)
+ ? nse_status2str(status)
+ : socket_strerror(nse_errorcode(evt)));
+ loguser("Trying next address...\n");
+ }
+ /* Delete the old IOD and make a new one for the next address.
+ * This also clears SSL session info. */
+ nsock_iod_delete(cs.sock_nsi, NSOCK_PENDING_NOTIFY);
+ cs.sock_nsi = new_iod(nsp);
+
+ try_nsock_connect(nsp, next_addr);
+ return;
+ }
+ else {
+ free_sockaddr_list(targetaddrs);
+ if (!o.zerobyte||o.verbose)
+ loguser("%s.\n",
+ (status == NSE_STATUS_TIMEOUT)
+ ? nse_status2str(status)
+ : socket_strerror(nse_errorcode(evt)));
+ exit(1);
+ }
+ } else {
+ ncat_assert(status == NSE_STATUS_SUCCESS);
+ }
+
+#ifdef HAVE_OPENSSL
+ if (nsock_iod_check_ssl(cs.sock_nsi)) {
+ /* Check the domain name. ssl_post_connect_check prints an
+ error message if appropriate. */
+ if (!ssl_post_connect_check((SSL *)nsock_iod_get_ssl(cs.sock_nsi), o.sslservername))
+ bye("Certificate verification error.");
+ }
+#endif
+
+ connect_report(cs.sock_nsi);
+ if (o.proto != IPPROTO_UDP && o.zerobyte) {
+ nsock_loop_quit(nsp);
+ }
+
+ /* Create IOD for nsp->stdin */
+ if ((cs.stdin_nsi = nsock_iod_new2(nsp, 0, NULL)) == NULL)
+ bye("Failed to create stdin nsiod.");
+
+ post_connect(nsp, nse_iod(evt));
+}
+
+/* Handle --exec if appropriate, otherwise start the initial read events and set
+ the idle timeout. */
+static void post_connect(nsock_pool nsp, nsock_iod iod)
+{
+ /* Command to execute. */
+ if (o.cmdexec) {
+ struct fdinfo info;
+
+ info.fd = nsock_iod_get_sd(iod);
+#ifdef HAVE_OPENSSL
+ info.ssl = (SSL *)nsock_iod_get_ssl(iod);
+#endif
+ /* Convert Nsock's non-blocking socket to an ordinary blocking one. It's
+ possible for a program to write fast enough that it will get an
+ EAGAIN on write on a non-blocking socket. */
+ block_socket(info.fd);
+ netexec(&info, o.cmdexec);
+ }
+
+ /* Start the initial reads. */
+
+ if (!o.sendonly && !o.zerobyte)
+ nsock_read(nsp, cs.sock_nsi, read_socket_handler, -1, NULL);
+
+ if (!o.recvonly && !o.zerobyte)
+ nsock_readbytes(nsp, cs.stdin_nsi, read_stdin_handler, -1, NULL, 0);
+
+ if (o.zerobyte && o.proto==IPPROTO_UDP)
+ send_udp_null(nsp);
+
+ /* The --idle-timeout option says to exit after a certain period of
+ inactivity. We start a timer here and reset it on every read event; see
+ refresh_idle_timer. */
+ if (o.idletimeout > 0) {
+ cs.idle_timer_event_id =
+ nsock_timer_create(nsp, idle_timer_handler, o.idletimeout, NULL);
+ }
+}
+
+static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data)
+{
+ enum nse_status status = nse_status(evt);
+ enum nse_type type = nse_type(evt);
+ char *buf, *tmp = NULL;
+ int nbytes;
+
+ ncat_assert(type == NSE_TYPE_READ);
+
+
+ if (status == NSE_STATUS_EOF) {
+ if (!o.noshutdown) {
+#ifdef HAVE_OPENSSL
+ SSL *ssl = NULL;
+ if (o.ssl && NULL != (ssl = (SSL *)nsock_iod_get_ssl(cs.sock_nsi))) {
+ SSL_shutdown(ssl);
+ }
+ else
+#endif
+ shutdown(nsock_iod_get_sd(cs.sock_nsi), SHUT_WR);
+ }
+ /* In --send-only mode or non-TCP mode, exit after EOF on stdin. */
+ if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.sendonly))
+ nsock_loop_quit(nsp);
+ return;
+ } else if (status == NSE_STATUS_ERROR) {
+ loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
+ exit(1);
+ } else if (status == NSE_STATUS_TIMEOUT) {
+ loguser("%s.\n", nse_status2str(status));
+ exit(1);
+ } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) {
+ return;
+ } else {
+ ncat_assert(status == NSE_STATUS_SUCCESS);
+ }
+
+ buf = nse_readbuf(evt, &nbytes);
+
+ /* read from stdin */
+ if (o.linedelay)
+ ncat_delay_timer(o.linedelay);
+
+ if (o.crlf) {
+ if (fix_line_endings(buf, &nbytes, &tmp, &cs.crlf_state))
+ buf = tmp;
+ }
+
+ nsock_write(nsp, cs.sock_nsi, write_socket_handler, -1, NULL, buf, nbytes);
+ ncat_log_send(buf, nbytes);
+
+ if (tmp)
+ free(tmp);
+
+ refresh_idle_timer(nsp);
+}
+
+static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
+{
+ enum nse_status status = nse_status(evt);
+ enum nse_type type = nse_type(evt);
+ char *buf;
+ int nbytes;
+
+ ncat_assert(type == NSE_TYPE_READ);
+
+ if (status == NSE_STATUS_EOF) {
+#ifdef WIN32
+ _close(STDOUT_FILENO);
+#else
+ Close(STDOUT_FILENO);
+#endif
+ /* In --recv-only mode or non-TCP mode, exit after EOF on the socket. */
+ if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.recvonly))
+ nsock_loop_quit(nsp);
+ return;
+ } else if (status == NSE_STATUS_ERROR) {
+ if (!o.zerobyte||o.verbose)
+ loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
+ exit(1);
+ } else if (status == NSE_STATUS_TIMEOUT) {
+ loguser("%s.\n", nse_status2str(status));
+ exit(1);
+ } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) {
+ return;
+ } else {
+ ncat_assert(status == NSE_STATUS_SUCCESS);
+ }
+
+ buf = nse_readbuf(evt, &nbytes);
+
+ if (o.linedelay)
+ ncat_delay_timer(o.linedelay);
+
+ if (o.telnet)
+ dotelnet(nsock_iod_get_sd(nse_iod(evt)), (unsigned char *) buf, nbytes);
+
+ /* Write socket data to stdout */
+ Write(STDOUT_FILENO, buf, nbytes);
+ ncat_log_recv(buf, nbytes);
+
+ nsock_readbytes(nsp, cs.sock_nsi, read_socket_handler, -1, NULL, 0);
+
+ refresh_idle_timer(nsp);
+}
+
+static void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
+{
+ enum nse_status status = nse_status(evt);
+ enum nse_type type = nse_type(evt);
+
+ ncat_assert(type == NSE_TYPE_WRITE);
+
+ if (status == NSE_STATUS_ERROR) {
+ loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
+ exit(1);
+ } else if (status == NSE_STATUS_TIMEOUT) {
+ loguser("%s.\n", nse_status2str(status));
+ exit(1);
+ } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) {
+ return;
+ } else {
+ ncat_assert(status == NSE_STATUS_SUCCESS);
+ }
+
+ if (o.zerobyte){
+ ncat_assert(o.proto == IPPROTO_UDP);
+ nsock_read(nsp, cs.sock_nsi, read_socket_handler, -1, NULL);
+ return;
+ }
+ /* The write to the socket was successful. Allow reading more from stdin
+ now. */
+ nsock_readbytes(nsp, cs.stdin_nsi, read_stdin_handler, -1, NULL, 0);
+}
+
+static void idle_timer_handler(nsock_pool nsp, nsock_event evt, void *data)
+{
+ enum nse_status status = nse_status(evt);
+ enum nse_type type = nse_type(evt);
+
+ ncat_assert(type == NSE_TYPE_TIMER);
+
+ if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL)
+ return;
+
+ ncat_assert(status == NSE_STATUS_SUCCESS);
+
+ if (o.zerobyte&&o.proto==IPPROTO_UDP){
+ if (o.verbose)
+ loguser("UDP packet sent successfully\n");
+ nsock_loop_quit(nsp);
+ return;
+ }
+
+ loguser("Idle timeout expired (%d ms).\n", o.idletimeout);
+
+ exit(1);
+}
+
+static void refresh_idle_timer(nsock_pool nsp)
+{
+ if (o.idletimeout <= 0)
+ return;
+ nsock_event_cancel(nsp, cs.idle_timer_event_id, 0);
+ cs.idle_timer_event_id =
+ nsock_timer_create(nsp, idle_timer_handler, o.idletimeout, NULL);
+}
diff --git a/ncat/ncat_connect.h b/ncat/ncat_connect.h
new file mode 100644
index 0000000..b6d84eb
--- /dev/null
+++ b/ncat/ncat_connect.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * ncat_connect.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+#ifndef NCAT_CONNECT_H
+#define NCAT_CONNECT_H
+
+#include "nsock.h"
+
+/* handle nsock-powered connections */
+extern int ncat_connect(void);
+
+#endif
diff --git a/ncat/ncat_core.c b/ncat/ncat_core.c
new file mode 100644
index 0000000..a758749
--- /dev/null
+++ b/ncat/ncat_core.c
@@ -0,0 +1,645 @@
+/***************************************************************************
+ * ncat_core.c -- Contains option definitions and miscellaneous functions. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "ncat.h"
+#include "util.h"
+#include "sys_wrap.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <time.h>
+
+/* Only two for now because we might have to listen on IPV4 and IPV6 */
+union sockaddr_u listenaddrs[NUM_LISTEN_ADDRS];
+int num_listenaddrs = 0;
+
+union sockaddr_u srcaddr;
+size_t srcaddrlen;
+
+struct sockaddr_list *targetaddrs;
+
+/* Global options structure. */
+struct options o;
+
+/* The time the program was started, for exit statistics in connect mode. */
+struct timeval start_time;
+
+/* Initializes global options to their default values. */
+void options_init(void)
+{
+ o.verbose = 0;
+ o.debug = 0;
+ o.target = NULL;
+ o.af = AF_UNSPEC;
+ o.proto = IPPROTO_TCP;
+ o.broker = 0;
+ o.listen = 0;
+ o.keepopen = 0;
+ o.sendonly = 0;
+ o.recvonly = 0;
+ o.noshutdown = 0;
+ o.telnet = 0;
+ o.linedelay = 0;
+ o.chat = 0;
+ o.nodns = 0;
+ o.normlog = NULL;
+ o.hexlog = NULL;
+ o.normlogfd = -1;
+ o.hexlogfd = -1;
+ o.append = 0;
+ o.idletimeout = 0;
+ o.crlf = 0;
+ o.allow = 0;
+ o.deny = 0;
+ o.allowset = addrset_new();
+ o.denyset = addrset_new();
+ o.httpserver = 0;
+
+ o.nsock_engine = 0;
+
+ o.test = 0;
+
+ o.numsrcrtes = 0;
+ o.srcrteptr = 4;
+
+ o.conn_limit = -1; /* Unset. */
+ o.conntimeout = DEFAULT_CONNECT_TIMEOUT;
+
+ o.cmdexec = NULL;
+ o.execmode = EXEC_PLAIN;
+ o.proxy_auth = NULL;
+ o.proxytype = NULL;
+ o.proxyaddr = NULL;
+ o.proxydns = PROXYDNS_REMOTE;
+ o.zerobyte = 0;
+
+#ifdef HAVE_OPENSSL
+ o.ssl = 0;
+ o.sslcert = NULL;
+ o.sslkey = NULL;
+ o.sslverify = 0;
+ o.ssltrustfile = NULL;
+ o.sslciphers = NULL;
+ o.sslservername = NULL;
+ o.sslalpn = NULL;
+#endif
+}
+
+/* Internal helper for resolve and resolve_numeric. addl_flags is ored into
+ hints.ai_flags, so you can add AI_NUMERICHOST.
+ sl is a pointer to first element of sockaddr linked list, which is always
+ statically allocated. Next list elements are dynamically allocated.
+ If multiple_addrs is false then only first address is returned. */
+static int resolve_internal(const char *hostname, unsigned short port,
+ struct sockaddr_list *sl, int af, int addl_flags, int multiple_addrs)
+{
+ struct addrinfo hints;
+ struct addrinfo *result;
+ struct addrinfo *next;
+ struct sockaddr_list **item_ptr = &sl;
+ struct sockaddr_list *new_item;
+ char portbuf[16];
+ int rc;
+
+ ncat_assert(hostname != NULL);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags |= addl_flags;
+
+ /* Make the port number a string to give to getaddrinfo. */
+ rc = Snprintf(portbuf, sizeof(portbuf), "%hu", port);
+ ncat_assert(rc >= 0 && (size_t) rc < sizeof(portbuf));
+
+ rc = getaddrinfo(hostname, portbuf, &hints, &result);
+ if (rc != 0)
+ return rc;
+ if (result == NULL)
+ return EAI_NONAME;
+ ncat_assert(result->ai_addrlen > 0 && result->ai_addrlen <= (int) sizeof(struct sockaddr_storage));
+ for (next = result; next != NULL; next = next->ai_next) {
+ if (*item_ptr == NULL)
+ {
+ *item_ptr = (struct sockaddr_list *)safe_malloc(sizeof(struct sockaddr_list));
+ (**item_ptr).next = NULL;
+ }
+ new_item = *item_ptr;
+ new_item->addrlen = next->ai_addrlen;
+ memcpy(&new_item->addr.storage, next->ai_addr, next->ai_addrlen);
+ if (!multiple_addrs)
+ break;
+ item_ptr = &new_item->next;
+ }
+ freeaddrinfo(result);
+
+ return 0;
+}
+
+/* Resolves the given hostname or IP address with getaddrinfo, and stores the
+ first result (if any) in *ss and *sslen. The value of port will be set in the
+ appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in
+ which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one
+ is first depends on the system configuration. Returns 0 on success, or a
+ getaddrinfo return code (suitable for passing to gai_strerror) on failure.
+ *ss and *sslen are always defined when this function returns 0.
+
+ If the global o.nodns is true, then do not resolve any names with DNS. */
+int resolve(const char *hostname, unsigned short port,
+ struct sockaddr_storage *ss, size_t *sslen, int af)
+{
+ int flags;
+ struct sockaddr_list sl;
+ int result;
+
+ flags = 0;
+ if (o.nodns)
+ flags |= AI_NUMERICHOST;
+
+ result = resolve_internal(hostname, port, &sl, af, flags, 0);
+ *ss = sl.addr.storage;
+ *sslen = sl.addrlen;
+ return result;
+}
+
+/* Resolves the given hostname or IP address with getaddrinfo, and stores the
+ first result (if any) in *ss and *sslen. The value of port will be set in the
+ appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in
+ which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one
+ is first depends on the system configuration. Returns 0 on success, or a
+ getaddrinfo return code (suitable for passing to gai_strerror) on failure.
+ *ss and *sslen are always defined when this function returns 0.
+
+ Resolve the hostname with DNS only if global o.proxydns includes PROXYDNS_LOCAL. */
+int proxyresolve(const char *hostname, unsigned short port,
+ struct sockaddr_storage *ss, size_t *sslen, int af)
+{
+ int flags;
+ struct sockaddr_list sl;
+ int result;
+
+ flags = 0;
+ if (!(o.proxydns & PROXYDNS_LOCAL))
+ flags |= AI_NUMERICHOST;
+
+ result = resolve_internal(hostname, port, &sl, af, flags, 0);
+ *ss = sl.addr.storage;
+ *sslen = sl.addrlen;
+ return result;
+}
+
+/* Resolves the given hostname or IP address with getaddrinfo, and stores
+ all results into a linked list.
+ The rest of the behavior is same as resolve(). */
+int resolve_multi(const char *hostname, unsigned short port,
+ struct sockaddr_list *sl, int af)
+{
+ int flags;
+
+ flags = 0;
+ if (o.nodns)
+ flags |= AI_NUMERICHOST;
+
+ return resolve_internal(hostname, port, sl, af, flags, 1);
+}
+
+void free_sockaddr_list(struct sockaddr_list *sl)
+{
+ struct sockaddr_list *current, *next = sl;
+ while (next != NULL) {
+ current = next;
+ next = current->next;
+ free(current);
+ }
+}
+
+int fdinfo_close(struct fdinfo *fdn)
+{
+#ifdef HAVE_OPENSSL
+ if (o.ssl && fdn->ssl != NULL) {
+ SSL_shutdown(fdn->ssl);
+ SSL_free(fdn->ssl);
+ fdn->ssl = NULL;
+ }
+#endif
+
+ return close(fdn->fd);
+}
+
+/* Do a recv on an fdinfo, without other side effects. */
+int fdinfo_recv(struct fdinfo *fdn, char *buf, size_t size)
+{
+ int n;
+#ifdef HAVE_OPENSSL
+ int err = SSL_ERROR_NONE;
+ if (o.ssl && fdn->ssl)
+ {
+ do {
+ n = SSL_read(fdn->ssl, buf, size);
+ /* SSL_read returns <=0 in some cases like renegotiation. In these
+ * cases, SSL_get_error gives SSL_ERROR_WANT_{READ,WRITE}, and we
+ * should try the SSL_read again. */
+ err = (n <= 0) ? SSL_get_error(fdn->ssl, n) : SSL_ERROR_NONE;
+ } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
+ switch (err) {
+ case SSL_ERROR_NONE:
+ break;
+ case SSL_ERROR_ZERO_RETURN:
+ fdn->lasterr = EOF;
+ break;
+ default:
+ fdn->lasterr = err;
+ logdebug("SSL_read error on %d: %s\n", fdn->fd, ERR_error_string(err, NULL));
+ break;
+ }
+ return n;
+ }
+#endif
+ n = recv(fdn->fd, buf, size, 0);
+ if (n == 0)
+ fdn->lasterr = EOF;
+ else if (n < 0)
+ fdn->lasterr = socket_errno();
+ return n;
+}
+
+int fdinfo_pending(struct fdinfo *fdn)
+{
+#ifdef HAVE_OPENSSL
+ if (o.ssl && fdn->ssl)
+ return SSL_pending(fdn->ssl);
+#endif
+ return 0;
+}
+
+/* Read from a client socket into buf, returning the number of bytes read, or -1
+ on an error. This takes care of delays, Telnet negotiation, and logging.
+
+ If there is more data pending that won't be noticed by select, a 1 is stored
+ in *pending, otherwise 0 is stored there. The caller must loop, processing
+ read data until *pending is false. The reason for this is the SSL_read
+ function that this function may call, which takes data out of the socket
+ buffer (so select may not indicate the socket is readable) and keeps it in
+ its own buffer. *pending holds the result of calling SSL_pending. See
+ http://www.mail-archive.com/openssl-dev@openssl.org/msg24324.html. */
+int ncat_recv(struct fdinfo *fdn, char *buf, size_t size, int *pending)
+{
+ int n;
+
+ *pending = 0;
+
+ n = fdinfo_recv(fdn, buf, size);
+
+ if (n <= 0)
+ return n;
+
+ if (o.linedelay)
+ ncat_delay_timer(o.linedelay);
+ if (o.telnet)
+ dotelnet(fdn->fd, (unsigned char *) buf, n);
+ ncat_log_recv(buf, n);
+
+ /* SSL can buffer our input, so doing another select() won't necessarily
+ work for us. Indicate to the caller that this function must be called
+ again to get more data. */
+ *pending = fdinfo_pending(fdn);
+
+ return n;
+}
+
+/* Do a send on an fdinfo, without any logging or other side effects. */
+int fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size)
+{
+ int n;
+#ifdef HAVE_OPENSSL
+ int err = SSL_ERROR_NONE;
+ if (o.ssl && fdn->ssl != NULL)
+ {
+ do {
+ n = SSL_write(fdn->ssl, buf, size);
+ /* SSL_write returns <=0 in some cases like renegotiation. In these
+ * cases, SSL_get_error gives SSL_ERROR_WANT_{READ,WRITE}, and we
+ * should try the SSL_write again. */
+ err = (n <= 0) ? SSL_get_error(fdn->ssl, n) : SSL_ERROR_NONE;
+ } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
+ if (err != SSL_ERROR_NONE) {
+ fdn->lasterr = err;
+ logdebug("SSL_write error on %d: %s\n", fdn->fd, ERR_error_string(err, NULL));
+ }
+ return n;
+ }
+#endif
+ n = send(fdn->fd, buf, size, 0);
+ if (n <= 0)
+ fdn->lasterr = socket_errno();
+ return n;
+}
+
+/* If we are sending a large amount of data, we might momentarily run out of send
+ space and get an EAGAIN when we send. Temporarily convert a socket to
+ blocking more, do the send, and unblock it again. Assumes that the socket was
+ in nonblocking mode to begin with; it has the side effect of leaving the
+ socket nonblocking on return. */
+static int blocking_fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size)
+{
+ int ret;
+
+ block_socket(fdn->fd);
+ ret = fdinfo_send(fdn, buf, size);
+ unblock_socket(fdn->fd);
+
+ return ret;
+}
+
+int ncat_send(struct fdinfo *fdn, const char *buf, size_t size)
+{
+ int n;
+
+ if (o.recvonly)
+ return size;
+
+ n = blocking_fdinfo_send(fdn, buf, size);
+ if (n <= 0)
+ return n;
+
+ ncat_log_send(buf, size);
+
+ return n;
+}
+
+/* Broadcast a message to all the descriptors in fds. Returns -1 if any of the
+ sends failed. */
+int ncat_broadcast(fd_set *fds, const fd_list_t *fdlist, const char *msg, size_t size)
+{
+ struct fdinfo *fdn;
+ int i, ret;
+
+ if (o.recvonly)
+ return size;
+
+ ret = 0;
+ for (i = 0; i < fdlist->nfds; i++) {
+ fdn = &fdlist->fds[i];
+ if (!checked_fd_isset(fdn->fd, fds))
+ continue;
+
+ if (blocking_fdinfo_send(fdn, msg, size) <= 0) {
+ if (o.debug > 1)
+ logdebug("Error sending to fd %d: %s.\n", fdn->fd, socket_strerror(fdn->lasterr));
+ ret = -1;
+ }
+ }
+
+ ncat_log_send(msg, size);
+
+ return ret;
+}
+
+/* Do telnet WILL/WONT DO/DONT negotiations */
+void dotelnet(int s, unsigned char *buf, size_t bufsiz)
+{
+ unsigned char *end = buf + bufsiz, *p;
+ unsigned char tbuf[3];
+
+ for (p = buf; buf < end; p++) {
+ if (*p != 255) /* IAC */
+ break;
+
+ tbuf[0] = *p++;
+
+ /* Answer DONT for WILL or WONT */
+ if (*p == 251 || *p == 252)
+ tbuf[1] = 254;
+
+ /* Answer WONT for DO or DONT */
+ else if (*p == 253 || *p == 254)
+ tbuf[1] = 252;
+
+ tbuf[2] = *++p;
+
+ send(s, (const char *) tbuf, 3, 0);
+ }
+}
+
+/* sleep(), usleep(), msleep(), Sleep() -- all together now, "portability".
+ *
+ * There is no upper or lower limit to the delayval, so if you pass in a short
+ * length of time <100ms, then you're likely going to get odd results.
+ * This is because the Linux timeslice is 10ms-200ms. So don't expect
+ * it to return for at least that long.
+ *
+ * Block until the specified time has elapsed, then return 1.
+ */
+int ncat_delay_timer(int delayval)
+{
+ struct timeval s;
+
+ s.tv_sec = delayval / 1000;
+ s.tv_usec = (delayval % 1000) * (long) 1000;
+
+ select(0, NULL, NULL, NULL, &s);
+ return 1;
+}
+
+static int ncat_hexdump(int logfd, const char *data, int len);
+
+void ncat_log_send(const char *data, size_t len)
+{
+ if (o.normlogfd != -1)
+ Write(o.normlogfd, data, len);
+
+ if (o.hexlogfd != -1)
+ ncat_hexdump(o.hexlogfd, data, len);
+}
+
+void ncat_log_recv(const char *data, size_t len)
+{
+ /* Currently the log formats don't distinguish sends and receives. */
+ ncat_log_send(data, len);
+}
+
+/* Convert session data to a neat hexdump logfile */
+static int ncat_hexdump(int logfd, const char *data, int len)
+{
+ char *str = NULL;
+ str = hexdump((u8 *) data, len);
+ if (str) {
+ Write(logfd, str, strlen(str));
+ free(str);
+ }
+ else {
+ return 0;
+ }
+ return 1;
+}
+
+/* this function will return in what format the target
+ * host is specified. It will return:
+ * 1 - for ipv4,
+ * 2 - for ipv6,
+ * -1 - for hostname
+ * this has to work even if there is no IPv6 support on
+ * local system, proxy may support it.
+ */
+int getaddrfamily(const char *addr)
+{
+ int ret;
+ struct addrinfo hint, *info = 0;
+
+ if (strchr(addr,':'))
+ return 2;
+
+ zmem(&hint,sizeof(hint));
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_flags = AI_NUMERICHOST;
+ ret = getaddrinfo(addr, 0, &hint, &info);
+ if (ret)
+ return -1;
+ freeaddrinfo(info);
+ return 1;
+}
+
+void setup_environment(struct fdinfo *info)
+{
+ union sockaddr_u su;
+ char ip[INET6_ADDRSTRLEN];
+ char port[16];
+ socklen_t alen = sizeof(su);
+
+ if (getpeername(info->fd, &su.sockaddr, &alen) != 0) {
+ bye("getpeername failed: %s", socket_strerror(socket_errno()));
+ }
+#ifdef HAVE_SYS_UN_H
+ if (su.sockaddr.sa_family == AF_UNIX) {
+ /* say localhost to keep it backwards compatible */
+ setenv_portable("NCAT_REMOTE_ADDR", "localhost");
+ setenv_portable("NCAT_REMOTE_PORT", "");
+ } else
+#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ if (su.sockaddr.sa_family == AF_VSOCK) {
+ char char_u32[11];
+
+ snprintf(char_u32, sizeof(char_u32), "%u", su.vm.svm_cid);
+ setenv_portable("NCAT_REMOTE_ADDR", char_u32);
+
+ snprintf(char_u32, sizeof(char_u32), "%u", su.vm.svm_port);
+ setenv_portable("NCAT_REMOTE_PORT", char_u32);
+ } else
+#endif
+ if (getnameinfo((struct sockaddr *)&su, alen, ip, sizeof(ip),
+ port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
+ setenv_portable("NCAT_REMOTE_ADDR", ip);
+ setenv_portable("NCAT_REMOTE_PORT", port);
+ } else {
+ bye("getnameinfo failed: %s", socket_strerror(socket_errno()));
+ }
+
+ if (getsockname(info->fd, (struct sockaddr *)&su, &alen) < 0) {
+ bye("getsockname failed: %s", socket_strerror(socket_errno()));
+ }
+#ifdef HAVE_SYS_UN_H
+ if (su.sockaddr.sa_family == AF_UNIX) {
+ /* say localhost to keep it backwards compatible, else su.un.sun_path */
+ setenv_portable("NCAT_LOCAL_ADDR", "localhost");
+ setenv_portable("NCAT_LOCAL_PORT", "");
+ } else
+#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ if (su.sockaddr.sa_family == AF_VSOCK) {
+ char char_u32[11];
+
+ snprintf(char_u32, sizeof(char_u32), "%u", su.vm.svm_cid);
+ setenv_portable("NCAT_LOCAL_ADDR", char_u32);
+
+ snprintf(char_u32, sizeof(char_u32), "%u", su.vm.svm_port);
+ setenv_portable("NCAT_LOCAL_PORT", char_u32);
+ } else
+#endif
+ if (getnameinfo((struct sockaddr *)&su, alen, ip, sizeof(ip),
+ port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
+ setenv_portable("NCAT_LOCAL_ADDR", ip);
+ setenv_portable("NCAT_LOCAL_PORT", port);
+ } else {
+ bye("getnameinfo failed: %s", socket_strerror(socket_errno()));
+ }
+
+ switch(o.proto) {
+ case IPPROTO_TCP:
+ setenv_portable("NCAT_PROTO", "TCP");
+ break;
+ case IPPROTO_SCTP:
+ setenv_portable("NCAT_PROTO", "SCTP");
+ break;
+ case IPPROTO_UDP:
+ setenv_portable("NCAT_PROTO", "UDP");
+ break;
+ }
+}
diff --git a/ncat/ncat_core.h b/ncat/ncat_core.h
new file mode 100644
index 0000000..b1d66b0
--- /dev/null
+++ b/ncat/ncat_core.h
@@ -0,0 +1,245 @@
+/***************************************************************************
+ * ncat_core.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef NCAT_CORE_H
+#define NCAT_CORE_H
+
+#include "nsock.h"
+#include "nbase.h"
+#include "util.h"
+#include "sockaddr_u.h"
+
+/* Maximum size of the srcaddrs array. In this case two because we can only have
+ a IPV4 INADDR_ANY and a IPV6 in6addr_any at most or a user defined address */
+#define NUM_LISTEN_ADDRS 2
+
+/* Structure to store a linked list of resolved addresses. */
+struct sockaddr_list {
+ union sockaddr_u addr;
+ size_t addrlen;
+ struct sockaddr_list* next;
+};
+
+extern union sockaddr_u listenaddrs[NUM_LISTEN_ADDRS];
+extern int num_listenaddrs;
+
+extern union sockaddr_u srcaddr;
+extern size_t srcaddrlen;
+
+extern struct sockaddr_list *targetaddrs;
+
+enum exec_mode {
+ EXEC_PLAIN,
+ EXEC_SHELL,
+ EXEC_LUA,
+};
+
+/* Proxy DNS resolution options (mask bits) */
+#define PROXYDNS_LOCAL 1
+#define PROXYDNS_REMOTE 2
+
+struct options {
+ unsigned int portno;
+
+ int verbose;
+ int debug;
+ char *target;
+ int af;
+ /* IPPROTO_TCP, IPPROTO_SCTP, or IPPROTO_UDP */
+ int proto;
+ int broker;
+ int listen;
+ int keepopen;
+ int sendonly;
+ int recvonly;
+ int noshutdown;
+ int telnet;
+ int linedelay;
+ int chat;
+ int nodns;
+ const char *normlog;
+ const char *hexlog;
+ int normlogfd;
+ int hexlogfd;
+ int append;
+ int idletimeout;
+ int crlf;
+ /* Were any hosts specifically allowed? If so, deny all others. */
+ int allow;
+ int deny;
+ struct addrset *allowset;
+ struct addrset *denyset;
+ int httpserver;
+ int nsock_engine;
+ /* Output messages useful for testing to stderr? */
+ int test;
+
+ /* Loose source-routing stuff */
+ struct in_addr srcrtes[8];
+ int numsrcrtes;
+ int srcrteptr;
+
+ /* Maximum number of simultaneous connections */
+ int conn_limit;
+ int conntimeout;
+
+ /* When execmode == EXEC_LUA, cmdexec is the name of the file to run. */
+ char *cmdexec;
+ enum exec_mode execmode;
+ char *proxy_auth;
+ char *proxytype;
+ char *proxyaddr;
+ int proxydns;
+
+ int ssl;
+ char *sslcert;
+ char *sslkey;
+ int sslverify;
+ char *ssltrustfile;
+ char *sslciphers;
+ char* sslservername;
+ char *sslalpn;
+ int zerobyte;
+};
+
+extern struct options o;
+
+/* The time the program was started, for exit statistics in connect mode. */
+extern struct timeval start_time;
+
+/* Initializes global options to their default values. */
+void options_init(void);
+
+/* Resolves the given hostname or IP address with getaddrinfo, and stores the
+ first result (if any) in *ss and *sslen. The value of port will be set in the
+ appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in
+ which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one
+ is first depends on the system configuration. Returns 0 on success, or a
+ getaddrinfo return code (suitable for passing to gai_strerror) on failure.
+ *ss and *sslen are always defined when this function returns 0.
+
+ If the global o.nodns is true, then do not resolve any names with DNS. */
+int resolve(const char *hostname, unsigned short port,
+ struct sockaddr_storage *ss, size_t *sslen, int af);
+
+/* Resolves the given hostname or IP address with getaddrinfo, and stores the
+ first result (if any) in *ss and *sslen. The value of port will be set in the
+ appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in
+ which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one
+ is first depends on the system configuration. Returns 0 on success, or a
+ getaddrinfo return code (suitable for passing to gai_strerror) on failure.
+ *ss and *sslen are always defined when this function returns 0.
+
+ Resolve the hostname with DNS only if global o.proxydns includes PROXYDNS_LOCAL. */
+int proxyresolve(const char *hostname, unsigned short port,
+ struct sockaddr_storage *ss, size_t *sslen, int af);
+
+/* Resolves the given hostname or IP address with getaddrinfo, and stores
+ all results into a linked list.
+ The rest of behavior is same as resolve(). */
+int resolve_multi(const char *hostname, unsigned short port,
+ struct sockaddr_list *sl, int af);
+
+void free_sockaddr_list(struct sockaddr_list *sl);
+
+int fdinfo_close(struct fdinfo *fdn);
+int fdinfo_recv(struct fdinfo *fdn, char *buf, size_t size);
+int fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size);
+int fdinfo_pending(struct fdinfo *fdn);
+
+int ncat_recv(struct fdinfo *fdn, char *buf, size_t size, int *pending);
+int ncat_send(struct fdinfo *fdn, const char *buf, size_t size);
+
+/* Broadcast a message to all the descriptors in fds. Returns -1 if any of the
+ sends failed. */
+extern int ncat_broadcast(fd_set *fds, const fd_list_t *fdlist, const char *msg, size_t size);
+
+/* Do telnet WILL/WONT DO/DONT negotiations */
+extern void dotelnet(int s, unsigned char *buf, size_t bufsiz);
+
+/* sleep(), usleep(), msleep(), Sleep() -- all together now, "portability".
+ *
+ * There is no upper or lower limit to the delayval, so if you pass in a short
+ * length of time <100ms, then you're likely going to get odd results.
+ * This is because the Linux timeslice is 10ms-200ms. So don't expect
+ * it to return for at least that long.
+ *
+ * Block until the specified time has elapsed, then return 1.
+ */
+extern int ncat_delay_timer(int delayval);
+
+/* Open a logfile for writing.
+ * Return the open file descriptor. */
+extern int ncat_openlog(const char *logfile, int append);
+
+extern void ncat_log_send(const char *data, size_t len);
+
+extern void ncat_log_recv(const char *data, size_t len);
+
+extern int ncat_hostaccess(char *matchaddr, char *filename, char *remoteip);
+
+/* Make it so that line endings read from a console are always \n (not \r\n).
+ Defined in ncat_posix.c and ncat_win.c. */
+extern void set_lf_mode(void);
+
+extern int getaddrfamily(const char *addr);
+extern int setenv_portable(const char *name, const char *value);
+extern void setup_environment(struct fdinfo *fdinfo);
+
+#endif
diff --git a/ncat/ncat_exec.h b/ncat/ncat_exec.h
new file mode 100644
index 0000000..0c57a96
--- /dev/null
+++ b/ncat/ncat_exec.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * ncat_exec.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+#ifndef NCAT_EXEC_H
+#define NCAT_EXEC_H
+
+/* fork and exec a child process with netexec. Close the given file descriptor
+ in the parent process. Return the child's PID or -1 on error. */
+extern int netrun(struct fdinfo *info, char *cmdexec);
+
+/* exec the given command line. Before the exec, redirect stdin, stdout, and
+ stderr to the given file descriptor. Never returns. */
+extern void netexec(struct fdinfo *info, char *cmdexec);
+
+#ifdef WIN32
+/* Set a pseudo-signal handler that is called when a thread representing a
+ child process dies. This is only used on Windows. */
+extern void set_pseudo_sigchld_handler(void (*handler)(void));
+#endif
+
+#endif
diff --git a/ncat/ncat_exec_win.c b/ncat/ncat_exec_win.c
new file mode 100644
index 0000000..faa8cda
--- /dev/null
+++ b/ncat/ncat_exec_win.c
@@ -0,0 +1,698 @@
+/***************************************************************************
+ * ncat_exec_win.c -- Windows-specific subprocess execution. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "ncat.h"
+
+/* This structure holds information about a subprocess with redirected input
+ and output handles. */
+struct subprocess_info {
+ HANDLE proc;
+ struct fdinfo fdn;
+ HANDLE child_in_r;
+ HANDLE child_in_w;
+ HANDLE child_out_r;
+ HANDLE child_out_w;
+};
+
+/* A list of subprocesses, so we can kill them when the program exits. */
+static HANDLE subprocesses[DEFAULT_MAX_CONNS];
+static int subprocess_max_index = 0;
+/* Prevent concurrent access to the subprocesses table by the main process and
+ a thread. Protects subprocesses and subprocesses_max_index. */
+static HANDLE subprocesses_mutex = NULL;
+
+static int start_subprocess(char *cmdexec, struct subprocess_info *info);
+static DWORD WINAPI subprocess_thread_func(void *data);
+
+static int register_subprocess(HANDLE proc);
+static int unregister_subprocess(HANDLE proc);
+static int get_subprocess_slot(void);
+
+/* Have we registered the termination handler yet? */
+static int atexit_registered = 0;
+static void terminate_subprocesses(void);
+static void sigint_handler(int s);
+
+/* This may be set with set_pseudo_sigchld_handler. It is called when a thread
+ representing a child process ends. */
+static void (*pseudo_sigchld_handler)(void) = NULL;
+/* Simulates blocking of SIGCHLD while the handler runs. Also prevents
+ concurrent modification of pseudo_sigchld_handler. */
+static HANDLE pseudo_sigchld_mutex = NULL;
+
+/* Run a child process, redirecting its standard file handles to a socket
+ descriptor. Return the child's PID or -1 on error. */
+int netrun(struct fdinfo *fdn, char *cmdexec)
+{
+ struct subprocess_info *info;
+ HANDLE thread;
+ int pid;
+
+ info = (struct subprocess_info *) safe_malloc(sizeof(*info));
+ info->fdn = *fdn;
+
+ pid = start_subprocess(cmdexec, info);
+ if (pid == -1) {
+ close(info->fdn.fd);
+ free(info);
+ return -1;
+ }
+
+ /* Start up the thread to handle process I/O. */
+ thread = CreateThread(NULL, 0, subprocess_thread_func, info, 0, NULL);
+ if (thread == NULL) {
+ if (o.verbose)
+ logdebug("Error in CreateThread: %d\n", GetLastError());
+ free(info);
+ return -1;
+ }
+ CloseHandle(thread);
+
+ return pid;
+}
+
+/* Run the given command line as if by exec. Doesn't return. */
+void netexec(struct fdinfo *fdn, char *cmdexec)
+{
+ struct subprocess_info *info;
+ int pid;
+ DWORD ret;
+
+ info = (struct subprocess_info *) safe_malloc(sizeof(*info));
+ info->fdn = *fdn;
+
+ pid = start_subprocess(cmdexec, info);
+ if (pid == -1)
+ ExitProcess(2);
+
+ /* Run the subprocess thread function, but don't put it in a thread. Just
+ run it and exit with its return value because we're simulating exec. */
+ ExitProcess(subprocess_thread_func(info));
+}
+
+/* Set a pseudo-signal handler that is called when a thread representing a
+ child process dies. This is only used on Windows. */
+extern void set_pseudo_sigchld_handler(void (*handler)(void))
+{
+ DWORD rc;
+
+ if (pseudo_sigchld_mutex == NULL) {
+ pseudo_sigchld_mutex = CreateMutex(NULL, FALSE, NULL);
+ ncat_assert(pseudo_sigchld_mutex != NULL);
+ }
+ rc = WaitForSingleObject(pseudo_sigchld_mutex, INFINITE);
+ ncat_assert(rc == WAIT_OBJECT_0);
+ pseudo_sigchld_handler = handler;
+ rc = ReleaseMutex(pseudo_sigchld_mutex);
+ ncat_assert(rc != 0);
+}
+
+int setenv_portable(const char *name, const char *value)
+{
+ char *var;
+ int ret;
+ size_t len;
+ len = strlen(name) + strlen(value) + 2; /* 1 for '\0', 1 for =. */
+ var = (char *) safe_malloc(len);
+ Snprintf(var, len, "%s=%s", name, value);
+ /* _putenv was chosen over SetEnvironmentVariable because variables set
+ with the latter seem to be invisible to getenv() calls and Lua uses
+ these in the 'os' module. */
+ ret = _putenv(var) == 0;
+ free(var);
+ return ret;
+}
+
+/* Run a command and redirect its input and output handles to a pair of
+ anonymous pipes. The process handle and pipe handles are returned in the
+ info struct. Returns the PID of the new process, or -1 on error. */
+static int run_command_redirected(char *cmdexec, struct subprocess_info *info)
+{
+ /* Each named pipe we create has to have a unique name. */
+ static int pipe_serial_no = 0;
+ char pipe_name[32];
+ SECURITY_ATTRIBUTES sa;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ setup_environment(&info->fdn);
+
+ /* Make the pipe handles inheritable. */
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ /* The child's input pipe is an ordinary blocking pipe. */
+ if (CreatePipe(&info->child_in_r, &info->child_in_w, &sa, 0) == 0) {
+ if (o.verbose)
+ logdebug("Error in CreatePipe: %d\n", GetLastError());
+ return -1;
+ }
+
+ /* Pipe names must have this special form. */
+ Snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\pipe\\ncat-%d-%d",
+ GetCurrentProcessId(), pipe_serial_no);
+ if (o.debug > 1)
+ logdebug("Creating named pipe \"%s\"\n", pipe_name);
+
+ /* The output pipe has to be nonblocking, which requires this complicated
+ setup. */
+ info->child_out_r = CreateNamedPipe(pipe_name,
+ PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE, 1, 4096, 4096, 1000, &sa);
+ if (info->child_out_r == 0) {
+ if (o.verbose)
+ logdebug("Error in CreateNamedPipe: %d\n", GetLastError());
+ CloseHandle(info->child_in_r);
+ CloseHandle(info->child_in_w);
+ return -1;
+ }
+ info->child_out_w = CreateFile(pipe_name,
+ GENERIC_WRITE, 0, &sa, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+ if (info->child_out_w == 0) {
+ CloseHandle(info->child_in_r);
+ CloseHandle(info->child_in_w);
+ CloseHandle(info->child_out_r);
+ return -1;
+ }
+ pipe_serial_no++;
+
+ /* Don't inherit our end of the pipes. */
+ SetHandleInformation(info->child_in_w, HANDLE_FLAG_INHERIT, 0);
+ SetHandleInformation(info->child_out_r, HANDLE_FLAG_INHERIT, 0);
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.hStdInput = info->child_in_r;
+ si.hStdOutput = info->child_out_w;
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.dwFlags |= STARTF_USESTDHANDLES;
+
+ memset(&pi, 0, sizeof(pi));
+
+ if (CreateProcess(NULL, cmdexec, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == 0) {
+ if (o.verbose) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&lpMsgBuf,
+ 0, NULL);
+
+ logdebug("Error in CreateProcess: %s\nCommand was: %s\n", (lpMsgBuf), cmdexec);
+ }
+ CloseHandle(info->child_in_r);
+ CloseHandle(info->child_in_w);
+ CloseHandle(info->child_out_r);
+ CloseHandle(info->child_out_w);
+ return -1;
+ }
+
+ /* Close hThread here because we have no use for it. hProcess is closed in
+ subprocess_info_close. */
+ CloseHandle(pi.hThread);
+
+ info->proc = pi.hProcess;
+
+ return pi.dwProcessId;
+}
+
+static const char *get_shell(void)
+{
+ const char *comspec;
+
+ comspec = getenv("COMSPEC");
+ if (comspec == NULL)
+ comspec = "cmd.exe";
+
+ return comspec;
+}
+
+static void subprocess_info_close(struct subprocess_info *info)
+{
+#ifdef HAVE_OPENSSL
+ if (info->fdn.ssl != NULL) {
+ SSL_shutdown(info->fdn.ssl);
+ SSL_free(info->fdn.ssl);
+ }
+#endif
+ closesocket(info->fdn.fd);
+ CloseHandle(info->proc);
+ CloseHandle(info->child_in_r);
+ CloseHandle(info->child_in_w);
+ CloseHandle(info->child_out_r);
+ CloseHandle(info->child_out_w);
+}
+
+/* Start a subprocess with run_command_redirected and register it with the
+ termination handler. Takes care of o.shellexec. Returns the PID of the
+ subprocess or -1 on error. */
+static int start_subprocess(char *cmdexec, struct subprocess_info *info)
+{
+ char *cmdbuf;
+ int pid;
+
+ if (o.execmode == EXEC_SHELL) {
+ /* Run with cmd.exe. */
+ const char *shell;
+ size_t cmdlen;
+
+ shell = get_shell();
+ cmdlen = strlen(shell) + strlen(cmdexec) + 32;
+ cmdbuf = (char *) safe_malloc(cmdlen);
+ Snprintf(cmdbuf, cmdlen, "%s /C %s", shell, cmdexec);
+#ifdef HAVE_LUA
+ } else if (o.execmode == EXEC_LUA) {
+ char exepath[8192];
+ char *cmdexec_escaped, *exepath_escaped;
+ int n;
+
+ n = GetModuleFileName(GetModuleHandle(0), exepath, sizeof(exepath));
+ if (n == 0 || n == sizeof(exepath))
+ return -1;
+
+ cmdexec_escaped = escape_windows_command_arg(cmdexec);
+ if (cmdexec_escaped == NULL)
+ return -1;
+
+ exepath_escaped = escape_windows_command_arg(exepath);
+ if (exepath_escaped == NULL) {
+ free(cmdexec_escaped);
+ return -1;
+ }
+
+ n = asprintf(&cmdbuf, "%s --lua-exec-internal %s", exepath_escaped, cmdexec_escaped);
+ free(cmdexec_escaped);
+ free(exepath_escaped);
+ if (n < 0)
+ return -1;
+#endif
+ } else {
+ cmdbuf = cmdexec;
+ }
+
+ if (o.debug)
+ logdebug("Executing: %s\n", cmdbuf);
+
+ pid = run_command_redirected(cmdbuf, info);
+
+ if (cmdbuf != cmdexec)
+ free(cmdbuf);
+
+ if (pid == -1)
+ return -1;
+
+ if (register_subprocess(info->proc) == -1) {
+ if (o.verbose)
+ logdebug("Couldn't register subprocess with termination handler; not executing.\n");
+ TerminateProcess(info->proc, 2);
+ subprocess_info_close(info);
+ return -1;
+ }
+
+ return pid;
+}
+
+/* Relay data between a socket and a process until the process dies or stops
+ sending or receiving data. The socket descriptor and process pipe handles
+ are in the data argument, which must be a pointer to struct subprocess_info.
+
+ This function is a workaround for the fact that we can't just run a process
+ after redirecting its input handles to a socket. If the process, for
+ example, redirects its own stdin, it somehow confuses the socket and stdout
+ stops working. This is exactly what ncat does (as part of the Windows stdin
+ workaround), so it can't be ignored.
+
+ This function can be invoked through CreateThread to simulate fork+exec, or
+ called directly to simulate exec. It frees the subprocess_info struct and
+ closes the socket and pipe handles before returning. Returns the exit code
+ of the subprocess. */
+static DWORD WINAPI subprocess_thread_func(void *data)
+{
+ struct subprocess_info *info;
+ char pipe_buffer[BUFSIZ];
+ OVERLAPPED overlap = { 0 };
+ HANDLE events[3];
+ DWORD ret, rc;
+ int crlf_state = 0;
+
+ info = (struct subprocess_info *) data;
+
+ /* Three events we watch for: socket read, pipe read, and process end. */
+ events[0] = (HANDLE) WSACreateEvent();
+ WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE);
+ events[1] = info->child_out_r;
+ events[2] = info->proc;
+
+ /* To avoid blocking or polling, we use asynchronous I/O, or what Microsoft
+ calls "overlapped" I/O, on the process pipe. WaitForMultipleObjects
+ reports when the read operation is complete. */
+ ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap);
+
+ /* Loop until EOF or error. */
+ for (;;) {
+ DWORD n_r, n_w;
+ int i, n;
+ char *crlf = NULL, *wbuf;
+ char buffer[BUFSIZ];
+ int pending;
+
+ i = WaitForMultipleObjects(3, events, FALSE, INFINITE);
+ switch(i) {
+ case WAIT_OBJECT_0:
+ /* Read from socket, write to process. */
+
+ /* Reset events on the socket. SSL_read in particular does not
+ * clear the event. */
+ ResetEvent(events[0]);
+ WSAEventSelect(info->fdn.fd, events[0], 0);
+ block_socket(info->fdn.fd);
+ do {
+ n = ncat_recv(&info->fdn, buffer, sizeof(buffer), &pending);
+ if (n <= 0)
+ {
+ /* return value can be 0 without meaning EOF in some cases such as SSL
+ * renegotiations that require read/write socket operations but do not
+ * have any application data. */
+ if(n == 0 && info->fdn.lasterr == 0) {
+ continue; /* Check pending */
+ }
+ goto loop_end;
+ }
+ n_r = n;
+ if (WriteFile(info->child_in_w, buffer, n_r, &n_w, NULL) == 0)
+ {
+ goto loop_end;
+ }
+ if (n_w != n)
+ {
+ goto loop_end;
+ }
+ } while (pending);
+ /* Restore the select event (and non-block the socket again.) */
+ WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE);
+ /* Fall through to check other objects */
+ case WAIT_OBJECT_0 + 1:
+ /* Read from process, write to socket. */
+ if (GetOverlappedResult(info->child_out_r, &overlap, &n_r, FALSE)) {
+ wbuf = pipe_buffer;
+ if (o.crlf) {
+ n = n_r;
+ if (fix_line_endings((char *) pipe_buffer, &n, &crlf, &crlf_state))
+ wbuf = crlf;
+ n_r = n;
+ }
+ /* The above call to WSAEventSelect puts the socket in
+ non-blocking mode, but we want this send to block, not
+ potentially return WSAEWOULDBLOCK. We call block_socket, but
+ first we must clear out the select event. */
+ WSAEventSelect(info->fdn.fd, events[0], 0);
+ block_socket(info->fdn.fd);
+ n = ncat_send(&info->fdn, wbuf, n_r);
+ if (crlf != NULL)
+ free(crlf);
+ if (n != n_r)
+ {
+ goto loop_end;
+ }
+ /* Restore the select event (and non-block the socket again.) */
+ WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE);
+ /* Queue another asychronous read. */
+ ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap);
+ } else {
+ /* Probably read result wasn't ready, but we got here because
+ * there was data on the socket. */
+ switch (GetLastError()) {
+ case ERROR_IO_PENDING:
+ case ERROR_IO_INCOMPLETE:
+ break;
+ default:
+ /* Error or end of file. */
+ goto loop_end;
+ break;
+ }
+ }
+ /* Break here, don't go on. Need to finish all socket writes before
+ * checking if child process died. */
+ break;
+ case WAIT_OBJECT_0 + 2:
+ /* The child died. There are no more writes left in the pipe
+ because WaitForMultipleObjects guarantees events with lower
+ indexes are handled first. */
+ default:
+ goto loop_end;
+ break;
+ }
+ }
+
+loop_end:
+
+#ifdef HAVE_OPENSSL
+ if (o.ssl && info->fdn.ssl) {
+ SSL_shutdown(info->fdn.ssl);
+ SSL_free(info->fdn.ssl);
+ /* avoid shutting down and freeing this again in subprocess_info_close */
+ info->fdn.ssl = NULL;
+ }
+#endif
+
+ WSACloseEvent(events[0]);
+
+ rc = unregister_subprocess(info->proc);
+ ncat_assert(rc != -1);
+
+ GetExitCodeProcess(info->proc, &ret);
+ if (ret == STILL_ACTIVE) {
+ if (o.debug > 1)
+ logdebug("Subprocess still running, terminating it.\n");
+ rc = TerminateProcess(info->proc, 0);
+ if (rc == 0) {
+ if (o.debug > 1)
+ logdebug("TerminateProcess failed with code %d.\n", rc);
+ }
+ }
+ GetExitCodeProcess(info->proc, &ret);
+ if (o.debug > 1)
+ logdebug("Subprocess ended with exit code %d.\n", ret);
+
+ shutdown(info->fdn.fd, 2);
+ subprocess_info_close(info);
+ free(info);
+
+ rc = WaitForSingleObject(pseudo_sigchld_mutex, INFINITE);
+ ncat_assert(rc == WAIT_OBJECT_0);
+ if (pseudo_sigchld_handler != NULL)
+ pseudo_sigchld_handler();
+ rc = ReleaseMutex(pseudo_sigchld_mutex);
+ ncat_assert(rc != 0);
+
+ return ret;
+}
+
+/* Find a free slot in the subprocesses table. Update subprocesses_max_index to
+ be one greater than the maximum index containing a non-NULL handle. (It is
+ assumed that the index returned by this function will be filled by a
+ handle.) */
+static int get_subprocess_slot(void)
+{
+ int i, free_index, max_index;
+ DWORD rc;
+
+ rc = WaitForSingleObject(subprocesses_mutex, INFINITE);
+ ncat_assert(rc == WAIT_OBJECT_0);
+
+ free_index = -1;
+ max_index = 0;
+ for (i = 0; i < subprocess_max_index; i++) {
+ HANDLE proc = subprocesses[i];
+
+ if (proc == NULL) {
+ if (free_index == -1)
+ free_index = i;
+ } else {
+ max_index = i + 1;
+ }
+ }
+ if ((free_index == -1 || free_index == max_index)
+ && max_index < sizeof(subprocesses) / sizeof(subprocesses[0]))
+ free_index = max_index++;
+ subprocess_max_index = max_index;
+
+ rc = ReleaseMutex(subprocesses_mutex);
+ ncat_assert(rc != 0);
+
+ return free_index;
+}
+
+/* Add a process to the list of processes to kill at program exit. Once you
+ call this function, the process handle "belongs" to it and you shouldn't
+ modify the handle until you call unregister_subprocess. Returns -1 on
+ error. */
+static int register_subprocess(HANDLE proc)
+{
+ int i;
+ DWORD rc;
+
+ if (subprocesses_mutex == NULL) {
+ subprocesses_mutex = CreateMutex(NULL, FALSE, NULL);
+ ncat_assert(subprocesses_mutex != NULL);
+ }
+ if (pseudo_sigchld_mutex == NULL) {
+ pseudo_sigchld_mutex = CreateMutex(NULL, FALSE, NULL);
+ ncat_assert(pseudo_sigchld_mutex != NULL);
+ }
+
+ rc = WaitForSingleObject(subprocesses_mutex, INFINITE);
+ ncat_assert(rc == WAIT_OBJECT_0);
+
+ i = get_subprocess_slot();
+ if (i == -1) {
+ if (o.verbose)
+ logdebug("No free process slots for termination handler.\n");
+ } else {
+ subprocesses[i] = proc;
+
+ if (o.debug > 1)
+ logdebug("Register subprocess %p at index %d.\n", proc, i);
+
+ if (!atexit_registered) {
+ /* We register both an atexit and a SIGINT handler because ^C
+ doesn't seem to cause atexit handlers to be called. */
+ atexit(terminate_subprocesses);
+ signal(SIGINT, sigint_handler);
+ atexit_registered = 1;
+ }
+ }
+
+ rc = ReleaseMutex(subprocesses_mutex);
+ ncat_assert(rc != 0);
+
+ return i;
+}
+
+/* Remove a process handle from the termination handler list. Returns -1 if the
+ process was not already registered. */
+static int unregister_subprocess(HANDLE proc)
+{
+ int i;
+ DWORD rc;
+
+ rc = WaitForSingleObject(subprocesses_mutex, INFINITE);
+ ncat_assert(rc == WAIT_OBJECT_0);
+
+ for (i = 0; i < subprocess_max_index; i++) {
+ if (proc == subprocesses[i])
+ break;
+ }
+ if (i < subprocess_max_index) {
+ subprocesses[i] = NULL;
+ if (o.debug > 1)
+ logdebug("Unregister subprocess %p from index %d.\n", proc, i);
+ } else {
+ i = -1;
+ }
+
+ rc = ReleaseMutex(subprocesses_mutex);
+ ncat_assert(rc != 0);
+
+ return i;
+}
+
+static void terminate_subprocesses(void)
+{
+ int i;
+ DWORD rc;
+
+ if (o.debug)
+ logdebug("Terminating subprocesses\n");
+
+ rc = WaitForSingleObject(subprocesses_mutex, INFINITE);
+ ncat_assert(rc == WAIT_OBJECT_0);
+
+ if (o.debug > 1)
+ logdebug("max_index %d\n", subprocess_max_index);
+ for (i = 0; i < subprocess_max_index; i++) {
+ HANDLE proc = subprocesses[i];
+ DWORD ret;
+
+ if (proc == NULL)
+ continue;
+ GetExitCodeProcess(proc, &ret);
+ if (ret == STILL_ACTIVE) {
+ if (o.debug > 1)
+ logdebug("kill index %d\n", i);
+ TerminateProcess(proc, 0);
+ }
+ subprocesses[i] = NULL;
+ }
+
+ rc = ReleaseMutex(subprocesses_mutex);
+ ncat_assert(rc != 0);
+}
+
+static void sigint_handler(int s)
+{
+ terminate_subprocesses();
+ ExitProcess(0);
+}
diff --git a/ncat/ncat_listen.c b/ncat/ncat_listen.c
new file mode 100644
index 0000000..67e4d36
--- /dev/null
+++ b/ncat/ncat_listen.c
@@ -0,0 +1,902 @@
+/***************************************************************************
+ * ncat_listen.c -- --listen mode. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "ncat.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <limits.h>
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#else
+#include <fcntl.h>
+#endif
+
+#if HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
+
+#ifdef WIN32
+/* Define missing constant for shutdown(2).
+ * See:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740481%28v=vs.85%29.aspx
+ */
+#define SHUT_WR SD_SEND
+#endif
+
+/* read_fds is the clients we are accepting data from. broadcast_fds is the
+ clients were are sending data to. broadcast_fds doesn't include the listening
+ socket and stdin. Network clients are not added to read_fds when --send-only
+ is used, because they would be always selected without having data read.
+ write_fds is the list of clients that are waiting for some kind of response
+ from us, like a pending ssl negotiation. */
+static fd_set master_readfds, master_writefds, master_broadcastfds;
+#ifdef HAVE_OPENSSL
+/* sslpending_fds contains the list of ssl sockets that are waiting to complete
+ the ssl handshake */
+static fd_set sslpending_fds;
+#endif
+
+/* These are bookkeeping data structures that are parallel to read_fds and
+ broadcast_fds. */
+static fd_list_t client_fdlist, broadcast_fdlist;
+
+static int listen_socket[NUM_LISTEN_ADDRS];
+/* Has stdin seen EOF? */
+static int stdin_eof = 0;
+static int crlf_state = 0;
+
+static void handle_connection(int socket_accept, int type, fd_set *listen_fds);
+static int read_stdin(void);
+static int read_socket(int recv_fd);
+static void post_handle_connection(struct fdinfo *sinfo);
+static void close_fd(struct fdinfo *fdn, int eof);
+static void read_and_broadcast(int recv_socket);
+static void shutdown_sockets(int how);
+static int chat_announce_connect(const struct fdinfo *fdi);
+static int chat_announce_disconnect(int fd);
+static char *chat_filter(char *buf, size_t size, int fd, int *nwritten);
+
+/* The number of connected clients is the difference of conn_inc and conn_dec.
+ It is split up into two variables for signal safety. conn_dec is modified
+ (asynchronously) only in signal handlers and conn_inc is modified
+ (synchronously) only in the main program. get_conn_count loops while conn_dec
+ is being modified. */
+static unsigned int conn_inc = 0;
+static volatile unsigned int conn_dec = 0;
+static volatile sig_atomic_t conn_dec_changed;
+
+static void decrease_conn_count(void)
+{
+ conn_dec_changed = 1;
+ conn_dec++;
+}
+
+static int get_conn_count(void)
+{
+ unsigned int count;
+
+ /* conn_dec is modified in a signal handler, so loop until it stops
+ changing. */
+ do {
+ conn_dec_changed = 0;
+ count = conn_inc - conn_dec;
+ } while (conn_dec_changed);
+ ncat_assert(count <= INT_MAX);
+
+ return count;
+}
+
+#ifndef WIN32
+static void sigchld_handler(int signum)
+{
+ while (waitpid(-1, NULL, WNOHANG) > 0)
+ decrease_conn_count();
+}
+#endif
+
+int new_listen_socket(int type, int proto, const union sockaddr_u *addr, fd_set *listen_fds)
+{
+ struct fdinfo fdi = {0};
+ fdi.fd = do_listen(type, proto, addr);
+ if (fdi.fd < 0) {
+ return -1;
+ }
+ fdi.remoteaddr = *addr; /* actually our local addr, but whatevs */
+
+ /* Make our listening socket non-blocking because there are timing issues
+ * which could cause us to block on accept() even though select() says it's
+ * readable. See UNPv1 2nd ed, p422 for more.
+ */
+ unblock_socket(fdi.fd);
+
+ /* setup select sets and max fd */
+ checked_fd_set(fdi.fd, &master_readfds);
+ add_fdinfo(&client_fdlist, &fdi);
+
+ checked_fd_set(fdi.fd, listen_fds);
+
+ return fdi.fd;
+}
+
+int ncat_listen()
+{
+ int rc, i, j, fds_ready;
+ fd_set listen_fds;
+ struct timeval tv;
+ struct timeval *tvp = NULL;
+ unsigned int num_sockets;
+ int proto = o.proto;
+ int type = o.proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+
+ if (o.httpserver)
+ return ncat_http_server();
+
+#if HAVE_SYS_UN_H
+ if (o.af == AF_UNIX)
+ proto = 0;
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+ if (o.af == AF_VSOCK)
+ proto = 0;
+#endif
+ /* clear out structs */
+ FD_ZERO(&master_readfds);
+ FD_ZERO(&master_writefds);
+ FD_ZERO(&master_broadcastfds);
+ FD_ZERO(&listen_fds);
+#ifdef HAVE_OPENSSL
+ FD_ZERO(&sslpending_fds);
+#endif
+ zmem(&client_fdlist, sizeof(client_fdlist));
+ zmem(&broadcast_fdlist, sizeof(broadcast_fdlist));
+
+#ifdef WIN32
+ set_pseudo_sigchld_handler(decrease_conn_count);
+#else
+ /* Reap on SIGCHLD */
+ Signal(SIGCHLD, sigchld_handler);
+ /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we
+ send data to it before noticing. */
+ Signal(SIGPIPE, SIG_IGN);
+#endif
+
+#ifdef HAVE_OPENSSL
+ if (o.ssl)
+ {
+ if (o.sslalpn)
+ bye("ALPN is not supported in listen mode\n");
+ setup_ssl_listen(type == SOCK_STREAM ? SSLv23_server_method() : DTLS_server_method());
+ }
+#endif
+
+/* Not sure if this problem exists on Windows, but fcntl and /dev/null don't */
+#ifndef WIN32
+ /* Check whether stdin is closed. Because we treat this fd specially, we
+ * can't risk it being reopened for an incoming connection, so we'll hold
+ * it open instead. */
+ if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF) {
+ logdebug("stdin is closed, attempting to reserve STDIN_FILENO\n");
+ rc = open("/dev/null", O_RDONLY);
+ if (rc >= 0 && rc != STDIN_FILENO) {
+ /* Oh well, we tried */
+ logdebug("Couldn't reserve STDIN_FILENO\n");
+ close(rc);
+ }
+ }
+#endif
+
+ /* We need a list of fds to keep current fdmax. The second parameter is a
+ number added to the supplied connection limit, that will compensate
+ maxfds for the added by default listen and stdin sockets. */
+ init_fdlist(&client_fdlist, sadd(o.conn_limit, num_listenaddrs + 1));
+
+ for (i = 0; i < NUM_LISTEN_ADDRS; i++)
+ listen_socket[i] = -1;
+
+ num_sockets = 0;
+ for (i = 0; i < num_listenaddrs; i++) {
+ /* setup the main listening socket */
+ listen_socket[num_sockets] = new_listen_socket(type, proto, &listenaddrs[i], &listen_fds);
+ if (listen_socket[num_sockets] == -1) {
+ if (o.debug > 0)
+ logdebug("do_listen(\"%s\"): %s\n", socktop(&listenaddrs[i], 0), socket_strerror(socket_errno()));
+ continue;
+ }
+ num_sockets++;
+ }
+ if (num_sockets == 0) {
+ if (num_listenaddrs == 1)
+ bye("Unable to open listening socket on %s: %s", socktop(&listenaddrs[0], 0), socket_strerror(socket_errno()));
+ else
+ bye("Unable to open any listening sockets.");
+ }
+
+ add_fd(&client_fdlist, STDIN_FILENO);
+
+ init_fdlist(&broadcast_fdlist, o.conn_limit);
+
+ if (o.idletimeout > 0)
+ tvp = &tv;
+
+ while (client_fdlist.nfds > 1 || get_conn_count() > 0) {
+ /* We pass these temporary descriptor sets to fselect, since fselect
+ modifies the sets it receives. */
+ fd_set readfds = master_readfds, writefds = master_writefds;
+
+
+ if (o.debug > 1)
+ logdebug("selecting, fdmax %d\n", client_fdlist.fdmax);
+
+ if (o.debug > 1 && o.broker)
+ logdebug("Broker connection count is %d\n", get_conn_count());
+
+ if (o.idletimeout > 0)
+ ms_to_timeval(tvp, o.idletimeout);
+
+ /* The idle timer should only be running when there are active connections */
+ if (get_conn_count())
+ fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, tvp);
+ else
+ fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, NULL);
+
+ if (o.debug > 1)
+ logdebug("select returned %d fds ready\n", fds_ready);
+
+ if (fds_ready == 0)
+ bye("Idle timeout expired (%d ms).", o.idletimeout);
+
+ /* If client_fdlist.state increases, the list has changed and we
+ * need to go over it again. */
+restart_fd_loop:
+ client_fdlist.state = 0;
+ for (i = 0; i < client_fdlist.nfds && fds_ready > 0; i++) {
+ struct fdinfo *fdi = &client_fdlist.fds[i];
+ int cfd = fdi->fd;
+ /* If we saw an error, close this fd */
+ if (fdi->lasterr != 0) {
+ close_fd(fdi, 0);
+ goto restart_fd_loop;
+ }
+ /* Loop through descriptors until there's something to read */
+ if (!checked_fd_isset(cfd, &readfds) && !checked_fd_isset(cfd, &writefds))
+ continue;
+
+ if (o.debug > 1)
+ logdebug("fd %d is ready\n", cfd);
+
+#ifdef HAVE_OPENSSL
+ /* Is this an ssl socket pending a handshake? If so handle it. */
+ if (o.ssl && checked_fd_isset(cfd, &sslpending_fds)) {
+ checked_fd_clr(cfd, &master_readfds);
+ checked_fd_clr(cfd, &master_writefds);
+ switch (ssl_handshake(fdi)) {
+ case NCAT_SSL_HANDSHAKE_COMPLETED:
+ /* Clear from sslpending_fds once ssl is established */
+ checked_fd_clr(cfd, &sslpending_fds);
+ post_handle_connection(fdi);
+ break;
+ case NCAT_SSL_HANDSHAKE_PENDING_WRITE:
+ checked_fd_set(cfd, &master_writefds);
+ break;
+ case NCAT_SSL_HANDSHAKE_PENDING_READ:
+ checked_fd_set(cfd, &master_readfds);
+ break;
+ case NCAT_SSL_HANDSHAKE_FAILED:
+ default:
+ SSL_free(fdi->ssl);
+ Close(fdi->fd);
+ checked_fd_clr(cfd, &sslpending_fds);
+ checked_fd_clr(cfd, &master_readfds);
+ rm_fd(&client_fdlist, cfd);
+ /* Are we in single listening mode(without -k)? If so
+ then we should quit also. */
+ if (!o.keepopen && !o.broker)
+ return 1;
+ --conn_inc;
+ break;
+ }
+ } else
+#endif
+ if (checked_fd_isset(cfd, &listen_fds)) {
+ /* we have a new connection request */
+ handle_connection(cfd, type, &listen_fds);
+ } else if (cfd == STDIN_FILENO) {
+ if (o.broker) {
+ read_and_broadcast(cfd);
+ } else {
+ /* Read from stdin and write to all clients. */
+ rc = read_stdin();
+ if (rc == 0 && type == SOCK_STREAM) {
+ if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.sendonly)) {
+ /* There will be nothing more to send. If we're not
+ receiving anything, we can quit here. */
+ return 0;
+ }
+ if (!o.noshutdown) shutdown_sockets(SHUT_WR);
+ }
+ if (rc < 0)
+ return 1;
+ }
+ } else if (!o.sendonly) {
+ if (o.broker) {
+ read_and_broadcast(cfd);
+ } else {
+ /* Read from a client and write to stdout. */
+ rc = read_socket(cfd);
+ if (rc <= 0 && !o.keepopen)
+ return rc == 0 ? 0 : 1;
+ }
+ }
+
+ fds_ready--;
+ if (client_fdlist.state > 0)
+ goto restart_fd_loop;
+
+ /* Check if any send errors were logged. */
+ for (j = 0; j < broadcast_fdlist.nfds; j++) {
+ fdi = &broadcast_fdlist.fds[j];
+ if (fdi->lasterr != 0) {
+ close_fd(fdi, 0);
+ /* close_fd mucks with client_fdlist, so jump back and
+ * start the loop over */
+ goto restart_fd_loop;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Accept a connection on a listening socket. Allow or deny the connection.
+ Fork a command if o.cmdexec is set. Otherwise, add the new socket to the
+ watch set. */
+static void handle_connection(int socket_accept, int type, fd_set *listen_fds)
+{
+ struct fdinfo s = { 0 };
+ int conn_count;
+
+ zmem(&s, sizeof(s));
+
+ s.ss_len = sizeof(s.remoteaddr.storage);
+
+ errno = 0;
+ if (type == SOCK_STREAM) {
+ s.fd = accept(socket_accept, &s.remoteaddr.sockaddr, &s.ss_len);
+ }
+ else {
+ char buf[4] = {0};
+ int nbytes = recvfrom(socket_accept, buf, sizeof(buf), MSG_PEEK,
+ &s.remoteaddr.sockaddr, &s.ss_len);
+ if (nbytes < 0) {
+ loguser("%s.\n", socket_strerror(socket_errno()));
+ return;
+ }
+ /*
+ * We're using connected udp. This has the down side of only
+ * being able to handle one udp client at a time
+ */
+ Connect(socket_accept, &s.remoteaddr.sockaddr, s.ss_len);
+ s.fd = socket_accept;
+ /* If we expect new connections, we'll have to open a new listening
+ * socket to replace the one we just connected to a single client. */
+ if ((o.keepopen || o.broker)
+#if HAVE_SYS_UN_H
+ /* unless it's a UNIX socket, since we get EADDRINUSE when we try to bind */
+ && s.remoteaddr.storage.ss_family != AF_UNIX
+#endif
+ ) {
+ int i;
+ for (i = 0; i < num_listenaddrs; i++) {
+ if (listen_socket[i] == socket_accept) {
+ struct fdinfo *lfdi = get_fdinfo(&client_fdlist, socket_accept);
+ union sockaddr_u localaddr = lfdi->remoteaddr;
+ listen_socket[i] = new_listen_socket(type, (o.af == AF_INET || o.af == AF_INET6) ? o.proto : 0, &localaddr, listen_fds);
+ if (listen_socket[i] < 0) {
+ bye("do_listen(\"%s\"): %s\n", socktop(&listenaddrs[i], 0), socket_strerror(socket_errno()));
+ return;
+ }
+ break;
+ }
+ }
+ }
+ /* Remove this socket from listening */
+ checked_fd_clr(socket_accept, &master_readfds);
+ checked_fd_clr(socket_accept, listen_fds);
+ rm_fd(&client_fdlist, socket_accept);
+ }
+
+ if (s.fd < 0) {
+ if (o.debug)
+ logdebug("Error in accept: %s\n", strerror(errno));
+
+ close(s.fd);
+ return;
+ }
+
+ if (!o.keepopen && !o.broker) {
+ int i;
+ for (i = 0; i < num_listenaddrs; i++) {
+ /* If */
+ if (listen_socket[i] >= 0 && checked_fd_isset(listen_socket[i], listen_fds)) {
+ Close(listen_socket[i]);
+ checked_fd_clr(listen_socket[i], &master_readfds);
+ rm_fd(&client_fdlist, listen_socket[i]);
+ listen_socket[i] = -1;
+ }
+ }
+ }
+
+ if (o.verbose) {
+ loguser("Connection from %s", socktop(&s.remoteaddr, s.ss_len));
+ if (o.chat)
+ loguser_noprefix(" on file descriptor %d", s.fd);
+ loguser_noprefix(".\n");
+ }
+
+ /* Check conditions that might cause us to deny the connection. */
+ conn_count = get_conn_count();
+ if (conn_count >= o.conn_limit) {
+ if (o.verbose)
+ loguser("New connection denied: connection limit reached (%d)\n", conn_count);
+ Close(s.fd);
+ return;
+ }
+ if (!allow_access(&s.remoteaddr)) {
+ if (o.verbose)
+ loguser("New connection denied: not allowed\n");
+ Close(s.fd);
+ return;
+ }
+
+ conn_inc++;
+
+ unblock_socket(s.fd);
+
+#ifdef HAVE_OPENSSL
+ if (o.ssl) {
+ /* Add the socket to the necessary descriptor lists. */
+ checked_fd_set(s.fd, &sslpending_fds);
+ checked_fd_set(s.fd, &master_readfds);
+ checked_fd_set(s.fd, &master_writefds);
+ /* Add it to our list of fds too for maintaining maxfd. */
+ if (add_fdinfo(&client_fdlist, &s) < 0)
+ bye("add_fdinfo() failed.");
+ } else
+#endif
+ post_handle_connection(&s);
+}
+
+/* This function handles the post connection specific actions that are needed
+ * after a socket has been initialized(normal socket or ssl socket). */
+static void post_handle_connection(struct fdinfo *sinfo)
+{
+ /*
+ * Are we executing a command? If so then don't add this guy
+ * to our descriptor list or set.
+ */
+ if (o.cmdexec) {
+#ifdef HAVE_OPENSSL
+ /* We added this in handle_connection, but at this point the ssl
+ * connection has taken over. Stop tracking.
+ */
+ if (o.ssl) {
+ rm_fd(&client_fdlist, sinfo->fd);
+ }
+#endif
+ if (o.keepopen)
+ netrun(sinfo, o.cmdexec);
+ else
+ netexec(sinfo, o.cmdexec);
+ } else {
+ /* Now that a client is connected, pay attention to stdin. */
+ if (!stdin_eof)
+ checked_fd_set(STDIN_FILENO, &master_readfds);
+ if (!o.sendonly) {
+ /* add to our lists */
+ checked_fd_set(sinfo->fd, &master_readfds);
+ /* add it to our list of fds for maintaining maxfd */
+#ifdef HAVE_OPENSSL
+ /* Don't add it twice (see handle_connection above) */
+ if (!o.ssl) {
+#endif
+ if (add_fdinfo(&client_fdlist, sinfo) < 0)
+ bye("add_fdinfo() failed.");
+#ifdef HAVE_OPENSSL
+ }
+#endif
+ }
+ checked_fd_set(sinfo->fd, &master_broadcastfds);
+ if (add_fdinfo(&broadcast_fdlist, sinfo) < 0)
+ bye("add_fdinfo() failed.");
+
+ if (o.chat)
+ chat_announce_connect(sinfo);
+ }
+}
+
+static void close_fd(struct fdinfo *fdn, int eof) {
+ /* rm_fd invalidates fdn, so save what we need here. */
+ int fd = fdn->fd;
+ if (o.debug)
+ logdebug("Closing connection.\n");
+#ifdef HAVE_OPENSSL
+ if (o.ssl && fdn->ssl) {
+ if (eof)
+ SSL_shutdown(fdn->ssl);
+ SSL_free(fdn->ssl);
+ }
+#endif
+ Close(fd);
+ checked_fd_clr(fd, &master_readfds);
+ rm_fd(&client_fdlist, fd);
+ checked_fd_clr(fd, &master_broadcastfds);
+ rm_fd(&broadcast_fdlist, fd);
+
+ conn_inc--;
+ if (get_conn_count() == 0)
+ checked_fd_clr(STDIN_FILENO, &master_readfds);
+
+ if (o.chat)
+ chat_announce_disconnect(fd);
+}
+
+/* Read from stdin and broadcast to all client sockets. Return the number of
+ bytes read, or -1 on error. */
+int read_stdin(void)
+{
+ int nbytes;
+ char buf[DEFAULT_TCP_BUF_LEN];
+ char *tempbuf = NULL;
+
+ nbytes = read(STDIN_FILENO, buf, sizeof(buf));
+ if (nbytes <= 0) {
+ if (nbytes < 0 && o.verbose)
+ logdebug("Error reading from stdin: %s\n", strerror(errno));
+ if (nbytes == 0 && o.debug)
+ logdebug("EOF on stdin\n");
+
+ /* Don't close the file because that allows a socket to be fd 0. */
+ checked_fd_clr(STDIN_FILENO, &master_readfds);
+ /* Buf mark that we've seen EOF so it doesn't get re-added to the
+ select list. */
+ stdin_eof = 1;
+
+ return nbytes;
+ }
+
+ if (o.crlf)
+ fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state);
+
+ if (o.linedelay)
+ ncat_delay_timer(o.linedelay);
+
+ /* Write to everything in the broadcast set. */
+ if (tempbuf != NULL) {
+ ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, tempbuf, nbytes);
+ free(tempbuf);
+ tempbuf = NULL;
+ } else {
+ ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, buf, nbytes);
+ }
+
+ return nbytes;
+}
+
+/* Read from a client socket and write to stdout. Return the number of bytes
+ read from the socket, or -1 on error. */
+int read_socket(int recv_fd)
+{
+ char buf[DEFAULT_TCP_BUF_LEN];
+ struct fdinfo *fdn;
+ int nbytes, pending;
+
+ fdn = get_fdinfo(&client_fdlist, recv_fd);
+ ncat_assert(fdn != NULL);
+
+ nbytes = 0;
+ do {
+ int n;
+
+ n = ncat_recv(fdn, buf, sizeof(buf), &pending);
+ if (n <= 0) {
+ /* return value can be 0 without meaning EOF in some cases such as SSL
+ * renegotiations that require read/write socket operations but do not
+ * have any application data. */
+ if(n == 0 && fdn->lasterr == 0) {
+ continue; /* Check pending */
+ }
+ close_fd(fdn, n == 0);
+ return n;
+ }
+ else {
+ Write(STDOUT_FILENO, buf, n);
+ nbytes += n;
+ }
+ } while (pending);
+
+ return nbytes;
+}
+
+
+//---------------
+/* Read from recv_fd and broadcast whatever is read to all other descriptors in
+ read_fds, with the exception of stdin, listen_socket, and recv_fd itself.
+ Handles EOL translation and chat mode. On read error or end of stream,
+ closes the socket and removes it from the read_fds list. */
+static void read_and_broadcast(int recv_fd)
+{
+ struct fdinfo *fdn;
+ int pending;
+
+ fdn = get_fdinfo(&client_fdlist, recv_fd);
+ ncat_assert(fdn != NULL);
+
+ /* Loop while ncat_recv indicates data is pending. */
+ do {
+ char buf[DEFAULT_TCP_BUF_LEN];
+ char *chatbuf, *outbuf;
+ char *tempbuf = NULL;
+ fd_set broadcastfds;
+ int n;
+
+ /* Behavior differs depending on whether this is stdin or a socket. */
+ if (recv_fd == STDIN_FILENO) {
+ n = read(recv_fd, buf, sizeof(buf));
+ if (n <= 0) {
+ if (n < 0 && o.verbose)
+ logdebug("Error reading from stdin: %s\n", strerror(errno));
+ if (n == 0 && o.debug)
+ logdebug("EOF on stdin\n");
+
+ /* Don't close the file because that allows a socket to be
+ fd 0. */
+ checked_fd_clr(recv_fd, &master_readfds);
+ /* But mark that we've seen EOF so it doesn't get re-added to
+ the select list. */
+ stdin_eof = 1;
+
+ return;
+ }
+
+ if (o.crlf)
+ fix_line_endings((char *) buf, &n, &tempbuf, &crlf_state);
+
+ pending = 0;
+ } else {
+ /* From a connected socket, not stdin. */
+ n = ncat_recv(fdn, buf, sizeof(buf), &pending);
+
+ if (n <= 0) {
+ /* return value can be 0 without meaning EOF in some cases such as SSL
+ * renegotiations that require read/write socket operations but do not
+ * have any application data. */
+ if(n == 0 && fdn->lasterr == 0) {
+ continue; /* Check pending */
+ }
+ close_fd(fdn, n == 0);
+ return;
+ }
+ }
+
+ if (o.debug > 1)
+ logdebug("Handling data from client %d.\n", recv_fd);
+
+ chatbuf = NULL;
+ /* tempbuf is in use if we read from STDIN and fixed EOL */
+ if (tempbuf == NULL)
+ outbuf = buf;
+ else
+ outbuf = tempbuf;
+
+ if (o.chat) {
+ chatbuf = chat_filter(outbuf, n, recv_fd, &n);
+ if (chatbuf == NULL) {
+ if (o.verbose)
+ logdebug("Error formatting chat message from fd %d\n", recv_fd);
+ } else {
+ outbuf = chatbuf;
+ }
+ }
+
+ /* Send to everyone except the one who sent this message. */
+ broadcastfds = master_broadcastfds;
+ checked_fd_clr(recv_fd, &broadcastfds);
+ ncat_broadcast(&broadcastfds, &broadcast_fdlist, outbuf, n);
+
+ free(chatbuf);
+ free(tempbuf);
+ tempbuf = NULL;
+ } while (pending);
+}
+
+static void shutdown_sockets(int how)
+{
+ struct fdinfo *fdn;
+ int i;
+
+ for (i = 0; i <= broadcast_fdlist.fdmax; i++) {
+ if (!checked_fd_isset(i, &master_broadcastfds))
+ continue;
+
+ fdn = get_fdinfo(&broadcast_fdlist, i);
+ ncat_assert(fdn != NULL);
+#ifdef HAVE_OPENSSL
+ if (o.ssl && fdn->ssl) {
+ SSL_shutdown(fdn->ssl);
+ }
+ else
+#endif
+ shutdown(fdn->fd, how);
+ }
+}
+
+/* Announce the new connection and who is already connected. */
+static int chat_announce_connect(const struct fdinfo *fdi)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+ int i, count, ret;
+
+ strbuf_sprintf(&buf, &size, &offset,
+ "<announce> %s is connected as <user%d>.\n", socktop(&fdi->remoteaddr, fdi->ss_len), fdi->fd);
+
+ strbuf_sprintf(&buf, &size, &offset, "<announce> already connected: ");
+ count = 0;
+ for (i = 0; i <= client_fdlist.fdmax; i++) {
+ union sockaddr_u tsu;
+ socklen_t len = sizeof(tsu.storage);
+
+ if (i == fdi->fd || !checked_fd_isset(i, &master_broadcastfds))
+ continue;
+
+ if (getpeername(i, &tsu.sockaddr, &len) == -1)
+ bye("getpeername for sd %d failed: %s.", i, strerror(errno));
+
+ if (count > 0)
+ strbuf_sprintf(&buf, &size, &offset, ", ");
+
+ strbuf_sprintf(&buf, &size, &offset, "%s as <user%d>", socktop(&tsu, len), i);
+
+ count++;
+ }
+ if (count == 0)
+ strbuf_sprintf(&buf, &size, &offset, "nobody");
+ strbuf_sprintf(&buf, &size, &offset, ".\n");
+
+ ret = ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, buf, offset);
+
+ free(buf);
+
+ return ret;
+}
+
+static int chat_announce_disconnect(int fd)
+{
+ char buf[128];
+ int n;
+
+ n = Snprintf(buf, sizeof(buf),
+ "<announce> <user%d> is disconnected.\n", fd);
+ if (n < 0 || n >= sizeof(buf))
+ return -1;
+
+ return ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, buf, n);
+}
+
+/*
+ * This is stupid. But it's just a bit of fun.
+ *
+ * The file descriptor of the sender is prepended to the
+ * message sent to clients, so you can distinguish
+ * each other with a degree of sanity. This gives a
+ * similar effect to an IRC session. But stupider.
+ */
+static char *chat_filter(char *buf, size_t size, int fd, int *nwritten)
+{
+ char *result = NULL;
+ size_t n = 0;
+ const char *p;
+ int i;
+
+ n = 32;
+ result = (char *) safe_malloc(n);
+ i = Snprintf(result, n, "<user%d> ", fd);
+
+ /* Escape control characters. */
+ for (p = buf; p - buf < size; p++) {
+ char repl[32];
+ int repl_len;
+
+ if (isprint((int) (unsigned char) *p) || *p == '\r' || *p == '\n' || *p == '\t') {
+ repl[0] = *p;
+ repl_len = 1;
+ } else {
+ repl_len = Snprintf(repl, sizeof(repl), "\\%03o", (unsigned char) *p);
+ }
+
+ if (i + repl_len > n) {
+ n = (i + repl_len) * 2;
+ result = (char *) safe_realloc(result, n + 1);
+ }
+ memcpy(result + i, repl, repl_len);
+ i += repl_len;
+ }
+ /* Trim to length. (Also does initial allocation when str is empty.) */
+ result = (char *) safe_realloc(result, i + 1);
+ result[i] = '\0';
+
+ *nwritten = i;
+
+ return result;
+}
diff --git a/ncat/ncat_listen.h b/ncat/ncat_listen.h
new file mode 100644
index 0000000..5915c9b
--- /dev/null
+++ b/ncat/ncat_listen.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * ncat_listen.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+#ifndef NCAT_LISTEN_H
+#define NCAT_LISTEN_H
+
+extern int ncat_listen(void);
+
+#endif
diff --git a/ncat/ncat_lua.c b/ncat/ncat_lua.c
new file mode 100644
index 0000000..e5e6e8a
--- /dev/null
+++ b/ncat/ncat_lua.c
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * ncat_lua.c -- ncat lua facilities *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "ncat.h"
+#include "ncat_lua.h"
+
+static lua_State *L;
+static int last_function_number;
+
+static void report(char *prefix)
+{
+ const char *errormsg;
+ errormsg = lua_tostring(L, -1);
+ if (errormsg == NULL)
+ errormsg = "(error object is not a string)";
+ bye("%s: %s.", prefix, errormsg);
+}
+
+static int traceback (lua_State *LL)
+{
+ const char *msg;
+ msg = lua_tostring(LL, 1);
+ if (msg) {
+ luaL_traceback(LL, LL, msg, 1);
+ } else {
+ if (!lua_isnoneornil(LL, 1)) { /* is there an error object? */
+ if (!luaL_callmeta(LL, 1, "__tostring")) /* try its 'tostring' metamethod */
+ lua_pushliteral(LL, "(no error message)");
+ }
+ }
+ return 1;
+}
+
+void lua_setup(void)
+{
+ ncat_assert(o.cmdexec != NULL);
+
+ L = luaL_newstate();
+ luaL_openlibs(L);
+
+ if (luaL_loadfile(L, o.cmdexec) != 0)
+ report("Error loading the Lua script");
+
+ /* install the traceback function */
+ last_function_number = lua_gettop(L);
+ lua_pushcfunction(L, traceback);
+ lua_insert(L, last_function_number);
+}
+
+void lua_run(void)
+{
+ if (lua_pcall(L, 0, 0, last_function_number) != LUA_OK && !lua_isnil(L, -1)) {
+ /* handle the error; the code below is taken from lua.c, Lua source code */
+ lua_remove(L, last_function_number);
+ report("Error running the Lua script");
+ } else {
+ if (o.debug)
+ logdebug("%s returned successfully.\n", o.cmdexec);
+ lua_close(L);
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/ncat/ncat_lua.h b/ncat/ncat_lua.h
new file mode 100644
index 0000000..f71e96f
--- /dev/null
+++ b/ncat/ncat_lua.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * ncat_lua.h -- ncat lua facilities header file *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef _NCAT_LUA_H
+#define _NCAT_LUA_H
+
+#include "ncat_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_LUA5_4_LUA_H
+ #include <lua5.4/lua.h>
+ #include <lua5.4/lauxlib.h>
+ #include <lua5.4/lualib.h>
+#elif defined HAVE_LUA_5_4_LUA_H
+ #include <lua/5.4/lua.h>
+ #include <lua/5.4/lauxlib.h>
+ #include <lua/5.4/lualib.h>
+#elif defined HAVE_LUA_H || defined LUA_INCLUDED
+ #include <lua.h>
+ #include <lauxlib.h>
+ #include <lualib.h>
+#elif defined HAVE_LUA_LUA_H
+ #include <lua/lua.h>
+ #include <lua/lauxlib.h>
+ #include <lua/lualib.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+void lua_setup(void);
+void lua_run(void);
+
+#endif
diff --git a/ncat/ncat_main.c b/ncat/ncat_main.c
new file mode 100644
index 0000000..501c5a3
--- /dev/null
+++ b/ncat/ncat_main.c
@@ -0,0 +1,1091 @@
+/***************************************************************************
+ * ncat_main.c -- main function: option parsing and checking, dispatching *
+ * to mode-specific functions. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "nsock.h"
+#include "ncat.h"
+#include "util.h"
+#include "sys_wrap.h"
+
+#include <getopt.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#ifndef WIN32
+#include <netdb.h>
+#endif
+#include <fcntl.h>
+
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
+
+#ifdef HAVE_LUA
+#include "ncat_lua.h"
+#endif
+
+static int ncat_connect_mode(void);
+static int ncat_listen_mode(void);
+
+/* Parses a port number */
+static unsigned int parseport(char *str, unsigned int maxport, char *msg)
+{
+ unsigned long port;
+ char *next;
+ errno = 0;
+ port = strtoul(str, &next, 10);
+ if (errno || *next || (maxport && port > maxport))
+ bye("Invalid %s number \"%s\".", msg, str);
+ return (unsigned int) port;
+}
+
+/* Parses proxy address/port combo */
+static size_t parseproxy(char *str, struct sockaddr_storage *ss,
+ size_t *sslen, unsigned short *portno)
+{
+ char *p = str;
+ int rc;
+
+ if (*p == '[') {
+ p = strchr(p, ']');
+ if (p == NULL)
+ bye("Invalid proxy IPv6 address \"%s\".", str);
+ ++str;
+ *p++ = '\0';
+ }
+
+ p = strchr(p, ':');
+ if (p != NULL && strchr(p + 1, ':') == NULL) {
+ *p++ = '\0';
+ *portno = (unsigned short) parseport(p, 0xFFFF, "proxy port");
+ }
+
+ rc = resolve(str, *portno, ss, sslen, o.af);
+ if (rc != 0) {
+ loguser("Could not resolve proxy \"%s\": %s.\n", str, gai_strerror(rc));
+ if (o.af == AF_INET6)
+ loguser("Did you specify the port number? It's required for IPv6.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return *sslen;
+}
+
+static int parse_timespec (const char *const tspec, const char *const optname)
+{
+ const long l = tval2msecs(tspec);
+ if (l <= 0 || l > INT_MAX)
+ bye("Invalid %s \"%s\" (must be greater than 0 and less than %ds).",
+ optname, tspec, INT_MAX / 1000);
+ if (l >= 100 * 1000 && tval_unit(tspec) == NULL)
+ bye("Since April 2010, the default unit for %s is seconds, so your "
+ "time of \"%s\" is %.1f minutes. Use \"%sms\" for %s milliseconds.",
+ optname, optarg, l / 1000.0 / 60, optarg, optarg);
+ return (int)l;
+}
+
+/* These functions implement a simple linked list to hold allow/deny
+ specifications until the end of option parsing. */
+struct host_list_node {
+ /* If false, then spec is the name of a file containing host patterns. */
+ int is_filename;
+ char *spec;
+ struct host_list_node *next;
+};
+
+static void host_list_add_spec(struct host_list_node **list, char *spec)
+{
+ struct host_list_node *node = (struct host_list_node *) safe_malloc(sizeof(*node));
+ node->is_filename = 0;
+ node->spec = spec;
+ node->next = *list;
+ *list = node;
+}
+
+static void host_list_add_filename(struct host_list_node **list, char *filename)
+{
+ struct host_list_node *node = (struct host_list_node *) safe_malloc(sizeof(*node));
+ node->is_filename = 1;
+ node->spec = filename;
+ node->next = *list;
+ *list = node;
+}
+
+static void host_list_free(struct host_list_node *list)
+{
+ struct host_list_node *next;
+ for ( ; list != NULL; list = next) {
+ next = list->next;
+ free(list);
+ }
+}
+
+static void host_list_to_set(struct addrset *set, struct host_list_node *list)
+{
+ struct host_list_node *node;
+
+ for (node = list; node != NULL; node = node->next) {
+ if (node->is_filename) {
+ FILE *fd;
+
+ fd = fopen(node->spec, "r");
+ if (fd == NULL)
+ bye("can't open %s: %s.", node->spec, strerror(errno));
+ if (!addrset_add_file(set, fd, o.af, !o.nodns))
+ bye("error in hosts file %s.", node->spec);
+ fclose(fd);
+ } else {
+ char *spec, *commalist;
+
+ commalist = node->spec;
+ while ((spec = strtok(commalist, ",")) != NULL) {
+ commalist = NULL;
+ if (!addrset_add_spec(set, spec, o.af, !o.nodns))
+ bye("error in host specification \"%s\".", node->spec);
+ }
+ }
+ }
+}
+
+static void print_banner(void)
+{
+ loguser("Version %s ( %s )\n", NCAT_VERSION, NCAT_URL);
+}
+
+int main(int argc, char *argv[])
+{
+ /* We have to buffer the lists of hosts to allow and deny until after option
+ parsing is done. Adding hosts to an addrset can require name resolution,
+ which may differ as a result of options like -n and -6. */
+ struct host_list_node *allow_host_list = NULL;
+ struct host_list_node *deny_host_list = NULL;
+
+ unsigned short proxyport;
+ /* vsock ports are 32 bits, so port variables must be at least that wide. */
+ unsigned int max_port = 65535;
+ long long int srcport = -1;
+ char *source = NULL;
+
+ struct option long_options[] = {
+ {"4", no_argument, NULL, '4'},
+ {"6", no_argument, NULL, '6'},
+#if HAVE_SYS_UN_H
+ {"unixsock", no_argument, NULL, 'U'},
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+ {"vsock", no_argument, NULL, 0},
+#endif
+ {"crlf", no_argument, NULL, 'C'},
+ {"g", required_argument, NULL, 'g'},
+ {"G", required_argument, NULL, 'G'},
+ {"exec", required_argument, NULL, 'e'},
+ {"sh-exec", required_argument, NULL, 'c'},
+#ifdef HAVE_LUA
+ {"lua-exec", required_argument, NULL, 0},
+ {"lua-exec-internal",required_argument, NULL, 0},
+#endif
+ {"max-conns", required_argument, NULL, 'm'},
+ {"help", no_argument, NULL, 'h'},
+ {"delay", required_argument, NULL, 'd'},
+ {"listen", no_argument, NULL, 'l'},
+ {"output", required_argument, NULL, 'o'},
+ {"hex-dump", required_argument, NULL, 'x'},
+ {"append-output", no_argument, NULL, 0},
+ {"idle-timeout", required_argument, NULL, 'i'},
+ {"keep-open", no_argument, NULL, 'k'},
+ {"recv-only", no_argument, &o.recvonly, 1},
+ {"source-port", required_argument, NULL, 'p'},
+ {"source", required_argument, NULL, 's'},
+ {"send-only", no_argument, &o.sendonly, 1},
+ {"no-shutdown", no_argument, &o.noshutdown,1},
+ {"broker", no_argument, NULL, 0},
+ {"chat", no_argument, NULL, 0},
+ {"talk", no_argument, NULL, 0},
+ {"deny", required_argument, NULL, 0},
+ {"denyfile", required_argument, NULL, 0},
+ {"allow", required_argument, NULL, 0},
+ {"allowfile", required_argument, NULL, 0},
+ {"telnet", no_argument, NULL, 't'},
+ {"udp", no_argument, NULL, 'u'},
+ {"sctp", no_argument, NULL, 0},
+ {"version", no_argument, NULL, 0},
+ {"verbose", no_argument, NULL, 'v'},
+ {"wait", required_argument, NULL, 'w'},
+ {"nodns", no_argument, NULL, 'n'},
+ {"proxy", required_argument, NULL, 0},
+ {"proxy-type", required_argument, NULL, 0},
+ {"proxy-auth", required_argument, NULL, 0},
+ {"proxy-dns", required_argument, NULL, 0},
+ {"nsock-engine", required_argument, NULL, 0},
+ {"test", no_argument, NULL, 0},
+ {"ssl", no_argument, &o.ssl, 1},
+#ifdef HAVE_OPENSSL
+ {"ssl-cert", required_argument, NULL, 0},
+ {"ssl-key", required_argument, NULL, 0},
+ {"ssl-verify", no_argument, NULL, 0},
+ {"ssl-trustfile", required_argument, NULL, 0},
+ {"ssl-ciphers", required_argument, NULL, 0},
+ {"ssl-servername", required_argument, NULL, 0},
+ {"ssl-alpn", required_argument, NULL, 0},
+#else
+ {"ssl-cert", optional_argument, NULL, 0},
+ {"ssl-key", optional_argument, NULL, 0},
+ {"ssl-verify", no_argument, NULL, 0},
+ {"ssl-trustfile", optional_argument, NULL, 0},
+ {"ssl-ciphers", optional_argument, NULL, 0},
+ {"ssl-alpn", optional_argument, NULL, 0},
+#endif
+ {0, 0, 0, 0}
+ };
+
+ gettimeofday(&start_time, NULL);
+ /* Set default options. */
+ options_init();
+
+#ifdef WIN32
+ windows_init();
+#endif
+
+ while (1) {
+ /* handle command line arguments */
+ int option_index;
+ int c = getopt_long(argc, argv, "46UCc:e:g:G:i:km:hp:d:lo:x:ts:uvw:nz",
+ long_options, &option_index);
+
+ /* That's the end of the options. */
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case '4':
+ o.af = AF_INET;
+ break;
+ case '6':
+#ifdef HAVE_IPV6
+ o.af = AF_INET6;
+#else
+ bye("-6 chosen when IPv6 wasn't compiled in.");
+#endif
+ break;
+#if HAVE_SYS_UN_H
+ case 'U':
+ o.af = AF_UNIX;
+ break;
+#endif
+ case 'C':
+ o.crlf = 1;
+ break;
+ case 'c':
+ if (o.cmdexec != NULL)
+ bye("Only one of --exec, --sh-exec, and --lua-exec is allowed.");
+ o.cmdexec = optarg;
+ o.execmode = EXEC_SHELL;
+ break;
+ case 'e':
+ if (o.cmdexec != NULL)
+ bye("Only one of --exec, --sh-exec, and --lua-exec is allowed.");
+ o.cmdexec = optarg;
+ o.execmode = EXEC_PLAIN;
+ break;
+ case 'g': {
+ char *from = optarg;
+ char *a = NULL;
+ while (o.numsrcrtes < 8 && (a = strtok(from, ",")))
+ {
+ union sockaddr_u addr;
+ size_t sslen;
+ int rc;
+ from = NULL;
+
+ rc = resolve(a, 0, &addr.storage, &sslen, AF_INET);
+ if (rc != 0) {
+ bye("Sorry, could not resolve source route hop \"%s\": %s.",
+ a, gai_strerror(rc));
+ }
+ o.srcrtes[o.numsrcrtes++] = addr.in.sin_addr;
+ }
+ if (strtok(from, ","))
+ bye("Sorry, you gave too many source route hops.");
+ break;
+ }
+ case 'G':
+ o.srcrteptr = atoi(optarg);
+ if (o.srcrteptr < 4 || (o.srcrteptr % 4) || o.srcrteptr > 28)
+ bye("Invalid source-route hop pointer %d.", o.srcrteptr);
+ break;
+ case 'k':
+ o.keepopen = 1;
+ break;
+ case 'm':
+ o.conn_limit = atoi(optarg);
+ break;
+ case 'd':
+ o.linedelay = parse_timespec(optarg, "-d delay");
+ break;
+ case 'o':
+ o.normlog = optarg;
+ break;
+ case 'x':
+ o.hexlog = optarg;
+ break;
+ case 'p':
+ srcport = parseport(optarg, 0, "source port");
+ break;
+ case 'i':
+ o.idletimeout = parse_timespec(optarg, "-i timeout");
+ break;
+ case 's':
+ source = optarg;
+ break;
+ case 'l':
+ o.listen = 1;
+ break;
+ case 'u':
+ o.proto = IPPROTO_UDP;
+ break;
+ case 'v':
+ /* One -v activates verbose, after that it's debugging. */
+ if (o.verbose == 0)
+ o.verbose++;
+ else
+ o.debug++;
+ break;
+ case 'n':
+ o.nodns = 1;
+ break;
+ case 'w':
+ o.conntimeout = parse_timespec(optarg, "-w timeout");
+ break;
+ case 't':
+ o.telnet = 1;
+ break;
+ case 'z':
+ o.zerobyte = 1;
+ break;
+ case 0:
+ if (strcmp(long_options[option_index].name, "version") == 0) {
+ print_banner();
+ exit(EXIT_SUCCESS);
+ } else if (strcmp(long_options[option_index].name, "proxy") == 0) {
+ if (o.proxyaddr)
+ bye("You can't specify more than one --proxy.");
+ o.proxyaddr = optarg;
+ } else if (strcmp(long_options[option_index].name, "proxy-type") == 0) {
+ if (o.proxytype)
+ bye("You can't specify more than one --proxy-type.");
+ o.proxytype = optarg;
+ } else if (strcmp(long_options[option_index].name, "proxy-auth") == 0) {
+ if (o.proxy_auth)
+ bye("You can't specify more than one --proxy-auth.");
+ o.proxy_auth = optarg;
+ } else if (strcmp(long_options[option_index].name, "proxy-dns") == 0) {
+ if (strcmp(optarg, "none") == 0)
+ o.proxydns = 0;
+ else if (strcmp(optarg, "local") == 0)
+ o.proxydns = PROXYDNS_LOCAL;
+ else if (strcmp(optarg, "remote") == 0)
+ o.proxydns = PROXYDNS_REMOTE;
+ else if (strcmp(optarg, "both") == 0)
+ o.proxydns = PROXYDNS_LOCAL | PROXYDNS_REMOTE;
+ else
+ bye("Invalid proxy DNS type.");
+ } else if (strcmp(long_options[option_index].name, "nsock-engine") == 0) {
+ if (nsock_set_default_engine(optarg) < 0)
+ bye("Unknown or non-available engine: %s.", optarg);
+ o.nsock_engine = 1;
+ } else if (strcmp(long_options[option_index].name, "test") == 0) {
+ o.test = 1;
+ } else if (strcmp(long_options[option_index].name, "broker") == 0) {
+ o.broker = 1;
+ /* --broker implies --listen. */
+ o.listen = 1;
+ } else if (strcmp(long_options[option_index].name, "chat") == 0
+ || strcmp(long_options[option_index].name, "talk") == 0) {
+ /* --talk is an older name for --chat. */
+ o.chat = 1;
+ /* --chat implies --broker. */
+ o.broker = 1;
+ } else if (strcmp(long_options[option_index].name, "allow") == 0) {
+ o.allow = 1;
+ host_list_add_spec(&allow_host_list, optarg);
+ } else if (strcmp(long_options[option_index].name, "allowfile") == 0) {
+ o.allow = 1;
+ host_list_add_filename(&allow_host_list, optarg);
+ } else if (strcmp(long_options[option_index].name, "deny") == 0) {
+ host_list_add_spec(&deny_host_list, optarg);
+ } else if (strcmp(long_options[option_index].name, "denyfile") == 0) {
+ host_list_add_filename(&deny_host_list, optarg);
+ } else if (strcmp(long_options[option_index].name, "append-output") == 0) {
+ o.append = 1;
+ } else if (strcmp(long_options[option_index].name, "sctp") == 0) {
+ o.proto = IPPROTO_SCTP;
+ }
+#ifdef HAVE_OPENSSL
+ else if (strcmp(long_options[option_index].name, "ssl-cert") == 0) {
+ o.ssl = 1;
+ o.sslcert = Strdup(optarg);
+ } else if (strcmp(long_options[option_index].name, "ssl-key") == 0) {
+ o.ssl = 1;
+ o.sslkey = Strdup(optarg);
+ } else if (strcmp(long_options[option_index].name, "ssl-verify") == 0) {
+ o.sslverify = 1;
+ o.ssl = 1;
+ } else if (strcmp(long_options[option_index].name, "ssl-trustfile") == 0) {
+ o.ssl = 1;
+ if (o.ssltrustfile != NULL)
+ bye("The --ssl-trustfile option may be given only once.");
+ o.ssltrustfile = Strdup(optarg);
+ /* If they list a trustfile assume they want certificate
+ verification. */
+ o.sslverify = 1;
+ } else if (strcmp(long_options[option_index].name, "ssl-ciphers") == 0) {
+ o.ssl = 1;
+ o.sslciphers = Strdup(optarg);
+ } else if (strcmp(long_options[option_index].name, "ssl-servername") == 0) {
+ o.ssl = 1;
+ o.sslservername = Strdup(optarg);
+ }
+#ifdef HAVE_ALPN_SUPPORT
+ else if (strcmp(long_options[option_index].name, "ssl-alpn") == 0) {
+ o.ssl = 1;
+ o.sslalpn = Strdup(optarg);
+ }
+#else
+ else if (strcmp(long_options[option_index].name, "ssl-alpn") == 0) {
+ bye("OpenSSL does not have ALPN support compiled in. The --ssl-alpn option cannot be chosen.");
+ }
+#endif
+#else
+ else if (strcmp(long_options[option_index].name, "ssl-cert") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-cert option cannot be chosen.");
+ } else if (strcmp(long_options[option_index].name, "ssl-key") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-key option cannot be chosen.");
+ } else if (strcmp(long_options[option_index].name, "ssl-verify") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-verify option cannot be chosen.");
+ } else if (strcmp(long_options[option_index].name, "ssl-trustfile") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-trustfile option cannot be chosen.");
+ } else if (strcmp(long_options[option_index].name, "ssl-ciphers") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-ciphers option cannot be chosen.");
+ } else if (strcmp(long_options[option_index].name, "ssl-servername") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-servername option cannot be chosen.");
+ } else if (strcmp(long_options[option_index].name, "ssl-alpn") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-alpn option cannot be chosen.");
+ }
+#endif
+#ifdef HAVE_LUA
+ else if (strcmp(long_options[option_index].name, "lua-exec") == 0) {
+ if (o.cmdexec != NULL)
+ bye("Only one of --exec, --sh-exec, and --lua-exec is allowed.");
+ o.cmdexec = optarg;
+ o.execmode = EXEC_LUA;
+ } else if (strcmp(long_options[option_index].name, "lua-exec-internal") == 0) {
+ /* This command-line switch is undocumented on purpose. Do NOT use it
+ explicitly as its behavior might differ between Ncat releases.
+
+ Its goal is to switch the Ncat process to the Lua interpreter state
+ so that its standard output and input can be redirected to
+ particular connection's streams. Although it is implemented by
+ forking in POSIX builds, Windows does not have the fork() system
+ call and thus requires this workaround. More info here:
+ http://seclists.org/nmap-dev/2013/q2/492 */
+#ifdef WIN32
+ if (o.debug)
+ logdebug("Enabling binary stdout for the Lua output.\n");
+ int result = _setmode(_fileno(stdout), _O_BINARY);
+ if (result == -1)
+ perror("Cannot set mode");
+#endif
+ ncat_assert(argc == 3);
+ o.cmdexec = argv[2];
+ lua_setup();
+ lua_run();
+ }
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+ else if (strcmp(long_options[option_index].name, "vsock") == 0) {
+ o.af = AF_VSOCK;
+ }
+#endif
+ break;
+ case 'h':
+ printf("%s %s ( %s )\n", NCAT_NAME, NCAT_VERSION, NCAT_URL);
+ printf(
+"Usage: ncat [options] [hostname] [port]\n"
+"\n"
+"Options taking a time assume seconds. Append 'ms' for milliseconds,\n"
+"'s' for seconds, 'm' for minutes, or 'h' for hours (e.g. 500ms).\n"
+" -4 Use IPv4 only\n"
+" -6 Use IPv6 only\n"
+#if HAVE_SYS_UN_H
+" -U, --unixsock Use Unix domain sockets only\n"
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+" --vsock Use vsock sockets only\n"
+#endif
+" -C, --crlf Use CRLF for EOL sequence\n"
+" -c, --sh-exec <command> Executes the given command via /bin/sh\n"
+" -e, --exec <command> Executes the given command\n"
+#ifdef HAVE_LUA
+" --lua-exec <filename> Executes the given Lua script\n"
+#endif
+" -g hop1[,hop2,...] Loose source routing hop points (8 max)\n"
+" -G <n> Loose source routing hop pointer (4, 8, 12, ...)\n"
+" -m, --max-conns <n> Maximum <n> simultaneous connections\n"
+" -h, --help Display this help screen\n"
+" -d, --delay <time> Wait between read/writes\n"
+" -o, --output <filename> Dump session data to a file\n"
+" -x, --hex-dump <filename> Dump session data as hex to a file\n"
+" -i, --idle-timeout <time> Idle read/write timeout\n"
+" -p, --source-port port Specify source port to use\n"
+" -s, --source addr Specify source address to use (doesn't affect -l)\n"
+" -l, --listen Bind and listen for incoming connections\n"
+" -k, --keep-open Accept multiple connections in listen mode\n"
+" -n, --nodns Do not resolve hostnames via DNS\n"
+" -t, --telnet Answer Telnet negotiations\n"
+" -u, --udp Use UDP instead of default TCP\n"
+" --sctp Use SCTP instead of default TCP\n"
+" -v, --verbose Set verbosity level (can be used several times)\n"
+" -w, --wait <time> Connect timeout\n"
+" -z Zero-I/O mode, report connection status only\n"
+" --append-output Append rather than clobber specified output files\n"
+" --send-only Only send data, ignoring received; quit on EOF\n"
+" --recv-only Only receive data, never send anything\n"
+" --no-shutdown Continue half-duplex when receiving EOF on stdin\n"
+" --allow Allow only given hosts to connect to Ncat\n"
+" --allowfile A file of hosts allowed to connect to Ncat\n"
+" --deny Deny given hosts from connecting to Ncat\n"
+" --denyfile A file of hosts denied from connecting to Ncat\n"
+" --broker Enable Ncat's connection brokering mode\n"
+" --chat Start a simple Ncat chat server\n"
+" --proxy <addr[:port]> Specify address of host to proxy through\n"
+" --proxy-type <type> Specify proxy type (\"http\", \"socks4\", \"socks5\")\n"
+" --proxy-auth <auth> Authenticate with HTTP or SOCKS proxy server\n"
+" --proxy-dns <type> Specify where to resolve proxy destination\n"
+
+#ifdef HAVE_OPENSSL
+" --ssl Connect or listen with SSL\n"
+" --ssl-cert Specify SSL certificate file (PEM) for listening\n"
+" --ssl-key Specify SSL private key (PEM) for listening\n"
+" --ssl-verify Verify trust and domain name of certificates\n"
+" --ssl-trustfile PEM file containing trusted SSL certificates\n"
+" --ssl-ciphers Cipherlist containing SSL ciphers to use\n"
+" --ssl-servername Request distinct server name (SNI)\n"
+" --ssl-alpn ALPN protocol list to use\n"
+#endif
+" --version Display Ncat's version information and exit\n"
+"\n"
+"See the ncat(1) manpage for full options, descriptions and usage examples\n"
+ );
+ exit(EXIT_SUCCESS);
+ case '?':
+ /* Consider unrecognised parameters/arguments as fatal. */
+ bye("Try `--help' or man(1) ncat for more information, usage options and help.");
+ default:
+ /* We consider an unrecognised option fatal. */
+ bye("Unrecognised option.");
+ }
+ }
+
+#if HAVE_LINUX_VM_SOCKETS_H
+ if (o.af == AF_VSOCK)
+ max_port = UINT32_MAX;
+#endif
+
+ if (srcport > max_port)
+ bye("Invalid source port %lld.", srcport);
+
+#ifndef HAVE_OPENSSL
+ if (o.ssl)
+ bye("OpenSSL isn't compiled in. The --ssl option cannot be chosen.");
+#endif
+
+ if (o.normlog)
+ o.normlogfd = ncat_openlog(o.normlog, o.append);
+ if (o.hexlog)
+ o.hexlogfd = ncat_openlog(o.hexlog, o.append);
+
+ if (o.verbose)
+ print_banner();
+
+ if (o.debug)
+ nbase_set_log(loguser, logdebug);
+ else
+ nbase_set_log(loguser, NULL);
+
+#if HAVE_SYS_UN_H
+ /* Using Unix domain sockets, so do the checks now */
+ if (o.af == AF_UNIX) {
+ if (o.proxyaddr || o.proxytype)
+ bye("Proxy option not supported when using Unix domain sockets.");
+#ifdef HAVE_OPENSSL
+ if (o.ssl)
+ bye("SSL option not supported when using Unix domain sockets.");
+#endif
+ if (o.broker)
+ bye("Connection brokering not supported when using Unix domain sockets.");
+ if (srcport != -1)
+ bye("Specifying source port when using Unix domain sockets doesn't make sense.");
+ if (o.numsrcrtes > 0)
+ bye("Loose source routing not allowed when using Unix domain sockets.");
+ }
+#endif /* HAVE_SYS_UN_H */
+
+#if HAVE_LINUX_VM_SOCKETS_H
+ if (o.af == AF_VSOCK) {
+ if (o.proxyaddr || o.proxytype)
+ bye("Proxy option not supported when using vsock sockets.");
+#ifdef HAVE_OPENSSL
+ if (o.ssl)
+ bye("SSL option not supported when using vsock sockets.");
+#endif
+ if (o.broker)
+ bye("Connection brokering not supported when using vsock sockets.");
+ if (o.numsrcrtes > 0)
+ bye("Loose source routing not allowed when using vsock sockets.");
+ }
+#endif /* HAVE_LINUX_VM_SOCKETS_H */
+
+ /* Create a static target address, because at least one target address must be always allocated */
+ targetaddrs = (struct sockaddr_list *)safe_zalloc(sizeof(struct sockaddr_list));
+
+ /* Will be AF_INET or AF_INET6 or AF_UNIX when valid */
+ memset(&srcaddr.storage, 0, sizeof(srcaddr.storage));
+ srcaddr.storage.ss_family = AF_UNSPEC;
+ targetaddrs->addr.storage = srcaddr.storage;
+
+ /* Clear the listenaddrs array */
+ int i;
+ for (i = 0; i < NUM_LISTEN_ADDRS; i++) {
+ listenaddrs[i].storage = srcaddr.storage;
+ }
+
+ if (o.proxyaddr) {
+ if (!o.proxytype)
+ o.proxytype = Strdup("http");
+
+ /* validate proxy type and configure its default port */
+ if (!strcmp(o.proxytype, "http"))
+ proxyport = DEFAULT_PROXY_PORT;
+ else if (!strcmp(o.proxytype, "socks4") || !strcmp(o.proxytype, "4"))
+ proxyport = DEFAULT_SOCKS4_PORT;
+ else if (!strcmp(o.proxytype, "socks5") || !strcmp(o.proxytype, "5"))
+ proxyport = DEFAULT_SOCKS5_PORT;
+ else
+ bye("Invalid proxy type \"%s\".", o.proxytype);
+
+ /* Parse HTTP/SOCKS proxy address and store it in targetss.
+ * If the proxy server is given as an IPv6 address (not hostname),
+ * the port number MUST be specified as well or parsing will break
+ * (due to the colons in the IPv6 address and host:port separator).
+ */
+
+ targetaddrs->addrlen = parseproxy(o.proxyaddr,
+ &targetaddrs->addr.storage, &targetaddrs->addrlen, &proxyport);
+ if (o.af == AF_INET) {
+ targetaddrs->addr.in.sin_port = htons(proxyport);
+ } else { // might modify to else if and test AF_{INET6|UNIX|UNSPEC}
+ targetaddrs->addr.in6.sin6_port = htons(proxyport);
+ }
+
+ if (o.listen)
+ bye("Invalid option combination: --proxy and -l.");
+ } else {
+ if (o.proxytype) {
+ if (!o.listen)
+ bye("Proxy type (--proxy-type) specified without proxy address (--proxy).");
+ if (strcmp(o.proxytype, "http"))
+ bye("Invalid proxy type \"%s\"; Ncat proxy server only supports \"http\".", o.proxytype);
+ }
+ }
+
+ if (!o.proxy_auth)
+ o.proxy_auth = getenv("NCAT_PROXY_AUTH");
+
+ if (o.zerobyte) {
+ if (o.listen)
+ bye("Services designed for LISTENING can't be used with -z");
+ if (o.telnet)
+ bye("Invalid option combination: -z and -t.");
+ if (o.execmode||o.cmdexec)
+ bye("Command execution can't be done along with option -z.");
+ if (!o.idletimeout && o.proto == IPPROTO_UDP)
+ o.idletimeout = 2 * 1000;
+ }
+ /* Default port */
+ if (o.listen && o.proxytype && !o.portno && srcport == -1)
+ o.portno = DEFAULT_PROXY_PORT;
+ else
+ o.portno = DEFAULT_NCAT_PORT;
+
+ /* Resolve the given source address */
+ if (source) {
+ int rc = 0;
+
+ if (o.listen)
+ bye("-l and -s are incompatible. Specify the address and port to bind to like you would a host to connect to.");
+
+#if HAVE_SYS_UN_H
+ /* if using UNIX sockets just copy the path.
+ * If it's not valid, it will fail later! */
+ if (o.af == AF_UNIX) {
+ if (o.proto == IPPROTO_UDP) {
+ NCAT_INIT_SUN(&srcaddr, source);
+ srcaddrlen = SUN_LEN(&srcaddr.un);
+ }
+ else
+ if (o.verbose)
+ loguser("Specifying source socket for other than DATAGRAM Unix domain sockets have no effect.\n");
+ } else
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+ if (o.af == AF_VSOCK) {
+ long long_cid;
+
+ srcaddr.vm.svm_family = AF_VSOCK;
+
+ errno = 0;
+ long_cid = strtol(source, NULL, 10);
+ if (errno != 0 || long_cid <= 0 || long_cid > UINT32_MAX)
+ bye("Invalid source address CID \"%s\".", source);
+ srcaddr.vm.svm_cid = long_cid;
+
+ srcaddrlen = sizeof(srcaddr.vm);
+ } else
+#endif
+ rc = resolve(source, 0, &srcaddr.storage, &srcaddrlen, o.af);
+ if (rc != 0)
+ bye("Could not resolve source address \"%s\": %s.", source, gai_strerror(rc));
+ }
+
+ host_list_to_set(o.allowset, allow_host_list);
+ host_list_free(allow_host_list);
+ host_list_to_set(o.denyset, deny_host_list);
+ host_list_free(deny_host_list);
+
+ int rc;
+ int num_ports = 0;
+ if (srcport != -1 && o.listen) {
+ /* Treat "ncat -l -p <port>" the same as "ncat -l <port>" for nc
+ compatibility. */
+ o.portno = (unsigned int) srcport;
+ num_ports++;
+ }
+ /* How many arguments are left? */
+ ncat_assert(optind <= argc);
+ switch (argc - optind) {
+ case 2:
+#if HAVE_SYS_UN_H
+ /* We do not use ports with Unix domain sockets. */
+ if (o.af == AF_UNIX) {
+ bye("Using Unix domain sockets and specifying port doesn't make sense.");
+ }
+#endif
+ if (num_ports == 0)
+ o.portno = parseport(argv[optind + 1], max_port, "port");
+ num_ports++;
+ /* fall through: */
+ case 1:
+#if HAVE_SYS_UN_H
+ if (o.af == AF_UNIX) {
+ NCAT_INIT_SUN(&targetaddrs->addr, argv[optind]);
+ targetaddrs->addrlen = SUN_LEN(&targetaddrs->addr.un);
+ o.sslservername = o.target = argv[optind];
+ break;
+ }
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+ if (o.af == AF_VSOCK) {
+ long long_cid;
+
+ memset(&targetaddrs->addr.storage, 0, sizeof(struct sockaddr_vm));
+ targetaddrs->addr.vm.svm_family = AF_VSOCK;
+
+ errno = 0;
+ long_cid = strtol(argv[optind], NULL, 10);
+ if (errno != 0 || long_cid <= 0 || long_cid > UINT32_MAX)
+ bye("Invalid CID \"%s\".", argv[optind]);
+ targetaddrs->addr.vm.svm_cid = long_cid;
+
+ targetaddrs->addrlen = sizeof(targetaddrs->addr.vm);
+ o.sslservername = o.target = argv[optind];
+ break;
+ }
+#endif
+ /* Support ncat -l <port>, but otherwise assume ncat <target> */
+ if (num_ports == 0 && o.listen) {
+ rc = strspn(argv[optind], "1234567890");
+ /* If the last arg is 5 or fewer digits, assume it's a port number */
+ if (argv[optind][rc] == '\0' && rc <= 5) {
+ o.portno = parseport(argv[optind], max_port, "port");
+ num_ports++;
+ break;
+ }
+ }
+ o.target = argv[optind];
+ /* resolve hostname only if o.proxytype == NULL
+ * targetss contains data already and you don't want remove them
+ */
+ if( !o.proxytype
+ && (rc = resolve_multi(o.target, 0, targetaddrs, o.af)) != 0)
+
+ bye("Could not resolve hostname \"%s\": %s.", o.target, gai_strerror(rc));
+ if (!o.sslservername)
+ o.sslservername = o.target;
+ break;
+ case 0:
+#if HAVE_SYS_UN_H
+ if (o.af == AF_UNIX) {
+ bye("You must specify a path to a socket to %s.",
+ o.listen ? "listen on" : "connect to");
+ }
+#endif
+ /* Listen defaults to any address and DEFAULT_NCAT_PORT */
+ if (!o.listen)
+ bye("You must specify a host to connect to.");
+ break;
+ default:
+ if (num_ports == 0)
+ o.portno = parseport(argv[optind + 1], max_port, "port");
+ num_ports += argc - optind - 1;
+ break;
+ }
+
+ if (num_ports > 1) {
+ loguser("Got more than one port specification: %u", o.portno);
+ for (rc = argc - num_ports + 1; rc < argc; rc++)
+ loguser_noprefix(" %s", argv[rc]);
+ loguser_noprefix(". QUITTING.\n");
+ exit(2);
+ }
+
+ if (o.proxytype && !o.listen)
+ ; /* Do nothing - port is already set to proxyport */
+ else {
+ struct sockaddr_list *targetaddrs_item = targetaddrs;
+ while (targetaddrs_item != NULL)
+ {
+ if (targetaddrs_item->addr.storage.ss_family == AF_INET)
+ targetaddrs_item->addr.in.sin_port = htons(o.portno);
+#ifdef HAVE_IPV6
+ else if (targetaddrs_item->addr.storage.ss_family == AF_INET6)
+ targetaddrs_item->addr.in6.sin6_port = htons(o.portno);
+#endif
+#if HAVE_SYS_UN_H
+ /* If we use Unix domain sockets, we have to count with them. */
+ else if (targetaddrs_item->addr.storage.ss_family == AF_UNIX)
+ ; /* Do nothing. */
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+ else if (targetaddrs_item->addr.storage.ss_family == AF_VSOCK)
+ targetaddrs_item->addr.vm.svm_port = o.portno;
+#endif
+ else if (targetaddrs_item->addr.storage.ss_family == AF_UNSPEC)
+ ; /* Leave unspecified. */
+ else
+ bye("Unknown address family %d.", targetaddrs_item->addr.storage.ss_family);
+ targetaddrs_item = targetaddrs_item->next;
+ }
+ }
+
+ if (srcport != -1 && !o.listen) {
+ if (srcaddr.storage.ss_family == AF_UNSPEC) {
+ /* We have a source port but not an explicit source address;
+ fill in an unspecified address of the same family as the
+ target. */
+ srcaddr.storage.ss_family = targetaddrs->addr.storage.ss_family;
+ if (srcaddr.storage.ss_family == AF_INET)
+ srcaddr.in.sin_addr.s_addr = INADDR_ANY;
+ else if (srcaddr.storage.ss_family == AF_INET6)
+ srcaddr.in6.sin6_addr = in6addr_any;
+ }
+ if (srcaddr.storage.ss_family == AF_INET)
+ srcaddr.in.sin_port = htons((unsigned int) srcport);
+#ifdef HAVE_IPV6
+ else if (srcaddr.storage.ss_family == AF_INET6)
+ srcaddr.in6.sin6_port = htons((unsigned int) srcport);
+#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ else if (srcaddr.storage.ss_family == AF_VSOCK)
+ srcaddr.vm.svm_port = (unsigned int) srcport;
+#endif
+ }
+
+ if (o.proto == IPPROTO_UDP) {
+
+#ifndef HAVE_DTLS_CLIENT_METHOD
+ if (o.ssl)
+ bye("OpenSSL does not have DTLS support compiled in.");
+#endif
+ }
+
+ /* Do whatever is necessary to receive \n for line endings on input from
+ the console. A no-op on Unix. */
+ set_lf_mode();
+
+#ifdef HAVE_LUA
+ if (o.execmode == EXEC_LUA)
+ lua_setup();
+#endif
+
+ if (o.listen)
+ return ncat_listen_mode();
+ else
+ return ncat_connect_mode();
+}
+
+/* connect error handling and operations. */
+static int ncat_connect_mode(void)
+{
+ /*
+ * allow/deny commands with connect make no sense. If you don't want to
+ * connect to a host, don't try to.
+ */
+ if (o.allow || o.deny)
+ bye("Invalid option combination: allow/deny with connect.");
+
+ /* o.conn_limit with 'connect' doesn't make any sense. */
+ if (o.conn_limit != -1)
+ bye("Invalid option combination: `--max-conns' with connect.");
+
+ if (o.chat)
+ bye("Invalid option combination: `--chat' with connect.");
+
+ if (o.keepopen)
+ bye("Invalid option combination: `--keep-open' with connect.");
+
+ return ncat_connect();
+}
+
+static int ncat_listen_mode(void)
+{
+ /* Can't 'listen' AND 'connect' to a proxy server at the same time. */
+ if (o.proxyaddr != NULL)
+ bye("Invalid option combination: --proxy and -l.");
+
+ if (o.broker && o.cmdexec != NULL)
+ bye("Invalid option combination: --broker and -e.");
+
+ if (o.proxytype != NULL && o.telnet)
+ bye("Invalid option combination: --telnet has no effect with --proxy-type.");
+
+ if (o.conn_limit != -1 && !(o.keepopen || o.broker))
+ loguser("Warning: Maximum connections ignored, since it does not take "
+ "effect without -k or --broker.\n");
+
+ /* Set the default maximum simultaneous TCP connection limit. */
+ if (o.conn_limit == -1)
+ o.conn_limit = DEFAULT_MAX_CONNS;
+
+#ifndef WIN32
+ /* See if the shell is executable before we get deep into this */
+ if (o.execmode == EXEC_SHELL && access("/bin/sh", X_OK) == -1)
+ bye("/bin/sh is not executable, so `-c' won't work.");
+#endif
+
+ if (targetaddrs->addr.storage.ss_family != AF_UNSPEC) {
+ listenaddrs[num_listenaddrs++] = targetaddrs->addr;
+ } else {
+ size_t ss_len;
+ int rc;
+
+ /* No command-line address. Listen on IPv4 or IPv6 or both. */
+ /* Try to bind to IPv6 first; on AIX a bound IPv4 socket blocks an IPv6
+ socket on the same port, despite IPV6_V6ONLY. */
+#ifdef HAVE_IPV6
+ if (o.af == AF_INET6 || o.af == AF_UNSPEC) {
+ ss_len = sizeof(listenaddrs[num_listenaddrs]);
+ rc = resolve("::", o.portno, &listenaddrs[num_listenaddrs].storage, &ss_len, AF_INET6);
+ if (rc == 0)
+ num_listenaddrs++;
+ else if (o.debug > 0)
+ logdebug("Failed to resolve default IPv6 address: %s\n", gai_strerror(rc));
+ }
+#endif
+ if (o.af == AF_INET || o.af == AF_UNSPEC) {
+ ss_len = sizeof(listenaddrs[num_listenaddrs]);
+ rc = resolve("0.0.0.0", o.portno, &listenaddrs[num_listenaddrs].storage, &ss_len, AF_INET);
+ if (rc != 0)
+ bye("Failed to resolve default IPv4 address: %s.", gai_strerror(rc));
+ num_listenaddrs++;
+ }
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ if (o.af == AF_VSOCK) {
+ listenaddrs[num_listenaddrs].vm.svm_family = AF_VSOCK;
+ listenaddrs[num_listenaddrs].vm.svm_cid = VMADDR_CID_ANY;
+ listenaddrs[num_listenaddrs].vm.svm_port = o.portno;
+ num_listenaddrs++;
+ }
+#endif
+ }
+
+ if (o.proxytype) {
+ if (strcmp(o.proxytype, "http") == 0)
+ o.httpserver = 1;
+ }
+
+ /* Fire the listen/select dispatcher for bog-standard listen operations. */
+ return ncat_listen();
+}
diff --git a/ncat/ncat_posix.c b/ncat/ncat_posix.c
new file mode 100644
index 0000000..1465b2f
--- /dev/null
+++ b/ncat/ncat_posix.c
@@ -0,0 +1,388 @@
+/***************************************************************************
+ * ncat_posix.c -- POSIX-specific functions. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "ncat.h"
+
+#ifdef HAVE_LUA
+#include "ncat_lua.h"
+#endif
+
+char **cmdline_split(const char *cmdexec);
+
+/* fork and exec a child process with netexec. Close the given file descriptor
+ in the parent process. Return the child's PID or -1 on error. */
+int netrun(struct fdinfo *info, char *cmdexec)
+{
+ int pid;
+
+ errno = 0;
+ pid = fork();
+ if (pid == 0) {
+ /* In the child process. */
+ netexec(info, cmdexec);
+ }
+
+ Close(info->fd);
+
+ if (pid == -1 && o.verbose)
+ logdebug("Error in fork: %s\n", strerror(errno));
+
+ return pid;
+}
+
+/* Call write in a loop until all the data is written or an error occurs. The
+ return value is the number of bytes written. If it is less than size, then
+ there was an error. */
+static int write_loop(int fd, char *buf, size_t size)
+{
+ char *p;
+ int n;
+
+ p = buf;
+ while (p - buf < size) {
+ n = write(fd, p, size - (p - buf));
+ if (n == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ break;
+ }
+ p += n;
+ }
+
+ return p - buf;
+}
+
+/* Run the given command line as if with exec. What we actually do is fork the
+ command line as a subprocess, then loop, relaying data between the socket and
+ the subprocess. This allows Ncat to handle SSL from the socket and give plain
+ text to the subprocess, and also allows things like logging and line delays.
+ Never returns. */
+void netexec(struct fdinfo *info, char *cmdexec)
+{
+ int child_stdin[2];
+ int child_stdout[2];
+ int pid;
+ int crlf_state;
+
+ char buf[DEFAULT_TCP_BUF_LEN];
+ int maxfd;
+
+ if (o.debug) {
+ switch (o.execmode) {
+ case EXEC_SHELL:
+ logdebug("Executing with shell: %s\n", cmdexec);
+ break;
+#ifdef HAVE_LUA
+ case EXEC_LUA:
+ logdebug("Executing as lua script: %s\n", cmdexec);
+ break;
+#endif
+ default:
+ logdebug("Executing: %s\n", cmdexec);
+ break;
+ }
+ }
+
+ if (pipe(child_stdin) == -1 || pipe(child_stdout) == -1)
+ bye("Can't create child pipes: %s", strerror(errno));
+
+ pid = fork();
+ if (pid == -1)
+ bye("Error in fork: %s", strerror(errno));
+ if (pid == 0) {
+ /* This is the child process. Exec the command. */
+ close(child_stdin[1]);
+ close(child_stdout[0]);
+
+ /* We might have turned off SIGPIPE handling in ncat_listen.c. Since
+ the child process SIGPIPE might mean that the connection got broken,
+ ignoring it could result in an infinite loop if the code here
+ ignores the error codes of read()/write() calls. So, just in case,
+ let's restore SIGPIPE so that writing to a broken pipe results in
+ killing the child process. */
+ Signal(SIGPIPE, SIG_DFL);
+
+ /* rearrange stdin and stdout */
+ Dup2(child_stdin[0], STDIN_FILENO);
+ Dup2(child_stdout[1], STDOUT_FILENO);
+
+ setup_environment(info);
+
+ switch (o.execmode) {
+ char **cmdargs;
+
+ case EXEC_SHELL:
+ execl("/bin/sh", "sh", "-c", cmdexec, (void *) NULL);
+ break;
+#ifdef HAVE_LUA
+ case EXEC_LUA:
+ lua_run();
+ break;
+#endif
+ default:
+ cmdargs = cmdline_split(cmdexec);
+ execv(cmdargs[0], cmdargs);
+ break;
+ }
+
+ /* exec failed. */
+ die("exec");
+ }
+
+ close(child_stdin[0]);
+ close(child_stdout[1]);
+
+ maxfd = child_stdout[0];
+ if (info->fd > maxfd)
+ maxfd = info->fd;
+
+ /* This is the parent process. Enter a "caretaker" loop that reads from the
+ socket and writes to the subprocess, and reads from the subprocess and
+ writes to the socket. We exit the loop on any read error (or EOF). On a
+ write error we just close the opposite side of the conversation. */
+ crlf_state = 0;
+ for (;;) {
+ fd_set fds;
+ int r, n_r;
+
+ FD_ZERO(&fds);
+ checked_fd_set(info->fd, &fds);
+ checked_fd_set(child_stdout[0], &fds);
+
+ r = fselect(maxfd + 1, &fds, NULL, NULL, NULL);
+ if (r == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ break;
+ }
+ if (checked_fd_isset(info->fd, &fds)) {
+ int pending;
+
+ do {
+ n_r = ncat_recv(info, buf, sizeof(buf), &pending);
+ if (n_r <= 0) {
+ /* return value can be 0 without meaning EOF in some cases such as SSL
+ * renegotiations that require read/write socket operations but do not
+ * have any application data. */
+ if(n_r == 0 && info->lasterr == 0) {
+ continue; /* Check pending */
+ }
+ goto loop_end;
+ }
+ r = write_loop(child_stdin[1], buf, n_r);
+ if (r != n_r)
+ goto loop_end;
+ } while (pending);
+ }
+ if (checked_fd_isset(child_stdout[0], &fds)) {
+ char *crlf = NULL, *wbuf;
+ n_r = read(child_stdout[0], buf, sizeof(buf));
+ if (n_r <= 0)
+ break;
+ wbuf = buf;
+ if (o.crlf) {
+ if (fix_line_endings((char *) buf, &n_r, &crlf, &crlf_state))
+ wbuf = crlf;
+ }
+ r = ncat_send(info, wbuf, n_r);
+ if (crlf != NULL)
+ free(crlf);
+ if (r <= 0)
+ goto loop_end;
+ }
+ }
+loop_end:
+
+#ifdef HAVE_OPENSSL
+ if (info->ssl != NULL) {
+ SSL_shutdown(info->ssl);
+ SSL_free(info->ssl);
+ }
+#endif
+ close(info->fd);
+
+ exit(0);
+}
+
+/*
+ * Split a command line into an array suitable for handing to execv.
+ *
+ * A note on syntax: words are split on whitespace and '\' escapes characters.
+ * '\\' will show up as '\' and '\ ' will leave a space, combining two
+ * words. Examples:
+ * "ncat\ experiment -l -k" will be parsed as the following tokens:
+ * "ncat experiment", "-l", "-k".
+ * "ncat\\ -l -k" will be parsed as "ncat\", "-l", "-k"
+ * See the test program, test/test-cmdline-split to see additional cases.
+ */
+char **cmdline_split(const char *cmdexec)
+{
+ const char *ptr;
+ char *cur_arg, **cmd_args;
+ int max_tokens = 0, arg_idx = 0, ptr_idx = 0;
+
+ /* Figure out the maximum number of tokens needed */
+ ptr = cmdexec;
+ while (*ptr) {
+ // Find the start of the token
+ while (('\0' != *ptr) && isspace((int) (unsigned char) *ptr))
+ ptr++;
+ if ('\0' == *ptr)
+ break;
+ max_tokens++;
+ // Find the start of the whitespace again
+ while (('\0' != *ptr) && !isspace((int) (unsigned char) *ptr))
+ ptr++;
+ }
+
+ /* The line is not empty so we've got something to deal with */
+ cmd_args = (char **) safe_malloc(sizeof(char *) * (max_tokens + 1));
+ cur_arg = (char *) Calloc(sizeof(char), strlen(cmdexec) + 1);
+
+ /* Get and copy the tokens */
+ ptr = cmdexec;
+ while (*ptr) {
+ while (('\0' != *ptr) && isspace((int) (unsigned char) *ptr))
+ ptr++;
+ if ('\0' == *ptr)
+ break;
+
+ while (('\0' != *ptr) && !isspace((int) (unsigned char) *ptr)) {
+ if ('\\' == *ptr) {
+ ptr++;
+ if ('\0' == *ptr)
+ break;
+
+ cur_arg[ptr_idx] = *ptr;
+ ptr_idx++;
+ ptr++;
+
+ if ('\\' != *(ptr - 1)) {
+ while (('\0' != *ptr) && isspace((int) (unsigned char) *ptr))
+ ptr++;
+ }
+ } else {
+ cur_arg[ptr_idx] = *ptr;
+ ptr_idx++;
+ ptr++;
+ }
+ }
+ cur_arg[ptr_idx] = '\0';
+
+ cmd_args[arg_idx] = strdup(cur_arg);
+ cur_arg[0] = '\0';
+ ptr_idx = 0;
+ arg_idx++;
+ }
+
+ cmd_args[arg_idx] = NULL;
+
+ /* Clean up */
+ free(cur_arg);
+
+ return cmd_args;
+}
+
+int ncat_openlog(const char *logfile, int append)
+{
+ if (append)
+ return Open(logfile, O_WRONLY | O_CREAT | O_APPEND, 0664);
+ else
+ return Open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0664);
+}
+
+void set_lf_mode(void)
+{
+ /* Nothing needed. */
+}
+
+#ifdef HAVE_OPENSSL
+
+#define NCAT_CA_CERTS_PATH (NCAT_DATADIR "/" NCAT_CA_CERTS_FILE)
+
+int ssl_load_default_ca_certs(SSL_CTX *ctx)
+{
+ int rc;
+
+ if (o.debug)
+ logdebug("Using system default trusted CA certificates and those in %s.\n", NCAT_CA_CERTS_PATH);
+
+ /* Load distribution-provided defaults, if any. */
+ rc = SSL_CTX_set_default_verify_paths(ctx);
+ ncat_assert(rc > 0);
+
+ /* Also load the trusted certificates we ship. */
+ rc = SSL_CTX_load_verify_locations(ctx, NCAT_CA_CERTS_PATH, NULL);
+ if (rc != 1) {
+ if (o.debug)
+ logdebug("Unable to load trusted CA certificates from %s: %s\n",
+ NCAT_CA_CERTS_PATH, ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+int setenv_portable(const char *name, const char *value)
+{
+ return setenv(name, value, 1);
+}
diff --git a/ncat/ncat_proxy.c b/ncat/ncat_proxy.c
new file mode 100644
index 0000000..e1e3f0e
--- /dev/null
+++ b/ncat/ncat_proxy.c
@@ -0,0 +1,867 @@
+/***************************************************************************
+ * ncat_proxy.c -- HTTP proxy server. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "base64.h"
+#include "http.h"
+#include "nsock.h"
+#include "ncat.h"
+#include "sys_wrap.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#ifndef WIN32
+/* SIG_CHLD handler */
+static void proxyreaper(int signo)
+{
+ while (waitpid(-1, NULL, WNOHANG) > 0)
+ ;
+}
+#endif
+
+/* send a '\0'-terminated string. */
+static int send_string(struct fdinfo *fdn, const char *s)
+{
+ return fdinfo_send(fdn, s, strlen(s));
+}
+
+static void http_server_handler(int c);
+static int send_proxy_authenticate(struct fdinfo *fdn, int stale);
+static char *http_code2str(int code);
+
+static void fork_handler(int s, int c);
+
+static int handle_connect(struct socket_buffer *client_sock,
+ struct http_request *request);
+static int handle_method(struct socket_buffer *client_sock,
+ struct http_request *request);
+
+static int check_auth(const struct http_request *request,
+ const struct http_credentials *credentials, int *stale);
+
+/*
+ * Simple forking HTTP proxy. It is an HTTP/1.0 proxy with knowledge of
+ * HTTP/1.1. (The things lacking for HTTP/1.1 are the chunked transfer encoding
+ * and the expect mechanism.) The proxy supports the CONNECT, GET, HEAD, and
+ * POST methods. It supports Basic and Digest authentication of clients (use the
+ * --proxy-auth option).
+ *
+ * HTTP/1.1 is defined in RFC 2616. Many comments refer to that document.
+ * http://tools.ietf.org/html/rfc2616
+ *
+ * HTTP authentication is discussed in RFC 2617.
+ * http://tools.ietf.org/html/rfc2617
+ *
+ * The CONNECT method is documented in an Internet draft and is specified as the
+ * way to proxy HTTPS in RFC 2817, section 5.
+ * http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01
+ * http://tools.ietf.org/html/rfc2817#section-5
+ *
+ * The CONNECT method is not limited to HTTP, but is potentially capable of
+ * connecting to any TCP port on any host. The proxy connection is requested
+ * with an HTTP request, but after that, the proxy does no interpretation of the
+ * data passing through it. See section 6 of the above mentioned draft for the
+ * security implications.
+ */
+int ncat_http_server(void)
+{
+ int c, i, j;
+ int listen_socket[NUM_LISTEN_ADDRS];
+ socklen_t sslen;
+ union sockaddr_u conn;
+ unsigned int num_sockets;
+
+#ifndef WIN32
+ Signal(SIGCHLD, proxyreaper);
+#endif
+
+#if HAVE_HTTP_DIGEST
+ http_digest_init_secret();
+#endif
+
+#ifdef HAVE_OPENSSL
+ if (o.ssl)
+ setup_ssl_listen(SSLv23_server_method());
+#endif
+ /* Clear the socket list */
+ for (i = 0; i < NUM_LISTEN_ADDRS; i++)
+ listen_socket[i] = -1;
+
+ /* set for selecting listening sockets */
+ fd_set listen_fds;
+ fd_list_t listen_fdlist;
+ FD_ZERO(&listen_fds);
+ init_fdlist(&listen_fdlist, num_listenaddrs);
+
+ /* Listen on each address, set up lists for select */
+ num_sockets = 0;
+ for (i = 0; i < num_listenaddrs; i++) {
+ listen_socket[num_sockets] = do_listen(SOCK_STREAM, IPPROTO_TCP, &listenaddrs[i]);
+ if (listen_socket[num_sockets] == -1) {
+ if (o.debug > 0)
+ logdebug("do_listen(\"%s\"): %s\n", socktop(&listenaddrs[i], 0), socket_strerror(socket_errno()));
+ continue;
+ }
+
+ /* make us not block on accepts in weird cases. See ncat_listen.c:209 */
+ unblock_socket(listen_socket[num_sockets]);
+
+ /* setup select sets and max fd */
+ checked_fd_set(listen_socket[num_sockets], &listen_fds);
+ add_fd(&listen_fdlist, listen_socket[num_sockets]);
+
+ num_sockets++;
+ }
+ if (num_sockets == 0) {
+ if (num_listenaddrs == 1)
+ bye("Unable to open listening socket on %s: %s", socktop(&listenaddrs[0], 0), socket_strerror(socket_errno()));
+ else
+ bye("Unable to open any listening sockets.");
+ }
+
+ for (;;) {
+ fd_set read_fds;
+
+ sslen = sizeof(conn.storage);
+ /*
+ * We just select to get a list of sockets which we can talk to
+ */
+ if (o.debug > 1)
+ logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax);
+ read_fds = listen_fds;
+
+ int fds_ready = fselect(listen_fdlist.fdmax + 1, &read_fds, NULL, NULL, NULL);
+
+ if (o.debug > 1)
+ logdebug("select returned %d fds ready\n", fds_ready);
+
+ if (fds_ready == 0)
+ bye("Idle timeout expired (%d ms).", o.idletimeout);
+
+ for (i = 0; i <= listen_fdlist.fdmax && fds_ready > 0; i++) {
+ /* Loop through descriptors until there is something ready */
+ if (!checked_fd_isset(i, &read_fds))
+ continue;
+
+ /* Check each listening socket */
+ for (j = 0; j < num_sockets; j++) {
+ if (i == listen_socket[j]) {
+ fds_ready--;
+ c = accept(i, &conn.sockaddr, &sslen);
+
+ if (c == -1) {
+ if (errno == EINTR)
+ continue;
+ die("accept");
+ }
+
+ if (!allow_access(&conn)) {
+ Close(c);
+ continue;
+ }
+ if (o.debug > 1)
+ logdebug("forking handler for %d\n", i);
+ fork_handler(i, c);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+#ifdef WIN32
+/* On Windows we don't actually fork but rather start a thread. */
+
+static DWORD WINAPI handler_thread_func(void *data)
+{
+ http_server_handler(*((int *) data));
+ free(data);
+
+ return 0;
+}
+
+static void fork_handler(int s, int c)
+{
+ int *data;
+ HANDLE thread;
+
+ data = (int *) safe_malloc(sizeof(int));
+ *data = c;
+ thread = CreateThread(NULL, 0, handler_thread_func, data, 0, NULL);
+ if (thread == NULL) {
+ if (o.verbose)
+ logdebug("Error in CreateThread: %d\n", GetLastError());
+ free(data);
+ return;
+ }
+ CloseHandle(thread);
+}
+#else
+static void fork_handler(int s, int c)
+{
+ int rc;
+
+ rc = fork();
+ if (rc == -1) {
+ return;
+ } else if (rc == 0) {
+ Close(s);
+
+ if (!o.debug) {
+ Close(STDIN_FILENO);
+ Close(STDOUT_FILENO);
+ Close(STDERR_FILENO);
+ }
+
+ http_server_handler(c);
+ exit(0);
+ } else {
+ Close(c);
+ }
+}
+#endif
+
+/* Is this one of the methods we can handle? */
+static int method_is_known(const char *method)
+{
+ return strcmp(method, "CONNECT") == 0
+ || strcmp(method, "GET") == 0
+ || strcmp(method, "HEAD") == 0
+ || strcmp(method, "POST") == 0;
+}
+
+static void http_server_handler(int c)
+{
+ int code;
+ struct socket_buffer sock;
+ struct http_request request;
+ char *buf;
+
+ socket_buffer_init(&sock, c);
+#if HAVE_OPENSSL
+ if (o.ssl) {
+ sock.fdn.ssl = new_ssl(sock.fdn.fd);
+ if (SSL_accept(sock.fdn.ssl) != 1) {
+ loguser("Failed SSL connection: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+ }
+#endif
+
+ code = http_read_request_line(&sock, &buf);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error reading Request-Line.\n");
+ send_string(&sock.fdn, http_code2str(code));
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+ if (o.debug > 1)
+ logdebug("Request-Line: %s", buf);
+ code = http_parse_request_line(buf, &request);
+ free(buf);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error parsing Request-Line.\n");
+ send_string(&sock.fdn, http_code2str(code));
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+
+ if (!method_is_known(request.method)) {
+ if (o.debug > 1)
+ logdebug("Bad method: %s.\n", request.method);
+ http_request_free(&request);
+ send_string(&sock.fdn, http_code2str(405));
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+
+ code = http_read_header(&sock, &buf);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error reading header.\n");
+ http_request_free(&request);
+ send_string(&sock.fdn, http_code2str(code));
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+ if (o.debug > 1)
+ logdebug("Header:\n%s", buf);
+ code = http_request_parse_header(&request, buf);
+ free(buf);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error parsing header.\n");
+ http_request_free(&request);
+ send_string(&sock.fdn, http_code2str(code));
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+
+ /* Check authentication. */
+ if (o.proxy_auth) {
+ struct http_credentials credentials;
+ int ret, stale;
+
+ if (http_header_get_proxy_credentials(request.header, &credentials) == NULL) {
+ /* No credentials or a parsing error. */
+ send_proxy_authenticate(&sock.fdn, 0);
+ http_request_free(&request);
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+
+ ret = check_auth(&request, &credentials, &stale);
+ http_credentials_free(&credentials);
+ if (!ret) {
+ /* Password doesn't match. */
+ /* RFC 2617, section 1.2: "If a proxy does not accept the
+ credentials sent with a request, it SHOULD return a 407 (Proxy
+ Authentication Required). */
+ send_proxy_authenticate(&sock.fdn, stale);
+ http_request_free(&request);
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+ }
+
+ if (strcmp(request.method, "CONNECT") == 0) {
+ code = handle_connect(&sock, &request);
+ } else if (strcmp(request.method, "GET") == 0
+ || strcmp(request.method, "HEAD") == 0
+ || strcmp(request.method, "POST") == 0) {
+ code = handle_method(&sock, &request);
+ } else {
+ code = 500;
+ }
+ http_request_free(&request);
+
+ if (code != 0) {
+ send_string(&sock.fdn, http_code2str(code));
+ fdinfo_close(&sock.fdn);
+ return;
+ }
+
+ fdinfo_close(&sock.fdn);
+}
+
+static int handle_connect(struct socket_buffer *client_sock,
+ struct http_request *request)
+{
+ union sockaddr_u su;
+ size_t sslen = sizeof(su.storage);
+ int maxfd, s, rc;
+ char *line;
+ size_t len;
+ fd_set m, r;
+
+ if (request->uri.port == -1) {
+ if (o.verbose)
+ logdebug("No port number in CONNECT URI.\n");
+ return 400;
+ }
+ if (o.debug > 1)
+ logdebug("CONNECT to %s:%d.\n", request->uri.host, request->uri.port);
+
+ rc = resolve(request->uri.host, request->uri.port, &su.storage, &sslen, o.af);
+ if (rc != 0) {
+ if (o.debug) {
+ logdebug("Can't resolve name \"%s\": %s.\n",
+ request->uri.host, gai_strerror(rc));
+ }
+ return 504;
+ }
+
+ s = Socket(su.storage.ss_family, SOCK_STREAM, IPPROTO_TCP);
+
+ if (connect(s, &su.sockaddr, sslen) == -1) {
+ if (o.debug)
+ logdebug("Can't connect to %s: %s.\n", socktop(&su, sslen), socket_strerror(socket_errno()));
+ Close(s);
+ return 504;
+ }
+
+ send_string(&client_sock->fdn, http_code2str(200));
+
+ /* Clear out whatever is left in the socket buffer. The client may have
+ already sent the first part of its request to the origin server. */
+ line = socket_buffer_remainder(client_sock, &len);
+ if (send(s, line, len, 0) < 0) {
+ if (o.debug)
+ logdebug("Error sending %lu leftover bytes: %s.\n", (unsigned long) len, strerror(errno));
+ Close(s);
+ return 0;
+ }
+
+ maxfd = client_sock->fdn.fd < s ? s : client_sock->fdn.fd;
+ FD_ZERO(&m);
+ checked_fd_set(client_sock->fdn.fd, &m);
+ checked_fd_set(s, &m);
+
+ errno = 0;
+
+ while (!socket_errno() || socket_errno() == EINTR) {
+ char buf[DEFAULT_TCP_BUF_LEN];
+ int len, rc;
+
+ r = m;
+
+ fselect(maxfd + 1, &r, NULL, NULL, NULL);
+
+ zmem(buf, sizeof(buf));
+
+ if (checked_fd_isset(client_sock->fdn.fd, &r)) {
+ do {
+ do {
+ len = fdinfo_recv(&client_sock->fdn, buf, sizeof(buf));
+ } while (len == -1 && socket_errno() == EINTR);
+ if (len <= 0)
+ goto end;
+
+ do {
+ rc = send(s, buf, len, 0);
+ } while (rc == -1 && socket_errno() == EINTR);
+ if (rc == -1)
+ goto end;
+ } while (fdinfo_pending(&client_sock->fdn));
+ }
+
+ if (checked_fd_isset(s, &r)) {
+ do {
+ len = recv(s, buf, sizeof(buf), 0);
+ } while (len == -1 && socket_errno() == EINTR);
+ if (len <= 0)
+ goto end;
+
+ do {
+ rc = fdinfo_send(&client_sock->fdn, buf, len);
+ } while (rc == -1 && socket_errno() == EINTR);
+ if (rc == -1)
+ goto end;
+ }
+ }
+end:
+
+ close(s);
+
+ return 0;
+}
+
+static int do_transaction(struct http_request *request,
+ struct socket_buffer *client_sock, struct socket_buffer *server_sock);
+
+/* Generic handler for GET, HEAD, and POST methods. */
+static int handle_method(struct socket_buffer *client_sock,
+ struct http_request *request)
+{
+ struct socket_buffer server_sock;
+ union sockaddr_u su;
+ size_t sslen = sizeof(su.storage);
+ int code;
+ int s, rc;
+
+ if (strcmp(request->uri.scheme, "http") != 0) {
+ if (o.verbose)
+ logdebug("Unknown scheme in URI: %s.\n", request->uri.scheme);
+ return 400;
+ }
+ if (request->uri.port == -1) {
+ if (o.verbose)
+ logdebug("Unknown port in URI.\n");
+ return 400;
+ }
+
+ rc = resolve(request->uri.host, request->uri.port, &su.storage, &sslen, o.af);
+ if (rc != 0) {
+ if (o.debug) {
+ logdebug("Can't resolve name %s:%d: %s.\n",
+ request->uri.host, request->uri.port, gai_strerror(rc));
+ }
+ return 504;
+ }
+
+ /* RFC 2616, section 5.1.2: "In order to avoid request loops, a proxy MUST
+ be able to recognize all of its server names, including any aliases,
+ local variations, and the numeric IP address. */
+ if (request->uri.port == o.portno && addr_is_local(&su)) {
+ if (o.verbose)
+ logdebug("Proxy loop detected: %s:%d\n", request->uri.host, request->uri.port);
+ return 403;
+ }
+
+ s = Socket(su.storage.ss_family, SOCK_STREAM, IPPROTO_TCP);
+
+ if (connect(s, &su.sockaddr, sslen) == -1) {
+ if (o.debug)
+ logdebug("Can't connect to %s: %s.\n", socktop(&su, sslen), socket_strerror(socket_errno()));
+ Close(s);
+ return 504;
+ }
+
+ socket_buffer_init(&server_sock, s);
+
+ code = do_transaction(request, client_sock, &server_sock);
+
+ fdinfo_close(&server_sock.fdn);
+
+ if (code != 0)
+ return code;
+
+ return 0;
+}
+
+/* Do a GET, HEAD, or POST transaction. */
+static int do_transaction(struct http_request *request,
+ struct socket_buffer *client_sock, struct socket_buffer *server_sock)
+{
+ char buf[BUFSIZ];
+ struct http_response response;
+ char *line;
+ char *request_str, *response_str;
+ size_t len;
+ int code, n;
+
+ /* We don't handle the chunked transfer encoding, which in the absence of a
+ Content-Length is the only way we know the end of a request body. RFC
+ 2616, section 4.4 says, "If a request contains a message-body and a
+ Content-Length is not given, the server SHOULD respond with 400 (bad
+ request) if it cannot determine the length of the message, or with 411
+ (length required) if it wishes to insist on receiving a valid
+ Content-Length." */
+ if (strcmp(request->method, "POST") == 0 && !request->content_length_set) {
+ if (o.debug)
+ logdebug("POST request with no Content-Length.\n");
+ return 400;
+ }
+
+ /* The version we use to talk to the server. */
+ request->version = HTTP_10;
+
+ /* Remove headers that only apply to our connection with the client. */
+ code = http_header_remove_hop_by_hop(&request->header);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error removing hop-by-hop headers.\n");
+ return code;
+ }
+
+ /* Build the Host header. */
+ if (request->uri.port == -1 || request->uri.port == 80)
+ n = Snprintf(buf, sizeof(buf), "%s", request->uri.host);
+ else
+ n = Snprintf(buf, sizeof(buf), "%s:%d", request->uri.host, request->uri.port);
+ if (n < 0 || n >= sizeof(buf)) {
+ /* Request Entity Too Large. */
+ return 501;
+ }
+ request->header = http_header_set(request->header, "Host", buf);
+
+ request->header = http_header_set(request->header, "Connection", "close");
+
+ /* Send the request to the server. */
+ request_str = http_request_to_string(request, &len);
+ n = send(server_sock->fdn.fd, request_str, len, 0);
+ free(request_str);
+ if (n < 0)
+ return 504;
+ /* Send the request body, if any. Count up to Content-Length. */
+ while (request->bytes_transferred < request->content_length) {
+ n = socket_buffer_read(client_sock, buf, MIN(sizeof(buf), request->content_length - request->bytes_transferred));
+ if (n < 0)
+ return 504;
+ if (n == 0)
+ break;
+ request->bytes_transferred += n;
+ n = send(server_sock->fdn.fd, buf, n, 0);
+ if (n < 0)
+ return 504;
+ }
+ if (o.debug && request->bytes_transferred < request->content_length)
+ logdebug("Received only %lu request body bytes (Content-Length was %lu).\n", request->bytes_transferred, request->content_length);
+
+
+ /* Read the response. */
+ code = http_read_status_line(server_sock, &line);
+ if (o.debug > 1)
+ logdebug("Status-Line: %s", line);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error reading Status-Line.\n");
+ return 0;
+ }
+ code = http_parse_status_line(line, &response);
+ free(line);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error parsing Status-Line.\n");
+ return 0;
+ }
+
+ code = http_read_header(server_sock, &line);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error reading header.\n");
+ return 0;
+ }
+ if (o.debug > 1)
+ logdebug("Response header:\n%s", line);
+
+ code = http_response_parse_header(&response, line);
+ free(line);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error parsing response header.\n");
+ return 0;
+ }
+
+
+ /* The version we use to talk to the client. */
+ response.version = HTTP_10;
+
+ /* Remove headers that only apply to our connection with the server. */
+ code = http_header_remove_hop_by_hop(&response.header);
+ if (code != 0) {
+ if (o.verbose)
+ logdebug("Error removing hop-by-hop headers.\n");
+ return code;
+ }
+
+ response.header = http_header_set(response.header, "Connection", "close");
+
+ /* Send the response to the client. */
+ response_str = http_response_to_string(&response, &len);
+ n = fdinfo_send(&client_sock->fdn, response_str, len);
+ free(response_str);
+ if (n < 0) {
+ http_response_free(&response);
+ return 504;
+ }
+ /* If the Content-Length is 0, read until the connection is closed.
+ Otherwise read until the Content-Length. At this point it's too late to
+ return our own error code so return 0 in case of any error. */
+ while (!response.content_length_set
+ || response.bytes_transferred < response.content_length) {
+ size_t count;
+
+ count = sizeof(buf);
+ if (response.content_length_set) {
+ size_t remaining = response.content_length - response.bytes_transferred;
+ if (remaining < count)
+ count = remaining;
+ }
+ n = socket_buffer_read(server_sock, buf, count);
+ if (n <= 0)
+ break;
+ response.bytes_transferred += n;
+ n = fdinfo_send(&client_sock->fdn, buf, n);
+ if (n < 0)
+ break;
+ }
+
+ http_response_free(&response);
+
+ return 0;
+}
+
+/* Send a 407 Proxy Authenticate Required response. */
+static int send_proxy_authenticate(struct fdinfo *fdn, int stale)
+{
+ char *buf = NULL;
+ size_t size = 0, offset = 0;
+ int n;
+
+ strbuf_append_str(&buf, &size, &offset, "HTTP/1.0 407 Proxy Authentication Required\r\n");
+ strbuf_append_str(&buf, &size, &offset, "Proxy-Authenticate: Basic realm=\"Ncat\"\r\n");
+#if HAVE_HTTP_DIGEST
+ {
+ char *hdr;
+
+ hdr = http_digest_proxy_authenticate("Ncat", stale);
+ strbuf_sprintf(&buf, &size, &offset, "Proxy-Authenticate: %s\r\n", hdr);
+ free(hdr);
+ }
+#endif
+ strbuf_append_str(&buf, &size, &offset, "\r\n");
+
+ if (o.debug > 1)
+ logdebug("RESPONSE:\n%s", buf);
+
+ n = send_string(fdn, buf);
+ free(buf);
+
+ return n;
+}
+
+static char *http_code2str(int code)
+{
+ /* See RFC 2616, section 6.1.1 for status codes. */
+ switch (code) {
+ case 200:
+ return "HTTP/1.0 200 OK\r\n\r\n";
+ case 400:
+ return "HTTP/1.0 400 Bad Request\r\n\r\n";
+ case 403:
+ return "HTTP/1.0 403 Forbidden\r\n\r\n";
+ case 405:
+ /* RFC 2616, section 14.7 for Allow. */
+ return "\
+HTTP/1.0 405 Method Not Allowed\r\n\
+Allow: CONNECT, GET, HEAD, POST\r\n\
+\r\n";
+ case 413:
+ return "HTTP/1.0 413 Request Entity Too Large\r\n\r\n";
+ case 501:
+ return "HTTP/1.0 501 Not Implemented\r\n\r\n";
+ case 504:
+ return "HTTP/1.0 504 Gateway Timeout\r\n\r\n";
+ default:
+ return "HTTP/1.0 500 Internal Server Error\r\n\r\n";
+ }
+
+ return NULL;
+}
+
+/* userpass is a user:pass string (the argument to --proxy-auth). value is the
+ value of the Proxy-Authorization header field. Returns 0 on authentication
+ failure and nonzero on success. *stale is set to 1 if HTTP Digest credentials
+ are valid but out of date. */
+static int check_auth(const struct http_request *request,
+ const struct http_credentials *credentials, int *stale)
+{
+ if (o.proxy_auth == NULL)
+ return 1;
+
+ *stale = 0;
+
+ if (credentials->scheme == AUTH_BASIC) {
+ char *expected;
+ int cmp;
+
+ if (credentials->u.basic == NULL)
+ return 0;
+
+ /* We don't decode the received password, we encode the expected
+ password and compare the encoded strings. */
+ expected = b64enc((unsigned char *) o.proxy_auth, strlen(o.proxy_auth));
+ cmp = strcmp(expected, credentials->u.basic);
+ free(expected);
+
+ return cmp == 0;
+ }
+#if HAVE_HTTP_DIGEST
+ else if (credentials->scheme == AUTH_DIGEST) {
+ char *username, *password;
+ char *proxy_auth;
+ struct timeval nonce_tv, now;
+ int nonce_age;
+ int ret;
+
+ /* Split up the proxy auth argument. */
+ proxy_auth = Strdup(o.proxy_auth);
+ username = proxy_auth;
+ password = strchr(proxy_auth, ':');
+ if (password == NULL) {
+ free(proxy_auth);
+ return 0;
+ }
+ *password++ = '\0';
+ ret = http_digest_check_credentials(username, "Ncat", password,
+ request->method, credentials);
+ free(proxy_auth);
+
+ if (!ret)
+ return 0;
+
+ /* The nonce checks out as one we issued and it matches what we expect
+ given the credentials. Now check if it's too old. */
+ if (credentials->u.digest.nonce == NULL
+ || http_digest_nonce_time(credentials->u.digest.nonce, &nonce_tv) == -1)
+ return 0;
+ gettimeofday(&now, NULL);
+ if (TIMEVAL_AFTER(nonce_tv, now))
+ return 0;
+ nonce_age = TIMEVAL_SEC_SUBTRACT(now, nonce_tv);
+
+ if (nonce_age > HTTP_DIGEST_NONCE_EXPIRY) {
+ if (o.verbose)
+ loguser("Nonce is %d seconds old; rejecting.\n", nonce_age);
+ *stale = 1;
+ return 0;
+ }
+
+ /* To prevent replays, here we should additionally check against a list
+ of recently used nonces, where "recently used nonce" is one that has
+ been used to successfully authenticate within the last
+ HTTP_DIGEST_NONCE_EXPIRY seconds. (Older than that and we don't need
+ to keep it in the list, because the expiry test above will catch it.
+ This isn't supported because the fork-and-process architecture of the
+ proxy server makes it hard for us to change state in the parent
+ process from here in the child. */
+
+ return 1;
+ }
+#endif
+ else {
+ return 0;
+ }
+}
diff --git a/ncat/ncat_proxy.h b/ncat/ncat_proxy.h
new file mode 100644
index 0000000..49d6e2b
--- /dev/null
+++ b/ncat/ncat_proxy.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * ncat_proxy.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef NCAT_PROXY_H
+#define NCAT_PROXY_H
+
+/* How long we will honor nonces we issue, in seconds. The client gets back a
+ 407 with stale="true" if the nonce is valid but expired. Nonces are good only
+ once, so this is really a limit on how long we have to keep nonces on a
+ "used" list before forgetting them. */
+#define HTTP_DIGEST_NONCE_EXPIRY 10
+
+/*
+ * Simple forking HTTP proxy.
+ */
+extern int ncat_http_server(void);
+
+#endif
diff --git a/ncat/ncat_ssl.c b/ncat/ncat_ssl.c
new file mode 100644
index 0000000..43069c6
--- /dev/null
+++ b/ncat/ncat_ssl.c
@@ -0,0 +1,669 @@
+/***************************************************************************
+ * ncat_ssl.c -- SSL support functions. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "nbase.h"
+#include "ncat_config.h"
+#ifdef HAVE_OPENSSL
+#include "nsock.h"
+#include "ncat.h"
+
+#include <stdio.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER
+#define HAVE_OPAQUE_STRUCTS 1
+#define FUNC_ASN1_STRING_data ASN1_STRING_get0_data
+#else
+#define FUNC_ASN1_STRING_data ASN1_STRING_data
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+/* Deprecated in OpenSSL 3.0 */
+#define SSL_get_peer_certificate SSL_get1_peer_certificate
+#else
+#include <openssl/bn.h>
+#endif
+
+/* Required for windows compilation to Eliminate APPLINK errors.
+ See http://www.openssl.org/support/faq.html#PROG2 */
+#ifdef WIN32
+#include <openssl/applink.c>
+#endif
+
+static SSL_CTX *sslctx;
+
+static int ssl_gen_cert(X509 **cert, EVP_PKEY **key);
+
+/* Parameters for automatic key and certificate generation. */
+enum {
+ DEFAULT_KEY_BITS = 2048,
+ DEFAULT_CERT_DURATION = 60 * 60 * 24 * 365,
+};
+#define CERTIFICATE_COMMENT "Automatically generated by Ncat. See https://nmap.org/ncat/."
+
+SSL_CTX *setup_ssl_listen(const SSL_METHOD *method)
+{
+ if (sslctx)
+ goto done;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
+ if (NULL == OSSL_PROVIDER_load(NULL, "legacy") && o.debug)
+ {
+ loguser("OpenSSL legacy provider failed to load: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+ if (NULL == OSSL_PROVIDER_load(NULL, "default"))
+ {
+ loguser("OpenSSL default provider failed to load: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+#endif
+
+ /* RAND_status initializes the random number generator through a variety of
+ platform-dependent methods, then returns 1 if there is enough entropy or
+ 0 otherwise. This seems to be a good platform-independent way of seeding
+ the generator, as well as of refusing to continue without enough
+ entropy. */
+ if (!RAND_status())
+ bye("Failed to seed OpenSSL PRNG (RAND_status returned false).");
+
+ if (!method)
+ bye("Invalid SSL method: %s.", ERR_error_string(ERR_get_error(), NULL));
+ if (!(sslctx = SSL_CTX_new(method)))
+ bye("SSL_CTX_new(): %s.", ERR_error_string(ERR_get_error(), NULL));
+
+ SSL_CTX_set_options(sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
+
+ /* Secure ciphers list taken from Nsock. */
+ if (o.sslciphers == NULL) {
+ if (!SSL_CTX_set_cipher_list(sslctx, "ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!MD5:@STRENGTH"))
+ bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL));
+ }
+ else {
+ if (!SSL_CTX_set_cipher_list(sslctx, o.sslciphers))
+ bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL));
+ }
+
+ if (o.sslcert == NULL && o.sslkey == NULL) {
+ X509 *cert;
+ EVP_PKEY *key;
+ char digest_buf[SHA1_STRING_LENGTH + 1];
+
+ if (o.verbose)
+ loguser("Generating a temporary %d-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.\n", DEFAULT_KEY_BITS);
+ if (ssl_gen_cert(&cert, &key) == 0)
+ bye("ssl_gen_cert(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ if (o.verbose) {
+ char *fp;
+ fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf));
+ ncat_assert(fp == digest_buf);
+ loguser("SHA-1 fingerprint: %s\n", digest_buf);
+ }
+ if (SSL_CTX_use_certificate(sslctx, cert) != 1)
+ bye("SSL_CTX_use_certificate(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ if (SSL_CTX_use_PrivateKey(sslctx, key) != 1)
+ bye("SSL_CTX_use_PrivateKey(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ X509_free(cert);
+ EVP_PKEY_free(key);
+ } else {
+ if (o.sslcert == NULL || o.sslkey == NULL)
+ bye("The --ssl-key and --ssl-cert options must be used together.");
+ if (SSL_CTX_use_certificate_chain_file(sslctx, o.sslcert) != 1)
+ bye("SSL_CTX_use_certificate_chain_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ if (SSL_CTX_use_PrivateKey_file(sslctx, o.sslkey, SSL_FILETYPE_PEM) != 1)
+ bye("SSL_CTX_use_Privatekey_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ }
+
+done:
+ return sslctx;
+}
+
+SSL *new_ssl(int fd)
+{
+ SSL *ssl;
+
+ if (!(ssl = SSL_new(sslctx)))
+ bye("SSL_new(): %s.", ERR_error_string(ERR_get_error(), NULL));
+ if (!SSL_set_fd(ssl, fd))
+ bye("SSL_set_fd(): %s.", ERR_error_string(ERR_get_error(), NULL));
+
+ return ssl;
+}
+
+/* Match a (user-supplied) hostname against a (certificate-supplied) name, which
+ may be a wildcard pattern. A wildcard pattern may contain only one '*', it
+ must be the entire leftmost component, and there must be at least two
+ components following it. len is the length of pattern; pattern may contain
+ null bytes so that len != strlen(pattern); pattern may also not be null terminated.
+ hostname *must* be null-terminated. */
+static int wildcard_match(const char *pattern, const char *hostname, int len)
+{
+ const char *p = pattern;
+ const char *h = hostname;
+ int remaining = len;
+ if (len > 1 && pattern[0] == '*' && pattern[1] == '.') {
+ /* A wildcard pattern. */
+ const char *dot;
+
+ /* Skip the wildcard component. */
+ p += 2;
+ remaining -= 2;
+
+ /* Ensure there are no more wildcard characters. */
+ if (memchr(p, '*', remaining) != NULL)
+ return 0;
+
+ /* Ensure there's at least one more dot, not counting a dot at the
+ end. */
+ dot = (const char *) memchr(p, '.', remaining);
+ if (dot == NULL /* not found */
+ || dot - p == remaining /* dot in last position */
+ || *(dot + 1) == '\0') /* dot immediately before null terminator */
+ {
+ if (o.debug > 1) {
+ logdebug("Wildcard name \"%.*s\" doesn't have at least two"
+ " components after the wildcard; rejecting.\n", len, pattern);
+ }
+ return 0;
+ }
+
+ /* Skip the leftmost hostname component. */
+ h = strchr(hostname, '.');
+ if (h == NULL)
+ return 0;
+ h++;
+
+ }
+ /* Compare what remains of the pattern and hostname. */
+ /* Normal string comparison. Check the name length because I'm concerned
+ about someone somehow embedding a '\0' in the subject and matching
+ against a shorter name. */
+ return remaining == strlen(h) && strncmp(p, h, remaining) == 0;
+}
+
+/* Match a hostname against the contents of a dNSName field of the
+ subjectAltName extension, if present. This is the preferred place for a
+ certificate to store its domain name, as opposed to in the commonName field.
+ It has the advantage that multiple names can be stored, so that one
+ certificate can match both "example.com" and "www.example.com".
+
+ If num_checked is not NULL, the number of dNSName fields that were checked
+ before returning will be stored in it. This is so you can distinguish between
+ the check failing because there were names but none matched, or because there
+ were no names to match. */
+static int cert_match_dnsname(X509 *cert, const char *hostname,
+ unsigned int *num_checked)
+{
+ X509_EXTENSION *ext;
+ STACK_OF(GENERAL_NAME) *gen_names;
+ const X509V3_EXT_METHOD *method;
+ unsigned char *data;
+ int i;
+
+ if (num_checked != NULL)
+ *num_checked = 0;
+
+ i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
+ if (i < 0)
+ return 0;
+ /* If there's more than one subjectAltName extension, forget it. */
+ if (X509_get_ext_by_NID(cert, NID_subject_alt_name, i) >= 0)
+ return 0;
+ ext = X509_get_ext(cert, i);
+
+ /* See the function X509V3_EXT_print in the OpenSSL source for this method
+ of getting a string value from an extension. */
+ method = X509V3_EXT_get(ext);
+ if (method == NULL)
+ return 0;
+
+ /* We must copy this address into a temporary variable because ASN1_item_d2i
+ increments it. We don't want it to corrupt ext->value->data. */
+ ASN1_OCTET_STRING* asn1_str = X509_EXTENSION_get_data(ext);
+ data = asn1_str->data;
+ /* Here we rely on the fact that the internal representation (the "i" in
+ "i2d") for NID_subject_alt_name is STACK_OF(GENERAL_NAME). Converting it
+ to a stack of CONF_VALUE with a i2v method is not satisfactory, because a
+ CONF_VALUE doesn't contain the length of the value so you can't know the
+ presence of null bytes. */
+#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
+ if (method->it != NULL) {
+ ASN1_OCTET_STRING* asn1_str_a = X509_EXTENSION_get_data(ext);
+ gen_names = (STACK_OF(GENERAL_NAME) *) ASN1_item_d2i(NULL,
+ (const unsigned char **) &data,
+ asn1_str_a->length, ASN1_ITEM_ptr(method->it));
+ } else {
+ ASN1_OCTET_STRING* asn1_str_b = X509_EXTENSION_get_data(ext);
+ gen_names = (STACK_OF(GENERAL_NAME) *) method->d2i(NULL,
+ (const unsigned char **) &data,
+ asn1_str_b->length);
+ }
+#else
+ gen_names = (STACK_OF(GENERAL_NAME) *) method->d2i(NULL,
+ (const unsigned char **) &data,
+ ext->value->length);
+#endif
+ if (gen_names == NULL)
+ return 0;
+
+ /* Look for a dNSName field with a matching hostname. There may be more than
+ one dNSName field. */
+ for (i = 0; i < sk_GENERAL_NAME_num(gen_names); i++) {
+ GENERAL_NAME *gen_name;
+
+ gen_name = sk_GENERAL_NAME_value(gen_names, i);
+ if (gen_name->type == GEN_DNS) {
+ const char *dnsname = (const char *) FUNC_ASN1_STRING_data(gen_name->d.dNSName);
+ int dnslen = ASN1_STRING_length(gen_name->d.dNSName);
+ if (o.debug > 1)
+ logdebug("Checking certificate DNS name \"%.*s\" against \"%s\".\n", dnslen, dnsname, hostname);
+ if (num_checked != NULL)
+ (*num_checked)++;
+ if (wildcard_match(dnsname, hostname, dnslen))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Returns the number of contiguous blocks of bytes in pattern that do not
+ contain the '.' byte. */
+static unsigned int num_components(const unsigned char *pattern, size_t len)
+{
+ const unsigned char *p;
+ unsigned int count;
+
+ count = 0;
+ p = pattern;
+ for (;;) {
+ while (p - pattern < len && *p == '.')
+ p++;
+ if (p - pattern >= len)
+ break;
+ while (p - pattern < len && *p != '.')
+ p++;
+ count++;
+ }
+
+ return count;
+}
+
+/* Returns true if the a pattern is strictly less specific than the b
+ pattern. */
+static int less_specific(const unsigned char *a, size_t a_len,
+ const unsigned char *b, size_t b_len)
+{
+ /* Wildcard patterns are always less specific than non-wildcard patterns. */
+ if (memchr(a, '*', a_len) != NULL && memchr(b, '*', b_len) == NULL)
+ return 1;
+ if (memchr(a, '*', a_len) == NULL && memchr(b, '*', b_len) != NULL)
+ return 0;
+
+ return num_components(a, a_len) < num_components(b, b_len);
+}
+
+static int most_specific_commonname(X509_NAME *subject, const char **result)
+{
+ ASN1_STRING *best, *cur;
+ int i;
+
+ i = -1;
+ best = NULL;
+ while ((i = X509_NAME_get_index_by_NID(subject, NID_commonName, i)) != -1) {
+ cur = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i));
+ /* We use "not less specific" instead of "more specific" to allow later
+ entries to supersede earlier ones. */
+ if (best == NULL
+ || !less_specific(FUNC_ASN1_STRING_data(cur), ASN1_STRING_length(cur),
+ FUNC_ASN1_STRING_data(best), ASN1_STRING_length(best))) {
+ best = cur;
+ }
+ }
+
+ if (best == NULL) {
+ *result = NULL;
+ return -1;
+ } else {
+ *result = (char *) FUNC_ASN1_STRING_data(best);
+ return ASN1_STRING_length(best);
+ }
+}
+
+/* Match a hostname against the contents of the "most specific" commonName field
+ of a certificate. The "most specific" term is used in RFC 2818 but is not
+ defined anywhere that I (David Fifield) can find. This is what it means in
+ Ncat: wildcard patterns are always less specific than non-wildcard patterns.
+ If both patterns are wildcard or both are non-wildcard, the one with more
+ name components is more specific. If two names have the same number of
+ components, the one that comes later in the certificate is more specific. */
+static int cert_match_commonname(X509 *cert, const char *hostname)
+{
+ X509_NAME *subject;
+ const char *commonname;
+ int n;
+
+ subject = X509_get_subject_name(cert);
+ if (subject == NULL)
+ return 0;
+
+ n = most_specific_commonname(subject, &commonname);
+ if (n < 0 || commonname == NULL)
+ /* No commonName found. */
+ return 0;
+ if (wildcard_match(commonname, hostname, n))
+ return 1;
+
+ if (o.verbose)
+ loguser("Certificate verification error: Connected to \"%s\", but certificate is for \"%s\".\n", hostname, commonname);
+
+ return 0;
+}
+
+/* Verify a host's name against the name in its certificate after connection.
+ If the verify mode is SSL_VERIFY_NONE, always returns true. Returns nonzero
+ on success. */
+int ssl_post_connect_check(SSL *ssl, const char *hostname)
+{
+ X509 *cert = NULL;
+ unsigned int num_checked;
+
+ if (SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE)
+ return 1;
+
+ if (hostname == NULL)
+ return 0;
+
+ cert = SSL_get_peer_certificate(ssl);
+ if (cert == NULL)
+ return 0;
+
+ /* RFC 2818 (HTTP Over TLS): If a subjectAltName extension of type dNSName
+ is present, that MUST be used as the identity. Otherwise, the (most
+ specific) Common Name field in the Subject field of the certificate MUST
+ be used. Although the use of the Common Name is existing practice, it is
+ deprecated and Certification Authorities are encouraged to use the
+ dNSName instead. */
+ if (!cert_match_dnsname(cert, hostname, &num_checked)) {
+ /* If there were dNSNames, we're done. If not, try the commonNames. */
+ if (num_checked > 0 || !cert_match_commonname(cert, hostname)) {
+ X509_free(cert);
+ return 0;
+ }
+ }
+
+ X509_free(cert);
+
+ return SSL_get_verify_result(ssl) == X509_V_OK;
+}
+
+/* Generate a self-signed certificate and matching RSA keypair. References for
+ this code are the book Network Programming with OpenSSL, chapter 10, section
+ "Making Certificates"; and apps/req.c in the OpenSSL source. */
+static int ssl_gen_cert(X509 **cert, EVP_PKEY **key)
+{
+ X509_NAME *subj;
+ X509_EXTENSION *ext;
+ X509V3_CTX ctx;
+ const char *commonName = "localhost";
+ char dNSName[128];
+ int rc;
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+ int ret = 0;
+ RSA *rsa = NULL;
+ BIGNUM *bne = NULL;
+
+ *cert = NULL;
+ *key = NULL;
+
+ /* Generate a private key. */
+ *key = EVP_PKEY_new();
+ if (*key == NULL)
+ goto err;
+ do {
+ /* Generate RSA key. */
+ bne = BN_new();
+ ret = BN_set_word(bne, RSA_F4);
+ if (ret != 1)
+ goto err;
+
+ rsa = RSA_new();
+ ret = RSA_generate_key_ex(rsa, DEFAULT_KEY_BITS, bne, NULL);
+ if (ret != 1)
+ goto err;
+
+ rc = RSA_check_key(rsa);
+ } while (rc == 0);
+ if (rc == -1)
+ bye("Error generating RSA key: %s", ERR_error_string(ERR_get_error(), NULL));
+ if (EVP_PKEY_assign_RSA(*key, rsa) == 0) {
+ RSA_free(rsa);
+ goto err;
+ }
+#else
+ *cert = NULL;
+ *key = EVP_RSA_gen(DEFAULT_KEY_BITS);
+ if (*key == NULL)
+ goto err;
+#endif
+
+ /* Generate a certificate. */
+ *cert = X509_new();
+ if (*cert == NULL)
+ goto err;
+ if (X509_set_version(*cert, 2) == 0) /* Version 3. */
+ goto err;
+ ASN1_INTEGER_set(X509_get_serialNumber(*cert), get_random_u32() & 0x7FFFFFFF);
+
+ /* Set the commonName. */
+ subj = X509_get_subject_name(*cert);
+ if (o.target != NULL)
+ commonName = o.target;
+ if (X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
+ (unsigned char *) commonName, -1, -1, 0) == 0) {
+ goto err;
+ }
+
+ /* Set the dNSName. */
+ rc = Snprintf(dNSName, sizeof(dNSName), "DNS:%s", commonName);
+ if (rc < 0 || rc >= sizeof(dNSName))
+ goto err;
+ X509V3_set_ctx(&ctx, *cert, *cert, NULL, NULL, 0);
+ ext = X509V3_EXT_conf(NULL, &ctx, "subjectAltName", dNSName);
+ if (ext == NULL)
+ goto err;
+ if (X509_add_ext(*cert, ext, -1) == 0)
+ goto err;
+
+ /* Set a comment. */
+ ext = X509V3_EXT_conf(NULL, &ctx, "nsComment", CERTIFICATE_COMMENT);
+ if (ext == NULL)
+ goto err;
+ if (X509_add_ext(*cert, ext, -1) == 0)
+ goto err;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER
+ {
+ ASN1_TIME *tb, *ta;
+ tb = NULL;
+ ta = NULL;
+
+ if (X509_set_issuer_name(*cert, X509_get_subject_name(*cert)) == 0
+ || (tb = ASN1_STRING_dup(X509_get0_notBefore(*cert))) == 0
+ || X509_gmtime_adj(tb, 0) == 0
+ || X509_set1_notBefore(*cert, tb) == 0
+ || (ta = ASN1_STRING_dup(X509_get0_notAfter(*cert))) == 0
+ || X509_gmtime_adj(ta, DEFAULT_CERT_DURATION) == 0
+ || X509_set1_notAfter(*cert, ta) == 0
+ || X509_set_pubkey(*cert, *key) == 0) {
+ ASN1_STRING_free(tb);
+ ASN1_STRING_free(ta);
+ goto err;
+ }
+ ASN1_STRING_free(tb);
+ ASN1_STRING_free(ta);
+ }
+#else
+ if (X509_set_issuer_name(*cert, X509_get_subject_name(*cert)) == 0
+ || X509_gmtime_adj(X509_get_notBefore(*cert), 0) == 0
+ || X509_gmtime_adj(X509_get_notAfter(*cert), DEFAULT_CERT_DURATION) == 0
+ || X509_set_pubkey(*cert, *key) == 0) {
+ goto err;
+ }
+#endif
+
+ /* Sign it. */
+ if (X509_sign(*cert, *key, EVP_sha1()) == 0)
+ goto err;
+
+ return 1;
+
+err:
+ if (*cert != NULL)
+ X509_free(*cert);
+ if (*key != NULL)
+ EVP_PKEY_free(*key);
+
+ return 0;
+}
+
+/* Calculate a SHA-1 fingerprint of a certificate and format it as a
+ human-readable string. Returns strbuf or NULL on error. */
+char *ssl_cert_fp_str_sha1(const X509 *cert, char *strbuf, size_t len)
+{
+ unsigned char binbuf[SHA1_BYTES];
+ unsigned int n;
+ char *p;
+ unsigned int i;
+
+ if (len < SHA1_STRING_LENGTH + 1)
+ return NULL;
+ n = sizeof(binbuf);
+ if (X509_digest(cert, EVP_sha1(), binbuf, &n) != 1)
+ return NULL;
+
+ p = strbuf;
+ for (i = 0; i < n; i++) {
+ if (i > 0 && i % 2 == 0)
+ *p++ = ' ';
+ Snprintf(p, 3, "%02X", binbuf[i]);
+ p += 2;
+ }
+ ncat_assert(p - strbuf <= len);
+ *p = '\0';
+
+ return strbuf;
+}
+
+/* Tries to complete an ssl handshake on the socket received by fdinfo struct
+ if ssl is enabled on that socket. */
+
+int ssl_handshake(struct fdinfo *sinfo)
+{
+ int ret = 0;
+ int sslerr = 0;
+
+ if (sinfo == NULL) {
+ if (o.debug)
+ logdebug("ncat_ssl.c: Invoking ssl_handshake() with a NULL parameter "
+ "is a serious bug. Please fix it.\n");
+ return -1;
+ }
+
+ if (!o.ssl)
+ return -1;
+
+ /* Initialize the socket too if it isn't. */
+ if (!sinfo->ssl)
+ sinfo->ssl = new_ssl(sinfo->fd);
+
+ ret = SSL_accept(sinfo->ssl);
+
+ if (ret == 1)
+ return NCAT_SSL_HANDSHAKE_COMPLETED;
+
+ sslerr = SSL_get_error(sinfo->ssl, ret);
+
+ if (ret == -1) {
+ if (sslerr == SSL_ERROR_WANT_READ)
+ return NCAT_SSL_HANDSHAKE_PENDING_READ;
+ if (sslerr == SSL_ERROR_WANT_WRITE)
+ return NCAT_SSL_HANDSHAKE_PENDING_WRITE;
+ }
+
+ if (o.verbose) {
+ loguser("Failed SSL connection from %s: %s\n",
+ inet_socktop(&sinfo->remoteaddr),
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+ return NCAT_SSL_HANDSHAKE_FAILED;
+}
+
+#endif
diff --git a/ncat/ncat_ssl.h b/ncat/ncat_ssl.h
new file mode 100644
index 0000000..e720749
--- /dev/null
+++ b/ncat/ncat_ssl.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * ncat_ssl.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+#ifndef NCAT_SSL_H
+#define NCAT_SSL_H
+
+#include "ncat_config.h"
+
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#define NCAT_CA_CERTS_FILE "ca-bundle.crt"
+
+enum {
+ SHA1_BYTES = 160 / 8,
+ /* 40 bytes for hex digits and 9 bytes for ' '. */
+ SHA1_STRING_LENGTH = SHA1_BYTES * 2 + (SHA1_BYTES / 2 - 1)
+};
+
+/* These status variables are returned by ssl_handshake() to describe the
+ * status of a pending non-blocking ssl handshake(SSL_accept()). */
+enum {
+ NCAT_SSL_HANDSHAKE_COMPLETED = 0,
+ NCAT_SSL_HANDSHAKE_PENDING_READ = 1,
+ NCAT_SSL_HANDSHAKE_PENDING_WRITE = 2,
+ NCAT_SSL_HANDSHAKE_FAILED = 3
+};
+
+extern SSL_CTX *setup_ssl_listen(const SSL_METHOD *method);
+
+extern SSL *new_ssl(int fd);
+
+extern int ssl_post_connect_check(SSL *ssl, const char *hostname);
+
+extern char *ssl_cert_fp_str_sha1(const X509 *cert, char *strbuf, size_t len);
+
+extern int ssl_load_default_ca_certs(SSL_CTX *ctx);
+
+/* Try to complete an ssl handshake in a non-blocking way for the socket given
+ * in sinfo. Initialize the socket too with new_ssl() if it hasn't been done
+ * already. */
+extern int ssl_handshake(struct fdinfo *sinfo);
+
+#endif
+#endif
diff --git a/ncat/ncat_win.c b/ncat/ncat_win.c
new file mode 100644
index 0000000..b636e60
--- /dev/null
+++ b/ncat/ncat_win.c
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * ncat_win.c -- Windows-specific functions. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "nbase.h"
+#include "ncat.h"
+
+int ncat_openlog(const char *logfile, int append)
+{
+ if (append)
+ return Open(logfile, O_BINARY | O_WRONLY | O_CREAT | O_APPEND, 0664);
+ else
+ return Open(logfile, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0664);
+}
+
+void set_lf_mode(void)
+{
+ /* _O_TEXT (the default setting) converts \r\n to \n on input, making the
+ terminal look like a Unix terminal. However, use _O_BINARY if stdin is
+ not a terminal, to avoid breaking data from a pipe or other source. */
+ if (isatty(STDIN_FILENO))
+ _setmode(STDIN_FILENO, _O_TEXT);
+ else
+ _setmode(STDIN_FILENO, _O_BINARY);
+ /* Do not translate \n to \r\n on output. */
+ _setmode(STDOUT_FILENO, _O_BINARY);
+}
+
+#ifdef HAVE_OPENSSL
+
+int ssl_load_default_ca_certs(SSL_CTX *ctx)
+{
+ char buf[1024];
+ char *bundlename;
+ int n, rc;
+ size_t size, offset;
+
+ /* Get the executable's filename. */
+ n = GetModuleFileName(GetModuleHandle(0), buf, sizeof(buf));
+ if (n == 0 || n == sizeof(buf))
+ return -1;
+
+ bundlename = path_get_dirname(buf);
+ bundlename = (char *) safe_realloc(bundlename, 1024);
+ offset = strlen(bundlename);
+ size = offset + 1;
+ strbuf_sprintf(&bundlename, &size, &offset, "\\%s", NCAT_CA_CERTS_FILE);
+
+ if (o.debug)
+ logdebug("Using trusted CA certificates from %s.\n", bundlename);
+ rc = SSL_CTX_load_verify_locations(ctx, bundlename, NULL);
+ if (rc != 1) {
+ if (o.debug)
+ logdebug("Unable to load trusted CA certificates from %s: %s\n",
+ bundlename, ERR_error_string(ERR_get_error(), NULL));
+ }
+ free(bundlename);
+
+ return rc == 1 ? 0 : -1;
+}
+#endif
diff --git a/ncat/scripts/chargen.lua b/ncat/scripts/chargen.lua
new file mode 100644
index 0000000..70b937f
--- /dev/null
+++ b/ncat/scripts/chargen.lua
@@ -0,0 +1,7 @@
+--chargen.lua - implements the RFC 864 CHARGEN service which basically spams
+--the remote user until he decides to close the connection.
+
+while true do
+ print "chargen"
+end
+
diff --git a/ncat/scripts/conditional.lua b/ncat/scripts/conditional.lua
new file mode 100644
index 0000000..76817b2
--- /dev/null
+++ b/ncat/scripts/conditional.lua
@@ -0,0 +1,51 @@
+--This is another --lua-exec demo. It displays a menu to a user, waits for her
+--input and makes a decision according to what the user entered. All happens
+--in an infinite loop.
+
+--This function reads a line of at most 8096 bytes (or whatever the first
+--parameter says) from standard input. Returns the string and a boolean value
+--that is true if we hit the newline (defined as "\n") or false if the line had
+--to be truncated. This is here because io.stdin:read("*line") could lead to
+--memory exhaustion if we received gigabytes of characters with no newline.
+function read_line(max_len)
+ local ret = ""
+ for i = 1, (max_len or 8096) do
+ local chr = io.read(1)
+ if chr == "\n" then
+ return ret, true
+ end
+ ret = ret .. chr
+ end
+
+ return ret, false
+end
+
+while true do
+
+ print "Here's a menu for you: "
+ print "1. Repeat the menu."
+ print "0. Exit."
+
+ io.write "Please enter your choice: "
+ io.flush(io.stdout)
+ i = read_line()
+
+ --WARNING! Without this line, the script will go into an infinite loop
+ --that keeps consuming system resources when the connection gets broken.
+ --Ncat's subprocesses are NOT killed in this case!
+ if i == nil then
+ break
+ end
+
+ print("You wrote: ", i, ".")
+
+ if i == "0" then
+ break
+ elseif i == "1" then
+ print "As you wish."
+ else
+ print "No idea what you meant. Please try again."
+ end
+
+ print() --print a newline
+end
diff --git a/ncat/scripts/date.lua b/ncat/scripts/date.lua
new file mode 100644
index 0000000..a7116ef
--- /dev/null
+++ b/ncat/scripts/date.lua
@@ -0,0 +1,3 @@
+--Emulates the daytime service (RFC 867).
+
+print(os.date())
diff --git a/ncat/scripts/discard.lua b/ncat/scripts/discard.lua
new file mode 100644
index 0000000..6b386f6
--- /dev/null
+++ b/ncat/scripts/discard.lua
@@ -0,0 +1,11 @@
+--This script reads data from the standard input and discards them.
+
+while true do
+
+ data = io.stdin:read(512)
+
+ if data == nil then
+ break
+ end
+
+end
diff --git a/ncat/scripts/echo.lua b/ncat/scripts/echo.lua
new file mode 100644
index 0000000..3bfea90
--- /dev/null
+++ b/ncat/scripts/echo.lua
@@ -0,0 +1,16 @@
+--Emulates the RFC 862 echo service, behaving like Unix's "cat" tool.
+
+while true do
+
+ --We're reading in 1-byte chunks because calls like io.stdin:read(512) would
+ --wait for full 512 bytes of data before continuing.
+ data = io.stdin:read(1)
+
+ if data == nil then
+ break
+ end
+
+ io.stdout:write(data)
+ io.stdout:flush()
+
+end
diff --git a/ncat/scripts/hello-luaexec.lua b/ncat/scripts/hello-luaexec.lua
new file mode 100644
index 0000000..31bd498
--- /dev/null
+++ b/ncat/scripts/hello-luaexec.lua
@@ -0,0 +1,4 @@
+--This is a --lua-exec "Hello world" example. In order to send to a client,
+--all you need to do is output it to the standard output.
+
+print "Hello, world!"
diff --git a/ncat/scripts/httpd.lua b/ncat/scripts/httpd.lua
new file mode 100644
index 0000000..3837e32
--- /dev/null
+++ b/ncat/scripts/httpd.lua
@@ -0,0 +1,402 @@
+--httpd.lua - a dead simple HTTP server. Expects GET requests and serves files
+--matching these requests. Can guess mime based on an extension too. Currently
+--disallows any filenames that start or end with "..".
+
+------------------------------------------------------------------------------
+-- Configuration section --
+------------------------------------------------------------------------------
+
+server_headers = {
+ ["Server"] = "Ncat --lua-exec httpd.lua",
+ ["Connection"] = "close",
+}
+
+function guess_mime(resource)
+ if string.sub(resource, -5) == ".html" then return "text/html" end
+ if string.sub(resource, -4) == ".htm" then return "text/html" end
+ return "application/octet-stream"
+end
+
+------------------------------------------------------------------------------
+-- End of configuration section --
+------------------------------------------------------------------------------
+
+function print_rn(str)
+ io.stdout:write(str .. "\r\n")
+ io.stdout:flush()
+end
+
+function debug(str)
+ io.stderr:write("[" .. os.date() .. "] ")
+ io.stderr:write(str .. "\n")
+ io.stderr:flush()
+end
+
+function url_decode(str)
+ --taken from here: http://lua-users.org/wiki/StringRecipes
+ return str:gsub("%%(%x%x)",
+ function(h) return string.char(tonumber(h,16)) end)
+end
+
+--Read a line of at most 8096 bytes (or whatever the first parameter says)
+--from standard input. Returns the string and a boolean value that is true if
+--we hit the newline (defined as "\n") or false if the line had to be
+--truncated. This is here because io.stdin:read("*line") could lead to memory
+--exhaustion if we received gigabytes of characters with no newline.
+function read_line(max_len)
+ local ret = ""
+ for i = 1, (max_len or 8096) do
+ local chr = io.read(1)
+ if chr == "\n" then
+ return ret, true
+ end
+ ret = ret .. chr
+ end
+
+ return ret, false
+end
+
+--The following function and variables was translated from Go to Lua. The
+--original code can be found here:
+--
+--http://golang.org/src/pkg/unicode/utf8/utf8.go#L45
+local surrogate_min = 0xD800
+local surrogate_max = 0xDFFF
+
+local t1 = 0x00 -- 0000 0000
+local tx = 0x80 -- 1000 0000
+local t2 = 0xC0 -- 1100 0000
+local t3 = 0xE0 -- 1110 0000
+local t4 = 0xF0 -- 1111 0000
+local t5 = 0xF8 -- 1111 1000
+
+local maskx = 0x3F -- 0011 1111
+local mask2 = 0x1F -- 0001 1111
+local mask3 = 0x0F -- 0000 1111
+local mask4 = 0x07 -- 0000 0111
+
+local char1_max = 0x7F -- (1<<7) - 1
+local char2_max = 0x07FF -- (1<<11) - 1
+local char3_max = 0xFFFF -- (1<<16) - 1
+
+local max_char = 0x10FFFF -- \U0010FFFF
+
+function get_next_char_len(p)
+ local n = p:len()
+ local c0 = p:byte(1)
+
+ --1-byte, 7-bit sequence?
+ if c0 < tx then
+ return 1
+ end
+
+ --unexpected continuation byte?
+ if c0 < t2 then
+ return nil
+ end
+
+ --need first continuation byte
+ if n < 2 then
+ return nil
+ end
+ local c1 = p:byte(2)
+ if c1 < tx or t2 <= c1 then
+ return nil
+ end
+
+ --2-byte, 11-bit sequence?
+ if c0 < t3 then
+ local l1 = (c0 & mask2) << 6
+ local l2 = c1 & maskx
+ local r = l1 | l2
+ if r <= char1_max then
+ return nil
+ end
+ return 2
+ end
+
+ --need second continuation byte
+ if n < 3 then
+ return nil
+ end
+ local c2 = p:byte(3)
+ if c2 < tx or t2 <= c2 then
+ return nil
+ end
+
+ --3-byte, 16-bit sequence?
+ if c0 < t4 then
+ local l1 = (c0 & mask3) << 12
+ local l2 = (c1 & maskx) << 6
+ local l3 = c2 & maskx
+ local r = l1 | l2 | l3
+ if r <= char2_max then
+ return nil
+ end
+ if surrogate_min <= r and r <= surrogate_max then
+ return nil
+ end
+ return 3
+ end
+
+ --need third continuation byte
+ if n < 4 then
+ return nil
+ end
+ local c3 = p:byte(4)
+ if c3 < tx or t2 <= c3 then
+ return nil
+ end
+
+ --4-byte, 21-bit sequence?
+ if c0 < t5 then
+ local l1 = (c0 & mask4) << 18
+ local l2 = (c1 & maskx) << 12
+ local l3 = (c2 & maskx) << 6
+ local l4 = c3 & maskx
+ local r = l1 | l2 | l3 | l4
+ if r <= char3_max or max_char < r then
+ return nil
+ end
+ return 4
+ end
+
+ --error
+ return nil
+end
+
+function validate_utf8(s)
+ local i = 1
+ local len = s:len()
+ while i <= len do
+ local size = get_next_char_len(s:sub(i))
+ if size == nil then
+ return false
+ end
+ i = i + size
+ end
+ return true
+end
+
+--Returns a table containing the list of directories resulting from splitting
+--the argument by '/'.
+function split_path(path)
+ --[[
+ for _, v in pairs({"/a/b/c", "a/b/c", "//a/b/c", "a/b/c/", "a/b/c//"}) do
+ print(v,table.concat(split_path(v), ','))
+ end
+
+ -- /a/b/c ,a,b,c
+ -- a/b/c a,b,c
+ -- //a/b/c ,,a,b,c
+ -- a/b/c/ a,b,c
+ -- a/b/c// a,b,c,
+ ]]
+ local ret = {}
+ local j = 0
+ for i=1, path:len() do
+ if path:sub(i,i) == '/' then
+ if j == 0 then
+ ret[#ret+1] = path:sub(1, i-1)
+ else
+ ret[#ret+1] = path:sub(j+1, i-1)
+ end
+ j = i
+ end
+ end
+ if j ~= path:len() then
+ ret[#ret+1] = path:sub(j+1, path:len())
+ end
+ return ret
+end
+
+
+function is_path_valid(resource)
+ --remove the beginning slash
+ resource = string.sub(resource, 2, string.len(resource))
+
+ --Windows drive names are not welcome.
+ if resource:match("^([a-zA-Z]):") then
+ return false
+ end
+
+ --if it starts with a dot or a slash or a backslash, forbid any acccess to it.
+ local first_char = resource:sub(1, 1)
+
+ if first_char == "." then
+ return false
+ end
+
+ if first_char == "/" then
+ return false
+ end
+
+ if resource:find("\\") then
+ return false
+ end
+
+ for _, directory in pairs(split_path(resource)) do
+ if directory == '' then
+ return false
+ end
+
+ if directory == '..' then
+ return false
+ end
+ end
+
+ return true
+end
+
+--Make a response, output it and stop execution.
+--
+--It takes an associative array with three optional keys: status (status line)
+--and headers, which lists all additional headers to be sent. You can also
+--specify "data" - either a function that is expected to return nil at some
+--point or a plain string.
+function make_response(params)
+
+ --Print the status line. If we got none, assume it's all okay.
+ if not params["status"] then
+ params["status"] = "HTTP/1.1 200 OK"
+ end
+ print_rn(params["status"])
+
+ --Send the date.
+ print_rn("Date: " .. os.date("!%a, %d %b %Y %H:%M:%S GMT"))
+
+ --Send the server headers as described in the configuration.
+ for key, value in pairs(server_headers) do
+ print_rn(("%s: %s"):format(key, value))
+ end
+
+ --Now send the headers from the parameter, if any.
+ if params["headers"] then
+ for key, value in pairs(params["headers"]) do
+ print_rn(("%s: %s"):format(key, value))
+ end
+ end
+
+ --If there's any data, check if it's a function.
+ if params["data"] then
+
+ if type(params["data"]) == "function" then
+
+ print_rn("")
+ debug("Starting buffered output...")
+
+ --run the function and print its contents, until we hit nil.
+ local f = params["data"]
+ while true do
+ local ret = f()
+ if ret == nil then
+ debug("Buffered output finished.")
+ break
+ end
+ io.stdout:write(ret)
+ io.stdout:flush()
+ end
+
+ else
+
+ --It's a plain string. Send its length and output it.
+ debug("Just printing the data. Status='" .. params["status"] .. "'")
+ print_rn("Content-length: " .. params["data"]:len())
+ print_rn("")
+ io.stdout:write(params["data"])
+ io.stdout:flush()
+
+ end
+ else
+ print_rn("")
+ end
+
+ os.exit(0)
+end
+
+function make_error(error_str)
+ make_response({
+ ["status"] = "HTTP/1.1 "..error_str,
+ ["headers"] = {["Content-type"] = "text/html"},
+ ["data"] = "<h1>"..error_str.."</h1>",
+ })
+end
+
+do_400 = function() make_error("400 Bad Request") end
+do_403 = function() make_error("403 Forbidden") end
+do_404 = function() make_error("404 Not Found") end
+do_405 = function() make_error("405 Method Not Allowed") end
+do_414 = function() make_error("414 Request-URI Too Long") end
+
+------------------------------------------------------------------------------
+-- End of library section --
+------------------------------------------------------------------------------
+
+input, success = read_line()
+
+if not success then
+ do_414()
+end
+
+if input:sub(-1) == "\r" then
+ input = input:sub(1,-2)
+end
+
+--We assume that:
+-- * a method is alphanumeric uppercase,
+-- * resource may contain anything that's not a space,
+-- * protocol version is followed by a single space.
+method, resource, protocol = input:match("([A-Z]+) ([^ ]+) ?(.*)")
+
+if resource:find(string.char(0)) ~= nil then
+ do_400()
+end
+
+if not validate_utf8(resource) then
+ do_400()
+end
+
+if method ~= "GET" then
+ do_405()
+end
+
+while true do
+
+ input = read_line()
+ if input == "" or input == "\r" then
+ break
+ end
+end
+
+debug("Got a request for '" .. resource
+ .. "' (urldecoded: '" .. url_decode(resource) .. "').")
+resource = url_decode(resource)
+
+--make sure that the resource starts with a slash.
+if resource:sub(1, 1) ~= '/' then
+ do_400() --could probably use a fancier error here.
+end
+
+if not is_path_valid(resource) then
+ do_403()
+end
+
+--try to make all file openings from now on relative to the working directory.
+resource = "./" .. resource
+
+--If it's a directory, try to load index.html from it.
+if resource:sub(-1) == "/" then
+ resource = resource .. '/index.html'
+end
+
+--try to open the file...
+f = io.open(resource, "rb")
+if f == nil then
+ do_404() --opening file failed, throw a 404.
+end
+
+--and output it all.
+make_response({
+ ["data"] = function() return f:read(1024) end,
+ ["headers"] = {["Content-type"] = guess_mime(resource)},
+})
diff --git a/ncat/scripts/log_ips.sh b/ncat/scripts/log_ips.sh
new file mode 100644
index 0000000..8b0f0e5
--- /dev/null
+++ b/ncat/scripts/log_ips.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+LOGFILE="log_ips.log"
+
+MSG="[`date`] Incoming connection from $NCAT_REMOTE_ADDR:$NCAT_REMOTE_PORT"
+
+echo $MSG >&2
+echo $MSG >> $LOGFILE
+
+echo "Yeah, hi."
diff --git a/ncat/scripts/p0fme.py b/ncat/scripts/p0fme.py
new file mode 100755
index 0000000..5f4d42e
--- /dev/null
+++ b/ncat/scripts/p0fme.py
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+
+from __future__ import print_function # logging, python2-only.
+
+"""
+A script that reads data generated by p0f -f p0f.log, looking for all entries
+about an IP read from NCAT_REMOTE_ADDR environment variable. Then it prints out
+all the information it has found. To try it out, run "p0f -i any -o p0f.log"
+and ncat -l -k --sh-exec "python p0fme.py".
+
+Script tested under Python versions 2.7 and 3.3.
+"""
+
+P0F_LOG_FILE = "p0f.log"
+
+import datetime # logging
+import sys # logging
+import os # environ
+import time # sleeping to wait for data
+import sys # to flush STDOUT
+
+
+def expand_ipv6(ip):
+ """
+ Expands short IPv6 address like ::1 into an expanded form without trailing
+ zeros. Copied from:
+
+ http://svn.python.org/projects/python/tags/r31b1/Lib/ipaddr.py
+
+ (Py3 standard library; added some modifications to match p0f's output data)
+ """
+
+ new_ip = []
+ hextet = ip.split('::')
+ sep = len(hextet[0].split(':')) + len(hextet[1].split(':'))
+ new_ip = hextet[0].split(':')
+
+ for _ in range(8 - sep):
+ new_ip.append('0')
+ new_ip += hextet[1].split(':')
+
+ # Now need to make sure every hextet is 4 lower case characters.
+ # If a hextet is < 4 characters, we've got missing leading 0's.
+ ret_ip = []
+ for hextet in new_ip:
+ if hextet == '':
+ hextet = '0'
+ ret_ip.append(hextet.lower())
+ return ':'.join(ret_ip)
+
+
+def split_by_equals(str_):
+ ret = str_.split('=')
+ return ret[0], ''.join(ret[1:])
+
+if __name__ == "__main__":
+ try:
+ ip = os.environ['NCAT_REMOTE_ADDR']
+ if os.environ['NCAT_PROTO'] != 'TCP':
+ sys.exit("ERROR: This script works for TCP servers only!")
+ except KeyError:
+ sys.exit("ERROR: This script has to be run from inside of Ncat.")
+ print("[%s] Got a request from %s" % (
+ datetime.datetime.now().isoformat(' '), ip), file=sys.stderr)
+
+ print("Hold on, I'm collecting data on you...")
+ sys.stdout.flush()
+ time.sleep(3.0)
+
+ if ':' in ip: # We need to expand IPv6 addresses in a specific way.
+ ip = expand_ipv6(ip)
+ result = {}
+
+ # Reading the log backward will give us more recent results.
+ for line in reversed(open(P0F_LOG_FILE).readlines()):
+
+ without_date = line.split('] ')
+ if without_date == ['\n']:
+ continue
+ without_date = ''.join(without_date[1:])
+
+ # Create a key-value dictionary out of the '|'-separated substrings.
+ properties = dict(map(split_by_equals, without_date.split('|')))
+
+ if not properties['cli'].startswith(ip):
+ continue # Not the IP we're looking for, check next one.
+
+ for key in properties:
+ if not key in result or result[key] == '???':
+ result[key] = properties[key]
+
+ if not result:
+ print("Got nothing on you. Try again and I will, though.")
+
+ # Now that we've finished, print out the results.
+ for key in sorted(result):
+ print("%s: %s" % (key, result[key].rstrip()))
diff --git a/ncat/scripts/whatismyip.lua b/ncat/scripts/whatismyip.lua
new file mode 100644
index 0000000..13ade22
--- /dev/null
+++ b/ncat/scripts/whatismyip.lua
@@ -0,0 +1,4 @@
+--A "what is my IP" service code. Since most web browsers put up with servers
+--not sending proper HTTP headers, you can simply query the service with it.
+
+print(os.getenv "NCAT_REMOTE_ADDR")
diff --git a/ncat/sockaddr_u.h b/ncat/sockaddr_u.h
new file mode 100644
index 0000000..069e2c2
--- /dev/null
+++ b/ncat/sockaddr_u.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * sockaddr_u.h -- a union containing sockaddr types compatible with C99 *
+ * strict-aliasing rules. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id:$ */
+
+#include "ncat_config.h"
+
+#ifndef SOCKADDR_U_H_
+#define SOCKADDR_U_H_
+
+#ifdef WIN32
+# include <ws2def.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+#if HAVE_LINUX_VM_SOCKETS_H
+#include <linux/vm_sockets.h>
+#endif
+
+union sockaddr_u {
+ struct sockaddr_storage storage;
+#ifdef HAVE_SYS_UN_H
+ struct sockaddr_un un;
+#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ struct sockaddr_vm vm;
+#endif
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr sockaddr;
+};
+
+static inline socklen_t get_socklen(const union sockaddr_u *s)
+{
+ switch(s->storage.ss_family) {
+#ifdef HAVE_SYS_UN_H
+ case AF_UNIX:
+ return SUN_LEN(&s->un);
+ break;
+#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ case AF_VSOCK:
+ return sizeof(struct sockaddr_vm);
+ break;
+#endif
+#ifdef HAVE_SOCKADDR_SA_LEN
+ default:
+ return s->sockaddr.sa_len;
+ break;
+#else
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+ break;
+#ifdef AF_INET6
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+ break;
+#endif
+ default:
+ return sizeof(union sockaddr_u);
+ break;
+#endif
+ }
+ return 0;
+}
+#endif
diff --git a/ncat/sys_wrap.c b/ncat/sys_wrap.c
new file mode 100644
index 0000000..9c742c1
--- /dev/null
+++ b/ncat/sys_wrap.c
@@ -0,0 +1,190 @@
+/***************************************************************************
+ * sys_wrap.c -- Error-checked wrappers around common functions. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include <limits.h>
+
+#include "sys_wrap.h"
+#include "util.h"
+
+void *Calloc(size_t nmemb, size_t size)
+{
+ void *ret;
+
+ /* older libcs don't check for int overflow */
+ smul(nmemb, size);
+
+ ret = calloc(nmemb, size);
+ if (ret == NULL)
+ die("calloc");
+
+ return ret;
+}
+
+int Close(int fd)
+{
+ if (close(fd) < 0)
+ die("close");
+
+ return 0;
+}
+
+int Connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
+{
+ if (connect(sockfd, serv_addr, addrlen) < 0)
+ die("connect");
+
+ return 0;
+}
+
+int Dup2(int oldfd, int newfd)
+{
+ int ret;
+
+ ret = dup2(oldfd, newfd);
+ if (ret < 0)
+ die("dup2");
+
+ return ret;
+}
+
+int Listen(int s, int backlog)
+{
+ if (listen(s, backlog) < 0)
+ die("listen");
+
+ return 0;
+}
+
+int Open(const char *pathname, int flags, mode_t mode)
+{
+ int ret;
+
+ ret = open(pathname, flags, mode);
+ if (ret < 0)
+ die("open");
+
+ return ret;
+}
+
+ssize_t Read(int fd, void *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = read(fd, buf, count);
+ if (ret < 0)
+ die("read");
+
+ return ret;
+}
+
+int Setsockopt(int s, int level, int optname, const void *optval,
+ socklen_t optlen)
+{
+ int ret;
+
+ ret = setsockopt(s, level, optname, (const char *) optval, optlen);
+ if (ret < 0)
+ die("setsockopt");
+
+ return ret;
+}
+
+sighandler_t Signal(int signum, sighandler_t handler)
+{
+ sighandler_t ret;
+
+ ret = signal(signum, handler);
+ if (ret == SIG_ERR)
+ die("signal");
+
+ return ret;
+}
+
+
+int Socket(int domain, int type, int protocol)
+{
+ int ret;
+
+ ret = socket(domain, type, protocol);
+ if (ret < 0)
+ die("socket");
+
+ return ret;
+}
+
+char *Strdup(const char *s)
+{
+ char *ret;
+
+ ret = strdup(s);
+ if (ret == NULL)
+ die("strdup");
+
+ return ret;
+}
+
+ssize_t Write(int fd, const void *buf, size_t count)
+{
+ ssize_t ret = write(fd, buf, count);
+
+ if (ret < 0) /* we don't bail if < count bytes written */
+ die("write");
+
+ return ret;
+}
diff --git a/ncat/sys_wrap.h b/ncat/sys_wrap.h
new file mode 100644
index 0000000..165904e
--- /dev/null
+++ b/ncat/sys_wrap.h
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * sys_wrap.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef SYS_WRAP_H
+#define SYS_WRAP_H
+
+#include "nbase.h"
+
+#include "util.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#else
+#define pid_t int
+#define mode_t int
+#define uid_t int
+#define socklen_t int
+#define uint16_t int
+#define ssize_t int
+#include <WinDef.h>
+#endif
+
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* need an autoconf to check for this */
+typedef void (*sighandler_t)(int);
+
+void *Calloc(size_t nmemb, size_t size);
+int Close(int fd);
+int Connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
+int Dup2(int oldfd, int newfd);
+int Listen(int s, int backlog);
+int Open(const char *pathname, int flags, mode_t mode);
+ssize_t Read(int fd, void *buf, size_t count);
+int Setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
+sighandler_t Signal(int signum, sighandler_t handler);
+int Socket(int domain, int type, int protocol);
+char *Strdup(const char *s);
+ssize_t Write(int fd, const void *buf, size_t count);
+
+#endif
diff --git a/ncat/test/addrset.c b/ncat/test/addrset.c
new file mode 100644
index 0000000..61a0f0d
--- /dev/null
+++ b/ncat/test/addrset.c
@@ -0,0 +1,104 @@
+/*
+ Usage: ./addrset [<specification> ...]
+
+ This program tests the addrset functions in nbase/nbase_addrset.c,
+ the ones that maintain the lists of addresses for --allow and
+ --deny. It takes as arguments specifications that are added to an
+ addrset. It then reads whitespace-separated host names or IP
+ addresses from standard input and echoes only those that are in the
+ addrset.
+
+ David Fifield
+
+ Example:
+ $ echo "1.2.3.4 1.0.0.5 1.2.3.8" | ./addrset "1.2.3.10/24"
+ 1.2.3.4
+ 1.2.3.8
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ncat_core.h"
+
+#ifdef WIN32
+#include "../nsock/src/error.h"
+#endif
+
+
+#ifdef WIN32
+static void win_init(void)
+{
+ WSADATA data;
+ int rc;
+
+ rc = WSAStartup(MAKEWORD(2,2), &data);
+ if (rc)
+ fatal("failed to start winsock: %s\n", socket_strerror(rc));
+}
+#endif
+
+static int resolve_name(const char *name, struct addrinfo **result)
+{
+ struct addrinfo hints = { 0 };
+
+ hints.ai_protocol = IPPROTO_TCP;
+ *result = NULL;
+
+ return getaddrinfo(name, NULL, &hints, result);
+}
+
+int main(int argc, char *argv[])
+{
+ struct addrset *set;
+ char line[1024];
+ int i;
+
+#ifdef WIN32
+ win_init();
+#endif
+
+ set = addrset_new();
+
+ options_init();
+
+ for (i = 1; i < argc; i++) {
+ if (!addrset_add_spec(set, argv[i], o.af, !o.nodns)) {
+ fprintf(stderr, "Error adding spec \"%s\".\n", argv[i]);
+ exit(1);
+ }
+ }
+
+ while (fgets(line, sizeof(line), stdin) != NULL) {
+ char *s, *hostname;
+ struct addrinfo *addrs;
+
+ s = line;
+ while ((hostname = strtok(s, " \t\n")) != NULL) {
+ int rc;
+
+ s = NULL;
+
+ rc = resolve_name(hostname, &addrs);
+ if (rc != 0) {
+ fprintf(stderr, "Error resolving \"%s\": %s.\n", hostname, gai_strerror(rc));
+ continue;
+ }
+ if (addrs == NULL) {
+ fprintf(stderr, "No addresses found for \"%s\".\n", hostname);
+ continue;
+ }
+
+ /* Check just the first address returned. */
+ if (addrset_contains(set, addrs->ai_addr))
+ printf("%s\n", hostname);
+
+ freeaddrinfo(addrs);
+ }
+ }
+
+ addrset_free(set);
+
+ return 0;
+}
diff --git a/ncat/test/ncat-test.pl b/ncat/test/ncat-test.pl
new file mode 100755
index 0000000..5a1c98e
--- /dev/null
+++ b/ncat/test/ncat-test.pl
@@ -0,0 +1,3283 @@
+#!/usr/bin/perl -w
+
+# This file contains tests of the external behavior of Ncat.
+
+require HTTP::Response;
+require HTTP::Request;
+
+use MIME::Base64;
+use File::Temp qw/ tempfile /;
+use URI::Escape;
+use Data::Dumper;
+use Socket;
+use Socket6;
+use Digest::MD5 qw/md5_hex/;
+use POSIX ":sys_wait_h";
+use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
+
+use IPC::Open3;
+use strict;
+
+{ # If the cert has expired, generate a new one.
+ my $verify = `openssl verify -trusted test-cert.pem test-cert.pem`;
+ if ($verify =~ /error 10 at/) {
+ system("openssl req -new -x509 -nodes -subj /O=ncat-test/CN=localhost/ -keyout test-cert.pem -out test-cert.pem");
+ }
+}
+$| = 1;
+
+my $HOST = "127.0.0.1";
+my $IPV6_ADDR = "::1";
+my $PORT = 40000;
+my $PROXY_PORT = 40001;
+my $UNIXSOCK = "ncat.unixsock";
+my $UNIXSOCK_TMP = "ncat.unixsock_tmp";
+
+my $WIN32 = $^O eq "MSWin32" || $^O eq "cygwin";
+
+my $NCAT;
+if ($WIN32) {
+ $NCAT = "../Debug/ncat.exe";
+} else {
+ $NCAT = "../ncat";
+}
+
+my $CAT;
+my $ECHO;
+my $PERL;
+my $BINSH;
+if ($^O eq "cygwin") {
+ my $CYGPATH="C:/cygwin";
+ $CAT = "$CYGPATH/bin/cat";
+ $ECHO = "$CYGPATH/bin/echo";
+ $PERL = "$CYGPATH/bin/perl";
+ $BINSH = "$CYGPATH/bin/sh";
+} else {
+ $CAT = "/bin/cat";
+ $ECHO = "/bin/echo";
+ $PERL = "/usr/bin/perl";
+ $BINSH = "/bin/sh";
+}
+
+my $HAVE_SCTP = !$WIN32;
+my $HAVE_UNIXSOCK = !$WIN32;
+
+my $BUFSIZ = 1024;
+
+my $num_tests = 0;
+my $num_failures = 0;
+my $num_expected_failures = 0;
+my $num_unexpected_passes = 0;
+
+# If true during a test, failure is expected (XFAIL).
+our $xfail = 0;
+
+# Run $NCAT with the given arguments.
+sub ncat {
+ my $pid;
+ local *IN;
+ local *OUT;
+ local *ERR;
+ #print STDERR "RUN: " . join(" ", ($NCAT, @_)) . "\n";
+ $pid = open3(*IN, *OUT, *ERR, $NCAT, @_);
+ if (!defined $pid) {
+ die "open3 failed";
+ }
+ binmode *IN;
+ binmode *OUT;
+ binmode *ERR;
+ return ($pid, *OUT, *IN, *ERR);
+}
+
+sub wait_listen {
+ my $fh = shift;
+ my $timeout = shift || 0.3;
+ my $rd = "";
+ vec($rd, fileno($fh), 1) = 1;
+ my $partial = "";
+ for (;;) {
+ my ($n, $frag);
+ ($n, $timeout) = select($rd, undef, undef, $timeout);
+ last if $n == 0;
+ $n = sysread($fh, $frag, $BUFSIZ);
+ last if (not defined($n)) || $n == 0;
+ $partial = $partial . $frag;
+ while ($partial =~ /^(.*?)\n(.*)$/s) {
+ my $line = $1;
+ $partial = $2;
+ if ($line =~ /^NCAT TEST: LISTEN/) {
+ return;
+ }
+ }
+ }
+}
+
+sub ncat_server {
+ my @ret = ncat($PORT, "--test", "-l", @_);
+ wait_listen($ret[3]);
+ return @ret;
+}
+
+sub ncat_server_noport {
+ my @ret = ncat("--test", "-l", @_);
+ wait_listen($ret[3]);
+ return @ret;
+}
+
+sub host_for_args {
+ if (grep(/^-[^-]*6/, @_)) {
+ return "::1";
+ } else {
+ return "127.0.0.1";
+ }
+}
+
+sub ncat_client {
+ my $host;
+ my @ret = ncat(host_for_args(@_), $PORT, @_);
+ # Give it a moment to connect.
+ select(undef, undef, undef, 0.1);
+ return @ret;
+}
+
+# Kill all child processes.
+sub kill_children {
+ local $SIG{TERM} = "IGNORE";
+ kill "TERM", -$$;
+ while (waitpid(-1, 0) > 0) {
+ }
+}
+
+# Read until a timeout occurs. Return undef on EOF or "" on timeout.
+sub timeout_read {
+ my $fh = shift;
+ my $timeout = 0.50;
+ if (scalar(@_) > 0) {
+ $timeout = shift;
+ }
+ my $result = "";
+ my $rd = "";
+ my $frag;
+ vec($rd, fileno($fh), 1) = 1;
+ # Here we rely on $timeout being decremented after select returns,
+ # which may not be supported on all systems.
+ while (select($rd, undef, undef, $timeout) != 0) {
+ return ($result or undef) if sysread($fh, $frag, $BUFSIZ) == 0;
+ $result .= $frag;
+ }
+ #print STDERR "READ: $result\n";
+ return $result;
+}
+
+$Data::Dumper::Terse = 1;
+$Data::Dumper::Useqq = 1;
+$Data::Dumper::Indent = 0;
+sub d {
+ return Dumper(@_);
+}
+
+# Run the code reference received as an argument. Count it as a pass if the
+# evaluation is successful, a failure otherwise.
+sub test {
+ my $desc = shift;
+ my $code = shift;
+ $num_tests++;
+ if (eval { &$code() }) {
+ if ($xfail) {
+ print "UNEXPECTED PASS $desc\n";
+ $num_unexpected_passes++;
+ } else {
+ print "PASS $desc\n";
+ }
+ } else {
+ if ($xfail) {
+ print "XFAIL $desc\n";
+ $num_expected_failures++;
+ } else {
+ $num_failures++;
+ print "FAIL $desc\n";
+ print " $@";
+ }
+ }
+}
+
+my ($s_pid, $s_out, $s_in, $c_pid, $c_out, $c_in, $p_pid, $p_out, $p_in);
+
+# Handle a common test situation. Start up a server and client with the given
+# arguments and call test on a code block. Within the code block the server's
+# PID, output filehandle, and input filehandle are accessible through
+# $s_pid, $s_out, and $s_in
+# and likewise for the client:
+# $c_pid, $c_out, and $c_in.
+sub server_client_test {
+ my $desc = shift;
+ my $server_args = shift;
+ my $client_args = shift;
+ my $code = shift;
+ ($s_pid, $s_out, $s_in) = ncat_server(@$server_args);
+ ($c_pid, $c_out, $c_in) = ncat_client(@$client_args);
+ test($desc, $code);
+ kill_children;
+}
+
+sub server_client_test_multi {
+ my $specs = shift;
+ my $desc = shift;
+ my $server_args_ref = shift;
+ my $client_args_ref = shift;
+ my $code = shift;
+ my $outer_xfail = $xfail;
+
+ for my $spec (@$specs) {
+ my @server_args = @$server_args_ref;
+ my @client_args = @$client_args_ref;
+
+ local $xfail = $outer_xfail;
+ for my $proto (split(/ /, $spec)) {
+ if ($proto eq "tcp") {
+ # Nothing needed.
+ } elsif ($proto eq "udp") {
+ push @server_args, ("--udp");
+ push @client_args, ("--udp");
+ } elsif ($proto eq "sctp") {
+ push @server_args, ("--sctp");
+ push @client_args, ("--sctp");
+ $xfail = 1 if !$HAVE_SCTP;
+ } elsif ($proto eq "ssl") {
+ push @server_args, ("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem");
+ push @client_args, ("--ssl");
+ } elsif ($proto eq "xfail") {
+ $xfail = 1;
+ } else {
+ die "Unknown protocol $proto";
+ }
+ }
+ server_client_test("$desc ($spec)", [@server_args], [@client_args], $code);
+ }
+}
+
+# Like server_client_test, but run the test once each for each mix of TCP, UDP,
+# SCTP, and SSL.
+sub server_client_test_all {
+ server_client_test_multi(["tcp", "udp", "sctp", "tcp ssl", "sctp ssl"], @_);
+}
+
+sub server_client_test_tcp_sctp_ssl {
+ server_client_test_multi(["tcp", "sctp", "tcp ssl", "sctp ssl"], @_);
+}
+
+sub server_client_test_tcp_ssl {
+ server_client_test_multi(["tcp", "tcp ssl"], @_);
+}
+
+sub server_client_test_sctp_ssl {
+ server_client_test_multi(["sctp", "sctp ssl"], @_);
+}
+
+# Set up a proxy running on $PROXY_PORT. Start a server on $PORT and connect a
+# client to the server through the proxy. The proxy is controlled through the
+# variables
+# $p_pid, $p_out, and $p_in.
+sub proxy_test {
+ my $desc = shift;
+ my $proxy_args = shift;
+ my $server_args = shift;
+ my $client_args = shift;
+ my $code = shift;
+ ($p_pid, $p_out, $p_in) = ncat(host_for_args(@$proxy_args), ($PROXY_PORT, "-l", "--proxy-type", "http"), @$proxy_args);
+ ($s_pid, $s_out, $s_in) = ncat(host_for_args(@$server_args), ($PORT, "-l"), @$server_args);
+ ($c_pid, $c_out, $c_in) = ncat(host_for_args(@$client_args), ($PORT, "--proxy", "$HOST:$PROXY_PORT"), @$client_args);
+ test($desc, $code);
+ kill_children;
+}
+
+# Like proxy_test, but connect the client directly to the proxy so you can
+# control the proxy interaction.
+sub proxy_test_raw {
+ my $desc = shift;
+ my $proxy_args = shift;
+ my $server_args = shift;
+ my $client_args = shift;
+ my $code = shift;
+ ($p_pid, $p_out, $p_in) = ncat(host_for_args(@$proxy_args), ($PROXY_PORT, "-l", "--proxy-type", "http"), @$proxy_args);
+ ($s_pid, $s_out, $s_in) = ncat(host_for_args(@$server_args), ($PORT, "-l"), @$server_args);
+ ($c_pid, $c_out, $c_in) = ncat(host_for_args(@$client_args), ($PROXY_PORT), @$client_args);
+ test($desc, $code);
+ kill_children;
+}
+
+sub proxy_test_multi {
+ my $specs = shift;
+ my $desc = shift;
+ my $proxy_args_ref = shift;
+ my $server_args_ref = shift;
+ my $client_args_ref = shift;
+ my $code = shift;
+ my $outer_xfail = $xfail;
+ local $xfail;
+
+ for my $spec (@$specs) {
+ my @proxy_args = @$proxy_args_ref;
+ my @server_args = @$server_args_ref;
+ my @client_args = @$client_args_ref;
+
+ $xfail = $outer_xfail;
+ for my $proto (split(/ /, $spec)) {
+ if ($proto eq "tcp") {
+ # Nothing needed.
+ } elsif ($proto eq "udp") {
+ push @server_args, ("--udp");
+ push @client_args, ("--udp");
+ } elsif ($proto eq "sctp") {
+ push @server_args, ("--sctp");
+ push @client_args, ("--sctp");
+ $xfail = 1 if !$HAVE_SCTP;
+ } elsif ($proto eq "ssl") {
+ push @server_args, ("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem");
+ push @client_args, ("--ssl");
+ } elsif ($proto eq "xfail") {
+ $xfail = 1;
+ } else {
+ die "Unknown protocol $proto";
+ }
+ }
+ proxy_test("$desc ($spec)", [@proxy_args], [@server_args], [@client_args], $code);
+ }
+}
+
+sub max_conns_test {
+ my $desc = shift;
+ my $server_args = shift;
+ my $client_args = shift;
+ my $count = shift;
+ my @client_pids;
+ my @client_outs;
+ my @client_ins;
+
+ ($s_pid, $s_out, $s_in) = ncat_server(@$server_args, ("--max-conns", $count));
+ test $desc, sub {
+ my ($i, $resp);
+
+ # Fill the connection limit exactly.
+ for ($i = 0; $i < $count; $i++) {
+ my @tmp;
+ ($c_pid, $c_out, $c_in) = ncat_client(@$client_args);
+ push @client_pids, $c_pid;
+ push @client_outs, $c_out;
+ push @client_ins, $c_in;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out, 2.0);
+ if (!$resp) {
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ }
+ $resp = "" if not defined($resp);
+ $resp eq "abc\n" or die "--max-conns $count server did not accept client #" . ($i + 1);
+ }
+ # Try a few more times. Should be rejected.
+ for (; $i < $count + 2; $i++) {
+ ($c_pid, $c_out, $c_in) = ncat_client(@$client_args);
+ push @client_pids, $c_pid;
+ push @client_outs, $c_out;
+ push @client_ins, $c_in;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out, 2.0);
+ if (!$resp) {
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ }
+ !$resp or die "--max-conns $count server accepted client #" . ($i + 1);
+ }
+ # Kill one of the connected clients, which should open up a
+ # space.
+ {
+ kill "TERM", $client_pids[0];
+ while (waitpid($client_pids[0], 0) > 0) {
+ }
+ shift @client_pids;
+ shift @client_outs;
+ sleep 2;
+ }
+ if ($count > 0) {
+ ($c_pid, $c_out, $c_in) = ncat_client(@$client_args);
+ push @client_pids, $c_pid;
+ push @client_outs, $c_out;
+ push @client_ins, $c_in;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out, 2.0);
+ if (!$resp) {
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ }
+ $resp = "" if not defined($resp);
+ $resp eq "abc\n" or die "--max-conns $count server did not accept client #$count after freeing one space";
+ }
+ return 1;
+ };
+ kill_children;
+}
+
+sub max_conns_test_multi {
+ my $specs = shift;
+ my $desc = shift;
+ my $server_args_ref = shift;
+ my $client_args_ref = shift;
+ my $count = shift;
+ my $outer_xfail = $xfail;
+ local $xfail;
+
+ for my $spec (@$specs) {
+ my @server_args = @$server_args_ref;
+ my @client_args = @$client_args_ref;
+
+ $xfail = $outer_xfail;
+ for my $proto (split(/ /, $spec)) {
+ if ($proto eq "tcp") {
+ # Nothing needed.
+ } elsif ($proto eq "udp") {
+ push @server_args, ("--udp");
+ push @client_args, ("--udp");
+ } elsif ($proto eq "sctp") {
+ push @server_args, ("--sctp");
+ push @client_args, ("--sctp");
+ $xfail = 1 if !$HAVE_SCTP;
+ } elsif ($proto eq "ssl") {
+ push @server_args, ("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem");
+ push @client_args, ("--ssl");
+ } elsif ($proto eq "xfail") {
+ $xfail = 1;
+ } else {
+ die "Unknown protocol $proto";
+ }
+ }
+ max_conns_test("$desc ($spec)", [@server_args], [@client_args], $count);
+ }
+}
+
+sub max_conns_test_all {
+ max_conns_test_multi(["tcp", "udp", "sctp", "tcp ssl", "sctp ssl"], @_);
+}
+
+sub max_conns_test_tcp_sctp_ssl {
+ max_conns_test_multi(["tcp", "sctp", "tcp ssl", "sctp ssl"], @_);
+}
+
+sub max_conns_test_tcp_ssl {
+ max_conns_test_multi(["tcp", "tcp ssl"], @_);
+}
+
+sub match_ncat_environment {
+ $_ = shift;
+ return /NCAT_REMOTE_ADDR=.+\n
+ NCAT_REMOTE_PORT=.+\n
+ NCAT_LOCAL_ADDR=.+\n
+ NCAT_LOCAL_PORT=.+\n
+ NCAT_PROTO=.+
+ /x;
+}
+
+# Ignore broken pipe signals that result when trying to read from a terminated
+# client.
+$SIG{PIPE} = "IGNORE";
+# Don't have to wait on children.
+$SIG{CHLD} = "IGNORE";
+
+# Individual tests begin here.
+
+# Test server with no hostname or port.
+($s_pid, $s_out, $s_in) = ncat_server_noport();
+test "Server default listen address and port",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("127.0.0.1");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport();
+test "Server default listen address and port",
+sub {
+ my $resp;
+
+ my ($c_pid2, $c_out2, $c_in2) = ncat("-6", "::1");
+ syswrite($c_in2, "abc\n");
+ close $c_in2;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-4");
+test "Server -4 default listen address and port",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("127.0.0.1");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-6");
+test "Server -6 default listen address and port",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-6", $IPV6_ADDR);
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+# Test server with no port.
+($s_pid, $s_out, $s_in) = ncat_server_noport($HOST);
+test "Server default port",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat($HOST);
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+# Test server with no address.
+($s_pid, $s_out, $s_in) = ncat_server();
+test "Server default listen address",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat($HOST, $PORT);
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+{
+ # Expected to fail because we can't detect connection failure for IPv6 and retry IPv4
+ local $xfail=1;
+# Test server with UDP.
+($s_pid, $s_out, $s_in) = ncat_server_noport("--udp", "-4");
+test "Server default listen address --udp IPV4",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("localhost", "--udp");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from localhost";
+
+};
+kill_children;
+}
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("--udp", "-6");
+test "Server default listen address --udp IPV6",
+sub {
+ my $resp;
+
+ my ($c_pid1, $c_out1, $c_in1) = ncat("localhost", "--udp");
+ syswrite($c_in1, "abc\n");
+ close $c_in1;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from ::1";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("--udp");
+test "Server default listen address --udp IPV4 + IPV6",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("localhost", "--udp");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from localhost";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("--udp");
+test "Server default listen address --udp IPV4 + IPV6",
+sub {
+ my $resp;
+
+ my ($c_pid1, $c_out1, $c_in1) = ncat("::1", "--udp");
+ syswrite($c_in1, "abc\n");
+ close $c_in1;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from ::1";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-6", "--udp");
+test "Server default listen address -6 --udp not IPv4",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("127.0.0.1", "--udp");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ !$resp or die "Server got \"$resp\", not \"\" from 127.0.0.1";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-6", "--udp");
+test "Server default listen address -6 --udp",
+sub {
+ my $resp;
+ my ($c_pid1, $c_out1, $c_in1) = ncat("::1", "--udp");
+ syswrite($c_in1, "abc\n");
+ close $c_in1;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from ::1";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-4", "--udp");
+test "Server default listen address -4 --udp",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("127.0.0.1", "--udp");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from 127.0.0.1";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-4", "--udp");
+test "Server default listen address -4 --udp not IPv6",
+sub {
+ my $resp;
+
+ my ($c_pid1, $c_out1, $c_in1) = ncat("::1", "--udp");
+ syswrite($c_in1, "abc\n");
+ close $c_in1;
+ $resp = timeout_read($s_out);
+ !$resp or die "Server got \"$resp\", not \"\" from ::1";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-4");
+test "Connect fallback with IPv4 server",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("localhost");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+
+($s_pid, $s_out, $s_in) = ncat_server_noport("-6");
+test "Connect fallback with IPv6 server",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("localhost");
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+
+kill_children;
+# Test UNIX domain sockets listening
+{
+local $xfail = 1 if !$HAVE_UNIXSOCK;
+($s_pid, $s_out, $s_in) = ncat_server_noport("-U", $UNIXSOCK);
+test "Server UNIX socket listen on $UNIXSOCK (STREAM)",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-U", $UNIXSOCK);
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from client";
+};
+kill_children;
+unlink($UNIXSOCK);
+}
+
+{
+local $xfail = 1 if !$HAVE_UNIXSOCK;
+($s_pid, $s_out, $s_in) = ncat_server_noport("-U", "--udp", $UNIXSOCK);
+test "Server UNIX socket listen on $UNIXSOCK --udp (DGRAM)",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-U", "--udp", $UNIXSOCK);
+ syswrite($c_in, "abc\n");
+ close $c_in;
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from client";
+};
+kill_children;
+unlink($UNIXSOCK);
+}
+
+server_client_test "Connect success exit code",
+[], ["--send-only"], sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+
+ syswrite($c_in, "abc\n");
+ close($c_in);
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die;
+ $code = $? >> 8;
+ $code == 0 or die "Exit code was $code, not 0";
+};
+kill_children;
+
+test "Connect connection refused exit code",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+
+ my ($c_pid, $c_out, $c_in) = ncat($HOST, $PORT, "--send-only");
+ syswrite($c_in, "abc\n");
+ close($c_in);
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die;
+ $code = $? >> 8;
+ $code == 1 or die "Exit code was $code, not 1";
+};
+kill_children;
+
+test "Connect connection interrupted exit code",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, sockaddr_in($PORT, INADDR_ANY)) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat($HOST, $PORT);
+
+ accept(S, SOCK) or die;
+ # Shut down the socket with a RST.
+ setsockopt(S, SOL_SOCKET, SO_LINGER, pack("II", 1, 0)) or die;
+ close(S) or die;
+
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die;
+ $code = $? >> 8;
+ $code == 1 or die "Exit code was $code, not 1";
+};
+kill_children;
+
+server_client_test "Listen success exit code",
+[], ["--send-only"], sub {
+ my ($resp, $pid, $code);
+ local $SIG{CHLD} = sub { };
+
+ syswrite($c_in, "abc\n");
+ close($c_in);
+ do {
+ $pid = waitpid($s_pid, 0);
+ } while ($pid > 0 && $pid != $s_pid);
+ $pid == $s_pid or die "$pid != $s_pid";
+ $code = $? >> 8;
+ $code == 0 or die "Exit code was $code, not 0";
+};
+kill_children;
+
+test "Listen connection interrupted exit code",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+
+ my ($s_pid, $s_out, $s_in) = ncat_server("-4");
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ my $addr = gethostbyname($HOST);
+ connect(SOCK, sockaddr_in($PORT, $addr)) or die $!;
+ # Shut down the socket with a RST.
+ setsockopt(SOCK, SOL_SOCKET, SO_LINGER, pack("II", 1, 0)) or die;
+ close(SOCK) or die;
+
+ do {
+ $pid = waitpid($s_pid, 0);
+ } while ($pid > 0 && $pid != $s_pid);
+ $pid == $s_pid or die;
+ $code = $? >> 8;
+ $code == 1 or die "Exit code was $code, not 1";
+};
+kill_children;
+
+test "Program error exit code",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+
+ my ($c_pid, $c_out, $c_in) = ncat($HOST, $PORT, "--baffle");
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die;
+ $code = $? >> 8;
+ $code == 2 or die "Exit code was $code, not 2";
+
+ my ($s_pid, $s_out, $s_in) = ncat("-l", "--baffle");
+ do {
+ $pid = waitpid($s_pid, 0);
+ } while ($pid > 0 && $pid != $s_pid);
+ $pid == $s_pid or die;
+ $code = $? >> 8;
+ $code == 2 or die "Exit code was $code, not 2";
+};
+kill_children;
+
+server_client_test_all "Messages are logged to output file",
+["--output", "server.log"], ["--output", "client.log"], sub {
+
+ syswrite($c_in, "abc\n");
+ sleep 1;
+ syswrite($s_in, "def\n");
+ sleep 1;
+ close($c_in);
+ open(FH, "server.log");
+ binmode FH;
+ my $contents = join("", <FH>);
+ close(FH);
+ $contents eq "abc\ndef\n" or die "Server logged " . d($contents);
+ open(FH, "client.log");
+ binmode FH;
+ $contents = join("", <FH>);
+ close(FH);
+ $contents eq "abc\ndef\n" or die "Client logged " . d($contents);
+};
+unlink "server.log";
+unlink "client.log";
+kill_children;
+
+server_client_test_tcp_sctp_ssl "Debug messages go to stderr",
+["-vvv"], ["-vvv"], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+{
+local $xfail = 1;
+server_client_test_tcp_ssl "Client closes socket write and keeps running after stdin EOF",
+[], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ close($c_in);
+
+ $resp = timeout_read($s_out);
+ !defined($resp) or die "Server didn't get EOF (got \"$resp\")";
+ sleep 1;
+ waitpid($c_pid, WNOHANG) != -1 or die "Client stopped running";
+};
+kill_children;
+}
+
+server_client_test_tcp_ssl "--send-only client closes socket write and stops running after stdin EOF",
+[], ["--send-only"], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ close($c_in);
+
+ $resp = timeout_read($s_out);
+ !defined($resp) or die "Server didn't get EOF (got \"$resp\")";
+ sleep 1;
+ waitpid($c_pid, WNOHANG) == -1 or die "Client still running";
+};
+kill_children;
+
+server_client_test_tcp_ssl "Server closes socket write and keeps running after stdin EOF",
+[], [], sub {
+ my $resp;
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+
+ close($s_in);
+
+ $resp = timeout_read($c_out);
+ !defined($resp) or die "Client didn't get EOF (got \"$resp\")";
+ sleep 1;
+ waitpid($s_pid, WNOHANG) != -1 or die "Server stopped running";
+};
+kill_children;
+
+server_client_test_tcp_ssl "--send-only server closes socket write and stops running after stdin EOF",
+["--send-only"], [], sub {
+ my $resp;
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+
+ close($s_in);
+
+ $resp = timeout_read($c_out);
+ !defined($resp) or die "Client didn't get EOF (got \"$resp\")";
+ sleep 1;
+ waitpid($s_pid, WNOHANG) == -1 or die "Server still running";
+};
+kill_children;
+
+server_client_test_tcp_ssl "Client closes stdout and keeps running after socket EOF",
+[], [], sub {
+ my $resp;
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+
+ close($s_in);
+
+ $resp = timeout_read($c_out);
+ !defined($resp) or die "Client didn't get EOF and didn't exit (got \"$resp\")";
+ sleep 1;
+ waitpid($c_pid, WNOHANG) != -1 or die "Client stopped running";
+};
+kill_children;
+
+# SCTP doesn't have half-open sockets, so the program should exit.
+# http://seclists.org/nmap-dev/2013/q1/203
+server_client_test_sctp_ssl "Client closes stdout and stops running after socket EOF",
+[], [], sub {
+ my $resp;
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+
+ close($s_in);
+
+ $resp = timeout_read($c_out);
+ !defined($resp) or die "Client didn't get EOF and didn't exit (got \"$resp\")";
+ sleep 1;
+ waitpid($c_pid, WNOHANG) == -1 or die "Client still running";
+};
+kill_children;
+
+server_client_test_tcp_sctp_ssl "--recv-only client closes stdout and stops running after socket EOF",
+[], ["--recv-only"], sub {
+ my $resp;
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+
+ close($s_in);
+
+ $resp = timeout_read($c_out);
+ !defined($resp) or die "Client didn't get EOF and didn't exit (got \"$resp\")";
+ sleep 1;
+ waitpid($c_pid, WNOHANG) == -1 or die "Client still running";
+};
+kill_children;
+
+# Test that the server closes its output stream after a client disconnects.
+# This is for uses like
+# ncat -l | tar xzvf -
+# tar czf - <files> | ncat localhost --send-only
+# where tar on the listening side could be any program that potentially buffers
+# its input. The listener must close its standard output so the program knows
+# to stop reading and process what remains in its buffer.
+{
+# XFAIL because of http://seclists.org/nmap-dev/2013/q1/227. The "close stdout"
+# part works, but not the "server keeps running" part.
+local $xfail = 1;
+server_client_test_tcp_ssl "Server closes stdout and keeps running after socket EOF",
+[], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ close($c_in);
+
+ $resp = timeout_read($s_out);
+ !defined($resp) or die "Server didn't send EOF";
+ sleep 1;
+ waitpid($s_pid, WNOHANG) != -1 or die "Server stopped running";
+};
+kill_children;
+}
+
+server_client_test_sctp_ssl "Server closes stdout and stops running after socket EOF",
+[], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ close($c_in);
+
+ $resp = timeout_read($s_out);
+ !defined($resp) or die "Server didn't send EOF";
+ sleep 1;
+ waitpid($s_pid, WNOHANG) == -1 or die "Server still running";
+};
+kill_children;
+
+server_client_test_tcp_sctp_ssl "--recv-only server closes stdout and stops running after socket EOF",
+["--recv-only"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ close($c_in);
+
+ $resp = timeout_read($s_out);
+ !defined($resp) or die "Server didn't send EOF";
+ sleep 1;
+ waitpid($s_pid, WNOHANG) == -1 or die "Server still running";
+};
+kill_children;
+
+# Tests to check that server defaults to non-persistent without --keep-open.
+
+# Server immediately quits after the first connection closed without --keep-open
+($s_pid, $s_out, $s_in) = ncat_server();
+test "Server quits without --keep-open",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+ kill "TERM", $c_pid;
+ while (waitpid($c_pid, 0) > 0) {
+ }
+ sleep 1;
+ # -1 because children are automatically reaped; 0 means it's still running.
+ waitpid($s_pid, WNOHANG) == -1 or die "Server still running";
+};
+kill_children;
+
+# Server with --exec immediately quits after the first connection closed without --keep-open
+($s_pid, $s_out, $s_in) = ncat_server("--exec", "$CAT");
+test "Server with --exec quits without --keep-open",
+sub {
+ my $resp;
+
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($c_out);
+ $resp eq "abc\n" or die "Client got back \"$resp\", not \"abc\\n\"";
+ kill "TERM", $c_pid;
+ while (waitpid($c_pid, 0) > 0) {
+ }
+ sleep 1;
+ waitpid($s_pid, WNOHANG) == -1 or die "Server still running";
+};
+kill_children;
+
+# Server immediately quits after the first connection ssl negotiation fails without --keep-open
+{
+($s_pid, $s_out, $s_in) = ncat_server("--ssl");
+test "Server quits after a failed ssl negotiation without --keep-open",
+sub {
+ my $resp;
+
+ # Let's sleep for one second here, since in some cases the server might not
+ # get the chance to start listening before the client tries to connect.
+ sleep 1;
+
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "abc\n");
+
+ kill "TERM", $c_pid;
+ while (waitpid($c_pid, 0) > 0) {
+ }
+ sleep 1;
+ # -1 because children are automatically reaped; 0 means it's still running.
+ waitpid($s_pid, WNOHANG) == -1 or die "Server still running";
+};
+kill_children;
+}
+
+# Server does not accept multiple connections without --keep-open
+($s_pid, $s_out, $s_in) = ncat_server();
+test "Server does not accept multiple conns. without --keep-open",
+sub {
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+
+ sleep 1;
+
+ waitpid($c2_pid, WNOHANG) == -1 or die "A second client could connect to the server";
+
+};
+kill_children;
+
+# Test server persistence with --keep-open.
+
+($s_pid, $s_out, $s_in) = ncat_server("--keep-open");
+test "--keep-open",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--keep-open", "--exec", "$CAT");
+test "--keep-open --exec",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ $resp eq "abc\n" or die "Client 1 got back \"$resp\", not \"abc\\n\"";
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Client 2 got back \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--keep-open", "--udp", "--exec", "$CAT");
+test "--keep-open --exec (udp)",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client("--udp");
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ $resp eq "abc\n" or die "Client 1 got back \"$resp\", not \"abc\\n\"";
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--udp");
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Client 2 got back \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+# Test --exec, --sh-exec and --lua-exec.
+
+server_client_test_all "--exec",
+["--exec", "$PERL -e \$|=1;while(<>)\{tr/a-z/A-Z/;print\}"], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "ABC\n" or die "Client received " . d($resp) . ", not " . d("ABC\n");
+};
+
+server_client_test_all "--sh-exec",
+["--sh-exec", "perl -e '\$|=1;while(<>)\{tr/a-z/A-Z/;print\}'"], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "ABC\n" or die "Client received " . d($resp) . ", not " . d("ABC\n");
+};
+
+server_client_test_all "--exec, quits instantly",
+["--exec", "$ECHO abc"], [], sub {
+ syswrite($c_in, "test\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Client received " . d($resp) . ", not " . d("abc\n");
+};
+
+server_client_test_all "--sh-exec with -C",
+["--sh-exec", "$PERL -e '\$|=1;while(<>){tr/a-z/A-Z/;print}'", "-C"], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "ABC\r\n" or die "Client received " . d($resp) . ", not " . d("ABC\r\n");
+};
+
+proxy_test "--exec through proxy",
+[], [], ["--exec", "$ECHO abc"], sub {
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Server received " . d($resp) . ", not " . d("abc\n");
+};
+
+server_client_test_all "--lua-exec",
+["--lua-exec", "toupper.lua"], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "ABC\n" or die "Client received " . d($resp) . ", not " . d("ABC\n");
+};
+
+# Test environment variables being set for --exec, --sh-exec and --lua-exec.
+
+server_client_test_all "--exec, environment variables",
+["--exec", "$BINSH test-environment.sh"], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ match_ncat_environment($resp) or die "Client received " . d($resp) . ".";
+};
+
+server_client_test_all "--sh-exec, environment variables",
+["--sh-exec", "sh test-environment.sh"], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ match_ncat_environment($resp) or die "Client received " . d($resp) . ".";
+};
+
+proxy_test "--exec through proxy, environment variables",
+[], [], ["--exec", "$BINSH test-environment.sh"], sub {
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ match_ncat_environment($resp) or die "Client received " . d($resp) . ".";
+};
+
+server_client_test_all "--lua-exec, environment variables",
+["--lua-exec", "test-environment.lua"], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ match_ncat_environment($resp) or die "Client received " . d($resp) . ".";
+};
+
+# Do a syswrite and then a delay to force separate reads in the subprocess.
+sub delaywrite {
+ my ($handle, $data) = @_;
+ my $delay = 0.1;
+ syswrite($handle, $data);
+ select(undef, undef, undef, $delay);
+}
+
+server_client_test_all "-C translation on input",
+["-C"], ["-C"], sub {
+ my $resp;
+ my $expected = "\r\na\r\nb\r\n---\r\nc\r\nd\r\n---e\r\n\r\nf\r\n---\r\n";
+
+ delaywrite($c_in, "\na\nb\n");
+ delaywrite($c_in, "---");
+ delaywrite($c_in, "\r\nc\r\nd\r\n");
+ delaywrite($c_in, "---");
+ delaywrite($c_in, "e\n\nf\n");
+ delaywrite($c_in, "---\r");
+ delaywrite($c_in, "\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq $expected or die "Server received " . d($resp) . ", not " . d($expected);
+
+ delaywrite($s_in, "\na\nb\n");
+ delaywrite($s_in, "---");
+ delaywrite($s_in, "\r\nc\r\nd\r\n");
+ delaywrite($s_in, "---");
+ delaywrite($s_in, "e\n\nf\n");
+ delaywrite($s_in, "---\r");
+ delaywrite($s_in, "\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq $expected or die "Client received " . d($resp) . ", not " . d($expected);
+};
+kill_children;
+
+server_client_test_all "-C server no translation on output",
+["-C"], [], sub {
+ my $resp;
+ my $expected = "\na\nb\n---\r\nc\r\nd\r\n";
+
+ delaywrite($c_in, "\na\nb\n");
+ delaywrite($c_in, "---");
+ delaywrite($c_in, "\r\nc\r\nd\r\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq $expected or die "Server received " . d($resp) . ", not " . d($expected);
+};
+kill_children;
+
+server_client_test_tcp_sctp_ssl "-C client no translation on output",
+[], ["-C"], sub {
+ my $resp;
+ my $expected = "\na\nb\n---\r\nc\r\nd\r\n";
+
+ delaywrite($s_in, "\na\nb\n");
+ delaywrite($s_in, "---");
+ delaywrite($s_in, "\r\nc\r\nd\r\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq $expected or die "Client received " . d($resp) . ", not " . d($expected);
+};
+kill_children;
+
+# Test that both reads and writes reset the idle counter, and that the client
+# properly exits after the timeout expires.
+server_client_test_all "idle timeout (connect mode)",
+[], ["-i", "3000ms"], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ sleep 2;
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ sleep 2;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ sleep 4;
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ !$resp or die "Client received \"$resp\" after delay of 4000 ms with idle timeout of 3000 ms."
+};
+
+# Test that both reads and writes reset the idle counter, and that the server
+# properly exits after the timeout expires.
+server_client_test_tcp_sctp_ssl "idle timeout (listen mode)",
+["-i", "3000ms"], [], sub {
+ my $resp;
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ sleep 2;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ sleep 2;
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ sleep 4;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server received \"$resp\" after delay of 4000 ms with idle timeout of 3000 ms."
+};
+
+server_client_test_multi ["udp"], "idle timeout (listen mode)",
+["-i", "3000ms"], [], sub {
+ my $resp;
+
+ # when using UDP client must at least write something to the server
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Server didn't receive the message";
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ sleep 2;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ sleep 2;
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ sleep 4;
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server received \"$resp\" after delay of 4000 ms with idle timeout of 3000 ms."
+};
+
+# --send-only tests.
+
+server_client_test_all "--send-only client",
+[], ["--send-only"], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ !$resp or die "Client received \"$resp\" in --send-only mode";
+};
+
+server_client_test_all "--send-only server",
+["--send-only"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server received \"$resp\" in --send-only mode";
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+};
+
+($s_pid, $s_out, $s_in) = ncat_server("--broker", "--send-only");
+test "--send-only broker",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+ $resp = timeout_read($c2_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ !$resp or die "--send-only broker relayed \"$resp\"";
+};
+kill_children;
+
+# --recv-only tests.
+
+# Note this test excludes UDP. The --recv-only UDP client never sends anything
+# to the server, so the server never knows to start sending its data.
+server_client_test_tcp_sctp_ssl "--recv-only client",
+[], ["--recv-only"], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server received \"$resp\" from --recv-only client";
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+};
+
+server_client_test_all "--recv-only server",
+["--recv-only"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ !$resp or die "Client received \"$resp\" from --recv-only server";
+};
+
+($s_pid, $s_out, $s_in) = ncat_server("--broker", "--recv-only");
+test "--recv-only broker",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ !$resp or die "Client received \"$resp\" from --recv-only broker";
+ $resp = timeout_read($c2_out);
+ !$resp or die "Client received \"$resp\" from --recv-only broker";
+
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ !$resp or die "Client received \"$resp\" from --recv-only broker";
+};
+kill_children;
+
+#Broker Tests
+($s_pid, $s_out, $s_in) = ncat_server("--broker");
+test "--broker mode (tcp)",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ $resp eq "abc\n" or die "Client 1 received \"$resp\", not abc";
+
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Client 2 received \"$resp\", not abc";
+};
+kill_children;
+
+{
+ local $xfail=1 if !$HAVE_SCTP;
+($s_pid, $s_out, $s_in) = ncat_server("--broker", "--sctp");
+test "--broker mode (sctp)",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client("--sctp");
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--sctp");
+
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ $resp eq "abc\n" or die "Client 1 received \"$resp\", not abc";
+
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Client 2 received \"$resp\", not abc";
+};
+kill_children;
+}
+
+($s_pid, $s_out, $s_in) = ncat_server("--broker", "--ssl");
+test "--broker mode (tcp ssl)",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client("--ssl");
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl");
+
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ $resp eq "abc\n" or die "Client 1 received \"$resp\", not abc";
+
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Client 2 received \"$resp\", not abc";
+};
+kill_children;
+
+{
+ local $xfail=1 if !$HAVE_SCTP;
+($s_pid, $s_out, $s_in) = ncat_server("--broker", "--sctp", "--ssl");
+test "--broker mode (sctp ssl)",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client("--sctp", "--ssl");
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--sctp", "--ssl");
+
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($c1_out);
+ $resp eq "abc\n" or die "Client 1 received \"$resp\", not abc";
+
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Client 2 received \"$resp\", not abc";
+};
+kill_children;
+}
+
+($s_pid, $s_out, $s_in) = ncat_server("--broker");
+test "IPV4 and IPV6 clients can talk to each other in broker mode",
+sub {
+ my $resp;
+ sleep 1;
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client("-6");
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("-4");
+
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($c1_out, 2);
+ $resp eq "abc\n" or die "IPV6 Client received \"$resp\", not abc";
+
+ syswrite($c1_in, "abc\n");
+ $resp = timeout_read($c2_out, 2);
+ $resp eq "abc\n" or die "IPV4 Client received \"$resp\", not abc";
+};
+kill_children;
+
+
+# Source address tests.
+
+test "Connect with -p",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, sockaddr_in($PORT, INADDR_ANY)) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-p", "1234", $HOST, $PORT);
+
+ accept(S, SOCK) or die;
+ my ($port, $addr) = sockaddr_in(getpeername(S));
+ $port == 1234 or die "Client connected to proxy with source port $port, not 1234";
+ close(S);
+};
+kill_children;
+
+test "Connect through HTTP proxy with -p",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, sockaddr_in($PROXY_PORT, INADDR_ANY)) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("--proxy-type", "http", "--proxy", "$HOST:$PROXY_PORT", "-p", "1234", $HOST, $PORT);
+
+ accept(S, SOCK) or die;
+ my ($port, $addr) = sockaddr_in(getpeername(S));
+ $port == 1234 or die "Client connected to proxy with source port $port, not 1234";
+ close(S);
+};
+kill_children;
+
+test "Connect through SOCKS4 proxy with -p",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, sockaddr_in($PROXY_PORT, INADDR_ANY)) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("--proxy-type", "socks4", "--proxy", "$HOST:$PROXY_PORT", "-p", "1234", $HOST, $PORT);
+
+ accept(S, SOCK) or die;
+ my ($port, $addr) = sockaddr_in(getpeername(S));
+ $port == 1234 or die "Client connected to proxy with source port $port, not 1234";
+ close(S);
+};
+kill_children;
+
+{
+ local $xfail=1 if !$HAVE_UNIXSOCK;
+# Test connecting to UNIX datagram socket with -s
+test "Connect to UNIX datagram socket with -s",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ my $buff;
+
+ unlink($UNIXSOCK);
+ unlink($UNIXSOCK_TMP);
+
+ socket(SOCK, AF_UNIX, SOCK_DGRAM, 0) or die;
+ bind(SOCK, sockaddr_un($UNIXSOCK)) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-U", "--udp", "-s", $UNIXSOCK_TMP, $UNIXSOCK);
+ syswrite($c_in, "abc\n");
+ close($c_in);
+
+ my $peeraddr = recv(SOCK, $buff, 4, 0) or die;
+ my ($path) = sockaddr_un($peeraddr);
+ $path eq $UNIXSOCK_TMP or die "Client connected to proxy with source socket path $path, not $UNIXSOCK_TMP";
+};
+kill_children;
+unlink($UNIXSOCK);
+unlink($UNIXSOCK_TMP);
+}
+
+
+# HTTP proxy tests.
+
+sub http_request {
+ my ($method, $uri) = @_;
+ #print STDERR "$method $uri HTTP/1.0\r\n\r\n";
+ return "$method $uri HTTP/1.0\r\n\r\n";
+};
+
+server_client_test "HTTP proxy bad request",
+["--proxy-type", "http"], [], sub {
+ syswrite($c_in, "bad\r\n\r\n");
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 400 or die "Expected response code 400, got $code";
+};
+
+server_client_test "HTTP CONNECT no port number",
+["--proxy-type", "http"], [], sub {
+ # Supposed to have a port number.
+ my $req = http_request("CONNECT", "$HOST");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 400 or die "Expected response code 400, got $code";
+};
+
+server_client_test "HTTP CONNECT no port number",
+["--proxy-type", "http"], [], sub {
+ # Supposed to have a port number.
+ my $req = http_request("CONNECT", "$HOST:");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 400 or die "Expected response code 400, got $code";
+};
+
+server_client_test "HTTP CONNECT good request",
+["--proxy-type", "http"], [], sub {
+ my $req = http_request("CONNECT", "$HOST:$PORT");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+server_client_test "HTTP CONNECT IPv6 address, no port number",
+["--proxy-type", "http", "-6"], ["-6"], sub {
+ # Supposed to have a port number.
+ my $req = http_request("CONNECT", "[$IPV6_ADDR]");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 400 or die "Expected response code 400, got $code";
+};
+
+server_client_test "HTTP CONNECT IPv6 address, no port number",
+["--proxy-type", "http", "-6"], ["-6"], sub {
+ # Supposed to have a port number.
+ my $req = http_request("CONNECT", "[$IPV6_ADDR]:");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 400 or die "Expected response code 400, got $code";
+};
+
+server_client_test "HTTP CONNECT IPv6 address, good request",
+["--proxy-type", "http", "-6"], ["-6"], sub {
+ my $req = http_request("CONNECT", "[$IPV6_ADDR]:$PORT");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+# Try accessing an IPv6 server with a proxy that uses -4, should fail.
+proxy_test_raw "HTTP CONNECT IPv4-only proxy",
+["-4"], ["-6"], ["-4"], sub {
+ my $req = http_request("CONNECT", "[$IPV6_ADDR]:$PORT");
+ syswrite($c_in, $req);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 504 or die "Expected response code 504, got $code";
+};
+
+# Try accessing an IPv4 server with a proxy that uses -6, should fail.
+proxy_test_raw "HTTP CONNECT IPv6-only proxy",
+["-6"], ["-4"], ["-6"], sub {
+ my $req = http_request("CONNECT", "$HOST:$PORT");
+ syswrite($c_in, $req);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 504 or die "Expected response code 504, got $code";
+};
+
+proxy_test_raw "HTTP CONNECT IPv4 client, IPv6 server",
+[], ["-6"], ["-4"], sub {
+ my $req = http_request("CONNECT", "[$IPV6_ADDR]:$PORT");
+ syswrite($c_in, $req);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+proxy_test_raw "HTTP CONNECT IPv6 client, IPv4 server",
+[], ["-4"], ["-6"], sub {
+ my $req = http_request("CONNECT", "$HOST:$PORT");
+ syswrite($c_in, $req);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+# HTTP Digest functions.
+sub H {
+ return md5_hex(shift);
+}
+sub KD {
+ my ($s, $d) = @_;
+ return H("$s:$d");
+}
+sub digest_response {
+ # Assume MD5 algorithm.
+ my ($user, $pass, $realm, $method, $uri, $nonce, $qop, $nc, $cnonce) = @_;
+ my $A1 = "$user:$realm:$pass";
+ my $A2 = "$method:$uri";
+ if ($qop) {
+ return KD(H($A1), "$nonce:$nc:$cnonce:$qop:" . H($A2));
+ } else {
+ return KD(H($A1), "$nonce:" . H($A2));
+ }
+}
+# Parse Proxy-Authenticate or Proxy-Authorization. Return ($scheme, %attrs).
+sub parse_proxy_header {
+ my $s = shift;
+ my $scheme;
+ my %attrs;
+
+ if ($s =~ m/^\s*(\w+)/) {
+ $scheme = $1;
+ }
+ while ($s =~ m/(\w+)\s*=\s*(?:"([^"]*)"|(\w+))/g) {
+ $attrs{$1} = $2 || $3;
+ }
+
+ return ($scheme, %attrs);
+}
+
+server_client_test "HTTP proxy client prefers Digest auth",
+["-k"], ["--proxy", "$HOST:$PORT", "--proxy-auth", "user:pass", "--proxy-type", "http"],
+sub {
+ my $nonce = "0123456789abcdef";
+ my $realm = "realm";
+ my $req = timeout_read($s_out);
+ $req or die "No initial request from client";
+ syswrite($s_in, "HTTP/1.0 407 Authentication Required\r\
+Proxy-Authenticate: Basic realm=\"$realm\"\r\
+Proxy-Authenticate: Digest realm=\"$realm\", nonce=\"$nonce\", qop=\"auth\"\r\n\r\n");
+ $req = timeout_read($s_out);
+ $req or die "No followup request from client";
+ $req = HTTP::Request->parse($req);
+ foreach my $hdr ($req->header("Proxy-Authorization")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ if ($scheme eq "Basic") {
+ die "Client used Basic auth when Digest was available";
+ }
+ }
+ return 1;
+};
+
+server_client_test "HTTP proxy client prefers Digest auth, comma-separated",
+["-k"], ["--proxy", "$HOST:$PORT", "--proxy-auth", "user:pass", "--proxy-type", "http"],
+sub {
+ my $nonce = "0123456789abcdef";
+ my $realm = "realm";
+ my $req = timeout_read($s_out);
+ $req or die "No initial request from client";
+ syswrite($s_in, "HTTP/1.0 407 Authentication Required\r\
+Proxy-Authenticate: Basic realm=\"$realm\", Digest realm=\"$realm\", nonce=\"$nonce\", qop=\"auth\"\r\n\r\n");
+ $req = timeout_read($s_out);
+ $req or die "No followup request from client";
+ $req = HTTP::Request->parse($req);
+ foreach my $hdr ($req->header("Proxy-Authorization")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ if ($scheme eq "Basic") {
+ die "Client used Basic auth when Digest was available";
+ }
+ }
+ return 1;
+};
+
+server_client_test "HTTP proxy Digest client auth",
+["-k"], ["--proxy", "$HOST:$PORT", "--proxy-auth", "user:pass", "--proxy-type", "http"],
+sub {
+ my $nonce = "0123456789abcdef";
+ my $realm = "realm";
+ my $req = timeout_read($s_out);
+ $req or die "No initial request from client";
+ syswrite($s_in, "HTTP/1.0 407 Authentication Required\r\
+Proxy-Authenticate: Digest realm=\"$realm\", nonce=\"$nonce\", qop=\"auth\", opaque=\"abcd\"\r\n\r\n");
+ $req = timeout_read($s_out);
+ $req or die "No followup request from client";
+ $req = HTTP::Request->parse($req);
+ foreach my $hdr ($req->header("Proxy-Authorization")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ die "no qop" if not $attrs{"qop"};
+ die "no nonce" if not $attrs{"nonce"};
+ die "no uri" if not $attrs{"uri"};
+ die "no nc" if not $attrs{"nc"};
+ die "no cnonce" if not $attrs{"cnonce"};
+ die "no response" if not $attrs{"response"};
+ die "no opaque" if not $attrs{"opaque"};
+ die "qop mismatch" if $attrs{"qop"} ne "auth";
+ die "nonce mismatch" if $attrs{"nonce"} ne $nonce;
+ die "opaque mismatch" if $attrs{"opaque"} ne "abcd";
+ my $expected = digest_response("user", "pass", $realm, "CONNECT", $attrs{"uri"}, $nonce, "auth", $attrs{"nc"}, $attrs{"cnonce"});
+ die "auth mismatch: $attrs{response} but expected $expected" if $attrs{"response"} ne $expected;
+ return 1;
+ }
+ die "No Proxy-Authorization: Digest in client request";
+};
+
+server_client_test "HTTP proxy Digest client auth, no qop",
+["-k"], ["--proxy", "$HOST:$PORT", "--proxy-auth", "user:pass", "--proxy-type", "http"],
+sub {
+ my $nonce = "0123456789abcdef";
+ my $realm = "realm";
+ my $req = timeout_read($s_out);
+ $req or die "No initial request from client";
+ syswrite($s_in, "HTTP/1.0 407 Authentication Required\r\
+Proxy-Authenticate: Digest realm=\"$realm\", nonce=\"$nonce\", opaque=\"abcd\"\r\n\r\n");
+ $req = timeout_read($s_out);
+ $req or die "No followup request from client";
+ $req = HTTP::Request->parse($req);
+ foreach my $hdr ($req->header("Proxy-Authorization")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ die "no nonce" if not $attrs{"nonce"};
+ die "no uri" if not $attrs{"uri"};
+ die "no response" if not $attrs{"response"};
+ die "no opaque" if not $attrs{"opaque"};
+ die "nonce mismatch" if $attrs{"nonce"} ne $nonce;
+ die "opaque mismatch" if $attrs{"opaque"} ne "abcd";
+ die "nc present" if $attrs{"nc"};
+ die "cnonce present" if $attrs{"cnonce"};
+ my $expected = digest_response("user", "pass", $realm, "CONNECT", $attrs{"uri"}, $nonce, undef, undef, undef);
+ die "auth mismatch: $attrs{response} but expected $expected" if $attrs{"response"} ne $expected;
+ return 1;
+ }
+ die "No Proxy-Authorization: Digest in client request";
+};
+
+# This violates RFC 2617 section 1.2, which requires at least one auth-param.
+# But NTLM and Negotiate don't use any.
+server_client_test "HTTP proxy client handles scheme without auth-params",
+["-k"], ["--proxy", "$HOST:$PORT", "--proxy-auth", "user:pass", "--proxy-type", "http"],
+sub {
+ my $nonce = "0123456789abcdef";
+ my $realm = "realm";
+ my $req = timeout_read($s_out);
+ $req or die "No initial request from client";
+ syswrite($s_in, "HTTP/1.0 407 Authentication Required\r\
+Proxy-Authenticate: Basic realm=\"$realm\"\r\
+Proxy-Authenticate: NTLM\r\
+Proxy-Authenticate: Digest realm=\"$realm\", nonce=\"$nonce\", qop=\"auth\"\r\n\r\n");
+ $req = timeout_read($s_out);
+ $req or die "No followup request from client";
+ $req = HTTP::Request->parse($req);
+ $req->header("Proxy-Authorization") or die "Client didn't sent Proxy-Authorization";
+};
+
+server_client_test "HTTP proxy client handles scheme without auth-params, comma-separated",
+["-k"], ["--proxy", "$HOST:$PORT", "--proxy-auth", "user:pass", "--proxy-type", "http"],
+sub {
+ my $nonce = "0123456789abcdef";
+ my $realm = "realm";
+ my $req = timeout_read($s_out);
+ $req or die "No initial request from client";
+ syswrite($s_in, "HTTP/1.0 407 Authentication Required\r\
+Proxy-Authenticate: Basic realm=\"$realm\", NTLM, Digest realm=\"$realm\", nonce=\"$nonce\", qop=\"auth\"\r\n\r\n");
+ $req = timeout_read($s_out);
+ $req or die "No followup request from client";
+ $req = HTTP::Request->parse($req);
+ $req->header("Proxy-Authorization") or die "Client didn't sent Proxy-Authorization";
+};
+
+# Check that the proxy relays in both directions.
+proxy_test "HTTP CONNECT proxy relays",
+[], [], [], sub {
+ syswrite($c_in, "abc\n");
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Proxy relayed \"$resp\", not \"abc\\n\"";
+ syswrite($s_in, "def\n");
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp eq "def\n" or die "Proxy relayed \"$resp\", not \"def\\n\"";
+};
+
+# Proxy client shouldn't see the status line returned by the proxy server.
+server_client_test "HTTP CONNECT client hides proxy server response",
+["--proxy-type", "http"], ["--proxy", "$HOST:$PORT", "--proxy-type", "http"], sub {
+ my $resp = timeout_read($c_out);
+ !$resp or die "Proxy client sent " . d($resp) . " to the user stream";
+};
+
+server_client_test "HTTP CONNECT client, different Status-Line",
+[], ["--proxy", "$HOST:$PORT", "--proxy-type", "http"], sub {
+ my $resp;
+ syswrite($s_in, "HTTP/1.1 200 Go ahead\r\n\r\nabc\n");
+ $resp = timeout_read($c_out);
+ if (!defined($resp)) {
+ die "Client didn't recognize connection";
+ } elsif ($resp ne "abc\n") {
+ die "Proxy client sent " . d($resp) . " to the user stream";
+ }
+ return 1;
+};
+
+server_client_test "HTTP CONNECT client, server sends header",
+[], ["--proxy", "$HOST:$PORT", "--proxy-type", "http"], sub {
+ my $resp;
+ syswrite($s_in, "HTTP/1.0 200 OK\r\nServer: ncat-test 1.2.3\r\n\r\nabc\n");
+ $resp = timeout_read($c_out);
+ if (!defined($resp)) {
+ die "Client didn't recognize connection";
+ } elsif ($resp ne "abc\n") {
+ die "Proxy client sent " . d($resp) . " to the user stream";
+ }
+ return 1;
+};
+
+# Check that the proxy doesn't consume anything following the request when
+# request and body are combined in one send. Section 3.3 of the CONNECT spec
+# explicitly allows the client to send data before the connection is
+# established.
+proxy_test_raw "HTTP CONNECT server doesn't consume anything after request",
+[], [], [], sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\nUser-Agent: ncat-test\r\n\r\nabc\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 200 or die "Expected response code 200, got $code";
+
+ $resp = timeout_read($s_out) or die "Read timeout";
+ $resp eq "abc\n" or die "Proxy relayed \"$resp\", not \"abc\\n\"";
+};
+
+server_client_test "HTTP CONNECT overlong Request-Line",
+["--proxy-type", "http"], [], sub {
+ syswrite($c_in, "CONNECT " . ("A" x 24000) . ":$PORT HTTP/1.0\r\n\r\n");
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 413 or $code == 414 or die "Expected response code 413 or 414, got $code";
+};
+
+server_client_test "HTTP CONNECT overlong header",
+["--proxy-type", "http"], [], sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ for (my $i = 0; $i < 10000; $i++) {
+ syswrite($c_in, "Header: Value\r\n");
+ }
+ syswrite($c_in, "\r\n");
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 413 or die "Expected response code 413, got $code";
+};
+
+server_client_test "HTTP GET hostname only",
+["--proxy-type", "http"], [], sub {
+ my $req = http_request("GET", "$HOST");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 400 or die "Expected response code 400, got $code";
+};
+
+server_client_test "HTTP GET path only",
+["--proxy-type", "http"], [], sub {
+ my $req = http_request("GET", "/");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 400 or die "Expected response code 400, got $code";
+};
+
+proxy_test_raw "HTTP GET absolute URI",
+[], [], [], sub {
+ my $req = http_request("GET", "http://$HOST:$PORT/");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp =~ /^GET \/ HTTP\/1\./ or die "Proxy sent \"$resp\"";
+};
+
+proxy_test_raw "HTTP GET absolute URI, no path",
+[], [], [], sub {
+ my $req = http_request("GET", "http://$HOST:$PORT");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp =~ /^GET \/ HTTP\/1\./ or die "Proxy sent \"$resp\"";
+};
+
+proxy_test_raw "HTTP GET percent escape",
+[], [], [], sub {
+ my $req = http_request("GET", "http://$HOST:$PORT/%41");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ uri_unescape($resp) =~ /^GET \/A HTTP\/1\./ or die "Proxy sent \"$resp\"";
+};
+
+proxy_test_raw "HTTP GET remove Connection header fields",
+[], [], [], sub {
+ my $req = "GET http://$HOST:$PORT/ HTTP/1.0\r\nKeep-Alive: 300\r\nOne: 1\r\nConnection: keep-alive, two, close\r\nTwo: 2\r\nThree: 3\r\n\r\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp = HTTP::Request->parse($resp);
+ !defined($resp->header("Keep-Alive")) or die "Proxy did not remove Keep-Alive header field";
+ !defined($resp->header("Two")) or die "Proxy did not remove Two header field";
+ $resp->header("One") eq "1" or die "Proxy modified One header field";
+ $resp->header("Three") eq "3" or die "Proxy modified Three header field";
+};
+
+proxy_test_raw "HTTP GET combine multiple headers with the same name",
+[], [], [], sub {
+ my $req = "GET http://$HOST:$PORT/ HTTP/1.0\r\nConnection: keep-alive\r\nKeep-Alive: 300\r\nConnection: two\r\nOne: 1\r\nConnection: close\r\nTwo: 2\r\nThree: 3\r\n\r\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp = HTTP::Request->parse($resp);
+ !defined($resp->header("Keep-Alive")) or die "Proxy did not remove Keep-Alive header field";
+ !defined($resp->header("Two")) or die "Proxy did not remove Keep-Alive header field";
+ $resp->header("One") eq "1" or die "Proxy modified One header field";
+ $resp->header("Three") eq "3" or die "Proxy modified Three header field";
+};
+
+# RFC 2616 section 5.1.2: "In order to avoid request loops, a proxy MUST be able
+# to recognize all of its server names, including any aliases, local variations,
+# and the numeric IP address."
+server_client_test "HTTP GET request loop",
+["--proxy-type", "http"], [], sub {
+ my $req = http_request("GET", "http://$HOST:$PORT/");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 403 or die "Expected response code 403, got $code";
+};
+
+server_client_test "HTTP GET IPv6 request loop",
+["-6", "--proxy-type", "http"], ["-6"], sub {
+ my $req = http_request("GET", "http://[$IPV6_ADDR]:$PORT/");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 403 or die "Expected response code 403, got $code";
+};
+
+proxy_test_raw "HTTP HEAD absolute URI",
+[], [], [], sub {
+ my $req = http_request("HEAD", "http://$HOST:$PORT/");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp = HTTP::Request->parse($resp);
+ $resp->method eq "HEAD" or die "Proxy sent \"" . $resp->method . "\"";
+};
+
+proxy_test_raw "HTTP POST",
+[], [], [], sub {
+ my $req = "POST http://$HOST:$PORT/ HTTP/1.0\r\nContent-Length: 4\r\n\r\nabc\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp = HTTP::Request->parse($resp);
+ $resp->method eq "POST" or die "Proxy sent \"" . $resp->method . "\"";
+ $resp->content eq "abc\n" or die "Proxy sent \"" . $resp->content . "\"";
+};
+
+proxy_test_raw "HTTP POST Content-Length: 0",
+[], [], [], sub {
+ my $req = "POST http://$HOST:$PORT/ HTTP/1.0\r\nContent-Length: 0\r\n\r\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp = HTTP::Request->parse($resp);
+ $resp->method eq "POST" or die "Proxy sent \"" . $resp->method . "\"";
+ $resp->content eq "" or die "Proxy sent \"" . $resp->content . "\"";
+};
+
+proxy_test_raw "HTTP POST short Content-Length",
+[], [], [], sub {
+ my $req = "POST http://$HOST:$PORT/ HTTP/1.0\r\nContent-Length: 2\r\n\r\nabc\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp = HTTP::Request->parse($resp);
+ $resp->method eq "POST" or die "Proxy sent \"" . $resp->method . "\"";
+ $resp->content eq "ab" or die "Proxy sent \"" . $resp->content . "\"";
+};
+
+proxy_test_raw "HTTP POST long Content-Length",
+[], [], [], sub {
+ my $req = "POST http://$HOST:$PORT/ HTTP/1.0\r\nContent-Length: 10\r\n\r\nabc\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ $resp = HTTP::Request->parse($resp);
+ $resp->method eq "POST" or die "Proxy sent \"" . $resp->method . "\"";
+ $resp->content eq "abc\n" or die "Proxy sent \"" . $resp->content . "\"";
+};
+
+proxy_test_raw "HTTP POST chunked transfer encoding",
+[], [], [], sub {
+ my $req = "POST http://$HOST:$PORT/ HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n4\r\nabc\n0\r\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out);
+ # We expect the proxy to relay the request or else die with an error
+ # saying it can't do it.
+ if ($resp) {
+ $resp = HTTP::Request->parse($resp);
+ $resp->method eq "POST" or die "Proxy sent \"" . $resp->method . "\"";
+ $resp->content eq "abc\n" or die "Proxy sent \"" . $resp->content . "\"";
+ } else {
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ $resp->code == 400 or $resp->code == 411 or die "Proxy returned code " . $resp->code;
+ }
+};
+
+proxy_test_raw "HTTP POST chunked transfer encoding, no data",
+[], [], [], sub {
+ my $req = "POST http://$HOST:$PORT/ HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n";
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($s_out);
+ if ($resp) {
+ $resp = HTTP::Request->parse($resp);
+ $resp->method eq "POST" or die "Proxy sent \"" . $resp->method . "\"";
+ $resp->content eq "" or die "Proxy sent \"" . $resp->content . "\"";
+ } else {
+ $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ $resp->code == 400 or $resp->code == 411 or die "Proxy returned code " . $resp->code;
+ }
+};
+
+server_client_test "HTTP proxy unknown method",
+["--proxy-type", "http"], [], sub {
+ # Supposed to have a port number.
+ my $req = http_request("NOTHING", "http://$HOST:$PORT/");
+ syswrite($c_in, $req);
+ close($c_in);
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ my $code = HTTP::Response->parse($resp)->code;
+ $code == 405 or die "Expected response code 405, got $code";
+};
+
+# Check that proxy auth is base64 encoded properly. 's' and '~' are 0x77 and
+# 0x7E respectively, printing characters with many bits set.
+for my $auth ("", "a", "a:", ":a", "user:sss", "user:ssss", "user:sssss", "user:~~~", "user:~~~~", "user:~~~~~") {
+server_client_test "HTTP proxy auth base64 encoding: \"$auth\"",
+["-k"], ["--proxy", "$HOST:$PORT", "--proxy-type", "http", "--proxy-auth", $auth], sub {
+ my $resp = timeout_read($s_out) or die "Read timeout";
+ syswrite($s_in, "HTTP/1.0 407 Auth\r\nProxy-Authenticate: Basic realm=\"Ncat\"\r\n\r\n");
+ $resp = timeout_read($s_out) or die "Read timeout";
+ my $auth_header = HTTP::Response->parse($resp)->header("Proxy-Authorization") or die "Proxy client didn't send Proxy-Authorization header field";
+ my ($b64_auth) = ($auth_header =~ /^Basic (.*)/) or die "No auth data in \"$auth_header\"";
+ my $dec_auth = decode_base64($b64_auth);
+ $auth eq $dec_auth or die "Proxy client sent \"$b64_auth\" for \"$auth\", decodes to \"$dec_auth\"";
+};
+}
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy server auth challenge",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code == 407 or die "Expected response code 407, got $code";
+ my $auth = $resp->header("Proxy-Authenticate");
+ $auth or die "Proxy server didn't send Proxy-Authenticate header field";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy server correct auth",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization: Basic " . encode_base64("user:pass") . "\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy Basic wrong user",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization: Basic " . encode_base64("nobody:pass") . "\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code == 407 or die "Expected response code 407, got $code";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy Basic wrong pass",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization: Basic " . encode_base64("user:word") . "\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code == 407 or die "Expected response code 407, got $code";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy Basic correct auth, different case",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "pROXY-aUTHORIZATION: BASIC " . encode_base64("user:pass") . "\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+
+($s_pid, $s_out, $s_in) = ncat_server("--proxy-type", "http", "--proxy-auth", "user:pass");
+test "HTTP proxy Digest wrong user",
+sub {
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n\r\n");
+ my $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ foreach my $hdr ($resp->header("Proxy-Authenticate")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ die "no nonce" if not $attrs{"nonce"};
+ die "no realm" if not $attrs{"realm"};
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ my $response = digest_response("xxx", "pass", $attrs{"realm"}, "CONNECT", "$HOST:$PORT", $attrs{"nonce"}, undef, undef, undef);
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\
+Proxy-Authorization: Digest username=\"xxx\", realm=\"$attrs{realm}\", nonce=\"$attrs{nonce}\", uri=\"$HOST:$PORT\", response=\"$response\"\r\n\r\n");
+ $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $resp->code == 407 or die "Expected response code 407, got $code";
+ return 1;
+ }
+ die "No Proxy-Authenticate: Digest in server response";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--proxy-type", "http", "--proxy-auth", "user:pass");
+test "HTTP proxy Digest wrong pass",
+sub {
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n\r\n");
+ my $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ foreach my $hdr ($resp->header("Proxy-Authenticate")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ die "no nonce" if not $attrs{"nonce"};
+ die "no realm" if not $attrs{"realm"};
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ my $response = digest_response("user", "xxx", $attrs{"realm"}, "CONNECT", "$HOST:$PORT", $attrs{"nonce"}, undef, undef, undef);
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\
+Proxy-Authorization: Digest username=\"user\", realm=\"$attrs{realm}\", nonce=\"$attrs{nonce}\", uri=\"$HOST:$PORT\", response=\"$response\"\r\n\r\n");
+ $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $resp->code == 407 or die "Expected response code 407, got $code";
+ return 1;
+ }
+ die "No Proxy-Authenticate: Digest in server response";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--proxy-type", "http", "--proxy-auth", "user:pass");
+test "HTTP proxy Digest correct auth",
+sub {
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n\r\n");
+ my $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ foreach my $hdr ($resp->header("Proxy-Authenticate")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ die "no nonce" if not $attrs{"nonce"};
+ die "no realm" if not $attrs{"realm"};
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ my $response = digest_response("user", "pass", $attrs{"realm"}, "CONNECT", "$HOST:$PORT", $attrs{"nonce"}, "auth", "00000001", "abcdefg");
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\
+Proxy-Authorization: Digest username=\"user\", realm=\"$attrs{realm}\", nonce=\"$attrs{nonce}\", uri=\"$HOST:$PORT\", qop=\"auth\", nc=\"00000001\", cnonce=\"abcdefg\", response=\"$response\"\r\n\r\n");
+ $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $resp->code == 200 or die "Expected response code 200, got $code";
+ return 1;
+ }
+ die "No Proxy-Authenticate: Digest in server response";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--proxy-type", "http", "--proxy-auth", "user:pass");
+test "HTTP proxy Digest correct auth, no qop",
+sub {
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n\r\n");
+ my $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ foreach my $hdr ($resp->header("Proxy-Authenticate")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ die "no nonce" if not $attrs{"nonce"};
+ die "no realm" if not $attrs{"realm"};
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ my $response = digest_response("user", "pass", $attrs{"realm"}, "CONNECT", "$HOST:$PORT", $attrs{"nonce"}, undef, undef, undef);
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\
+Proxy-Authorization: Digest username=\"user\", realm=\"$attrs{realm}\", nonce=\"$attrs{nonce}\", uri=\"$HOST:$PORT\", response=\"$response\"\r\n\r\n");
+ $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $resp->code == 200 or die "Expected response code 200, got $code";
+ return 1;
+ }
+ die "No Proxy-Authenticate: Digest in server response";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--proxy-type", "http", "--proxy-auth", "user:pass");
+test "HTTP proxy Digest missing fields",
+sub {
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n\r\n");
+ my $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ foreach my $hdr ($resp->header("Proxy-Authenticate")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ my $response = digest_response("user", "pass", $attrs{"realm"}, "CONNECT", "$HOST:$PORT", $attrs{"nonce"}, undef, undef, undef);
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\
+Proxy-Authorization: Digest username=\"user\", nonce=\"$attrs{nonce}\", response=\"$response\"\r\n\r\n");
+ $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $resp->code == 407 or die "Expected response code 407, got $code";
+ return 1;
+ }
+ die "No Proxy-Authenticate: Digest in server response";
+};
+kill_children;
+
+{
+local $xfail = 1;
+($s_pid, $s_out, $s_in) = ncat_server("--proxy-type", "http", "--proxy-auth", "user:pass");
+test "HTTP proxy Digest prevents replay",
+sub {
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n\r\n");
+ my $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ foreach my $hdr ($resp->header("Proxy-Authenticate")) {
+ my ($scheme, %attrs) = parse_proxy_header($hdr);
+ next if $scheme ne "Digest";
+ die "no nonce" if not $attrs{"nonce"};
+ die "no realm" if not $attrs{"realm"};
+ my ($c_pid, $c_out, $c_in) = ncat_client();
+ my $response = digest_response("user", "pass", $attrs{"realm"}, "CONNECT", "$HOST:$PORT", $attrs{"nonce"}, "auth", "00000001", "abcdefg");
+ my $req = "CONNECT $HOST:$PORT HTTP/1.0\r\
+Proxy-Authorization: Digest username=\"user\", realm=\"$attrs{realm}\", nonce=\"$attrs{nonce}\", uri=\"$HOST:$PORT\", qop=\"auth\", nc=\"00000001\", cnonce=\"abcdefg\", response=\"$response\"\r\n\r\n";
+ syswrite($c_in, $req);
+ $resp = timeout_read($c_out);
+ $resp or die "No response from server";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $resp->code == 200 or die "Expected response code 200, got $code";
+ syswrite($c_in, $req);
+ $resp = timeout_read($c_out);
+ if ($resp) {
+ $resp = HTTP::Response->parse($resp);
+ $code = $resp->code;
+ $resp->code == 407 or die "Expected response code 407, got $code";
+ }
+ return 1;
+ }
+ die "No Proxy-Authenticate: Digest in server response";
+};
+kill_children;
+}
+
+# Test that header field values can be split across lines with LWS.
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy server LWS",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization:\t Basic \r\n\t \n dXNlcjpwYXNz\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy server LWS",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization: Basic\r\n dXNlcjpwYXNz\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code == 200 or die "Expected response code 200, got $code";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy server no auth",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization: \r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code != 200 or die "Got unexpected 200 response";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy server broken auth",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization: French fries\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code != 200 or die "Got unexpected 200 response";
+};
+
+server_client_test_multi ["tcp", "tcp ssl"], "HTTP proxy server extra auth",
+["--proxy-type", "http", "--proxy-auth", "user:pass"],
+[],
+sub {
+ syswrite($c_in, "CONNECT $HOST:$PORT HTTP/1.0\r\n");
+ syswrite($c_in, "Proxy-Authorization: Basic " . encode_base64("user:pass") . " extra\r\n");
+ syswrite($c_in, "\r\n");
+ my $resp = timeout_read($c_out) or die "Read timeout";
+ $resp = HTTP::Response->parse($resp);
+ my $code = $resp->code;
+ $code != 200 or die "Got unexpected 200 response";
+};
+
+# Allow and deny list tests.
+
+server_client_test_all "Allow localhost (IPv4 address)",
+["--allow", "127.0.0.1"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+
+server_client_test_all "Allow localhost (host name)",
+["--allow", "localhost"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+
+# Anyone not allowed is denied.
+server_client_test_all "Allow non-localhost",
+["--allow", "1.2.3.4"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server did not reject host not in allow list";
+};
+
+# --allow options should accumulate.
+server_client_test_all "--allow options accumulate",
+["--allow", "127.0.0.1", "--allow", "1.2.3.4"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+
+server_client_test_all "Deny localhost (IPv4 address)",
+["--deny", "127.0.0.1"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server did not reject host in deny list";
+};
+
+server_client_test_all "Deny localhost (host name)",
+["--deny", "localhost"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server did not reject host in deny list";
+};
+
+# Anyone not denied is allowed.
+server_client_test_all "Deny non-localhost",
+["--deny", "1.2.3.4"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+
+# --deny options should accumulate.
+server_client_test_all "--deny options accumulate",
+["--deny", "127.0.0.1", "--deny", "1.2.3.4"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server did not reject host in deny list";
+};
+
+# If a host is both allowed and denied, denial takes precedence.
+server_client_test_all "Allow and deny",
+["--allow", "127.0.0.1", "--deny", "127.0.0.1"], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server did not reject host in deny list";
+};
+
+# Test that --allowfile and --denyfile handle blank lines and more than one
+# specification per line.
+for my $contents (
+"1.2.3.4
+
+localhost",
+"1.2.3.4 localhost"
+) {
+my ($fh, $filename) = tempfile("ncat-test-XXXXX", SUFFIX => ".txt");
+print $fh $contents;
+server_client_test_all "--allowfile",
+["--allowfile", $filename], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+server_client_test_all "--denyfile",
+["--denyfile", $filename], [], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server did not reject host in --denyfile list";
+};
+unlink $filename;
+}
+
+# Test --ssl sending.
+server_client_test "SSL server relays",
+["--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem"], ["--ssl"], sub {
+ my $resp;
+
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Client got \"$resp\", not \"abc\\n\"";
+};
+
+# Test that an SSL server gracefully handles non-SSL connections.
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--keep-open");
+test "SSL server handles non-SSL connections",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ syswrite($c1_in, "abc\n");
+ kill "TERM", $c1_pid;
+ waitpid $c1_pid, 0;
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl");
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+ kill "TERM", $c2_pid;
+ waitpid $c2_pid, 0;
+};
+kill_children;
+
+{
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem");
+test "SSL server doesn't block during handshake",
+sub {
+ my $resp;
+
+ # Connect without SSL so the handshake isn't completed.
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl");
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server is still accepting connections.";
+};
+kill_children;
+}
+
+{
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--keep-open");
+test "SSL server doesn't block during handshake(--keep-open)",
+sub {
+ my $resp;
+
+ # Connect without SSL so the handshake isn't completed.
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl");
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+}
+{
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--exec","$PERL -e \$|=1;while(<>)\{tr/a-z/A-Z/;print\}", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--keep-open");
+test "SSL --exec server doesn't block during handshake",
+sub {
+ my $resp;
+
+ # Connect without SSL so the handshake isn't completed.
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl");
+ syswrite($c2_in, "abc\n");
+
+ $resp = timeout_read($c2_out);
+ $resp eq "ABC\n" or die "Client2 got \"$resp\", not \"ABC\\n\"";
+};
+kill_children;
+}
+
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem");
+test "SSL verification, correct domain name",
+sub {
+ my $resp;
+
+ ($c_pid, $c_out, $c_in) = ncat("localhost", $PORT, "--ssl-verify", "--ssl-trustfile", "test-cert.pem");
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp or die "Read timeout";
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem");
+test "SSL verification, wrong domain name",
+sub {
+ my $resp;
+
+ # Use the IPv6 address as an alternate name that doesn't match the one
+ # on the certificate.
+ ($c_pid, $c_out, $c_in) = ncat($IPV6_ADDR, $PORT, "-6", "--ssl-verify", "--ssl-trustfile", "test-cert.pem");
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server got \"$resp\" when verification should have failed";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--ssl");
+test "SSL verification, no server cert",
+sub {
+ my $resp;
+
+ ($c_pid, $c_out, $c_in) = ncat("localhost", $PORT, "--ssl-verify", "--ssl-trustfile", "test-cert.pem");
+ syswrite($c_in, "abc\n");
+ $resp = timeout_read($s_out);
+ !$resp or die "Server got \"$resp\" when verification should have failed";
+};
+kill_children;
+
+# Test --max-conns.
+($s_pid, $s_out, $s_in) = ncat_server("--keep-open", "--max-conns", "1");
+test "--keep-open server keeps connection count properly.",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ kill "TERM", $c1_pid;
+ waitpid $c1_pid, 0;
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--broker", "--max-conns", "1");
+test "--broker server keeps connection count properly.",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ kill "TERM", $c1_pid;
+ waitpid $c1_pid, 0;
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client();
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Second client got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--keep-open", "--max-conns", "1");
+test "SSL --keep-open server keeps connection count properly.",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ kill "TERM", $c1_pid;
+ waitpid $c1_pid, 0;
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl");
+ syswrite($c2_in, "abc\n");
+ $resp = timeout_read($s_out);
+ $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--broker", "--max-conns", "1");
+test "SSL --broker server keeps connection count properly.",
+sub {
+ my $resp;
+
+ my ($c1_pid, $c1_out, $c1_in) = ncat_client();
+ syswrite($c1_in, "abc\n");
+ kill "TERM", $c1_pid;
+ waitpid $c1_pid, 0;
+
+ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl");
+ syswrite($s_in, "abc\n");
+ $resp = timeout_read($c2_out);
+ $resp eq "abc\n" or die "Second client got \"$resp\", not \"abc\\n\"";
+};
+kill_children;
+
+# expand IPv6
+sub ipv6_expand {
+ local($_) = shift;
+ s/^:/0:/;
+ s/:$/:0/;
+ s/(^|:)([^:]{1,3})(?=:|$)/$1.substr("0000$2", -4)/ge;
+ my $c = tr/:/:/;
+ s/::/":".("0000:" x (8-$c))/e;
+ return $_;
+}
+sub socks5_auth {
+ my ($pid,$code);
+ my $buf="";
+ my @Barray;
+ my $auth_data = shift;
+ my $ipvx = shift;
+ my $dest_addr = shift;
+ my $passed = 0;
+
+ my $username= "";
+ my $passwd= "";
+ my $recv_addr = "";
+ my $recv_port;
+
+ my ($pf,$s_addr);
+
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ if ($ipvx eq -4) {
+ $pf = PF_INET;
+ $s_addr = sockaddr_in($PROXY_PORT, INADDR_ANY);
+ } else {
+ $pf = PF_INET6;
+ $s_addr = sockaddr_in6($PROXY_PORT, inet_pton(PF_INET6, "::1"));
+ }
+
+
+ socket(SOCK, $pf, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, $s_addr) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("--proxy-type", "socks5", "--proxy", "localhost:$PROXY_PORT", @$auth_data, $ipvx, $dest_addr, $PORT);
+
+ accept(S, SOCK) or die "Client not connected";
+ binmode(S);
+ sysread(S, $buf, 10) or die "Connection closed";
+
+ @Barray = map hex($_), unpack("H*", $buf) =~ /(..)/g;
+ die "wrong request format" if scalar(@Barray) < 3;
+ die "wrong protocol version" if $Barray[0] != 5;
+
+ if(scalar(@$auth_data) > 0) {
+ # subnegotiation for authentication
+ for(my $i=2; $i < scalar(@Barray); $i++) {
+ if($Barray[$i] == 2) {
+ $passed = 1;
+ }
+ }
+
+ die "Client did not sent required authentication method x02" if $passed == 0;
+
+
+ send(S, "\x05\x02",0) or die "Send: Connection closed";
+ sysread(S, $buf, $BUFSIZ) or die "Read: Connection closed";
+
+ @Barray = map hex($_), unpack("H*", $buf) =~ /(..)/g;
+ die "wrong request format - small length" if scalar(@Barray) < 5;
+ die "wrong request format - wrong version" if $Barray[0] != 1;
+ die "wrong request format - username legth longer then packet size"
+ if $Barray[1] >= scalar(@Barray);
+
+ # get username
+ for (my $i=2; $i < $Barray[1]+2; $i++) {
+ $username .= chr($Barray[$i]);
+ }
+
+ #get password
+ for (my $i=3+$Barray[1]; $i < scalar(@Barray); $i++) {
+ $passwd .= chr($Barray[$i]);
+ }
+
+ if ($username ne "vasek" or $passwd ne "admin") {
+ send(S, "\x01\x11", 0);
+ # do not close connection - we can check if client try continue
+ } else {
+ send(S, "\x01\x00",0);
+ }
+ } else {
+ # no authentication
+ send(S, "\x05\x00",0) or die "Send: Connection closed";
+
+ }
+
+ sysread(S, $buf, $BUFSIZ) or die "Read: connection closed";
+
+ @Barray = map hex($_), unpack("H*", $buf) =~ /(..)/g;
+ die "wrong request length format" if scalar(@Barray) < 10;
+ die "wrong protocol version after success authentication" if $Barray[0] != 5;
+ die "expected connect cmd" if $Barray[1] != 1;
+
+ if($Barray[3] == 1) {
+ # IPv4
+
+ $recv_addr = $Barray[4] .".". $Barray[5] .".". $Barray[6] .".". $Barray[7];
+ die "received wrong destination IPv4" if $recv_addr ne $dest_addr;
+ } elsif ($Barray[3] == 4) {
+ #IPv6
+
+ for(my $i=4; $i<20;$i++) {
+ if($i > 4 and $i % 2 == 0) {
+ $recv_addr .= ":";
+ }
+ $recv_addr .= sprintf("%02X",$Barray[$i]);
+ }
+
+ die "received wrong destination IPv6" if $recv_addr ne ipv6_expand($dest_addr);
+ } elsif ($Barray[3] == 3) {
+ # domaint name
+
+ for my $i (@Barray[5..(scalar(@Barray)-3)]) {
+ $recv_addr .= chr($i);
+ }
+ die "received wrong destination domain name" if $recv_addr ne $dest_addr;
+ die "received wrong length of domain name" if length($recv_addr) != $Barray[4];
+ } else {
+ die "unknown ATYP: $Barray[3]";
+ }
+
+ $recv_port = $Barray[-2]*256 + $Barray[-1];
+ die "received wrong destination port" if $recv_port ne $PORT;
+
+ send(S, "\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00", 0);
+
+ # check if connection is still open
+ syswrite($c_in, "abc\n");
+ sysread(S, $buf, 10) or die "Connection closed";
+
+
+ close(S);
+ close(SOCK);
+};
+
+
+test "SOCKS5 client, server require auth username/password (access allowed), IPv4",
+ sub { socks5_auth(["--proxy-auth","vasek:admin"], "-4", "127.0.0.1"); };
+kill_children;
+
+test "SOCKS5 client, server require auth username/password (access allowed), IPv6",
+ sub { socks5_auth(["--proxy-auth","vasek:admin"], "-6", "::1"); };
+kill_children;
+
+test "SOCKS5 client, server require auth username/password (access allowed), domain",
+ sub { socks5_auth(["--proxy-auth","vasek:admin"], "-4", "www.seznam.cz"); };
+kill_children;
+
+test "SOCKS5 client, server allows connection - no auth",
+ sub { socks5_auth([], "-4", "127.0.0.1")};
+kill_children;
+{
+local $xfail = 1;
+ test "SOCKS5 client, server require auth username/password (access denied)",
+ sub { socks5_auth(["--proxy-auth","klara:admin"], "-4", "127.0.0.1"); };
+ kill_children;
+
+ test "SOCKS5 client, server require auth username/password (too long login)",
+ sub { socks5_auth(["--proxy-auth",'monika' x 100 . ':admindd'], "-4", "127.0.0.1");};
+ kill_children;
+}
+
+{
+local $xfail = 1;
+test "SOCKS5 client, server sends short response",
+sub {
+ my ($pid,$code);
+ my $buf="";
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, sockaddr_in($PROXY_PORT, INADDR_ANY)) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-4","--proxy-type", "socks5", "--proxy", "$HOST:$PROXY_PORT", "127.0.0.1", $PORT);
+
+ accept(S, SOCK) or die "Client not connected";
+ binmode(S);
+ sysread(S, $buf, 10) or die "Connection closed";
+ # not important received data now,
+ # when we know that's ok from test above
+
+ # we need O_NONBLOCK for read/write actions else
+ # client block us until we kill process manually
+ fcntl(S, F_SETFL, O_NONBLOCK) or
+ die "Can't set flags for the socket: $!\n";
+ send(S, "\x05", 0) or die "Send: Connection closed";
+
+ sysread(S, $buf, $BUFSIZ) or die "Connection closed";
+
+ close(S);
+ close(SOCK);
+};
+kill_children;
+}
+
+{
+local $xfail = 1;
+test "SOCKS5 client, server sends no acceptable auth method",
+sub {
+ my ($pid,$code);
+ my $buf="";
+ my ($my_addr,$recv_addr,$recv_port);
+
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, sockaddr_in($PROXY_PORT, INADDR_ANY)) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-4","--proxy-type", "socks5", "--proxy", "$HOST:$PROXY_PORT", "127.0.0.1", $PORT);
+
+ accept(S, SOCK) or die "Client not connected";
+ binmode(S);
+ sysread(S, $buf, 10) or die "Connection closed";
+
+ send(S, "\x05\xFF",0) or die "Send: Connection closed";
+ sysread(S, $buf, $BUFSIZ) or die "Connection closed";
+
+ close(S);
+ close(SOCK);
+};
+kill_children;
+}
+
+{
+ local $xfail = 1;
+test "SOCKS5 client, server sends unknown code",
+ sub {
+ my ($pid,$code);
+ my $buf="";
+ my ($my_addr,$recv_addr,$recv_port);
+
+ local $SIG{CHLD} = sub { };
+ local *SOCK;
+ local *S;
+
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp")) or die;
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die;
+ bind(SOCK, sockaddr_in($PROXY_PORT, INADDR_ANY)) or die;
+ listen(SOCK, 1) or die;
+
+ my ($c_pid, $c_out, $c_in) = ncat("-4","--proxy-type", "socks5", "--proxy", "$HOST:$PROXY_PORT", "127.0.0.1", $PORT);
+
+ accept(S, SOCK) or die "Client not connected";
+ binmode(S);
+ sysread(S, $buf, 10) or die "Connection closed";
+
+ send(S, "\x05\xAA",0) or die "Send: Connection closed";
+ sysread(S, $buf, $BUFSIZ) or die "Connection closed";
+
+ close(S);
+ close(SOCK);
+ };
+ kill_children;
+}
+
+for my $count (0, 1, 10) {
+ max_conns_test_tcp_sctp_ssl("--max-conns $count --keep-open", ["--keep-open"], [], $count);
+}
+
+for my $count (0, 1, 10) {
+ max_conns_test_tcp_ssl("--max-conns $count --broker", ["--broker"], [], $count);
+}
+
+max_conns_test_all("--max-conns 0 --keep-open with exec", ["--keep-open", "--exec", "$CAT"], [], 0);
+for my $count (1, 10) {
+ max_conns_test_multi(["tcp", "sctp", "udp xfail", "tcp ssl", "sctp ssl"],
+ "--max-conns $count --keep-open with exec", ["--keep-open", "--exec", "$CAT"], [], $count);
+}
+
+# Tests for zero byte option.
+
+($s_pid, $s_out, $s_in) = ncat_server();
+test "-z client with Connect success exit code (tcp)",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+
+ my ($c_pid, $c_out, $c_in) = ncat_client("-z");
+
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die "$pid != $c_pid";
+ $code = $? >> 8;
+ $code == 0 or die "Exit code was $code, not 0";
+};
+kill_children;
+
+($s_pid, $s_out, $s_in) = ncat_server("--udp");
+test "-z client sends \"\\0\" to server and exits with success exit code (udp)",
+sub {
+ my ($resp, $pid, $code);
+ local $SIG{CHLD} = sub { };
+
+ my ($c_pid, $c_out, $c_in) = ncat_client("-z", "--udp");
+ $resp = timeout_read($s_out);
+ $resp eq "\0" or die "Server got \"$resp\", not \"\\0\" from client";
+
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die "$pid != $c_pid";
+ $code = $? >> 8;
+ $code == 0 or die "Exit code was $code, not 0";
+};
+kill_children;
+
+test "-z client with connection refused exit code (tcp)",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ ($c_pid, $c_out, $c_in) = ncat_client("-z");
+
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die "$pid != $c_pid";
+ $code = $? >> 8;
+ $code == 1 or die "Exit code was $code, not 1";
+};
+kill_children;
+
+test "-z client with connection refused exit code (udp)",
+sub {
+ my ($pid, $code);
+ local $SIG{CHLD} = sub { };
+ ($c_pid, $c_out, $c_in) = ncat_client("-z", "--udp");
+
+ do {
+ $pid = waitpid($c_pid, 0);
+ } while ($pid > 0 && $pid != $c_pid);
+ $pid == $c_pid or die "$pid != $c_pid";
+ $code = $? >> 8;
+ $code == 1 or die "Exit code was $code, not 1";
+};
+kill_children;
+
+# Without --keep-open, just make sure that --max-conns 0 disallows any connection.
+max_conns_test_all("--max-conns 0", [], [], 0);
+max_conns_test_all("--max-conns 0 with exec", ["--exec", "$CAT"], [], 0);
+
+print "$num_expected_failures expected failures.\n" if $num_expected_failures > 0;
+print "$num_unexpected_passes unexpected passes.\n" if $num_unexpected_passes > 0;
+print "$num_failures unexpected failures.\n";
+print "$num_tests tests total.\n";
+
+if ($num_failures + $num_unexpected_passes == 0) {
+ exit 0;
+} else {
+ exit 1;
+}
diff --git a/ncat/test/test-addrset.sh b/ncat/test/test-addrset.sh
new file mode 100755
index 0000000..819afe2
--- /dev/null
+++ b/ncat/test/test-addrset.sh
@@ -0,0 +1,333 @@
+#!/bin/sh
+
+# Automated tests for the addrset functions in ncat_hostmatch.c. This
+# program runs various addresses against different host specifications
+# and checks that the output is what is expected.
+
+ADDRSET=./addrset
+TESTS=0
+TEST_PASS=0
+TEST_FAIL=0
+
+# Takes as arguments a whitespace-separated list of host specifications
+# and a space-separated list of expected matching addresses. Tests hosts
+# are passed in stdin.
+test_addrset() {
+ specs=$1
+ expected=$2
+ result=$($ADDRSET $specs)
+ ret=$?
+ # Change newlines to spaces.
+ result=$(echo $result)
+ TESTS=$(expr $TESTS + 1);
+ if [ "$ret" != "0" ]; then
+ echo "FAIL $specs: $ADDRSET returned $ret."
+ TEST_FAIL=$(expr $TEST_FAIL + 1)
+ elif [ "$result" != "$expected" ]; then
+ echo "FAIL $specs: \"$result\" !="
+ echo " \"$expected\"."
+ TEST_FAIL=$(expr $TEST_FAIL + 1)
+ else
+ echo "PASS $specs"
+ TEST_PASS=$(expr $TEST_PASS + 1)
+ fi
+}
+
+# Takes as an argument a host specification with invalid syntax. The
+# test passes if addrset returns with a non-zero exit code.
+expect_fail() {
+ specs=$1
+ $ADDRSET $specs < /dev/null 2> /dev/null
+ ret=$?
+ TESTS=$(expr $TESTS + 1)
+ if [ "$ret" = "0" ]; then
+ echo "FAIL $ADDRSET $specs was expected to fail, but didn't."
+ TEST_FAIL=$(expr $TEST_FAIL + 1)
+ else
+ echo "PASS $specs"
+ TEST_PASS=$(expr $TEST_PASS + 1)
+ fi
+}
+
+# seq replacement for systems without seq.
+seq() {
+ low=$1
+ high=$2
+ while [ $low -le $high ]; do
+ echo $low
+ low=$(expr $low + 1)
+ done
+}
+
+# No specifications.
+test_addrset "" "" <<EOF
+1.1.1.1
+2.2.2.2
+EOF
+
+# IPv4 address equality.
+(for a in `seq 0 255`; do echo 192.168.0.$a; done) \
+ | test_addrset "192.168.0.0" "192.168.0.0"
+
+# IPv6 address equality.
+(for a in `seq 0 255`; do printf "FE80:0000:0000:0000:0202:E3%02X:FE14:1102\n" $a; done) \
+ | test_addrset "fe80::202:e3ff:fe14:1102" "FE80:0000:0000:0000:0202:E3FF:FE14:1102"
+
+# IPv4 and IPv6 at once.
+test_addrset "1.2.3.4 1:2:3::4" "1.2.3.4 1:2:3::4 1:2:3:0::4" <<EOF
+0.0.0.0
+1.2.3.4
+::
+1:2:3::4
+1:2:3:0::4
+f:e:d:c:b::a
+EOF
+
+# Simple IPv4 range.
+(for a in `seq 0 255`; do echo 192.168.0.$a; done) \
+ | test_addrset "192.168.0.1-5" "192.168.0.1 192.168.0.2 192.168.0.3 192.168.0.4 192.168.0.5"
+
+# Addresses outside IPv4 range.
+(for a in `seq 0 255`; do echo 192.168.0.$a; done) \
+ | test_addrset "192.168.1.1-5" ""
+
+# One-element range.
+(for a in `seq 0 255`; do echo 192.168.0.$a; done) \
+ | test_addrset "192.168-168.0.1" "192.168.0.1"
+
+# Double IPv4 ranges.
+(for a in `seq 0 255`; do echo 192.168.$a.$a; done) \
+ | test_addrset "192.168.3-8.1-5" "192.168.3.3 192.168.4.4 192.168.5.5"
+
+# Half-open range.
+(for a in `seq 0 255`; do echo 192.168.$a.0; done) \
+ | test_addrset "192.168.-3.0" "192.168.0.0 192.168.1.0 192.168.2.0 192.168.3.0"
+
+# Half-open range.
+(for a in `seq 0 255`; do echo 192.168.$a.0; done) \
+ | test_addrset "192.168.252-.0" "192.168.252.0 192.168.253.0 192.168.254.0 192.168.255.0"
+
+# Full-open range.
+test_addrset "192.168.-.0" "192.168.0.0 192.168.10.0 192.168.100.0 192.168.255.0" <<EOF
+192.168.0.0
+192.168.10.0
+192.168.100.0
+192.168.255.0
+192.168.0.1
+1.2.3.4
+EOF
+
+# Comma ranges.
+(for a in `seq 0 255`; do echo 192.168.0.$a; done) \
+ | test_addrset "192.168.0.2,3,5,7,11" "192.168.0.2 192.168.0.3 192.168.0.5 192.168.0.7 192.168.0.11"
+
+# Comma ranges combined with dash ranges.
+test_addrset "192-200,202.0.0.1,3-5" "202.0.0.1 202.0.0.5 192.0.0.3" <<EOF
+201.0.0.1
+202.0.0.1
+202.0.0.5
+202.0.0.6
+192.0.0.3
+EOF
+
+# Wildcard octet.
+test_addrset "192.168.0.*" "192.168.0.3 192.168.0.200 192.168.0.255" <<EOF
+1.2.3.4
+192.168.0.3
+192.168.0.200
+192.161.0.0
+192.168.0.255
+EOF
+
+# Two wildcards.
+test_addrset "192.*.0.*" "192.168.0.3 192.168.0.200 192.161.0.0 192.168.0.255" <<EOF
+1.2.3.4
+192.168.0.3
+192.168.0.200
+192.161.0.0
+192.168.0.255
+EOF
+
+# Many range types.
+test_addrset "*.1-10,12.*.4-5,6,7" "1.2.3.4 4.5.6.7 70.10.4.4" <<EOF
+1.2.3.4
+4.5.6.7
+70.11.4.4
+70.10.4.4
+255.255.255.255
+EOF
+
+# IPv4 CIDR netmask.
+test_addrset "192.168.0.0/24" "192.168.0.5 192.168.0.90" <<EOF
+192.168.0.5
+192.168.0.90
+192.168.1.5
+1.2.3.4
+EOF
+
+# /32 netmask.
+test_addrset "1.2.3.4/32" "1.2.3.4" <<EOF
+192.168.0.10
+192.168.0.90
+192.168.1.5
+1.2.3.4
+EOF
+
+# /0 netmask.
+test_addrset "5.5.5.5/0" "0.0.0.0 123.123.123.123 255.255.255.255" <<EOF
+0.0.0.0
+123.123.123.123
+255.255.255.255
+EOF
+
+# IPv4 range combined with CIDR netmask.
+test_addrset "1-5.1-5.1-5.1-5/28" "1.2.3.4 1.2.3.5 1.2.3.7 1.2.3.0" <<EOF
+1.2.3.4
+1.2.3.5
+6.1.2.3
+1.2.3.7
+1.2.3.0
+EOF
+
+# Exhaustive listing of a range with netmask.
+(for a in `seq 0 255`; do echo 192.168.0.$a; done) \
+ | test_addrset "192.168.0.5,30,191/30" \
+"192.168.0.4 192.168.0.5 192.168.0.6 192.168.0.7 192.168.0.28 192.168.0.29 192.168.0.30 192.168.0.31 192.168.0.188 192.168.0.189 192.168.0.190 192.168.0.191"
+
+# Exhaustive listing of a range with netmask, different octet.
+(for a in `seq 0 255`; do echo 192.168.$a.0; done) \
+ | test_addrset "192.168.5,30,191.0/22" \
+"192.168.4.0 192.168.5.0 192.168.6.0 192.168.7.0 192.168.28.0 192.168.29.0 192.168.30.0 192.168.31.0 192.168.188.0 192.168.189.0 192.168.190.0 192.168.191.0"
+
+# IPv6 CIDR netmask.
+test_addrset "1:2::0003/120" "1:2::3 1:2::0 1:2::ff" <<EOF
+1:2::3
+1:2::0
+1:2::ff
+1:2::1ff
+1:3::3
+EOF
+
+# IPv6 CIDR netmask.
+test_addrset "1:2::3:4:5/95" "1:2::3:4:5 1:2::2:0:0 1:2::3:ffff:ffff" <<EOF
+1:2::3:4:5
+1:2::1:ffff:ffff
+1:2::2:0:0
+1:2::3:ffff:ffff
+1:2::4:0:0
+1:3::3
+EOF
+
+# IPv6 CIDR netmask.
+test_addrset "11::2/15" "11::2:3:4:5 10::1 11:ffff:ffff:ffff:ffff:ffff:ffff:ffff" <<EOF
+11::2:3:4:5
+9:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+10::1
+11:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+12::0
+EOF
+
+# /128 netmask.
+test_addrset "1:2::0003/128" "1:2::3" <<EOF
+1:2::3
+1:2::0
+1:2::ff
+1:2::1ff
+1:3::3
+EOF
+
+# /0 netmask.
+test_addrset "1:2::0003/0" "1:2::3 1:2::0 1:2::ff 1:2::1ff 1:3::3 ff::00" <<EOF
+1:2::3
+1:2::0
+1:2::ff
+1:2::1ff
+1:3::3
+ff::00
+EOF
+
+# Name lookup.
+test_addrset "scanme.nmap.org" "scanme.nmap.org" <<EOF
+1:2::3:4
+1.2.3.4
+scanme.nmap.org
+EOF
+
+# Name lookup combined with CIDR netmask.
+test_addrset "scanme.nmap.org/30" "scanme.nmap.org" <<EOF
+1:2::3:4
+1.2.3.4
+scanme.nmap.org
+EOF
+
+# Name lookup combined with /0 CIDR netmask.
+test_addrset "scanme.nmap.org/0" "1.2.3.4 scanme.nmap.org" <<EOF
+1.2.3.4
+scanme.nmap.org
+EOF
+
+expect_fail "."
+expect_fail "-"
+expect_fail ","
+expect_fail "1.2.3.4,"
+expect_fail ",1.2.3.4"
+expect_fail "1.2.3.4.5"
+expect_fail "1:2:3:4:5:6:7:8:9"
+expect_fail "11::22::33"
+
+expect_fail "256.256.256.256"
+expect_fail "FFFFF::FFFFF"
+
+# Backwards range.
+expect_fail "10-5.2.3.4"
+
+expect_fail "*10.10.10.10"
+expect_fail "5-10-15.10.10.10"
+expect_fail "-10-15.10.10.10"
+expect_fail "10-15-.10.10.10"
+expect_fail ",.6.7.8"
+expect_fail "5,.5.5.5"
+expect_fail ",5.5.5.5"
+expect_fail ",5.5.5.5"
+expect_fail "+1.2.3.4"
+expect_fail "+1.+2.+3.+4"
+
+expect_fail "1.2.3.4/"
+expect_fail "1.2.3.4/33"
+expect_fail "1.2.3.4/+24"
+expect_fail "1.2.3.4/24abc"
+expect_fail "1.2.3.4//24"
+expect_fail "1.2.3.4/-0"
+expect_fail "FF::FF/129"
+
+# Specifications whose behavior is unspecified but not important; that
+# is, if the behavior of these changed it wouldn't matter much to users.
+
+# test_addrset "01.02.03.04" "1.2.3.4" <<EOF
+# 1.2.3.4
+# 5.6.7.8
+# EOF
+#
+# test_addrset "1" "0.0.0.1" <<EOF
+# 1.0.0.0
+# 0.0.0.1
+# 1.2.3.4
+# EOF
+#
+# test_addrset "1.2" "1.0.0.2" <<EOF
+# 1.0.0.2
+# 1.2.0.0
+# 1.2.3.4
+# EOF
+#
+# test_addrset "1.2.3" "1.2.0.3" <<EOF
+# 1.0.2.3
+# 1.2.0.3
+# 1.2.3.4
+# EOF
+
+if [ "$TEST_FAIL" -gt 0 ]; then
+ echo "$TEST_PASS / $TESTS passed, $TEST_FAIL failed"
+ exit 1
+fi
+echo "$TEST_PASS / $TESTS passed"
diff --git a/ncat/test/test-cert.pem b/ncat/test/test-cert.pem
new file mode 100644
index 0000000..a64fc2f
--- /dev/null
+++ b/ncat/test/test-cert.pem
@@ -0,0 +1,47 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQChGGUWUm7QUE2Z
+xBNaKuz7eSuR6LkGhhc5kzwRp4BqbUzHkdKr8glFeyP8Vmqszp+pKcdVahFE9WH3
+/mWk1Vuu8dGf6omhDwdzkqzASnSK8XDYYs8wWZycgewRkzJ2ZWqkN0MjiVnek4XV
+jcom6ZxQb000V0/rpkzcmHfzatnkSo6cIjiF/Yk886bulMFwbtQ69KPtg/7jNgPE
+N2me8nzSRW6cdBKcFR9tSJ196W5CxZzL7dUDitk+mUwghsCVhAygCUEMsAxlzZsv
+Rio6Hx5Jjaoeb3ZrWJSrQP11MNQ6aXYWHYPKFQrJlWqvmUdPNUNZA5UJg3jWZj89
+/UkTYrmLAgMBAAECggEBAIeyKNRYs4c9XWB8zWBScDSTqKPLSK+6G64f26VzVrRP
+RTGGH9M+mZixVWqk0E6n7c1sp7/HDKztlYxz+eKS5hvDDjSKN0w3gKtVjbacAPdY
+0Rk0ghnUIhujRNq5BvS8EMwq0J8Kf20BDucH/JQyi70lQ/8m3Oc+udfHhqLACrJE
+1R/8hRKasqRChA7YytC8W9KUEJHiThCVeMO5ljg+nfV3ElCnVm9WZI3YY6LjHJ5b
+xJt0XxHFK3fpwrHc+9FT8n1A2eKQhojZrfmZqMvpwqQ5tGdRfiXWYWKahnyCqQZU
+EOF4pvjtq4JCRJtdTbdO+SO6/gYIGBnSKFX6SRmCHsECgYEAzRVUpQkvyRKVLpp6
+vy4d3D1bmeQJETorpteQWH6u8mJT1SiTxr4DTjcK1FSwNhT1L5YWuaIbcy5N9cRc
+CVCOx9ynVpvlmVGXbGWCpO8thC8kHS4C0o6meN7Hdc4XlvhnsP6lXVx0+IiYkO97
+DAkcNfYq9VCCfwxShSint0u6gkMCgYEAyRdGypoOoW8bj5oHYKZWn6nUTvUeQYI4
+AbrpKvmyHziy7A3nDXR20bFsZLzwIx5cWXC2IgxnV67PxJBKx6zC8eqGVQvtOXoL
++EZclDx7X/qPuOV9cGQC0g90+vEMtho7Y0+OOMjnX4Mp5Mxe0MKsHBVPJXV+J9au
+HzbEQgS+axkCgYAfY8dr50cQIK8CzhRBlN5vKlkN6fBVWbD6vX3TfbhrUw9/zdEo
+l0bMPvKCY2ABNx38JZ3e1egbrheyqVZo+pKQFr7qK7xtxiZGKhdgBVfTJqABc1xt
+O/ZRA9BFwMCtk+HTHnbTHmas78NiU7VitzZBMCeNGsCOj6VFyl45WPb4HwKBgFlK
+0a9zOx3qBVX9slrzYbGiKtkotNen6BC0m4buu25rsd9pyPhLh9tTKmuNDiC6AY3h
+o654zYa85BtHaz1A9IuRdTbchekozZngPInCVZJn41vZ45p9flcib/JiCR/vhAF0
+ORXz9/GMf5TOPyf52Yza1XsvseYkyMqpefpKuvc5AoGBALdY8Eq/GQzHCWQtGnrC
+J1FF9FdmnRFx3eoCktFQHrYTXg0NDAUykTENoHTHiXpm8AGZIe2amMQdFxIO6xQl
+mb9QDUWe9pw0CkDIjrcqq5qSoZP7fkdKxPDrM4nK78Mxl7TiZiEZ66LNV4L3DL3y
+Icb8eZxcfAFT0vH4cAjIgjG3
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIDIzCCAgugAwIBAgIJANerJEEww4jYMA0GCSqGSIb3DQEBCwUAMCgxEjAQBgNV
+BAoMCW5jYXQtdGVzdDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIyMDkyMjAxMzEz
+MFoXDTIyMTAyMjAxMzEzMFowKDESMBAGA1UECgwJbmNhdC10ZXN0MRIwEAYDVQQD
+DAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQChGGUW
+Um7QUE2ZxBNaKuz7eSuR6LkGhhc5kzwRp4BqbUzHkdKr8glFeyP8Vmqszp+pKcdV
+ahFE9WH3/mWk1Vuu8dGf6omhDwdzkqzASnSK8XDYYs8wWZycgewRkzJ2ZWqkN0Mj
+iVnek4XVjcom6ZxQb000V0/rpkzcmHfzatnkSo6cIjiF/Yk886bulMFwbtQ69KPt
+g/7jNgPEN2me8nzSRW6cdBKcFR9tSJ196W5CxZzL7dUDitk+mUwghsCVhAygCUEM
+sAxlzZsvRio6Hx5Jjaoeb3ZrWJSrQP11MNQ6aXYWHYPKFQrJlWqvmUdPNUNZA5UJ
+g3jWZj89/UkTYrmLAgMBAAGjUDBOMB0GA1UdDgQWBBSnNuK9hPnalhF9DrnQ3B23
+1h8slzAfBgNVHSMEGDAWgBSnNuK9hPnalhF9DrnQ3B231h8slzAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAQm68Dk8jc3jGkvJSLbXpC6M3FJbCS2wD5
+rmf51uEoeqzoCnlWWLlX5PvZw9cpS93SfqhNOIulP0sg/sXaCZrfQ5WbrezjR+vT
+MrY6ZyaIMCEX2D+9mpkNdrP/s5k2Rkz2ZZa6YComXWAnEY2N1eIHr2BLiP/gL41G
+GGuS+0SopoWSgINoYLzE+X0dMVsrS01u41056BAnFTv5IQjygQVd5673ras82a3N
+41G+2CKxAtbZ3Bdgz4LJ0pzSVWRwLm2mCqn9eabMtJFjg6v5AlOBgbOHdsLgkMkf
+GnjLBSbr9t37MFFJWK7JFNXfH9MYOrsiaEK1/+N0NQXF733a6fbP
+-----END CERTIFICATE-----
diff --git a/ncat/test/test-cmdline-split.c b/ncat/test/test-cmdline-split.c
new file mode 100644
index 0000000..faaa555
--- /dev/null
+++ b/ncat/test/test-cmdline-split.c
@@ -0,0 +1,100 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static long test_count = 0;
+static long success_count = 0;
+char **cmdline_split(const char *cmdexec);
+
+int test_cmdline(const char *line, const char **target_args)
+{
+ char **cmd_args;
+ int args_match = 1;
+
+ test_count++;
+
+ cmd_args = cmdline_split(line);
+
+ /*
+ * Make sure that all of the target arguments are have been extracted
+ * by cmdline_split.
+ */
+ while (*cmd_args && *target_args) {
+ if (strcmp(*cmd_args, *target_args)) {
+ args_match = 0;
+ break;
+ }
+ cmd_args++;
+ target_args++;
+ }
+ if ((*cmd_args != NULL) || (*target_args != NULL)) {
+ /*
+ * One of the argument list had more arguments than the other.
+ * Therefore, they do not match
+ */
+ args_match = 0;
+ }
+
+ if (args_match) {
+ success_count++;
+ printf("PASS '%s'\n", line);
+ return 1;
+ } else {
+ printf("FAIL '%s'\n", line);
+ return 0;
+ }
+}
+
+int test_cmdline_fail(const char *line)
+{
+ char **cmd_args;
+
+ test_count++;
+
+ cmd_args = cmdline_split(line);
+
+ if (*cmd_args == NULL) {
+ success_count++;
+ printf("PASS '%s'\n", line);
+ return 1;
+ } else {
+ printf("PASS '%s'\n", line);
+ return 0;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ struct {
+ const char *cmdexec;
+ const char *args[10];
+ } TEST_CASES[] = {
+ {"ncat -l -k", {"ncat", "-l", "-k", NULL}},
+ {"ncat localhost 793", {"ncat", "localhost", "793", NULL}},
+ {"./ncat scanme.nmap.org 80", {"./ncat", "scanme.nmap.org", "80",
+ NULL}},
+ {"t\\ p\\ s hello world how are you?", {"t p s", "hello", "world", "how", "are",
+ "you?", NULL}},
+ {"t\\ p\\ s hello world how\\ are you?", {"t p s", "hello", "world", "how are",
+ "you?", NULL}},
+ {"ncat\\", {"ncat", NULL}},
+ {"a\\nb", {"anb", NULL}},
+ {" ncat a ", {"ncat", "a", NULL}},
+ {"\\ncat \\a", {"ncat", "a", NULL}},
+ {"ncat\\\\ a", {"ncat\\", "a", NULL}},
+ {"ncat\\", {"ncat", NULL}},
+ {"ncat\\ \\", {"ncat ", NULL}},
+ };
+
+ for (i = 0; i < sizeof(TEST_CASES)/sizeof(TEST_CASES[0]); i++) {
+ test_cmdline(TEST_CASES[i].cmdexec,
+ TEST_CASES[i].args);
+ }
+
+ test_cmdline_fail("");
+ printf("%ld / %ld tests passed.\n", success_count, test_count);
+ return success_count == test_count ? 0 : 1;
+}
diff --git a/ncat/test/test-environment.lua b/ncat/test/test-environment.lua
new file mode 100644
index 0000000..bae265b
--- /dev/null
+++ b/ncat/test/test-environment.lua
@@ -0,0 +1,13 @@
+#!/usr/bin/lua
+
+function print_env(v)
+ print(("%s=%s"):format(v, os.getenv(v)))
+end
+
+print_env("NCAT_REMOTE_ADDR")
+print_env("NCAT_REMOTE_PORT")
+
+print_env("NCAT_LOCAL_ADDR")
+print_env("NCAT_LOCAL_PORT")
+
+print_env("NCAT_PROTO")
diff --git a/ncat/test/test-environment.sh b/ncat/test/test-environment.sh
new file mode 100755
index 0000000..e78a220
--- /dev/null
+++ b/ncat/test/test-environment.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# Print the contents of all environment variables set by Ncat.
+
+echo "NCAT_REMOTE_ADDR=$NCAT_REMOTE_ADDR"
+echo "NCAT_REMOTE_PORT=$NCAT_REMOTE_PORT"
+
+echo "NCAT_LOCAL_ADDR=$NCAT_LOCAL_ADDR"
+echo "NCAT_LOCAL_PORT=$NCAT_LOCAL_PORT"
+
+echo "NCAT_PROTO=$NCAT_PROTO"
diff --git a/ncat/test/test-uri.c b/ncat/test/test-uri.c
new file mode 100644
index 0000000..eb6f5df
--- /dev/null
+++ b/ncat/test/test-uri.c
@@ -0,0 +1,129 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ncat_core.h"
+#include "http.h"
+
+static long test_count = 0;
+static long success_count = 0;
+
+/* Check strings or null pointers for equality. */
+int nullstreq(const char *s, const char *t)
+{
+ if (s == NULL) {
+ if (t == NULL)
+ return 1;
+ else
+ return 0;
+ } else {
+ if (t == NULL)
+ return 0;
+ else
+ return strcmp(s, t) == 0;
+ }
+}
+
+int test_uri(const char *uri_s, const char *scheme, const char *host, int port, const char *path)
+{
+ struct uri uri;
+ int scheme_match, host_match, port_match, path_match;
+
+ test_count++;
+
+ if (uri_parse(&uri, uri_s) == NULL) {
+ printf("FAIL %s: couldn't parse.\n", uri_s);
+ return 0;
+ }
+
+ scheme_match = nullstreq(uri.scheme, scheme);
+ host_match = nullstreq(uri.host, host);
+ port_match = uri.port == port;
+ path_match = nullstreq(uri.path, path);
+
+ if (scheme_match && host_match && port_match && path_match) {
+ printf("PASS %s\n", uri_s);
+ uri_free(&uri);
+ success_count++;
+ return 1;
+ } else {
+ printf("FAIL %s:", uri_s);
+ if (!scheme_match)
+ printf(" \"%s\" != \"%s\".", uri.scheme, scheme);
+ if (!host_match)
+ printf(" \"%s\" != \"%s\".", uri.host, host);
+ if (!port_match)
+ printf(" %d != %d.", uri.port, port);
+ if (!path_match)
+ printf(" \"%s\" != \"%s\".", uri.path, path);
+ printf("\n");
+ uri_free(&uri);
+ return 0;
+ }
+}
+
+int test_fail(const char *uri_s)
+{
+ struct uri uri;
+
+ test_count++;
+
+ if (uri_parse(&uri, uri_s) != NULL) {
+ uri_free(&uri);
+ printf("FAIL %s: not expected to parse.\n", uri_s);
+ return 0;
+ } else {
+ printf("PASS %s\n", uri_s);
+ success_count++;
+ return 0;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ test_uri("http://www.example.com", "http", "www.example.com", 80, "");
+
+ test_uri("HTTP://www.example.com", "http", "www.example.com", 80, "");
+ test_uri("http://WWW.EXAMPLE.COM", "http", "WWW.EXAMPLE.COM", 80, "");
+
+ test_uri("http://www.example.com:100", "http", "www.example.com", 100, "");
+ test_uri("http://www.example.com:1", "http", "www.example.com", 1, "");
+ test_uri("http://www.example.com:65535", "http", "www.example.com", 65535, "");
+ test_uri("http://www.example.com:", "http", "www.example.com", 80, "");
+ test_uri("http://www.example.com:/", "http", "www.example.com", 80, "/");
+
+ test_uri("http://www.example.com/", "http", "www.example.com", 80, "/");
+ test_uri("http://www.example.com:100/", "http", "www.example.com", 100, "/");
+
+ test_uri("http://1.2.3.4", "http", "1.2.3.4", 80, "");
+ test_uri("http://1.2.3.4:100", "http", "1.2.3.4", 100, "");
+ test_uri("http://[::ffff]", "http", "::ffff", 80, "");
+ test_uri("http://[::ffff]:100", "http", "::ffff", 100, "");
+
+ test_uri("http://www.example.com/path?query#frag", "http", "www.example.com", 80, "/path?query#frag");
+
+ test_uri("http://www.exampl%65.com", "http", "www.example.com", 80, "");
+ test_uri("http://www.exampl%6a.com", "http", "www.examplj.com", 80, "");
+ test_uri("http://www.exampl%6A.com", "http", "www.examplj.com", 80, "");
+ test_uri("http://www.exampl%2523.com", "http", "www.exampl%23.com", 80, "");
+ test_fail("http://www.example.com:%380");
+ test_uri("http://www.example.com/a%23b", "http", "www.example.com", 80, "/a%23b");
+
+ test_uri("unknown://www.example.com", "unknown", "www.example.com", -1, "");
+
+ test_uri("unknown:", "unknown", NULL, -1, "");
+
+ test_fail("");
+ test_fail("/dir/file");
+ test_fail("http://www.example.com:-1");
+ test_fail("http://www.example.com:0");
+ test_fail("http://www.example.com:65536");
+
+ /* We explicitly don't support userinfo in the authority. */
+ test_fail("http://user@www.example.com");
+ test_fail("http://user:pass@www.example.com");
+
+ printf("%ld / %ld tests passed.\n", success_count, test_count);
+
+ return success_count == test_count ? 0 : 1;
+}
diff --git a/ncat/test/test-wildcard.c b/ncat/test/test-wildcard.c
new file mode 100644
index 0000000..fe55e19
--- /dev/null
+++ b/ncat/test/test-wildcard.c
@@ -0,0 +1,626 @@
+/*
+Usage: ./test-wildcard
+
+This is a test program for the ssl_post_connect_check function. It generates
+certificates with a variety of different combinations of commonNames and
+dNSNames, then checks that matching names are accepted and non-matching names
+are rejected. The SSL transactions happen over OpenSSL BIO pairs.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "ncat_core.h"
+#include "ncat_ssl.h"
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+#include <openssl/bn.h>
+#endif
+
+#define KEY_BITS 2048
+
+static int tests_run = 0, tests_passed = 0;
+
+/* A length-delimited string. */
+struct lstr {
+ size_t len;
+ const char *s;
+};
+
+/* Make an anonymous struct lstr. */
+#define LSTR(s) { sizeof(s) - 1, (s) }
+
+/* Variable-length arrays of struct lstr are terminated with a special sentinel
+ value. */
+#define LSTR_SENTINEL { -1, NULL }
+const struct lstr lstr_sentinel = LSTR_SENTINEL;
+
+int is_sentinel(const struct lstr *name) {
+ return name->len == -1;
+}
+
+int ssl_post_connect_check(SSL *ssl, const char *hostname);
+
+static struct lstr *check(SSL *ssl, const struct lstr names[]);
+static int ssl_ctx_trust_cert(SSL_CTX *ctx, X509 *cert);
+static int gen_cert(X509 **cert, EVP_PKEY **key,
+ const struct lstr commonNames[], const struct lstr dNSNames[]);
+static void print_escaped(const char *s, size_t len);
+static void print_array(const struct lstr array[]);
+static int arrays_equal(const struct lstr a[], const struct lstr b[]);
+
+/* Returns positive on success, 0 on failure. The various arrays must be
+ NULL-terminated. */
+static int test(const struct lstr commonNames[], const struct lstr dNSNames[],
+ const struct lstr test_names[], const struct lstr expected[])
+{
+ SSL_CTX *server_ctx, *client_ctx;
+ SSL *server_ssl, *client_ssl;
+ BIO *server_bio, *client_bio;
+ X509 *cert;
+ EVP_PKEY *key;
+ struct lstr *results;
+ int need_accept, need_connect;
+ int passed;
+
+ tests_run++;
+
+ ncat_assert(gen_cert(&cert, &key, commonNames, dNSNames) == 1);
+
+ ncat_assert(BIO_new_bio_pair(&server_bio, 0, &client_bio, 0) == 1);
+
+ server_ctx = SSL_CTX_new(SSLv23_server_method());
+ ncat_assert(server_ctx != NULL);
+
+ client_ctx = SSL_CTX_new(SSLv23_client_method());
+ ncat_assert(client_ctx != NULL);
+ SSL_CTX_set_verify(client_ctx, SSL_VERIFY_PEER, NULL);
+ SSL_CTX_set_verify_depth(client_ctx, 1);
+ ssl_ctx_trust_cert(client_ctx, cert);
+
+ server_ssl = SSL_new(server_ctx);
+ ncat_assert(server_ssl != NULL);
+ SSL_set_accept_state(server_ssl);
+ SSL_set_bio(server_ssl, server_bio, server_bio);
+ ncat_assert(SSL_use_certificate(server_ssl, cert) == 1);
+ ncat_assert(SSL_use_PrivateKey(server_ssl, key) == 1);
+
+ client_ssl = SSL_new(client_ctx);
+ ncat_assert(client_ssl != NULL);
+ SSL_set_connect_state(client_ssl);
+ SSL_set_bio(client_ssl, client_bio, client_bio);
+
+ passed = 0;
+
+ need_accept = 1;
+ need_connect = 1;
+ do {
+ int rc, err;
+
+ if (need_accept) {
+ rc = SSL_accept(server_ssl);
+ err = SSL_get_error(server_ssl, rc);
+ if (rc == 1) {
+ need_accept = 0;
+ } else {
+ if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
+ printf("SSL_accept: %s \n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto end;
+ }
+ }
+ }
+ if (need_connect) {
+ rc = SSL_connect(client_ssl);
+ err = SSL_get_error(client_ssl, rc);
+ if (rc == 1) {
+ need_connect = 0;
+ } else {
+ if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
+ printf("SSL_connect: %s \n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto end;
+ }
+ }
+ }
+ } while (need_accept || need_connect);
+
+ results = check(client_ssl, test_names);
+ if (arrays_equal(results, expected)) {
+ tests_passed++;
+ passed = 1;
+ printf("PASS CN");
+ print_array(commonNames);
+ printf(" DNS");
+ print_array(dNSNames);
+ printf("\n");
+ } else {
+ printf("FAIL CN");
+ print_array(commonNames);
+ printf(" DNS");
+ print_array(dNSNames);
+ printf("\n");
+ printf(" got ");
+ print_array(results);
+ printf("\n");
+ printf("expected ");
+ print_array(expected);
+ printf("\n");
+ }
+ free(results);
+
+end:
+ X509_free(cert);
+ EVP_PKEY_free(key);
+
+ (void) BIO_destroy_bio_pair(server_bio);
+
+ SSL_CTX_free(server_ctx);
+ SSL_CTX_free(client_ctx);
+
+ SSL_free(server_ssl);
+ SSL_free(client_ssl);
+
+ return passed;
+}
+
+/* Returns a sentinel-terminated malloc-allocated array of names that match ssl
+ with ssl_post_connect_check. */
+static struct lstr *check(SSL *ssl, const struct lstr names[])
+{
+ const struct lstr *name;
+ struct lstr *results = NULL;
+ size_t size = 0, capacity = 0;
+
+ if (names == NULL)
+ return NULL;
+
+ for (name = names; !is_sentinel(name); name++) {
+ if (ssl_post_connect_check(ssl, name->s)) {
+ if (size >= capacity) {
+ capacity = (size + 1) * 2;
+ results = safe_realloc(results, (capacity + 1) * sizeof(results[0]));
+ }
+ results[size++] = *name;
+ }
+ }
+ results = safe_realloc(results, (size + 1) * sizeof(results[0]));
+ results[size] = lstr_sentinel;
+
+ return results;
+}
+
+/* Make a certificate object trusted by an SSL_CTX. I couldn't find a way to do
+ this directly, so the certificate is written in PEM format to a temporary
+ file and then loaded with SSL_CTX_load_verify_locations. Returns 1 on success
+ and 0 on failure. */
+static int ssl_ctx_trust_cert(SSL_CTX *ctx, X509 *cert)
+{
+ char name[] = "ncat-test-XXXXXX";
+ int fd;
+ FILE *fp;
+ int rc;
+
+ fd = mkstemp(name);
+ if (fd == -1)
+ return 0;
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ close(fd);
+ return 0;
+ }
+ if (PEM_write_X509(fp, cert) == 0) {
+ fclose(fp);
+ return 0;
+ }
+ fclose(fp);
+
+ rc = SSL_CTX_load_verify_locations(ctx, name, NULL);
+ if (rc == 0) {
+ fprintf(stderr, "SSL_CTX_load_verify_locations: %s \n",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+ if (unlink(name) == -1)
+ fprintf(stderr, "unlink(\"%s\"): %s\n", name, strerror(errno));
+
+ return rc;
+}
+
+static int set_dNSNames(X509 *cert, const struct lstr dNSNames[])
+{
+ STACK_OF(GENERAL_NAME) *gen_names;
+ GENERAL_NAME *gen_name;
+ X509_EXTENSION *ext;
+ const struct lstr *name;
+
+ if (dNSNames == NULL || is_sentinel(&dNSNames[0]))
+ return 1;
+
+ /* We break the abstraction here a bit because the normal way of setting
+ a list of values, using an i2v method, uses a stack of CONF_VALUE that
+ doesn't contain the length of each value. We rely on the fact that
+ the internal representation (the "i" in "i2d") for
+ NID_subject_alt_name is STACK_OF(GENERAL_NAME). */
+
+ gen_names = sk_GENERAL_NAME_new_null();
+ if (gen_names == NULL)
+ return 0;
+
+ for (name = dNSNames; !is_sentinel(name); name++) {
+ gen_name = GENERAL_NAME_new();
+ if (gen_name == NULL)
+ goto stack_err;
+ gen_name->type = GEN_DNS;
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER
+ gen_name->d.dNSName = ASN1_IA5STRING_new();
+#else
+ gen_name->d.dNSName = M_ASN1_IA5STRING_new();
+#endif
+ if (gen_name->d.dNSName == NULL)
+ goto name_err;
+ if (ASN1_STRING_set(gen_name->d.dNSName, name->s, name->len) == 0)
+ goto name_err;
+ if (sk_GENERAL_NAME_push(gen_names, gen_name) == 0)
+ goto name_err;
+ }
+ ext = X509V3_EXT_i2d(NID_subject_alt_name, 0, gen_names);
+ if (ext == NULL)
+ goto stack_err;
+ if (X509_add_ext(cert, ext, -1) == 0) {
+ X509_EXTENSION_free(ext);
+ goto stack_err;
+ }
+ X509_EXTENSION_free(ext);
+ sk_GENERAL_NAME_pop_free(gen_names, GENERAL_NAME_free);
+
+ return 1;
+
+name_err:
+ GENERAL_NAME_free(gen_name);
+
+stack_err:
+ sk_GENERAL_NAME_pop_free(gen_names, GENERAL_NAME_free);
+
+ return 0;
+}
+
+static int gen_cert(X509 **cert, EVP_PKEY **key,
+ const struct lstr commonNames[], const struct lstr dNSNames[])
+{
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+ int rc, ret=0;
+ RSA *rsa = NULL;
+ BIGNUM *bne = NULL;
+
+ *cert = NULL;
+ *key = NULL;
+
+ /* Generate a private key. */
+ *key = EVP_PKEY_new();
+ if (*key == NULL)
+ goto err;
+ do {
+ /* Generate RSA key. */
+ bne = BN_new();
+ ret = BN_set_word(bne, RSA_F4);
+ if (ret != 1)
+ goto err;
+
+ rsa = RSA_new();
+ ret = RSA_generate_key_ex(rsa, KEY_BITS, bne, NULL);
+ if (ret != 1)
+ goto err;
+ /* Check RSA key. */
+ rc = RSA_check_key(rsa);
+ } while (rc == 0);
+ if (rc == -1)
+ goto err;
+ if (EVP_PKEY_assign_RSA(*key, rsa) == 0) {
+ RSA_free(rsa);
+ goto err;
+ }
+#else
+ *cert = NULL;
+ *key = EVP_RSA_gen(KEY_BITS);
+ if (*key == NULL)
+ goto err;
+#endif
+
+ /* Generate a certificate. */
+ *cert = X509_new();
+ if (*cert == NULL)
+ goto err;
+ if (X509_set_version(*cert, 2) == 0) /* Version 3. */
+ goto err;
+ ASN1_INTEGER_set(X509_get_serialNumber(*cert), get_random_u32() & 0x7FFFFFFF);
+
+ /* Set the commonNames. */
+ if (commonNames != NULL) {
+ X509_NAME *subj;
+ const struct lstr *name;
+
+ subj = X509_get_subject_name(*cert);
+ for (name = commonNames; !is_sentinel(name); name++) {
+ if (X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
+ (unsigned char *) name->s, name->len, -1, 0) == 0) {
+ goto err;
+ }
+ }
+ }
+
+ /* Set the dNSNames. */
+ if (set_dNSNames(*cert, dNSNames) == 0)
+ goto err;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER
+ {
+ ASN1_TIME *tb, *ta;
+ tb = NULL;
+ ta = NULL;
+
+ if (X509_set_issuer_name(*cert, X509_get_subject_name(*cert)) == 0
+ || (tb = ASN1_STRING_dup(X509_get0_notBefore(*cert))) == 0
+ || X509_gmtime_adj(tb, 0) == 0
+ || X509_set1_notBefore(*cert, tb) == 0
+ || (ta = ASN1_STRING_dup(X509_get0_notAfter(*cert))) == 0
+ || X509_gmtime_adj(ta, 60) == 0
+ || X509_set1_notAfter(*cert, ta) == 0
+ || X509_set_pubkey(*cert, *key) == 0) {
+ ASN1_STRING_free(tb);
+ ASN1_STRING_free(ta);
+ goto err;
+ }
+ ASN1_STRING_free(tb);
+ ASN1_STRING_free(ta);
+ }
+#else
+ if (X509_set_issuer_name(*cert, X509_get_subject_name(*cert)) == 0
+ || X509_gmtime_adj(X509_get_notBefore(*cert), 0) == 0
+ || X509_gmtime_adj(X509_get_notAfter(*cert), 60) == 0
+ || X509_set_pubkey(*cert, *key) == 0) {
+ goto err;
+ }
+#endif
+
+ /* Sign it. */
+ if (X509_sign(*cert, *key, EVP_sha1()) == 0)
+ goto err;
+
+ return 1;
+
+err:
+ if (*cert != NULL)
+ X509_free(*cert);
+ if (*key != NULL)
+ EVP_PKEY_free(*key);
+
+ return 0;
+}
+
+static void print_escaped(const char *s, size_t len)
+{
+ int c;
+ for ( ; len > 0; len--) {
+ c = (unsigned char) *s++;
+ if (isprint(c) && !isspace(c))
+ putchar(c);
+ else
+ printf("\\%03o", c);
+ }
+}
+
+static void print_array(const struct lstr array[])
+{
+ const struct lstr *p;
+
+ if (array == NULL) {
+ printf("[]");
+ return;
+ }
+ printf("[");
+ for (p = array; !is_sentinel(p); p++) {
+ if (p != array)
+ printf(" ");
+ print_escaped(p->s, p->len);
+ }
+ printf("]");
+}
+
+static int lstr_equal(const struct lstr *a, const struct lstr *b)
+{
+ return a->len == b->len && memcmp(a->s, b->s, a->len) == 0;
+}
+
+static int arrays_equal(const struct lstr a[], const struct lstr b[])
+{
+ if (a == NULL)
+ return b == NULL;
+ if (b == NULL)
+ return a == NULL;
+ while (!is_sentinel(a) && !is_sentinel(b)) {
+ if (!lstr_equal(a, b))
+ return 0;
+ a++;
+ b++;
+ }
+
+ return is_sentinel(a) && is_sentinel(b);
+}
+
+/* This is just a constant used to give a fixed length to the arrays that are
+ conceptually variable-length in the test cases. Increase it if some array
+ grows too big. */
+#define ARR_LEN 10
+
+const struct lstr test_names[] = {
+ LSTR("a.com"), LSTR("www.a.com"), LSTR("sub.www.a.com"),
+ LSTR("www.example.com"), LSTR("example.co.uk"), LSTR("*.*.com"),
+ LSTR_SENTINEL
+};
+
+/* These tests just check that matching a single string works properly. */
+struct {
+ const struct lstr name[ARR_LEN];
+ const struct lstr expected[ARR_LEN];
+} single_tests[] = {
+ { { LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ { { LSTR("a.com"), LSTR_SENTINEL },
+ { LSTR("a.com"), LSTR_SENTINEL } },
+ { { LSTR("www.a.com"), LSTR_SENTINEL },
+ { LSTR("www.a.com"), LSTR_SENTINEL } },
+ { { LSTR("*.a.com"), LSTR_SENTINEL },
+ { LSTR("www.a.com"), LSTR_SENTINEL } },
+ { { LSTR("w*.a.com"), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ { { LSTR("*w.a.com"), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ { { LSTR("www.*.com"), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ { { LSTR("*.com"), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ { { LSTR("*.com."), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ { { LSTR("*.*.com"), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ { { LSTR("a.com\0evil.com"), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+};
+
+/* These test different combinations of commonName and dNSName. */
+struct {
+ const struct lstr common[ARR_LEN];
+ const struct lstr dns[ARR_LEN];
+ const struct lstr expected[ARR_LEN];
+} double_tests[] = {
+ /* Should not match any commonName if any dNSNames exist. */
+ { { LSTR("a.com"), LSTR_SENTINEL },
+ { LSTR("example.co.uk"), LSTR_SENTINEL },
+ { LSTR("example.co.uk"), LSTR_SENTINEL } },
+ { { LSTR("a.com"), LSTR_SENTINEL },
+ { LSTR("b.com"), LSTR_SENTINEL },
+ { LSTR_SENTINEL } },
+ /* Should check against all of the dNSNames. */
+ { { LSTR_SENTINEL },
+ { LSTR("a.com"), LSTR("example.co.uk"), LSTR("b.com"), LSTR_SENTINEL },
+ { LSTR("a.com"), LSTR("example.co.uk"), LSTR_SENTINEL } },
+};
+
+const struct lstr specificity_test_names[] = {
+ LSTR("a.com"),
+ LSTR("sub.b.com"), LSTR("sub.c.com"), LSTR("sub.d.com"),
+ LSTR("sub.sub.e.com"), LSTR("sub.sub.f.com"), LSTR("sub.sub.g.com"),
+ LSTR_SENTINEL
+};
+
+/* Validation should check only the "most specific" commonName if multiple
+ exist. This "most specific" term is used in RFCs 2818, 4261, and 5018 at
+ least, but is not defined anywhere that I can find. Let's interpret it as the
+ greatest number of name elements, with wildcard names considered less
+ specific than all non-wildcard names. For ties, the name that comes later is
+ considered more specific. */
+struct {
+ const struct lstr patterns[ARR_LEN];
+ const struct lstr expected_forward;
+ const struct lstr expected_backward;
+} specificity_tests[] = {
+ { { LSTR("a.com"), LSTR("*.b.com"), LSTR("sub.c.com"), LSTR("sub.d.com"), LSTR("*.sub.e.com"), LSTR("*.sub.f.com"), LSTR("sub.sub.g.com"), LSTR_SENTINEL },
+ LSTR("sub.sub.g.com"), LSTR("sub.sub.g.com") },
+ { { LSTR("a.com"), LSTR("*.b.com"), LSTR("sub.c.com"), LSTR("sub.d.com"), LSTR("*.sub.e.com"), LSTR("*.sub.f.com"), LSTR_SENTINEL },
+ LSTR("sub.d.com"), LSTR("sub.c.com") },
+ { { LSTR("a.com"), LSTR("*.b.com"), LSTR("sub.c.com"), LSTR("*.sub.e.com"), LSTR("*.sub.f.com"), LSTR_SENTINEL },
+ LSTR("sub.c.com"), LSTR("sub.c.com") },
+ { { LSTR("a.com"), LSTR("*.b.com"), LSTR("*.sub.e.com"), LSTR("*.sub.f.com"), LSTR_SENTINEL },
+ LSTR("a.com"), LSTR("a.com") },
+ { { LSTR("*.b.com"), LSTR("*.sub.e.com"), LSTR("*.sub.f.com"), LSTR_SENTINEL },
+ LSTR("sub.sub.f.com"), LSTR("sub.sub.e.com") },
+ { { LSTR("*.b.com"), LSTR("*.sub.e.com"), LSTR_SENTINEL },
+ LSTR("sub.sub.e.com"), LSTR("sub.sub.e.com") },
+};
+
+#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
+
+void reverse(struct lstr a[])
+{
+ struct lstr tmp;
+ unsigned int i, j;
+
+ i = 0;
+ for (j = 0; !is_sentinel(&a[j]); j++)
+ ;
+ if (j == 0)
+ return;
+ j--;
+ while (i < j) {
+ tmp = a[i];
+ a[i] = a[j];
+ a[j] = tmp;
+ i++;
+ j--;
+ }
+}
+
+void test_specificity(const struct lstr patterns[],
+ const struct lstr test_names[],
+ const struct lstr expected_forward[],
+ const struct lstr expected_backward[])
+{
+ struct lstr scratch[ARR_LEN];
+ unsigned int i;
+
+ for (i = 0; i < ARR_LEN && !is_sentinel(&patterns[i]); i++)
+ scratch[i] = patterns[i];
+ ncat_assert(i < ARR_LEN);
+ scratch[i] = lstr_sentinel;
+
+ test(scratch, NULL, test_names, expected_forward);
+ reverse(scratch);
+ test(scratch, NULL, test_names, expected_backward);
+
+ return;
+}
+
+int main(void)
+{
+ unsigned int i;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
+ SSL_library_init();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+#endif
+
+ /* Test single pattens in both the commonName and dNSName positions. */
+ for (i = 0; i < NELEMS(single_tests); i++)
+ test(single_tests[i].name, NULL, test_names, single_tests[i].expected);
+ for (i = 0; i < NELEMS(single_tests); i++)
+ test(NULL, single_tests[i].name, test_names, single_tests[i].expected);
+
+ for (i = 0; i < NELEMS(double_tests); i++) {
+ test(double_tests[i].common, double_tests[i].dns,
+ test_names, double_tests[i].expected);
+ }
+
+ for (i = 0; i < NELEMS(specificity_tests); i++) {
+ struct lstr expected_forward[2], expected_backward[2];
+
+ /* Put the expected names in arrays for the test. */
+ expected_forward[0] = specificity_tests[i].expected_forward;
+ expected_forward[1] = lstr_sentinel;
+ expected_backward[0] = specificity_tests[i].expected_backward;
+ expected_backward[1] = lstr_sentinel;
+ test_specificity(specificity_tests[i].patterns,
+ specificity_test_names, expected_forward, expected_backward);
+ }
+
+ printf("%d / %d tests passed.\n", tests_passed, tests_run);
+
+ return tests_passed == tests_run ? 0 : 1;
+}
diff --git a/ncat/test/toupper.lua b/ncat/test/toupper.lua
new file mode 100644
index 0000000..7b9d79a
--- /dev/null
+++ b/ncat/test/toupper.lua
@@ -0,0 +1,14 @@
+--Emulates the RFC 862 echo service, behaving like Unix's "cat" tool.
+
+while true do
+
+ data = io.stdin:read(1)
+
+ if data == nil then
+ break
+ end
+
+ io.write(data:upper())
+ io.flush()
+
+end
diff --git a/ncat/util.c b/ncat/util.c
new file mode 100644
index 0000000..e87acc5
--- /dev/null
+++ b/ncat/util.c
@@ -0,0 +1,773 @@
+/***************************************************************************
+ * util.c -- Various utility functions. *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#include "sys_wrap.h"
+#include "util.h"
+#include "ncat.h"
+#include "nbase.h"
+#include "sockaddr_u.h"
+
+#include <stdio.h>
+#ifdef WIN32
+#include <iphlpapi.h>
+#endif
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stddef.h>
+
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if HAVE_LINUX_VM_SOCKETS_H
+#include <linux/vm_sockets.h>
+#endif
+
+/* safely add 2 size_t */
+size_t sadd(size_t l, size_t r)
+{
+ size_t t;
+
+ t = l + r;
+ if (t < l)
+ bye("integer overflow %lu + %lu.", (u_long) l, (u_long) r);
+ return t;
+}
+
+/* safely multiply 2 size_t */
+size_t smul(size_t l, size_t r)
+{
+ size_t t;
+
+ t = l * r;
+ if (l && t / l != r)
+ bye("integer overflow %lu * %lu.", (u_long) l, (u_long) r);
+ return t;
+}
+
+#ifdef WIN32
+void windows_init()
+{
+ WORD werd;
+ WSADATA data;
+
+ werd = MAKEWORD(2, 2);
+ if ((WSAStartup(werd, &data)) != 0)
+ bye("Failed to start WinSock.");
+}
+#endif
+
+/* Use this to print debug or diagnostic messages to avoid polluting the user
+ stream. */
+void loguser(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s: ", NCAT_NAME);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fflush(stderr);
+}
+
+/* Log a user message without the "Ncat: " prefix, to allow building up a line
+ with a series of strings. */
+void loguser_noprefix(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fflush(stderr);
+}
+
+void logdebug(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "NCAT DEBUG: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fflush(stderr);
+}
+
+void logtest(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "NCAT TEST: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fflush(stderr);
+}
+
+/* Exit status 2 indicates a program error other than a network error. */
+void die(char *err)
+{
+#ifdef WIN32
+ int error_number;
+ char *strerror_s;
+ error_number = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error_number, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &strerror_s, 0, NULL);
+ fprintf(stderr, "%s: %s\n", err, strerror_s);
+ HeapFree(GetProcessHeap(), 0, strerror_s);
+#else
+ perror(err);
+#endif
+ fflush(stderr);
+ exit(2);
+}
+
+/* adds newline for you */
+void bye(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s: ", NCAT_NAME);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, " QUITTING.\n");
+ fflush(stderr);
+
+ exit(2);
+}
+
+/* zero out some mem, bzero() is deprecated */
+void zmem(void *mem, size_t n)
+{
+ memset(mem, 0, n);
+}
+
+/* Append n bytes starting at s to a malloc-allocated buffer. Reallocates the
+ buffer and updates the variables to make room if necessary. */
+int strbuf_append(char **buf, size_t *size, size_t *offset, const char *s, size_t n)
+{
+ ncat_assert(*offset <= *size);
+
+ if (n >= *size - *offset) {
+ *size += n + 1;
+ *buf = (char *) safe_realloc(*buf, *size);
+ }
+
+ memcpy(*buf + *offset, s, n);
+ *offset += n;
+ (*buf)[*offset] = '\0';
+
+ return n;
+}
+
+/* Append a '\0'-terminated string as with strbuf_append. */
+int strbuf_append_str(char **buf, size_t *size, size_t *offset, const char *s)
+{
+ return strbuf_append(buf, size, offset, s, strlen(s));
+}
+
+/* Do a sprintf at the given offset into a malloc-allocated buffer. Reallocates
+ the buffer and updates the variables to make room if necessary. */
+int strbuf_sprintf(char **buf, size_t *size, size_t *offset, const char *fmt, ...)
+{
+ va_list va;
+ int n;
+
+ ncat_assert(*offset <= *size);
+
+ if (*buf == NULL) {
+ *size = 1;
+ *buf = (char *) safe_malloc(*size);
+ }
+
+ for (;;) {
+ va_start(va, fmt);
+ n = Vsnprintf(*buf + *offset, *size - *offset, fmt, va);
+ va_end(va);
+ if (n < 0)
+ *size = MAX(*size, 1) * 2;
+ else if (n >= *size - *offset)
+ *size += n + 1;
+ else
+ break;
+ *buf = (char *) safe_realloc(*buf, *size);
+ }
+ *offset += n;
+
+ return n;
+}
+
+/* Return true if the given address is a local one. */
+int addr_is_local(const union sockaddr_u *su)
+{
+ struct addrinfo hints = { 0 }, *addrs, *addr;
+ char hostname[128];
+
+ /* Check loopback addresses. */
+ if (su->storage.ss_family == AF_INET) {
+ if ((ntohl(su->in.sin_addr.s_addr) & 0xFF000000UL) == 0x7F000000UL)
+ return 1;
+ if (ntohl(su->in.sin_addr.s_addr) == 0x00000000UL)
+ return 1;
+ }
+#ifdef HAVE_IPV6
+ else if (su->storage.ss_family == AF_INET6) {
+ if (memcmp(&su->in6.sin6_addr, &in6addr_any, sizeof(su->in6.sin6_addr)) == 0
+ || memcmp(&su->in6.sin6_addr, &in6addr_loopback, sizeof(su->in6.sin6_addr)) == 0)
+ return 1;
+ }
+#endif
+
+ /* Check addresses assigned to the local host name. */
+ if (gethostname(hostname, sizeof(hostname)) == -1)
+ return 0;
+ hints.ai_family = su->storage.ss_family;
+ if (getaddrinfo(hostname, NULL, &hints, &addrs) != 0)
+ return 0;
+ for (addr = addrs; addr != NULL; addr = addr->ai_next) {
+ union sockaddr_u addr_su;
+
+ if (addr->ai_family != su->storage.ss_family)
+ continue;
+ if (addr->ai_addrlen > sizeof(addr_su)) {
+ bye("getaddrinfo returned oversized address (%lu > %lu)",
+ (unsigned long) addr->ai_addrlen, (unsigned long) sizeof(addr_su));
+ }
+ memcpy(&addr_su, addr->ai_addr, addr->ai_addrlen);
+ if (su->storage.ss_family == AF_INET) {
+ if (su->in.sin_addr.s_addr == addr_su.in.sin_addr.s_addr)
+ break;
+ } else if (su->storage.ss_family == AF_INET6) {
+ if (memcmp(&su->in6.sin6_addr, &addr_su.in6.sin6_addr, sizeof(su->in6.sin6_addr)) == 0)
+ break;
+ }
+ }
+ if (addr != NULL) {
+ freeaddrinfo(addrs);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* Converts a sockaddr_u to a string representation. Since a static buffer is
+ * returned, this is not thread-safe and can only be used once in calls like
+ * printf(). ss_len may be 0 if it is not already known.
+*/
+const char *socktop(const union sockaddr_u *su, socklen_t ss_len)
+{
+ static char buf[INET6_ADDRSTRLEN + sizeof(union sockaddr_u)];
+ size_t size = sizeof(buf);
+
+ switch (su->storage.ss_family) {
+#if HAVE_SYS_UN_H
+ case AF_UNIX:
+ ncat_assert(ss_len <= sizeof(struct sockaddr_un));
+ if (ss_len == sizeof(sa_family_t)) {
+ /* Unnamed socket */
+ Strncpy(buf, "(unnamed socket)", sizeof(buf));
+ }
+ else {
+ if (ss_len < sizeof(sa_family_t)) {
+ /* socket path not guaranteed to be valid, but we'll try. */
+ size = sizeof(su->un.sun_path);
+ }
+ else {
+ /* We will add null terminator at size + 1 in case it was missing. */
+ size = MIN(sizeof(buf) - 1,
+ ss_len - offsetof(struct sockaddr_un, sun_path));
+ }
+ if (su->un.sun_path[0] == '\0') {
+ /* Abstract socket (Linux extension) */
+ memcpy(buf, su->un.sun_path + 1, size - 1);
+ Strncpy(buf + size, " (abstract socket)", sizeof(buf) - size);
+ }
+ else {
+ memcpy(buf, su->un.sun_path, size);
+ buf[size+1] = '\0';
+ }
+ /* In case we got junk data, make it safe. */
+ replacenonprintable(buf, strlen(buf), '?');
+ }
+ break;
+#endif
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+ case AF_VSOCK:
+ Snprintf(buf, sizeof(buf), "%u:%u", su->vm.svm_cid, su->vm.svm_port);
+ break;
+#endif
+ case AF_INET:
+ Snprintf(buf, sizeof(buf), "%s:%hu", inet_socktop(su), inet_port(su));
+ break;
+ case AF_INET6:
+ Snprintf(buf, sizeof(buf), "[%s]:%hu", inet_socktop(su), inet_port(su));
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ return buf;
+}
+
+/* Converts an IP address given in a sockaddr_u to an IPv4 or
+ IPv6 IP address string. Since a static buffer is returned, this is
+ not thread-safe and can only be used once in calls like printf()
+*/
+const char *inet_socktop(const union sockaddr_u *su)
+{
+ static char buf[INET6_ADDRSTRLEN + 1];
+ void *addr;
+
+ if (su->storage.ss_family == AF_INET)
+ addr = (void *) &su->in.sin_addr;
+#if HAVE_IPV6
+ else if (su->storage.ss_family == AF_INET6)
+ addr = (void *) &su->in6.sin6_addr;
+#endif
+ else
+ bye("Invalid address family passed to inet_socktop().");
+
+ if (inet_ntop(su->storage.ss_family, addr, buf, sizeof(buf)) == NULL) {
+ bye("Failed to convert address to presentation format! Error: %s.",
+ strerror(socket_errno()));
+ }
+
+ return buf;
+}
+
+/* Returns the port number in HOST BYTE ORDER based on the su's family */
+unsigned short inet_port(const union sockaddr_u *su)
+{
+ switch (su->storage.ss_family) {
+ case AF_INET:
+ return ntohs(su->in.sin_port);
+ break;
+#if HAVE_IPV6
+ case AF_INET6:
+ return ntohs(su->in6.sin6_port);
+ break;
+#endif
+ default:
+ bye("Invalid address family passed to inet_port().");
+ break;
+ }
+ return 0;
+}
+
+/* Return a listening socket after setting various characteristics on it.
+ Returns -1 on error. */
+int do_listen(int type, int proto, const union sockaddr_u *srcaddr_u)
+{
+ int sock = 0, option_on = 1;
+ size_t sa_len;
+
+ if (type != SOCK_STREAM && type != SOCK_DGRAM)
+ return -1;
+
+ /* We need a socket that can be inherited by child processes in
+ ncat_exec_win.c, for --exec and --sh-exec. inheritable_socket is from
+ nbase. */
+ sock = inheritable_socket(srcaddr_u->storage.ss_family, type, proto);
+ if (sock < 0)
+ return -1;
+
+ Setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option_on, sizeof(int));
+
+/* IPPROTO_IPV6 is defined in Visual C++ only when _WIN32_WINNT >= 0x501.
+ Nbase's nbase_winunix.h defines _WIN32_WINNT to a lower value for
+ compatibility with older versions of Windows. This code disables IPv6 sockets
+ that also receive IPv4 connections. This is the default on Windows anyway so
+ it doesn't make a difference.
+ http://support.microsoft.com/kb/950688
+ http://msdn.microsoft.com/en-us/library/bb513665
+*/
+#ifdef IPPROTO_IPV6
+#ifdef IPV6_V6ONLY
+ if (srcaddr_u->storage.ss_family == AF_INET6) {
+ int set = 1;
+ /* Tell it to not try and bind to IPV4 */
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &set, sizeof(set)) == -1)
+ die("Unable to set IPV6 socket to bind only to IPV6");
+ }
+#endif
+#endif
+
+ sa_len = get_socklen(srcaddr_u);
+
+ if (bind(sock, &srcaddr_u->sockaddr, sa_len) < 0) {
+ bye("bind to %s: %s.", socktop(srcaddr_u, sa_len),
+ socket_strerror(socket_errno()));
+ }
+
+ if (type == SOCK_STREAM)
+ Listen(sock, BACKLOG);
+
+ if (o.verbose) {
+ loguser("Listening on %s\n", socktop(srcaddr_u, sa_len));
+ }
+ if (o.test)
+ logtest("LISTEN\n");
+
+ return sock;
+}
+
+/* Only used in proxy connect functions, so doesn't need to support address
+ * families that don't support proxying like AF_UNIX and AF_VSOCK */
+int do_connect(int type)
+{
+ int sock = 0;
+
+ if (type != SOCK_STREAM && type != SOCK_DGRAM)
+ return -1;
+
+ /* We need a socket that can be inherited by child processes in
+ ncat_exec_win.c, for --exec and --sh-exec. inheritable_socket is from
+ nbase. */
+ sock = inheritable_socket(targetaddrs->addr.storage.ss_family, type, 0);
+
+ if (srcaddr.storage.ss_family != AF_UNSPEC) {
+ size_t sa_len = get_socklen(&srcaddr);
+
+ if (bind(sock, &srcaddr.sockaddr, sa_len) < 0) {
+ bye("bind to %s: %s.", socktop(&srcaddr, sa_len),
+ socket_strerror(socket_errno()));
+ }
+ }
+
+ if (sock != -1) {
+ if (connect(sock, &targetaddrs->addr.sockaddr, (int) targetaddrs->addrlen) != -1)
+ return sock;
+ else if (socket_errno() == EINPROGRESS || socket_errno() == EAGAIN)
+ return sock;
+ }
+ return -1;
+}
+
+unsigned char *buildsrcrte(struct in_addr dstaddr, struct in_addr routes[],
+ int numroutes, int ptr, size_t *len)
+{
+ int x;
+ unsigned char *opts, *p;
+
+ *len = (numroutes + 1) * sizeof(struct in_addr) + 4;
+
+ if (numroutes > 8)
+ bye("Bad number of routes passed to buildsrcrte().");
+
+ opts = (unsigned char *) safe_malloc(*len);
+ p = opts;
+
+ zmem(opts, *len);
+
+ *p++ = 0x01; /* IPOPT_NOP, for alignment */
+ *p++ = 0x83; /* IPOPT_LSRR */
+ *p++ = (char) (*len - 1); /* subtract nop */
+ *p++ = (char) ptr;
+
+ for (x = 0; x < numroutes; x++) {
+ memcpy(p, &routes[x], sizeof(routes[x]));
+ p += sizeof(routes[x]);
+ }
+
+ memcpy(p, &dstaddr, sizeof(dstaddr));
+
+ return opts;
+}
+
+int allow_access(const union sockaddr_u *su)
+{
+ /* A host not in the allow set is denied, but only if the --allow or
+ --allowfile option was given. */
+ if (o.allow && !addrset_contains(o.allowset, &su->sockaddr))
+ return 0;
+ if (addrset_contains(o.denyset, &su->sockaddr))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Fills the given timeval struct with proper
+ * values based on the given time in milliseconds.
+ * The pointer to timeval struct must NOT be NULL.
+ */
+void ms_to_timeval(struct timeval *tv, long ms)
+{
+ tv->tv_sec = ms / 1000;
+ tv->tv_usec = (ms - (tv->tv_sec * 1000)) * 1000;
+}
+
+/*
+ * ugly code to maintain our list of fds so we can have proper fdmax for
+ * select(). really this should be generic list code, not this silly bit of
+ * stupidity. -sean
+ */
+
+/* add an fdinfo to our list */
+int add_fdinfo(fd_list_t *fdl, struct fdinfo *s)
+{
+ if (fdl->nfds >= fdl->maxfds)
+ return -1;
+
+ fdl->fds[fdl->nfds] = *s;
+
+ fdl->nfds++;
+
+ if (s->fd > fdl->fdmax)
+ fdl->fdmax = s->fd;
+
+ if (o.debug > 1)
+ logdebug("Added fd %d to list, nfds %d, maxfd %d\n", s->fd, fdl->nfds, fdl->fdmax);
+ return 0;
+}
+
+/* Add a descriptor to the list. Use this when you are only adding to the list
+ * for the side effect of increasing fdmax, and don't care about fdinfo
+ * members. */
+int add_fd(fd_list_t *fdl, int fd)
+{
+ struct fdinfo info = { 0 };
+
+ info.fd = fd;
+
+ return add_fdinfo(fdl, &info);
+}
+
+/* remove a descriptor from our list */
+int rm_fd(fd_list_t *fdl, int fd)
+{
+ int x = 0, last = fdl->nfds;
+ int found = -1;
+ int newfdmax = 0;
+
+ /* make sure we have a list */
+ if (last == 0)
+ bye("Program bug: Trying to remove fd from list with no fds.");
+
+ /* find the fd in the list */
+ for (x = 0; x < last; x++) {
+ struct fdinfo *fdi = &fdl->fds[x];
+ if (fdi->fd == fd) {
+ found = x;
+ /* If it's not the max, we can bail early. */
+ if (fd < fdl->fdmax) {
+ newfdmax = fdl->fdmax;
+ break;
+ }
+ }
+ else if (fdi->fd > newfdmax)
+ newfdmax = fdi->fd;
+ }
+ fdl->fdmax = newfdmax;
+
+ /* make sure we found it */
+ if (found < 0)
+ bye("Program bug: fd (%d) not on list.", fd);
+
+ /* remove it, does nothing if (last == 1) */
+ if (o.debug > 1)
+ logdebug("Swapping fd[%d] (%d) with fd[%d] (%d)\n",
+ found, fdl->fds[found].fd, last - 1, fdl->fds[last - 1].fd);
+ fdl->fds[found] = fdl->fds[last - 1];
+ fdl->state++;
+
+ fdl->nfds--;
+
+ if (o.debug > 1)
+ logdebug("Removed fd %d from list, nfds %d, maxfd %d\n", fd, fdl->nfds, fdl->fdmax);
+ return 0;
+}
+
+/* find the max descriptor in our list */
+int get_maxfd(fd_list_t *fdl)
+{
+ int x = 0, max = -1, nfds = fdl->nfds;
+
+ for (x = 0; x < nfds; x++)
+ if (fdl->fds[x].fd > max)
+ max = fdl->fds[x].fd;
+
+ return max;
+}
+
+struct fdinfo *get_fdinfo(const fd_list_t *fdl, int fd)
+{
+ int x;
+
+ for (x = 0; x < fdl->nfds; x++)
+ if (fdl->fds[x].fd == fd)
+ return &fdl->fds[x];
+
+ return NULL;
+}
+
+void init_fdlist(fd_list_t *fdl, int maxfds)
+{
+ fdl->fds = (struct fdinfo *) Calloc(maxfds, sizeof(struct fdinfo));
+ fdl->nfds = 0;
+ fdl->fdmax = -1;
+ fdl->maxfds = maxfds;
+ fdl->state = 0;
+
+ if (o.debug > 1)
+ logdebug("Initialized fdlist with %d maxfds\n", maxfds);
+}
+
+void free_fdlist(fd_list_t *fdl)
+{
+ free(fdl->fds);
+ fdl->nfds = 0;
+ fdl->fdmax = -1;
+ fdl->state = 0;
+}
+
+
+/* If any changes need to be made to EOL sequences to comply with --crlf
+ * then dst will be populated with the modified src, len will be adjusted
+ * accordingly and the return will be non-zero.
+ *
+ * state is used to keep track of line endings that span more than one call to
+ * this function. On the first call, state should be a pointer to a int
+ * containing 0. Thereafter, keep passing the same pointer. Separate logical
+ * streams should use separate state pointers.
+ *
+ * Returns 0 if changes were not made - len and dst will remain untouched.
+ */
+int fix_line_endings(char *src, int *len, char **dst, int *state)
+{
+ int fix_count;
+ int i, j;
+ int num_bytes = *len;
+ int prev_state = *state;
+
+ /* *state is true iff the last byte of the previous block was \r. */
+ if (num_bytes > 0)
+ *state = (src[num_bytes - 1] == '\r');
+
+ /* get count of \n without matching \r */
+ fix_count = 0;
+ for (i = 0; i < num_bytes; i++) {
+ if (src[i] == '\n' && ((i == 0) ? !prev_state : src[i - 1] != '\r'))
+ fix_count++;
+ }
+ if (fix_count <= 0)
+ return 0;
+
+ /* now insert matching \r */
+ *dst = (char *) safe_malloc(num_bytes + fix_count);
+ j = 0;
+
+ for (i = 0; i < num_bytes; i++) {
+ if (src[i] == '\n' && ((i == 0) ? !prev_state : src[i - 1] != '\r')) {
+ memcpy(*dst + j, "\r\n", 2);
+ j += 2;
+ } else {
+ memcpy(*dst + j, src + i, 1);
+ j++;
+ }
+ }
+ *len += fix_count;
+
+ return 1;
+}
+
+/*-
+ * next_protos_parse parses a comma separated list of strings into a string
+ * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
+ * outlen: (output) set to the length of the resulting buffer on success.
+ * err: NULL on failure
+ * in: a NULL terminated string like "abc,def,ghi"
+ *
+ * returns: a malloc'd buffer or NULL on failure.
+ */
+unsigned char *next_protos_parse(size_t *outlen, const char *in)
+{
+ size_t len;
+ unsigned char *out;
+ size_t i, start = 0;
+
+ len = strlen(in);
+ if (len >= 65535)
+ return NULL;
+
+ out = (unsigned char *)safe_malloc(strlen(in) + 1);
+ for (i = 0; i <= len; ++i) {
+ if (i == len || in[i] == ',') {
+ if (i - start > 255) {
+ free(out);
+ return NULL;
+ }
+ out[start] = i - start;
+ start = i + 1;
+ } else
+ out[i + 1] = in[i];
+ }
+
+ *outlen = len + 1;
+ return out;
+}
diff --git a/ncat/util.h b/ncat/util.h
new file mode 100644
index 0000000..87ba74d
--- /dev/null
+++ b/ncat/util.h
@@ -0,0 +1,179 @@
+/***************************************************************************
+ * util.h *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include "ncat_config.h"
+
+#include "nbase.h"
+#ifndef WIN32
+#include <sys/types.h>
+#include <netinet/in.h>
+#endif
+
+#include "sockaddr_u.h"
+
+#if HAVE_SYS_UN_H
+#include <sys/un.h>
+#include <string.h>
+
+#define NCAT_INIT_SUN(_Sock, _Source) do { \
+ memset(_Sock, 0, sizeof(union sockaddr_u)); \
+ (_Sock)->un.sun_family = AF_UNIX; \
+ if (strlen(_Source) > sizeof((_Sock)->un.sun_path) - 1) \
+ bye("Socket path length is too long. Max: %lu", sizeof((_Sock)->un.sun_path) - 1); \
+ strncpy((_Sock)->un.sun_path, _Source, sizeof((_Sock)->un.sun_path) - 1); \
+} while (0);
+
+#endif
+
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#endif
+
+/* add/multiply unsigned values safely */
+size_t sadd(size_t, size_t);
+size_t smul(size_t, size_t);
+
+#ifdef WIN32
+void windows_init();
+#endif
+
+void loguser(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+void loguser_noprefix(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+void logdebug(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+void logtest(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+/* handle errors */
+
+#define ncat_assert(expr) \
+do { \
+ if (!(expr)) \
+ bye("assertion failed: %s", #expr); \
+} while (0)
+
+void die(char *);
+
+NORETURN void bye(const char *, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+/* zero out some memory, bzero() is deprecated */
+void zmem(void *, size_t);
+
+int strbuf_append(char **buf, size_t *size, size_t *offset, const char *s, size_t n);
+
+int strbuf_append_str(char **buf, size_t *size, size_t *offset, const char *s);
+
+int strbuf_sprintf(char **buf, size_t *size, size_t *offset, const char *fmt, ...)
+ __attribute__ ((format (printf, 4, 5)));
+
+int addr_is_local(const union sockaddr_u *su);
+
+const char *socktop(const union sockaddr_u *su, socklen_t ss_len);
+const char *inet_socktop(const union sockaddr_u *su);
+
+unsigned short inet_port(const union sockaddr_u *su);
+
+int do_listen(int, int, const union sockaddr_u *);
+
+
+int do_connect(int);
+
+unsigned char *buildsrcrte(struct in_addr dstaddr, struct in_addr routes[],
+ int numroutes, int ptr, size_t *len);
+
+int allow_access(const union sockaddr_u *su);
+
+void ms_to_timeval(struct timeval *tv, long ms)
+ __attribute__ ((nonnull));
+
+struct fdinfo {
+ int fd;
+ int lasterr;
+ union sockaddr_u remoteaddr;
+ socklen_t ss_len;
+#ifdef HAVE_OPENSSL
+ SSL *ssl;
+#endif
+};
+
+typedef struct fd_list {
+ struct fdinfo *fds;
+ int nfds, maxfds, fdmax;
+ int state; /* incremented each time the list is modified */
+} fd_list_t;
+
+int add_fdinfo(fd_list_t *, struct fdinfo *);
+int add_fd(fd_list_t *fdl, int fd);
+int rm_fd(fd_list_t *, int);
+void free_fdlist(fd_list_t *);
+void init_fdlist(fd_list_t *, int);
+int get_maxfd(fd_list_t *);
+struct fdinfo *get_fdinfo(const fd_list_t *, int);
+
+int fix_line_endings(char *src, int *len, char **dst, int *state);
+
+unsigned char *next_protos_parse(size_t *outlen, const char *in);
+
+#endif