From b62709eb2031a17d91075b09e31d2b4862318b2f Mon Sep 17 00:00:00 2001 From: d33tah Date: Tue, 2 Jul 2013 16:56:03 +0000 Subject: [PATCH] merging in the --lua-exec feature for ncat. --- nbase/nbase.h | 2 + nbase/nbase_str.c | 70 ++ nbase/test/nmakefile | 13 + nbase/test/test-escape_windows_command_arg.c | 204 ++++++ ncat/Makefile.in | 57 +- ncat/config_win.h | 1 + ncat/configure | 682 ++++++++++++++++++- ncat/configure.ac | 103 +++ ncat/docs/ncat.usage.txt | 1 + ncat/docs/ncat.xml | 13 + ncat/ncat.vcxproj | 13 +- ncat/ncat_core.c | 2 +- ncat/ncat_core.h | 9 +- ncat/ncat_exec_win.c | 28 +- ncat/ncat_lua.c | 150 ++++ ncat/ncat_lua.h | 112 +++ ncat/ncat_main.c | 48 +- ncat/ncat_posix.c | 30 +- ncat/scripts/conditional.lua | 33 + ncat/scripts/date.lua | 3 + ncat/scripts/discard.lua | 11 + ncat/scripts/echo.lua | 14 + ncat/scripts/hello-luaexec.lua | 4 + ncat/test/ncat-test.pl | 9 +- ncat/test/toupper.lua | 13 + 25 files changed, 1594 insertions(+), 31 deletions(-) create mode 100644 nbase/test/nmakefile create mode 100644 nbase/test/test-escape_windows_command_arg.c create mode 100644 ncat/ncat_lua.c create mode 100644 ncat/ncat_lua.h create mode 100644 ncat/scripts/conditional.lua create mode 100644 ncat/scripts/date.lua create mode 100644 ncat/scripts/discard.lua create mode 100644 ncat/scripts/echo.lua create mode 100644 ncat/scripts/hello-luaexec.lua create mode 100644 ncat/test/toupper.lua diff --git a/nbase/nbase.h b/nbase/nbase.h index f8a465521..717e3e2d5 100644 --- a/nbase/nbase.h +++ b/nbase/nbase.h @@ -436,6 +436,8 @@ char *mkstr(const char *start, const char *end); int alloc_vsprintf(char **strp, const char *fmt, va_list va) __attribute__ ((format (printf, 2, 0))); +char *escape_windows_command_arg(const char *arg); + /* Trivial function that returns nonzero if all characters in str of length strlength are printable (as defined by isprint()) */ int stringisprintable(const char *str, int strlength); diff --git a/nbase/nbase_str.c b/nbase/nbase_str.c index f76d9ec86..5b2eba830 100644 --- a/nbase/nbase_str.c +++ b/nbase/nbase_str.c @@ -216,6 +216,76 @@ int alloc_vsprintf(char **strp, const char *fmt, va_list va) { return n; } +/* Used by escape_windows_command_arg to append a character to the given buffer + at a given position, resizing the buffer if necessary. The position gets + moved by one byte after the call. */ + +static char* safe_append_char(char* buf, char byte, unsigned int *rpos, unsigned int *rsize) +{ + if (*rpos >= *rsize) { + *rsize += 512; + buf = (char*) safe_realloc(buf, *rsize); + } + buf[(*rpos)++] = byte; + return buf; +} + +/* Escape a string so that it can be round-tripped into a command line string + and retrieved by the default C/C++ command line parser. You can escape a list + of strings with this function, join them with spaces, pass them to + CreateProcess, and the new process will get the same list of strings in its + argv array. + + http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx + http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx + + Returns a dynamically allocated string. + + This function has a test program in test/test-escape_windows_command_arg.c. + Run that program after making any changes. */ +char *escape_windows_command_arg(const char *arg) +{ + const char *p; + char *ret; + unsigned int rpos = 0, rsize = 1; + + ret = (char *) safe_malloc(rsize); + ret = safe_append_char(ret, '"', &rpos, &rsize); + + for (p = arg; *p != '\0'; p++) { + unsigned int num_backslashes; + unsigned int i; + + num_backslashes = 0; + for (; *p == '\\'; p++) + num_backslashes++; + + if (*p == '\0') { + /* Escape all backslashes, but let the terminating double quotation + mark we add below be interpreted as a metacharacter. */ + for (i = 0; i < num_backslashes*2; i++) + ret = safe_append_char(ret, '\\', &rpos, &rsize); + break; + } else if (*p == '"') { + /* Escape all backslashes and the following double quotation + mark. */ + for (i = 0; i < num_backslashes*2 + 1; i++) + ret = safe_append_char(ret, '\\', &rpos, &rsize); + ret[rpos++] = *p; + } else { + /* Backslashes aren't special here. */ + for (i = 0; i < num_backslashes; i++) + ret = safe_append_char(ret, '\\', &rpos, &rsize); + ret = safe_append_char(ret, *p, &rpos, &rsize); + } + } + + ret = safe_append_char(ret, '"', &rpos, &rsize); + ret = safe_append_char(ret, '\0', &rpos, &rsize); + + return ret; +} + /* Trivial function that returns nonzero if all characters in str of length strlength are printable (as defined by isprint()) */ int stringisprintable(const char *str, int strlength) { diff --git a/nbase/test/nmakefile b/nbase/test/nmakefile new file mode 100644 index 000000000..bf3f52148 --- /dev/null +++ b/nbase/test/nmakefile @@ -0,0 +1,13 @@ +# Build nbase in Visual C++ (so ..\nbase.lib exists). Then open a Visual +# Studio Command Prompt (from the Start menu), and run: +# nmake /F nmakefile + +!include + +all: test-escape_windows_command_arg + +.c.obj: + $(cc) /c /D WIN32=1 /I .. $*.c + +test-escape_windows_command_arg: test-escape_windows_command_arg.obj + $(link) /OUT:test-escape_windows_command_arg.exe test-escape_windows_command_arg.obj /NODEFAULTLIB:LIBCMT ..\nbase.lib shell32.lib diff --git a/nbase/test/test-escape_windows_command_arg.c b/nbase/test/test-escape_windows_command_arg.c new file mode 100644 index 000000000..4b7bcdc8e --- /dev/null +++ b/nbase/test/test-escape_windows_command_arg.c @@ -0,0 +1,204 @@ +/* +Usage: test-escape_windows_command_arg.exe + +This is a test program for the escape_windows_command_arg function from +nbase_str.c. Its code is strictly Windows-specific. Basically, it performs +escape_windows_command_arg on arrays of strings merging its results with spaces +and tests if an attempt to decode them with CommandLineToArgvW results in the +same strings. +*/ + +#include +#include +#include + +#include "nbase.h" + +#include + +const char *TESTS[][5] = { + { NULL }, + {"", NULL}, + {"", "", NULL}, + {"1", "2", "3", "4", NULL}, + {"a", "b", "c", NULL}, + {"a b", "c", NULL}, + {"a b c", NULL}, + {" a b c ", NULL}, + {"\"quote\"", NULL}, + {"back\\slash", NULL}, + {"backslash at end\\", NULL}, + {"double\"\"quote", NULL}, + {" a\nb\tc\rd\ne", NULL}, + {"..\\test\\toupper.lua", NULL}, + {"backslash at end\\", "som\\ething\"af\\te\\r", NULL}, + {"three\\\\\\backslashes", "som\\ething\"af\\te\\r", NULL}, + {"three\"\"\"quotes", "som\\ething\"af\\te\\r", NULL}, +}; + +static LPWSTR utf8_to_wchar(const char *s) +{ + LPWSTR result; + int size, ret; + + /* Get needed buffer size. */ + size = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0); + if (size == 0) { + fprintf(stderr, "MultiByteToWideChar 1 failed: %d\n", GetLastError()); + exit(1); + } + result = (LPWSTR) malloc(sizeof(*result) * size); + ret = MultiByteToWideChar(CP_UTF8, 0, s, -1, result, size); + if (ret == 0) { + fprintf(stderr, "MultiByteToWideChar 2 failed: %d\n", GetLastError()); + exit(1); + } + + return result; +} + +static char *wchar_to_utf8(const LPWSTR s) +{ + char *result; + int size, ret; + + /* Get needed buffer size. */ + size = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL); + if (size == 0) { + fprintf(stderr, "WideCharToMultiByte 1 failed: %d\n", GetLastError()); + exit(1); + } + result = (char *) malloc(size); + ret = WideCharToMultiByte(CP_UTF8, 0, s, -1, result, size, NULL, NULL); + if (ret == 0) { + fprintf(stderr, "WideCharToMultiByte 2 failed: %d\n", GetLastError()); + exit(1); + } + + return result; +} + +static char **wchar_to_utf8_array(const LPWSTR a[], unsigned int len) +{ + char **result; + unsigned int i; + + result = (char **) malloc(sizeof(*result) * len); + if (result == NULL) + return NULL; + for (i = 0; i < len; i++) + result[i] = wchar_to_utf8(a[i]); + + return result; +} + +static unsigned int nullarray_length(const char *a[]) +{ + unsigned int i; + + for (i = 0; a[i] != NULL; i++) + ; + + return i; +} + +static char *append(char *p, const char *s) +{ + size_t plen, slen; + + plen = strlen(p); + slen = strlen(s); + p = (char *) realloc(p, plen + slen + 1); + if (p == NULL) + return NULL; + + return strncat(p, s, plen+slen); +} + +/* Turns an array of strings into an escaped flat command line. */ +static LPWSTR build_commandline(const char *args[], unsigned int len) +{ + unsigned int i; + char *result; + + result = strdup("progname"); + for (i = 0; i < len; i++) { + result = append(result, " "); + result = append(result, escape_windows_command_arg(args[i])); + } + + return utf8_to_wchar(result); +} + +static int arrays_equal(const char **a, unsigned int alen, const char **b, unsigned int blen) +{ + unsigned int i; + + if (alen != blen) + return 0; + for (i = 0; i < alen; i++) { + if (strcmp(a[i], b[i]) != 0) + return 0; + } + + return 1; +} + +static char *format_array(const char **args, unsigned int len) +{ + char *result; + unsigned int i; + + result = strdup(""); + result = append(result, "{"); + for (i = 0; i < len; i++) { + if (i > 0) + result = append(result, ", "); + result = append(result, "["); + result = append(result, args[i]); + result = append(result, "]"); + } + result = append(result, "}"); + + return result; +} + +static int run_test(const char *args[]) +{ + LPWSTR *argvw; + char **result; + int args_len, argvw_len, result_len; + + args_len = nullarray_length(args); + argvw = CommandLineToArgvW(build_commandline(args, args_len), &argvw_len); + /* Account for added argv[0] in argvw. */ + result = wchar_to_utf8_array(argvw+1, argvw_len-1); + result_len = argvw_len - 1; + + if (arrays_equal((const char **) result, result_len, args, args_len)) { + printf("PASS %s\n", format_array(args, args_len)); + return 1; + } else { + printf("FAIL got %s\n", format_array((const char **) result, result_len)); + printf("expected %s\n", format_array(args, args_len)); + return 0; + } +} + +int main(int argc, char *argv[]) +{ + unsigned int num_tests, num_passed; + unsigned int i; + + num_tests = 0; + num_passed = 0; + for (i = 0; i < sizeof(TESTS) / sizeof(*TESTS); i++) { + num_tests++; + if (run_test(TESTS[i])) + num_passed++; + } + + printf("%ld / %ld tests passed.\n", num_passed, num_tests); + + return num_passed == num_tests ? 0 : 1; +} diff --git a/ncat/Makefile.in b/ncat/Makefile.in index a9707aed3..3de9fdcc9 100644 --- a/ncat/Makefile.in +++ b/ncat/Makefile.in @@ -59,6 +59,10 @@ STRIP = @STRIP@ OPENSSL_LIBS = @OPENSSL_LIBS@ HAVE_OPENSSL = @HAVE_OPENSSL@ PCAP_LIBS = @PCAP_LIBS@ +HAVE_LUA = @LIBLUA_LIBS@ +LIBLUADIR = @LIBLUADIR@ +LUA_CFLAGS = @LUA_CFLAGS@ + CPPFLAGS += $(DEFS) $(INCLS) @@ -78,6 +82,21 @@ OBJS += http_digest.o DATAFILES = certs/ca-bundle.crt endif +ifneq ($(HAVE_LUA),) +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 @@ -88,13 +107,17 @@ ifneq ($(HAVE_OPENSSL),) TEST_PROGS += test/test-wildcard endif -all: $(TARGET) $(TEST_PROGS) +all: @LUA_BUILD@ $(TARGET) $(TEST_PROGS) -$(TARGET): $(OBJS) $(NSOCKLIB) - $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(OBJS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LIBS) +lua_build: $(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) $(CFLAGS) -c $< -o $@ + $(CC) $(CPPFLAGS) $(LUA_CFLAGS) $(CFLAGS) -c $< -o $@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ @@ -112,17 +135,17 @@ config.h: $(SHELL) ./config.status; \ fi -test/addrset: test/addrset.o ncat_core.o sys_wrap.o util.o - $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) +test/addrset: test/addrset.o ncat_core.o sys_wrap.o util.o $(LUA_OBJS) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) -test/test-uri: test/test-uri.o base64.o http.o ncat_core.o sys_wrap.o util.o - $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) +test/test-uri: test/test-uri.o base64.o http.o ncat_core.o sys_wrap.o util.o $(LUA_OBJS) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) -test/test-cmdline-split: test/test-cmdline-split.o ncat_posix.o ncat_core.o sys_wrap.o util.o - $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) +test/test-cmdline-split: test/test-cmdline-split.o ncat_posix.o ncat_core.o sys_wrap.o util.o $(LUA_OBJS) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) -test/test-wildcard: test/test-wildcard.o ncat_core.o ncat_ssl.o sys_wrap.o util.o - $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) +test/test-wildcard: test/test-wildcard.o ncat_core.o ncat_ssl.o sys_wrap.o util.o $(LUA_OBJS) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LIBS) $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) .PHONY: uninstall all clean distclean @@ -158,9 +181,15 @@ uninstall: ncat_clean: $(RM) -f *.o test/*.o $(TARGET) $(TEST_PROGS) -clean: ncat_clean +clean: ncat_clean @LUA_CLEAN@ -distclean: clean +lua_clean: + -cd $(LIBLUADIR) && $(MAKE) clean + +lua_dist_clean: + -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 diff --git a/ncat/config_win.h b/ncat/config_win.h index d65b9d9b5..391dae8b6 100644 --- a/ncat/config_win.h +++ b/ncat/config_win.h @@ -93,3 +93,4 @@ #define HAVE_OPENSSL 1 #define HAVE_HTTP_DIGEST 1 +#define HAVE_LUA 1 \ No newline at end of file diff --git a/ncat/configure b/ncat/configure index b0b5be696..21e2a9f42 100755 --- a/ncat/configure +++ b/ncat/configure @@ -601,6 +601,16 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +LUA_DIST_CLEAN +LUA_CLEAN +LUA_BUILD +LUA_DEPENDS +LIBLUADIR +LIBLUA_LIBS +ac_ct_CXX +CXXFLAGS +CXX +LUA_CFLAGS PCAP_LIBS PCAP_DIST_CLEAN PCAP_CLEAN @@ -674,6 +684,7 @@ ac_user_opts=' enable_option_checking with_openssl with_libpcap +with_liblua ' ac_precious_vars='build_alias host_alias @@ -683,7 +694,10 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP' +CPP +CXX +CXXFLAGS +CCC' # Initialize some variables set by options. @@ -1299,6 +1313,11 @@ Optional Packages: --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 @@ -1309,6 +1328,8 @@ Some influential environment variables: CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1837,6 +1858,86 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_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_cxx_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_cxx_try_compile + +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_cxx_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_cxx_try_run cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. @@ -5052,6 +5153,584 @@ _ACEOF 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="lua_build" + LUA_CLEAN="lua_clean" + LUA_DIST_CLEAN="lua_dist_clean" + have_lua="yes" + + ;; + 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" + + +# OpenSSL and NSE C modules can require dlopen +{ $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 + + +# They don't want lua +if test "$no_lua" = "yes"; then + CPPFLAGS="-DNOLUA $CPPFLAGS" + 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 lua.h lua/lua.h lua5.2/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 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_yieldk in -llua" >&5 +$as_echo_n "checking for lua_yieldk in -llua... " >&6; } +if ${ac_cv_lib_lua_lua_yieldk+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llua -lm $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_yieldk (); +int +main () +{ +return lua_yieldk (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lua_lua_yieldk=yes +else + ac_cv_lib_lua_lua_yieldk=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_lua_lua_yieldk" >&5 +$as_echo "$ac_cv_lib_lua_lua_yieldk" >&6; } +if test "x$ac_cv_lib_lua_lua_yieldk" = xyes; then : + have_lua=yes; LIBLUA_LIBS="-llua"; CPPFLAGS="-I/usr/include/lua $CPPFLAGS"; break +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_yieldk in -llua52" >&5 +$as_echo_n "checking for lua_yieldk in -llua52... " >&6; } +if ${ac_cv_lib_lua52_lua_yieldk+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llua52 -lm $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_yieldk (); +int +main () +{ +return lua_yieldk (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lua52_lua_yieldk=yes +else + ac_cv_lib_lua52_lua_yieldk=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_lua52_lua_yieldk" >&5 +$as_echo "$ac_cv_lib_lua52_lua_yieldk" >&6; } +if test "x$ac_cv_lib_lua52_lua_yieldk" = xyes; then : + have_lua=yes; LIBLUA_LIBS="-llua52"; CPPFLAGS="-I/usr/include/lua52 $CPPFLAGS"; break +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_yieldk in -llua5.2" >&5 +$as_echo_n "checking for lua_yieldk in -llua5.2... " >&6; } +if ${ac_cv_lib_lua5_2_lua_yieldk+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llua5.2 -lm $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_yieldk (); +int +main () +{ +return lua_yieldk (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lua5_2_lua_yieldk=yes +else + ac_cv_lib_lua5_2_lua_yieldk=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_lua5_2_lua_yieldk" >&5 +$as_echo "$ac_cv_lib_lua5_2_lua_yieldk" >&6; } +if test "x$ac_cv_lib_lua5_2_lua_yieldk" = xyes; then : + have_lua=yes; LIBLUA_LIBS="-llua5.2"; CPPFLAGS="-I/usr/include/lua5.2 $CPPFLAGS"; break +fi + + +fi + +done + + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua version >= 502" >&5 +$as_echo_n "checking for lua version >= 502... " >&6; } + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + 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_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$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 +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +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_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$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_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + 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 + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# 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 + +{ $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_cxx_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_cxx_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_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_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_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +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_lua=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + #include +int +main () +{ +if(LUA_VERSION_NUM < 502) return 1; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + have_lua=yes +else + have_lua=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +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 + + + 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="lua_build" + LUA_CLEAN="lua_clean" + LUA_DIST_CLEAN="lua_dist_clean" + $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 @@ -6348,4 +7027,5 @@ fi 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 index 8ee523c2c..5ea713f6f 100644 --- a/ncat/configure.ac +++ b/ncat/configure.ac @@ -203,10 +203,113 @@ AC_CHECK_LIB(odm, odm_initialize) 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="lua_build" + LUA_CLEAN="lua_clean" + LUA_DIST_CLEAN="lua_dist_clean" + have_lua="yes" + + ;; + 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) + +# OpenSSL and NSE C modules can require dlopen +AC_SEARCH_LIBS(dlopen, dl) + +# They don't want lua +if test "$no_lua" = "yes"; then + CPPFLAGS="-DNOLUA $CPPFLAGS" + 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([lua.h lua/lua.h lua5.2/lua.h], + AC_CHECK_LIB(lua, lua_yieldk, [have_lua=yes; LIBLUA_LIBS="-llua"; CPPFLAGS="-I/usr/include/lua $CPPFLAGS"; break],, [-lm]) + AC_CHECK_LIB(lua52, lua_yieldk, [have_lua=yes; LIBLUA_LIBS="-llua52"; CPPFLAGS="-I/usr/include/lua52 $CPPFLAGS"; break],, [-lm]) + AC_CHECK_LIB(lua5.2, lua_yieldk, [have_lua=yes; LIBLUA_LIBS="-llua5.2"; CPPFLAGS="-I/usr/include/lua5.2 $CPPFLAGS"; break],, [-lm]) + ) + + AC_LANG_PUSH(C++) + AC_MSG_CHECKING([for lua version >= 502]) + AC_RUN_IFELSE([ AC_LANG_PROGRAM( + [[#include ]], + [[if(LUA_VERSION_NUM < 502) return 1;]])], + have_lua=yes, have_lua=no, AC_MSG_RESULT(cross-compiling -- assuming yes); have_lua=yes) + 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="lua_build" + LUA_CLEAN="lua_clean" + LUA_DIST_CLEAN="lua_dist_clean" + AC_DEFINE(LUA_INCLUDED) + else + AC_MSG_RESULT(yes) + fi + + INSTALLNSE="install-nse" +fi + +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/ncat.usage.txt b/ncat/docs/ncat.usage.txt index 73118a27e..a66f055c9 100644 --- a/ncat/docs/ncat.usage.txt +++ b/ncat/docs/ncat.usage.txt @@ -44,6 +44,7 @@ Options taking a time assume seconds. Append 'ms' for milliseconds, --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 + --lua-exec Execute a .lua Ncat script --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 index 1a8105ebe..e04f44b34 100644 --- a/ncat/docs/ncat.xml +++ b/ncat/docs/ncat.xml @@ -479,6 +479,19 @@ like environment variables are available. + + + + (Execute a .lua script) + (Ncat option) + + + 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. + + + diff --git a/ncat/ncat.vcxproj b/ncat/ncat.vcxproj index 3dc187114..2e773cb75 100644 --- a/ncat/ncat.vcxproj +++ b/ncat/ncat.vcxproj @@ -70,7 +70,7 @@ Disabled - .;..;../nbase;..\nsock\include;..\mswin32\pcap-include;..\..\nmap-mswin32-aux\OpenSSL\include;%(AdditionalIncludeDirectories) + .;..;../nbase;..\nsock\include;..\mswin32\pcap-include;..\..\nmap-mswin32-aux\OpenSSL\include;..\liblua;%(AdditionalIncludeDirectories) WIN32;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -90,10 +90,10 @@ - nbase.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;nsock.lib;advapi32.lib;libeay32.lib;ssleay32.lib + nbase.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;nsock.lib;advapi32.lib;libeay32.lib;ssleay32.lib;liblua.lib .\Debug\ncat.exe true - ..\mswin32\lib;..\nsock;..\nbase;..\..\nmap-mswin32-aux\OpenSSL\lib;%(AdditionalLibraryDirectories) + ..\mswin32\lib;..\nsock;..\nbase;..\..\nmap-mswin32-aux\OpenSSL\lib;..\liblua;%(AdditionalLibraryDirectories) %(IgnoreSpecificDefaultLibraries) wpcap.dll;%(DelayLoadDLLs) true @@ -117,7 +117,7 @@ MaxSpeed OnlyExplicitInline - .;..;../nbase;..\nsock\include;..\mswin32\pcap-include;..\..\nmap-mswin32-aux\OpenSSL\include;%(AdditionalIncludeDirectories) + .;..;../nbase;..\nsock\include;..\mswin32\pcap-include;..\..\nmap-mswin32-aux\OpenSSL\include;..\liblua;%(AdditionalIncludeDirectories) WIN32;_CONSOLE;%(PreprocessorDefinitions) true true @@ -198,6 +198,7 @@ + @@ -215,6 +216,7 @@ + @@ -240,6 +242,9 @@ + + {31fb0767-a71f-4575-8379-002d72b8af86} + {b630c8f7-3138-43e8-89ed-78742fa2ac5f} false diff --git a/ncat/ncat_core.c b/ncat/ncat_core.c index 168f2e4f2..49235d49e 100644 --- a/ncat/ncat_core.c +++ b/ncat/ncat_core.c @@ -166,7 +166,7 @@ void options_init(void) o.conntimeout = DEFAULT_CONNECT_TIMEOUT; o.cmdexec = NULL; - o.shellexec = 0; + o.execmode = EXEC_PLAIN; o.proxy_auth = NULL; o.proxytype = NULL; diff --git a/ncat/ncat_core.h b/ncat/ncat_core.h index caee21abb..58e4f6a82 100644 --- a/ncat/ncat_core.h +++ b/ncat/ncat_core.h @@ -110,6 +110,12 @@ extern size_t targetsslen; extern union sockaddr_u httpconnect, socksconnect; extern size_t httpconnectlen, socksconnectlen; +enum exec_mode { + EXEC_PLAIN, + EXEC_SHELL, + EXEC_LUA, +}; + struct options { unsigned short portno; @@ -152,8 +158,9 @@ struct options { int conn_limit; int conntimeout; + /* When execmode == EXEC_LUA, cmdexec is the name of the file to run. */ char *cmdexec; - int shellexec; + enum exec_mode execmode; char *proxy_auth; char *proxytype; diff --git a/ncat/ncat_exec_win.c b/ncat/ncat_exec_win.c index 77ad31968..8c04933e5 100644 --- a/ncat/ncat_exec_win.c +++ b/ncat/ncat_exec_win.c @@ -315,7 +315,7 @@ static int start_subprocess(char *cmdexec, struct subprocess_info *info) char *cmdbuf; int pid; - if (o.shellexec) { + if (o.execmode == EXEC_SHELL) { /* Run with cmd.exe. */ const char *shell; size_t cmdlen; @@ -324,6 +324,32 @@ static int start_subprocess(char *cmdexec, struct subprocess_info *info) 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; } diff --git a/ncat/ncat_lua.c b/ncat/ncat_lua.c new file mode 100644 index 000000000..d51b8f06c --- /dev/null +++ b/ncat/ncat_lua.c @@ -0,0 +1,150 @@ +/*************************************************************************** + * ncat_lua.c -- ncat lua facilities * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2012 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, version detection, and the Nmap Scripting Engine. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap, as well as other software we distribute under this * + * license such as Zenmap, Ncat, and Nping. This list is not exclusive, * + * but is meant to clarify our interpretation of derived works with some * + * common examples. Our interpretation applies only to Nmap--we don't * + * speak for other people's GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of Nmap. Please email sales@insecure.com for * + * further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * 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). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the dev@nmap.org mailing list for possible incorporation into the * + * main distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, or checking them into the Nmap * + * source code repository, it is understood (unless you specify otherwise) * + * that you are offering the Nmap Project (Insecure.Com 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 above. * + * If you wish to specify special license conditions of your * + * contributions, just say so when you send them. * + * * + * 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 * + * license file for more details (it's in a COPYING file included with * + * Nmap, and also available from https://svn.nmap.org/nmap/COPYING * + * * + ***************************************************************************/ + +/* $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 *L) +{ + const char *msg; + msg = lua_tostring(L, 1); + if (msg) { + luaL_traceback(L, L, msg, 1); + } else { + if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ + if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ + lua_pushliteral(L, "(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 000000000..fa9bfcbec --- /dev/null +++ b/ncat/ncat_lua.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * ncat_lua.h -- ncat lua facilities header file * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2012 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, version detection, and the Nmap Scripting Engine. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap, as well as other software we distribute under this * + * license such as Zenmap, Ncat, and Nping. This list is not exclusive, * + * but is meant to clarify our interpretation of derived works with some * + * common examples. Our interpretation applies only to Nmap--we don't * + * speak for other people's GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of Nmap. Please email sales@insecure.com for * + * further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * 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). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the dev@nmap.org mailing list for possible incorporation into the * + * main distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, or checking them into the Nmap * + * source code repository, it is understood (unless you specify otherwise) * + * that you are offering the Nmap Project (Insecure.Com 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 above. * + * If you wish to specify special license conditions of your * + * contributions, just say so when you send them. * + * * + * 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 * + * license file for more details (it's in a COPYING file included with * + * Nmap, and also available from https://svn.nmap.org/nmap/COPYING * + * * + ***************************************************************************/ + +/* $Id$ */ + +#ifndef _NCAT_LUA_H +#define _NCAT_LUA_H + +#include "ncat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + +#ifdef __cplusplus +} +#endif + +void lua_setup(void); +void lua_run(void); + +#endif diff --git a/ncat/ncat_main.c b/ncat/ncat_main.c index e322c1365..b7b72e50c 100644 --- a/ncat/ncat_main.c +++ b/ncat/ncat_main.c @@ -114,6 +114,10 @@ #include #endif +#ifdef HAVE_LUA +#include "ncat_lua.h" +#endif + static int ncat_connect_mode(void); static int ncat_listen_mode(void); @@ -238,6 +242,10 @@ int main(int argc, char *argv[]) {"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'}, @@ -317,11 +325,16 @@ int main(int argc, char *argv[]) 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.shellexec = 1; + 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 *a = strtok(optarg, ","); @@ -470,6 +483,29 @@ int main(int argc, char *argv[]) verification. */ o.sslverify = 1; } +#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 */ + ncat_assert(argc == 3); + o.cmdexec = argv[2]; + lua_setup(); + lua_run(); + } #endif break; case 'h': @@ -487,6 +523,9 @@ int main(int argc, char *argv[]) " -C, --crlf Use CRLF for EOL sequence\n" " -c, --sh-exec Executes the given command via /bin/sh\n" " -e, --exec Executes the given command\n" +#ifdef HAVE_LUA +" --lua-exec Executes the given Lua script\n" +#endif " -g hop1[,hop2,...] Loose source routing hop points (8 max)\n" " -G Loose source routing hop pointer (4, 8, 12, ...)\n" " -m, --max-conns Maximum simultaneous connections\n" @@ -787,6 +826,11 @@ connection brokering should work."); 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 @@ -838,7 +882,7 @@ static int ncat_listen_mode(void) #ifndef WIN32 /* See if the shell is executable before we get deep into this */ - if (o.shellexec && access("/bin/sh", X_OK) == -1) + if (o.execmode == EXEC_SHELL && access("/bin/sh", X_OK) == -1) bye("/bin/sh is not executable, so `-c' won't work."); #endif diff --git a/ncat/ncat_posix.c b/ncat/ncat_posix.c index fab397427..2a1758714 100644 --- a/ncat/ncat_posix.c +++ b/ncat/ncat_posix.c @@ -90,6 +90,7 @@ /* $Id$ */ #include "ncat.h" +#include "ncat_lua.h" char **cmdline_split(const char *cmdexec); @@ -153,10 +154,19 @@ void netexec(struct fdinfo *info, char *cmdexec) int maxfd; if (o.debug) { - if (o.shellexec) + switch (o.execmode) { + case EXEC_SHELL: logdebug("Executing with shell: %s\n", cmdexec); - else + 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) @@ -174,13 +184,21 @@ void netexec(struct fdinfo *info, char *cmdexec) Dup2(child_stdin[0], STDIN_FILENO); Dup2(child_stdout[1], STDOUT_FILENO); - if (o.shellexec) { - execl("/bin/sh", "sh", "-c", cmdexec, (void *) NULL); - } else { - char **cmdargs; + 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. */ diff --git a/ncat/scripts/conditional.lua b/ncat/scripts/conditional.lua new file mode 100644 index 000000000..18b31e767 --- /dev/null +++ b/ncat/scripts/conditional.lua @@ -0,0 +1,33 @@ +--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. + +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 = io.read() + + --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 000000000..a7116ef6a --- /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 000000000..9979c1466 --- /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 000000000..0db39d01e --- /dev/null +++ b/ncat/scripts/echo.lua @@ -0,0 +1,14 @@ +--Emulates the RFC 862 echo service, behaving like Unix's "cat" tool. + +while true do + + data = io.stdin:read(512) + + 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 000000000..bce250acf --- /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/test/ncat-test.pl b/ncat/test/ncat-test.pl index 2876d8883..e3b1f0a49 100755 --- a/ncat/test/ncat-test.pl +++ b/ncat/test/ncat-test.pl @@ -1041,7 +1041,7 @@ sub { }; kill_children; -# Test --exec and --sh-exec. +# Test --exec, --sh-exec and --lua-exec. server_client_test_all "--exec", ["--exec", "/usr/bin/perl -e \$|=1;while(<>){tr/a-z/A-Z/;print}"], [], sub { @@ -1077,6 +1077,13 @@ proxy_test "--exec through proxy", $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"); +}; + # Do a syswrite and then a delay to force separate reads in the subprocess. sub delaywrite { my ($handle, $data) = @_; diff --git a/ncat/test/toupper.lua b/ncat/test/toupper.lua new file mode 100644 index 000000000..a8ab4e17c --- /dev/null +++ b/ncat/test/toupper.lua @@ -0,0 +1,13 @@ +--Emulates the RFC 862 echo service, behaving like Unix's "cat" tool. + +while true do + + data = io.stdin:read(1024) + + if data == nil then + break + end + + io.write(data:upper()) + +end