extcap: add sshdump.
authorDario Lombardo <lomato@gmail.com>
Thu, 19 Nov 2015 10:30:44 +0000 (11:30 +0100)
committerAnders Broman <a.broman58@gmail.com>
Thu, 19 Nov 2015 15:29:18 +0000 (15:29 +0000)
sshdump is an extcap module that allows dumping from a remote host using an ssh connection.
It goes with the existing extcap plugin interface.

Change-Id: I8987614fdd817b8173a50130812bc643a4833bca
Reviewed-on: https://code.wireshark.org/review/11402
Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
21 files changed:
.gitignore
CMakeLists.txt
CMakeOptions.txt
Makefile.am
Makefile.common
Makefile.nmake
acinclude.m4
cmake/modules/FindLIBSSH.cmake [new file with mode: 0644]
cmakeconfig.h.in
config.nmake
configure.ac
debian/wireshark-common.manpages
doc/Makefile.am
doc/Makefile.nmake
doc/extcap.pod
doc/sshdump.pod [new file with mode: 0644]
extcap/sshdump.c [new file with mode: 0644]
packaging/macosx/osx-app.sh
packaging/nsis/Makefile.nmake
packaging/nsis/uninstall.nsi
packaging/nsis/wireshark.nsi

index 0004e49e55f8ace5ba6fa484c08acec41706eee6..0b4efeb72e4fffa088d4362efd1ca5c8e8c12112 100644 (file)
@@ -101,6 +101,7 @@ randpkt
 rawshark
 reordercap
 reassemble_test
+sshdump
 stamp-h1
 text2pcap
 tfshark
index 7827725ad5883580801c822a06aaa9cdc34b3d31..6a82046a6425f789db246be51b7b500cb050d4ec 100644 (file)
@@ -656,6 +656,9 @@ endif()
 
 set(PACKAGELIST ${PACKAGELIST} HtmlViewer)
 
+set(PACKAGELIST ${PACKAGELIST} LIBSSH)
+set(LIBSSH_OPTIONS "0.6")
+
 if(ENABLE_PCAP)
        set(PACKAGELIST ${PACKAGELIST} PCAP)
 endif()
@@ -869,6 +872,9 @@ endif()
 if(HAVE_LIBGEOIP)
        set(HAVE_GEOIP 1)
 endif()
+if(LIBSSH_FOUND)
+       set(HAVE_LIBSSH 1)
+endif()
 if(HAVE_LIBCARES)
        set(HAVE_C_ARES 1)
 endif()
@@ -1039,6 +1045,14 @@ if(ENABLE_EXTCAP)
        set(EXTCAP_DIR "${ABSOLUTE_CMAKE_INSTALL_LIBDIR}/${CPACK_PACKAGE_NAME}/extcap/")
 endif()
 
+if(LIBSSH_FOUND)
+       SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LIBSSH_LIBRARIES})
+       CHECK_FUNCTION_EXISTS(ssh_userauth_agent LIBSSH_USERAUTH_AGENT_FOUND)
+       if(LIBSSH_USERAUTH_AGENT_FOUND)
+               set(HAVE_SSH_USERAUTH_AGENT 1)
+       endif()
+endif()
+
 # Location of our plugins. PLUGIN_DIRECTORY should allow running
 # from the build directory similar to DATAFILE_DIR above.
 if(ENABLE_PLUGINS)
@@ -1168,6 +1182,7 @@ endforeach()
 include(FeatureSummary)
 #SET_FEATURE_INFO(NAME DESCRIPTION [URL [COMMENT] ])
 SET_FEATURE_INFO(SBC "SBC Codec for Bluetooth A2DP stream playing" "www: http://git.kernel.org/cgit/bluetooth/sbc.git" )
+SET_FEATURE_INFO(LIBSSH "libssh is library for ssh connections and it is needed to build sshdump" "www: https://www.libssh.org/get-it/" )
 
 FEATURE_SUMMARY(WHAT ALL)
 
@@ -1254,6 +1269,7 @@ set(INSTALL_DIRS
 
 set(INSTALL_FILES
        ${CMAKE_BINARY_DIR}/androiddump.html
+       ${CMAKE_BINARY_DIR}/sshdump.html
        ${CMAKE_BINARY_DIR}/AUTHORS-SHORT
        ${CMAKE_BINARY_DIR}/capinfos.html
        ${CMAKE_BINARY_DIR}/captype.html
@@ -1305,6 +1321,7 @@ set(MAN1_FILES
        ${CMAKE_BINARY_DIR}/randpkt.1
        ${CMAKE_BINARY_DIR}/rawshark.1
        ${CMAKE_BINARY_DIR}/reordercap.1
+       ${CMAKE_BINARY_DIR}/sshdump.1
        ${CMAKE_BINARY_DIR}/text2pcap.1
        ${CMAKE_BINARY_DIR}/tshark.1
        ${CMAKE_BINARY_DIR}/wireshark.1
@@ -1405,6 +1422,13 @@ if(WIN32)
                                "${_dll_output_dir}"
                )
        endif(GEOIP_FOUND)
+       if (LIBSSH_FOUND)
+               add_custom_command(TARGET copy_cli_dlls PRE_BUILD
+                       COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                               "${LIBSSH_DLL_DIR}/${LIBSSH_DLL}"
+                               "${_dll_output_dir}"
+               )
+       endif(LIBSSH_FOUND)
        if(GCRYPT_FOUND)
                foreach( _dll ${GCRYPT_DLLS} )
                        add_custom_command(TARGET copy_cli_dlls PRE_BUILD
@@ -1861,7 +1885,7 @@ macro(set_extra_executable_properties _executable _folder)
 endmacro()
 
 macro(set_extcap_executable_properties _executable)
-       set_target_properties(androiddump PROPERTIES FOLDER "Executables/Extcaps")
+       set_target_properties(${_executable} PROPERTIES FOLDER "Executables/Extcaps")
 
        set(PROGLIST ${PROGLIST} ${_executable})
 
@@ -2309,6 +2333,28 @@ if(BUILD_androiddump)
        install(TARGETS androiddump RUNTIME DESTINATION ${EXTCAP_DIR})
 endif()
 
+if(BUILD_sshdump AND LIBSSH_FOUND)
+       set(sshdump_LIBS
+               ${GLIB2_LIBRARIES}
+               ${CMAKE_DL_LIBS}
+               ${LIBSSH_LIBRARIES}
+       )
+       if (WIN32)
+               set(sshdump_LIBS wsutil ${sshdump_LIBS})
+       endif()
+       set(sshdump_FILES
+               extcap/sshdump.c
+       )
+
+       add_executable(sshdump WIN32 ${sshdump_FILES})
+       set_extcap_executable_properties(sshdump)
+       target_link_libraries(sshdump ${sshdump_LIBS})
+       target_include_directories(sshdump PUBLIC ${LIBSSH_INCLUDE_DIR})
+       install(TARGETS sshdump RUNTIME DESTINATION ${EXTCAP_DIR})
+elseif (BUILD_sshdump)
+       #message( WARNING "Cannot find libssh, cannot build sshdump" )
+endif()
+
 ADD_CUSTOM_COMMAND(
        OUTPUT  ${CMAKE_BINARY_DIR}/AUTHORS-SHORT
        COMMAND ${PERL_EXECUTABLE}
@@ -2430,6 +2476,7 @@ pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/mergecap 1 )
 pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/randpkt 1 )
 pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/rawshark 1 )
 pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/reordercap 1 )
+pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/sshdump 1 )
 pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/text2pcap 1 )
 pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/tshark 1 )
 pod2manhtml( ${CMAKE_BINARY_DIR}/wireshark 1 )
@@ -2452,6 +2499,7 @@ add_custom_target(
                randpkt.html
                rawshark.html
                reordercap.html
+               sshdump.html
                text2pcap.html
                tshark.html
                wireshark.html
@@ -2472,6 +2520,7 @@ set(CLEAN_FILES
        ${editcap_FILES}
        ${dumpcap_FILES}
        ${androiddump_FILES}
+       ${sshdump_FILES}
 )
 
 if (WERROR_COMMON_FLAGS)
@@ -2607,7 +2656,7 @@ else ()
        if (NOT "${HARDENING_CHECK_EXECUTABLE}" STREQUAL "HARDENING_CHECK_EXECUTABLE-NOTFOUND")
                foreach(_prog ${PROGLIST})
                        get_target_property(_prog_dir ${_prog} RUNTIME_OUTPUT_DIRECTORY)
-                       if ("${_prog_dir}" STREQUAL "_prog_dir-NOTFOUND")
+                       if (${_prog_dir} STREQUAL "_prog_dir-NOTFOUND")
                                set(_prog_dir "${CMAKE_BINARY_DIR}/run")
                        endif()
                        set(_prog_paths ${_prog_paths} "${_prog_dir}/${_prog}")
index 4f2440c5ac05f82bc49dde81fb35c34f93899366..b547e74343a24500a647818d6f5b3d771d4fe199 100644 (file)
@@ -15,6 +15,7 @@ option(BUILD_captype       "Build captype" ON)
 option(BUILD_randpkt       "Build randpkt" ON)
 option(BUILD_dftest        "Build dftest" ON)
 option(BUILD_androiddump   "Build androiddump" ON)
+option(BUILD_sshdump       "Build sshdump" ON)
 option(AUTOGEN_dcerpc      "Autogenerate DCE RPC dissectors" OFF)
 option(AUTOGEN_pidl        "Autogenerate pidl dissectors" OFF)
 
index e3a12dbce53a8a22bee1868ff9ef1033b043473f..ebce8cc270467bd4a8e2584a0cae772f62ef067e 100644 (file)
@@ -43,11 +43,12 @@ bin_PROGRAMS = \
        @reordercap_bin@        \
        @rawshark_bin@          \
        @androiddump_bin@       \
+       @sshdump_bin@           \
        @echld_test_bin@
 
 EXTRA_PROGRAMS = wireshark-gtk wireshark tshark tfshark capinfos captype editcap \
        mergecap dftest randpkt text2pcap dumpcap reordercap rawshark androiddump \
-       echld_test
+       sshdump echld_test
 
 #
 # Wireshark configuration files are put in $(pkgdatadir).
@@ -547,6 +548,23 @@ androiddump_LDADD = \
 
 androiddump_CFLAGS = $(AM_CLEAN_CFLAGS)
 
+if ENABLE_STATIC
+       sshdump_LDFLAGS = -Wl,-static -all-static
+else
+       sshdump_LDFLAGS = -export-dynamic
+endif
+
+# Libraries and plugin flags with which to link sshdump.
+sshdump_LDADD = \
+       wiretap/libwiretap.la           \
+       wsutil/libwsutil.la             \
+       @GLIB_LIBS@                     \
+       @LIBSSH_LIBS@           \
+       @SOCKET_LIBS@
+
+sshdump_CFLAGS = $(AM_CLEAN_CFLAGS)
+
+
 # Libraries with which to link text2pcap.
 text2pcap_LDADD = \
        wsutil/libwsutil.la             \
@@ -1322,6 +1340,7 @@ EXTRA_DIST = \
        cmake/modules/FindSETCAP.cmake          \
        cmake/modules/FindSH.cmake              \
        cmake/modules/FindSMI.cmake             \
+       cmake/modules/FindLIBSSH.cmake  \
        cmake/modules/FindWinSparkle.cmake      \
        cmake/modules/FindWireshark.cmake       \
        cmake/modules/FindWSWinLibs.cmake       \
index 0321fc5e5c69af3d70e55713dd79eaac97e355b8..1f0fe02200f8ca857f5f1fc8645f476c5e9b31cd 100644 (file)
@@ -99,6 +99,10 @@ rawshark_SOURCES =   \
 androiddump_SOURCES =  \
        extcap/androiddump.c
 
+# sshdump specifics
+sshdump_SOURCES =      \
+       extcap/sshdump.c
+
 # text2pcap specifics
 text2pcap_SOURCES = \
        pcapio.c                \
index cb1043bc242d3b4bad4837c43e0a944895e37177..63fc01354b8f0648ad0c362616f4f63d04c7058d 100644 (file)
@@ -42,7 +42,7 @@ GENERATED_CFLAGS=\
        /I.  /Iwiretap $(GLIB_CFLAGS) \
        $(ZLIB_CFLAGS) /I$(PCAP_DIR)\include $(AIRPCAP_CFLAGS) \
        $(C_ARES_CFLAGS) $(ADNS_CFLAGS) $(GNUTLS_CFLAGS) \
-       $(SMI_CFLAGS) $(GEOIP_CFLAGS) $(WINSPARKLE_CFLAGS)
+       $(SMI_CFLAGS) $(GEOIP_CFLAGS) $(LIBSSH_CFLAGS) $(WINSPARKLE_CFLAGS)
 
 CFLAGS=$(WARNINGS_ARE_ERRORS) $(GENERATED_CFLAGS)
 
@@ -182,6 +182,12 @@ androiddump_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \
        wsutil\libwsutil.lib \
        $(GLIB_LIBS)
 
+sshdump_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \
+       wsock32.lib user32.lib \
+       wsutil\libwsutil.lib \
+       $(LIBSSH_LIBS) \
+       $(GLIB_LIBS)
+
 dumpcap_LIBS= \
        wsock32.lib user32.lib \
        caputils\libcaputils.lib \
@@ -214,6 +220,10 @@ EXECUTABLES=$(PROGRAM_NAME_GTK).exe tshark.exe tfshark.exe rawshark.exe \
        capinfos.exe captype.exe editcap.exe mergecap.exe text2pcap.exe \
        randpkt.exe reordercap.exe dumpcap.exe androiddump.exe dftest.exe
 
+!IFDEF LIBSSH_DIR
+EXECUTABLES += sshdump.exe
+!ENDIF
+
 !IFDEF QT5_BASE_DIR
 EXECUTABLES=$(EXECUTABLES) $(PROGRAM_NAME).exe
 !ENDIF
@@ -439,6 +449,17 @@ androiddump.exe    : $(LIBS_CHECK) config.h androiddump.obj wsutil\libwsutil.lib wi
        mt.exe -nologo -manifest "androiddump.exe.manifest" -outputresource:androiddump.exe;1
 !ENDIF
 
+!IFDEF LIBSSH_DIR
+sshdump.exe    : $(LIBS_CHECK) config.h sshdump.obj wsutil\libwsutil.lib wiretap\wiretap-$(WTAP_VERSION).lib
+       @echo Linking $@
+       $(LINK) @<<
+               /OUT:sshdump.exe $(conflags) $(conlibsdll) $(LDFLAGS) /SUBSYSTEM:WINDOWS sshdump.obj $(sshdump_LIBS)
+<<
+!IFDEF MANIFEST_INFO_REQUIRED
+       mt.exe -nologo -manifest "sshdump.exe.manifest" -outputresource:sshdump.exe;1
+!ENDIF
+!ENDIF
+
 dumpcap.exe    : $(LIBS_CHECK) config.h $(dumpcap_OBJECTS) caputils wsutil\libwsutil.lib image\dumpcap.res
        @echo Linking $@
        $(LINK) @<<
@@ -485,6 +506,7 @@ config.h    : config.h.win32 config.nmake
            -e "s/@HAVE_SMI@/$(SMI_CONFIG)/" \
            -e "s/@HAVE_GEOIP@/$(GEOIP_CONFIG)/" \
            -e "s/@HAVE_GEOIP_V6@/$(GEOIP_V6_CONFIG)/" \
+           -e "s/@HAVE_LIBSSH/$(LIBSSH_CONFIG)/" \
            -e "s/@HAVE_SOFTWARE_UPDATE@/$(WINSPARKLE_CONFIG)/" \
            -e "s/@INET6@/$(INET6_CONFIG)/" \
            -e "s/@HAVE_NTDDNDIS_H@/$(NTDDNDIS_CONFIG)/" \
@@ -517,6 +539,7 @@ SMI_DIR = $(SMI_DIR:\=/)
 KFW_DIR = $(KFW_DIR:\=/)
 LUA_DIR = $(LUA_DIR:\=/)
 GEOIP_DIR = $(GEOIP_DIR:\=/)
+LIBSSH_DIR = $(LIBSSH_DIR:\=/)
 WINSPARKLE_DIR = $(WINSPARKLE_DIR:\=/)
 
 GCC_DLL = $(GCC_DLL)
@@ -573,6 +596,9 @@ text2pcap-scanner.obj : text2pcap-scanner.c
 androiddump.obj : extcap/androiddump.c
        $(CC) $(CFLAGS) -Fd.\ -c $?
 
+sshdump.obj : extcap/sshdump.c
+       $(CC) $(CFLAGS) -Fd.\ -c $?
+
 test-programs:
        cd epan
        $(MAKE) /$(MAKEFLAGS) -f Makefile.nmake test-programs
@@ -581,7 +607,7 @@ test-programs:
 clean-local:
        rm -f $(wireshark_gtk_OBJECTS) $(tshark_OBJECTS) $(tfshark_OBJECTS) $(dumpcap_OBJECTS) $(rawshark_OBJECTS) \
                $(EXECUTABLES) *.nativecodeanalysis.xml *.pdb *.sbr *.exe.manifest \
-               androiddump.obj \
+               androiddump.obj sshdump.obj \
                capinfos.obj capinfos.exp capinfos.lib \
                captype.obj captype.exp captype.lib \
                editcap.obj editcap.exp editcap.lib \
@@ -1088,6 +1114,12 @@ process_libs:
                GeoIP-$(GEOIP_PKG)-$(WIRESHARK_TARGET_PLATFORM)ws.zip \
                "$(DOWNLOAD_TAG)" "$(WIRESHARK_TARGET_PLATFORM)"
 !ENDIF
+!IFDEF LIBSSH_DIR
+       @$(SH) $(WIN_SETUP) "$(WIN_SETUP_OPT)" "$(WIRESHARK_LIB_DIR)" \
+               libssh-$(LIBSSH_PKG)-$(WIRESHARK_TARGET_PLATFORM)ws \
+               libssh-$(LIBSSH_PKG)-$(WIRESHARK_TARGET_PLATFORM)ws.zip \
+               "$(DOWNLOAD_TAG)" "$(WIRESHARK_TARGET_PLATFORM)"
+!ENDIF
 !IFDEF WINSPARKLE_DIR
        @$(SH) $(WIN_SETUP) "$(WIN_SETUP_OPT)" "$(WIRESHARK_LIB_DIR)" \
                . \
@@ -1184,6 +1216,7 @@ clean_setup:
        rm -r -f AirPcap_Devpack_4_1_0_1622
        rm -r -f GeoIP-1.4.5ws
        rm -r -f GeoIP-1.*-win??ws
+       rm -r -f libssh-0.7.2
        rm -r -f WinSparkle-0.3-44-g2c8d9d3-win??ws
        rm -r -f WpdPack
        cd "$(MAKEDIR)"
@@ -1234,9 +1267,13 @@ install-generated-files: doc
        if not exist $(INSTALL_DIR)\extcap mkdir $(INSTALL_DIR)\extcap
        if exist androiddump.exe xcopy androiddump.exe $(INSTALL_DIR)\extcap /d
        if exist androiddump.pdb xcopy androiddump.pdb $(INSTALL_DIR)\extcap /d
+       if exist sshdump.exe xcopy sshdump.exe $(INSTALL_DIR)\extcap /d
+       if exist sshdump.pdb xcopy sshdump.pdb $(INSTALL_DIR)\extcap /d
        if not exist $(INSTALL_DIR_QT)\extcap mkdir $(INSTALL_DIR_QT)\extcap
        if exist androiddump.exe xcopy androiddump.exe $(INSTALL_DIR_QT)\extcap /d
        if exist androiddump.pdb xcopy androiddump.pdb $(INSTALL_DIR_QT)\extcap /d
+       if exist sshdump.exe xcopy sshdump.exe $(INSTALL_DIR_QT)\extcap /d
+       if exist sshdump.pdb xcopy sshdump.pdb $(INSTALL_DIR_QT)\extcap /d
        if exist capinfos.exe xcopy capinfos.exe $(INSTALL_DIR) /d
        if exist capinfos.pdb xcopy capinfos.pdb $(INSTALL_DIR) /d
        if exist captype.exe xcopy captype.exe $(INSTALL_DIR) /d
@@ -1463,6 +1500,9 @@ install-all: install-generated-files
 !IFDEF GEOIP_DIR
        xcopy "$(GEOIP_DIR)\bin\libGeoip-1.dll" $(INSTALL_DIR) /d
 !ENDIF
+!IFDEF LIBSSH_DIR
+       xcopy "$(LIBSSH_DIR)\bin\libssh.dll" $(INSTALL_DIR) /d
+!ENDIF
 !IFDEF WINSPARKLE_DIR
        xcopy "$(WINSPARKLE_DIR)\WinSparkle.dll" $(INSTALL_DIR) /d
 !ENDIF
index 4220fb86c54c9af31457eb17d7c6ba01e549aadf..89a77016a11e24b49fac19ec18187f8f6490ee4b 100644 (file)
@@ -1476,6 +1476,43 @@ AC_DEFUN([AC_WIRESHARK_GEOIP_CHECK],
        fi
 ])
 
+#
+# AC_WIRESHARK_LIBSSH_CHECK
+#
+AC_DEFUN([AC_WIRESHARK_LIBSSH_CHECK],
+[
+       want_libssh=defaultyes
+
+       if test "x$want_libssh" = "xdefaultyes"; then
+               want_libssh=yes
+               if test "x$ac_cv_enable_usr_local" = "xyes" ; then
+                       withval=/usr/local
+                       if test -d "$withval"; then
+                               AC_WIRESHARK_ADD_DASH_L(LDFLAGS, ${withval}/lib)
+                       fi
+               fi
+       fi
+
+       if test "x$want_libssh" = "xyes"; then
+               AC_CHECK_LIB(ssh, ssh_new,
+                 [
+                   LIBSSH_LIBS=-lssh
+                       AC_DEFINE(HAVE_LIBSSH, 1, [Define to use libssh library])
+                       have_good_libssh=yes
+                 ],,
+               )
+               AC_CHECK_LIB(ssh, ssh_userauth_agent,
+                 [
+                   LIBSSH_LIBS=-lssh
+                       AC_DEFINE(HAVE_SSH_USERAUTH_AGENT, 1, [Libssh library has ssh_userauth_agent])
+                       have_ssh_userauth_agent=yes
+                 ],,
+               )
+       else
+               AC_MSG_RESULT(not required)
+       fi
+])
+
 #AC_WIRESHARK_LDFLAGS_CHECK
 #
 # $1 : ldflag(s) to test
diff --git a/cmake/modules/FindLIBSSH.cmake b/cmake/modules/FindLIBSSH.cmake
new file mode 100644 (file)
index 0000000..db13825
--- /dev/null
@@ -0,0 +1,101 @@
+# - Try to find LibSSH
+# Once done this will define
+#
+#  LIBSSH_FOUND - system has LibSSH
+#  LIBSSH_INCLUDE_DIRS - the LibSSH include directory
+#  LIBSSH_LIBRARIES - Link these to use LibSSH
+#
+#  Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
+#  Modified by Peter Wu <peter@lekensteyn.nl> to use standard
+#  find_package(LIBSSH ...) without external module.
+#
+#  Redistribution and use is allowed according to the terms of the New
+#  BSD license.
+#  For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+if(LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)
+  # in cache already
+  set(LIBSSH_FOUND TRUE)
+else ()
+
+  include(FindWSWinLibs)
+  FindWSWinLibs("libssh-.*" "LIBSSH_HINTS")
+
+  find_path(LIBSSH_INCLUDE_DIR
+    NAMES
+      libssh/libssh.h
+    HINTS
+      "${LIBSSH_HINTS}/include"
+    PATHS
+      /usr/include
+      /usr/local/include
+      /opt/local/include
+      /sw/include
+      ${CMAKE_INCLUDE_PATH}
+      ${CMAKE_INSTALL_PREFIX}/include
+  )
+
+  find_library(LIBSSH_LIBRARY
+    NAMES
+      ssh
+      libssh
+    HINTS
+      "${LIBSSH_HINTS}/lib"
+    PATHS
+      /usr/lib
+      /usr/local/lib
+      /opt/local/lib
+      /sw/lib
+      ${CMAKE_LIBRARY_PATH}
+      ${CMAKE_INSTALL_PREFIX}/lib
+  )
+
+  if(LIBSSH_INCLUDE_DIR AND LIBSSH_LIBRARY)
+    set(LIBSSH_INCLUDE_DIRS
+      ${LIBSSH_INCLUDE_DIR}
+    )
+    set(LIBSSH_LIBRARIES
+      ${LIBSSH_LIBRARY}
+    )
+
+    file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_MAJOR
+      REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+")
+    # Older versions of libssh like libssh-0.2 have LIBSSH_VERSION but not LIBSSH_VERSION_MAJOR
+    if(LIBSSH_VERSION_MAJOR)
+      string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MAJOR ${LIBSSH_VERSION_MAJOR})
+      file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_MINOR
+        REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+")
+      string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MINOR ${LIBSSH_VERSION_MINOR})
+      file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_PATCH
+        REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+")
+      string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_PATCH ${LIBSSH_VERSION_PATCH})
+      set(LIBSSH_VERSION ${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH})
+    endif()
+  endif()
+
+  # handle the QUIETLY and REQUIRED arguments and set LIBSSH_FOUND to TRUE if
+  # all listed variables are TRUE and the requested version matches.
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(LIBSSH
+    REQUIRED_VARS   LIBSSH_LIBRARIES LIBSSH_INCLUDE_DIRS LIBSSH_VERSION
+    VERSION_VAR     LIBSSH_VERSION)
+
+  if(WIN32)
+    set(LIBSSH_DLL_DIR "${LIBSSH_HINTS}/bin"
+      CACHE PATH "Path to libssh DLL"
+    )
+    file(GLOB _libssh_dll RELATIVE "${LIBSSH_DLL_DIR}"
+      "${LIBSSH_DLL_DIR}/ssh.dll"
+    )
+    set(LIBSSH_DLL ${_libssh_dll}
+      # We're storing filenames only. Should we use STRING instead?
+      CACHE FILEPATH "libssh DLL file name"
+    )
+    mark_as_advanced(LIBSSH_DLL_DIR LIBSSH_DLL)
+  endif()
+
+  # show the LIBSSH_INCLUDE_DIRS and LIBSSH_LIBRARIES variables only in the advanced view
+  mark_as_advanced(LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES)
+
+endif()
index dfc7e3290c18c7f8f47dba69812fafc547ea6492..81812f1f942f7fca3c251b08880abe03569d5b12 100644 (file)
 /* Define if GeoIP supports IPv6 (GeoIP 1.4.5 and later) */
 #cmakedefine HAVE_GEOIP_V6 1
 
+/* Define if LIBSSH support is enabled */
+#cmakedefine HAVE_LIBSSH 1
+
+/* Define if LIBSSH has ssh_userauth_agent() function */
+#cmakedefine HAVE_SSH_USERAUTH_AGENT 1
+
 /* Define if you have the 'floorl' function. */
 #cmakedefine HAVE_FLOORL 1
 
index 700f28023a463ef0a97dc029eb9d167ad246d8ee..261948645777d908393fc7d918f2539769ccd442 100644 (file)
@@ -431,6 +431,13 @@ GNUTLS_PKG=3.2.15-2.7
 GPGERROR_DLL=libgpg-error-0.dll
 GCC_DLL=libgcc_s_sjlj-1.dll
 
+# Optional: libssh library is required for sshdump support
+#
+# If you don't have libssh, comment this line out so that LIBSSH_DIR
+# isn't defined.
+#
+#LIBSSH_DIR=$(WIRESHARK_LIB_DIR)\libssh-0.7.2
+
 #
 # Optional: the KFW library enables kerberos/sasl/dcerpc decryption.
 #
@@ -1686,6 +1693,18 @@ GNUTLS_CONFIG=
 LIBGCRYPT_CONFIG=
 !ENDIF
 
+!IFDEF LIBSSH_DIR
+LIBSSH_CFLAGS=/I$(LIBSSH_DIR)\include
+LIBSSH_LIBS=$(LIBSSH_DIR)\lib\ssh.lib
+# Nmake uses carets to escape special characters
+LIBSSH_CONFIG=^#define HAVE_LIBSSH 1
+LIBSSH_VERSION=^#define HAVE_LIBSSH 1
+!else
+LIBSSH_CFLAGS=
+LIBSSH_LIBS=
+LIBSSH_CONFIG=
+!ENDIF
+
 !IFDEF LUA_DIR
 LUA_CFLAGS=/I$(LUA_DIR)\include
 LUA_LIBS=$(LUA_DIR)\lua52.lib
index 4bd21bf75e0202c489a85705dcedc09b3e06a3e2..524c86148521293d53a9b92a03ff089d4eabc4dc 100644 (file)
@@ -2331,6 +2331,37 @@ fi
 AC_SUBST(androiddump_bin)
 AC_SUBST(androiddump_man)
 
+dnl sshdump check
+AC_MSG_CHECKING(whether to build sshdump)
+
+AC_ARG_ENABLE(sshdump,
+  AC_HELP_STRING( [--enable-sshdump],
+                 [build sshdump @<:@default=yes@:>@]),
+    sshdump=$enableval,enable_sshdump=yes)
+
+if test "x$enable_sshdump" = "xyes" ; then
+       AC_MSG_RESULT(yes)
+else
+       AC_MSG_RESULT(no)
+fi
+
+if test "x$enable_sshdump" = "xyes" ; then
+       if  test "x$have_good_libssh" = "xyes" ; then
+               sshdump_bin="sshdump\$(EXEEXT)"
+               sshdump_man="sshdump.1"
+       else
+               echo "Can't find libssh. Disabling sshdump."
+               enable_sshdump=no
+               sshdump_bin=""
+               sshdump_man=""
+       fi
+else
+       sshdump_bin=""
+       sshdump_man=""
+fi
+AC_SUBST(sshdump_bin)
+AC_SUBST(sshdump_man)
+
 # Enable/disable echld
 AC_ARG_ENABLE(echld,
   AC_HELP_STRING( [--enable-echld],
@@ -2816,6 +2847,31 @@ else
 fi
 AC_SUBST(GEOIP_LIBS)
 
+dnl LIBSSH Check
+LIBSSH=''
+AC_MSG_CHECKING(whether to use the libssh library if available)
+
+AC_ARG_WITH(ssh,
+  AC_HELP_STRING( [--with-libssh@<:@=DIR@:>@],
+                 [use libssh (located in directory DIR, if supplied) @<:@default=yes, if present@:>@]),
+[
+if   test "x$withval" = "xno";  then
+       want_libssh=no
+elif test "x$withval" = "xyes"; then
+       want_libssh=yes
+elif test -d "$withval"; then
+       want_libssh=yes
+       AC_WIRESHARK_ADD_DASH_L(LDFLAGS, ${withval}/lib)
+fi
+])
+if test "x$want_libssh" = "xno"; then
+       AC_MSG_RESULT(no)
+else
+       AC_MSG_RESULT(yes)
+       AC_WIRESHARK_LIBSSH_CHECK
+fi
+AC_SUBST(LIBSSH_LIBS)
+
 #
 # Define WS_MSVC_NORETURN appropriately for declarations of routines that
 # never return (just like Charlie on the MTA).
@@ -3377,6 +3433,18 @@ else
        geoip_message="no"
 fi
 
+if test "x$have_good_libssh" = "xyes" ; then
+       libssh_message="yes"
+else
+       libssh_message="no"
+fi
+
+if test "x$have_ssh_userauth_agent" = "xyes" ; then
+       ssh_userauth_agent_message="yes"
+else
+       ssh_userauth_agent_message="no"
+fi
+
 echo ""
 echo "The Wireshark package has been configured with the following options."
 echo "                    Build wireshark : $enable_wireshark_qt$qt_lib_message"
@@ -3394,6 +3462,7 @@ echo "                      Build randpkt : $enable_randpkt"
 echo "                       Build dftest : $enable_dftest"
 echo "                     Build rawshark : $enable_rawshark"
 echo "                  Build androiddump : $enable_androiddump"
+echo "                      Build sshdump : $enable_sshdump"
 echo "                        Build echld : $have_echld"
 echo ""
 echo "   Save files as pcap-ng by default : $enable_pcap_ng_default"
@@ -3418,6 +3487,8 @@ echo "           Use IPv6 name resolution : $enable_ipv6"
 echo "                 Use gnutls library : $tls_message"
 echo "     Use POSIX capabilities library : $libcap_message"
 echo "                  Use GeoIP library : $geoip_message"
+echo "                 Use libssh library : $libssh_message"
+echo "            Have ssh_userauth_agent : $ssh_userauth_agent_message"
 echo "                     Use nl library : $libnl_message"
 echo "              Use SBC codec library : $have_sbc"
 #echo "                      Use GResource : $have_gresource"
index f91eb8e0f2ca5f5ed99d857b6276b1b78817b582..b78326dcd2b50bfcb8fa337158c5b2b8d2606af0 100644 (file)
@@ -1,4 +1,5 @@
 obj-*/androiddump.1
+obj-*/sshdump.1
 obj-*/editcap.1
 obj-*/extcap.4
 obj-*/mergecap.1
index 8f00fdfd4984554188d3e099dca7e4d7a8d774dd..1c4381ec23be8e92469821d5660f94e555dabbf8 100644 (file)
@@ -71,7 +71,8 @@ man1_MANS = \
        @rawshark_man@          \
        @dftest_man@            \
        @randpkt_man@           \
-       @androiddump_man@
+       @androiddump_man@       \
+       @sshdump_man@
 man4_MANS = @wiresharkfilter_man@
 man_MANS =
 
@@ -83,7 +84,7 @@ noinst_DATA = asn2deb.1 asn2deb.html idl2deb.1 idl2deb.html idl2wrs.1 idl2wrs.ht
 pkgdata_DATA = AUTHORS-SHORT $(top_srcdir)/docbook/ws.css wireshark.html \
        tshark.html wireshark-filter.html capinfos.html editcap.html \
        mergecap.html reordercap.html text2pcap.html dumpcap.html androiddump.html \
-       rawshark.html dftest.html randpkt.html
+       sshdump.html rawshark.html dftest.html randpkt.html
 
 #
 # Build the short version of the authors file for the about dialog
@@ -212,6 +213,13 @@ androiddump.html: androiddump.pod ../config.h $(top_srcdir)/docbook/ws.css
        --noindex                                                       \
        $(srcdir)/androiddump.pod > androiddump.html
 
+sshdump.html: sshdump.pod ../config.h $(top_srcdir)/docbook/ws.css
+       $(AM_V_POD2HTML)$(POD2HTML)                     \
+       --title="sshdump - The Wireshark Network Analyzer $(VERSION)"   \
+       --css=$(POD_CSS_URL)                                            \
+       --noindex                                                       \
+       $(srcdir)/sshdump.pod > sshdump.html
+
 rawshark.html: rawshark.pod ../config.h $(top_srcdir)/docbook/ws.css
        $(AM_V_POD2HTML)$(POD2HTML)                     \
        --title="rawshark - The Wireshark Network Analyzer $(VERSION)"  \
@@ -293,6 +301,7 @@ EXTRA_DIST =                                \
        rawshark.pod                    \
        reordercap.pod                  \
        sgml.doc.template               \
+       sshdump.pod                             \
        text2pcap.pod                   \
        tshark.pod                      \
        wireshark-filter.pod            \
index dfe2710cf435fc07d20b6c71d4f86d913f993725..35e114b37c1a0c5db7e3612c2e82f4378bdd71e7 100644 (file)
@@ -26,12 +26,13 @@ include ../config.nmake
 
 doc: wireshark.html tshark.html wireshark-filter.html capinfos.html \
        editcap.html idl2wrs.html mergecap.html reordercap.html \
-       text2pcap.html dumpcap.html androiddump.html rawshark.html dftest.html randpkt.html \
+       text2pcap.html dumpcap.html androiddump.html sshdump.html rawshark.html \
+       dftest.html randpkt.html \
        idl2deb.html asn2deb.html extcap.html
 
 man: wireshark.1 tshark.1 wireshark-filter.4 capinfos.1 \
        editcap.1 idl2wrs.1 mergecap.1 reordercap.1 \
-       text2pcap.1 dumpcap.1 androiddump.1 rawshark.1 dftest.1 randpkt.1 \
+       text2pcap.1 dumpcap.1 androiddump.1 sshdump.1 rawshark.1 dftest.1 randpkt.1 \
        idl2deb.1 asn2deb.1 extcap.4
 
 wireshark.pod: wireshark.pod.template AUTHORS-SHORT-FORMAT
@@ -235,6 +236,19 @@ androiddump.html: androiddump.pod ../config.h ws.css
        --noindex                                 \
        androiddump.pod > androiddump.html
 
+sshdump.1: sshdump.pod ../config.h
+       $(POD2MAN)                      \
+       --center="The Wireshark Network Analyzer" \
+       --release=$(VERSION)                     \
+       sshdump.pod > sshdump.1
+
+sshdump.html: sshdump.pod ../config.h ws.css
+       $(POD2HTML)                     \
+       --title="sshdump - The Wireshark Network Analyzer $(VERSION)" \
+       --css=ws.css \
+       --noindex                                 \
+       sshdump.pod > sshdump.html
+
 rawshark.1: rawshark.pod ../config.h
        $(POD2MAN)                      \
        --center="The Wireshark Network Analyzer" \
index 9795beb256f406bc9881edc76487f7acf5c31128..d267ec28c71cb6cd1f2527cd260167a81c67826d 100644 (file)
@@ -96,7 +96,7 @@ Example 3:
 
 =head1 SEE ALSO
 
-wireshark(1), tshark(1), dumpcap(1), androiddump(1)
+wireshark(1), tshark(1), dumpcap(1), androiddump(1), sshdump(1)
 
 =head1 NOTES
 
diff --git a/doc/sshdump.pod b/doc/sshdump.pod
new file mode 100644 (file)
index 0000000..6defdf1
--- /dev/null
@@ -0,0 +1,212 @@
+
+=head1 NAME
+
+sshdump - Provide interfaces to capture from a remote host through SSH using a remote capture binary.
+
+=head1 SYNOPSIS
+
+B<sshdump>
+S<[ B<--help> ]>
+S<[ B<--version> ]>
+S<[ B<--extcap-interfaces> ]>
+S<[ B<--extcap-dlts> ]>
+S<[ B<--extcap-interface>=E<lt>interfaceE<gt> ]>
+S<[ B<--extcap-config> ]>
+S<[ B<--extcap-capture-filter>=E<lt>capture filterE<gt> ]>
+S<[ B<--capture> ]>
+S<[ B<--fifo>=E<lt>path to file or pipeE<gt> ]>
+S<[ B<--remote-host>=E<lt>IP addressE<gt> ]>
+S<[ B<--remote-port>=E<lt>TCP portE<gt> ]>
+S<[ B<--remote-username>=E<lt>usernameE<gt> ]>
+S<[ B<--remote-password>=E<lt>passwordE<gt> ]>
+S<[ B<--sshkey>=E<lt>public key path<gt> ]>
+S<[ B<--remote-interface>=E<lt>interfaceE<gt> ]>
+S<[ B<--remote-capture-bin>=E<lt>capture binaryE<gt> ]>
+
+B<sshdump>
+S< B<--extcap-interfaces> >
+
+B<sshdump>
+S< B<--extcap-interface>=E<lt>interfaceE<gt> >
+S<[ B<--extcap-dlts> ]>
+
+B<sshdump>
+S< B<--extcap-interface>=E<lt>interfaceE<gt> >
+S<[ B<--extcap-config> ]>
+
+B<sshdump>
+S< B<--extcap-interface>=E<lt>interfaceE<gt> >
+S< B<--fifo>=E<lt>path to file or pipeE<gt> >
+S< B<--capture> >
+S< B<--remote-host=myremotehost> >
+S< B<--remote-port=22> >
+S< B<--remote-username=user> >
+S< B<--remote-interface=eth2> >
+S< B<--remote-capture-bin=/usr/sbin/dumpcap> >
+
+=head1 DESCRIPTION
+
+B<Sshdump> is a extcap tool that allows to run a remote capture
+tool in a SSH connection. The requirement is that the capture
+executable must have the capabilities to capture from the wanted
+interface.
+
+The feature is functionally equivalent to run commands like
+
+$ ssh remoteuser@remotehost -p 22222 'dumpcap -i IFACE -P -w -' > FILE &
+$ wireshark FILE
+
+$ ssh remoteuser@remotehost '/sbin/dumpcap -i IFACE -P -w - -f "not port 22"' > FILE &
+$ wireshark FILE
+
+Supported interfaces:
+
+=over 4
+
+=item 1. ssh
+
+=back
+
+=head1 OPTIONS
+
+=over 4
+
+=item --help
+
+Print program arguments.
+
+=item --version
+
+Print program version.
+
+=item --extcap-interfaces
+
+List available interfaces.
+
+=item --extcap-interface=E<lt>interfaceE<gt>
+
+Use specified interfaces.
+
+=item --extcap-dlts
+
+List DLTs of specified interface.
+
+=item --extcap-config
+
+List configuration options of specified interface.
+
+=item --capture
+
+Start capturing from specified interface save saved it in place specified by --fifo.
+
+=item --fifo=E<lt>path to file or pipeE<gt>
+
+Save captured packet to file or send it through pipe.
+
+=item --remote-host=E<lt>remote hostE<gt>
+
+The address of the remote host for capture.
+
+=item --remote-port=E<lt>remote portE<gt>
+
+The SSH port of the remote host.
+
+=item --remote-username=E<lt>usernameE<gt>
+
+The username for ssh authentication.
+
+=item --remote-password=E<lt>passwordE<gt>
+
+The password to use (if not ssh-agent and pubkey are used). WARNING: the
+passwords are stored in plaintext and visible to all users on this system. It is
+recommended to use keyfiles with a SSH agent.
+
+=item --sshkey=E<lt>SSH private key pathE<gt>
+
+The path to a private key for authentication.
+
+=item --remote-interface=E<lt>remote interfaceE<gt>
+
+The remote network interface to capture from.
+
+=item --remote-capture-bin=E<lt>capture binaryE<gt>
+
+The remote capture binary.
+
+=item --extcap-capture-filter=E<lt>capture filterE<gt>
+
+The capture filter
+
+=back
+
+=head1 EXAMPLES
+
+To see program arguments:
+
+    sshdump --help
+
+To see program version:
+
+    sshdump --version
+
+To see interfaces:
+
+    sshdump --extcap-interfaces
+
+Only one interface (ssh) is supported.
+
+  Output:
+    interface {value=ssh}{display=SSH remote capture}
+
+To see interface DLTs:
+
+    sshdump --extcap-interface=ssh --extcap-dlts
+
+  Output:
+    dlt {number=147}{name=ssh}{display=Remote capture dependant DLT}
+
+To see interface configuration options:
+
+    sshdump --extcap-interface=ssh --extcap-config
+
+  Output:
+    arg {number=0}{call=--remote-host}{display=Remote SSH server address}{type=string}{default=127.0.0.1}
+    {tooltip=The remote SSH host. It can be both an IP address or an hostname}
+    arg {number=1}{call=--remote-port}{display=Remote SSH server port}{type=unsigned}{default=22}
+    {tooltip=The remote SSH host port}
+    arg {number=2}{call=--remote-username}{display=Remote SSH server username}{type=string}{default=dario}
+    {tooltip=The remote SSH username. If not provided, the current user will be used}
+    arg {number=3}{call=--remote-password}{display=Remote SSH server password}{type=string}
+    {tooltip=The SSH password. SSH agent and certificate are used before it.If they fail, password will
+    be used, and, if it fails, the connection is not established.}
+    arg {number=4}{call=--remote-interface}{display=Remote SSH server interface}{type=string}{default=eth0}
+    {tooltip=The remote network interface used for capture}
+    arg {number=5}{call=--remote-capture-bin}{display=Remote SSH capture bin}{type=string}{default=dumpcap}
+    {tooltip=The remote dumcap binary used for capture.}
+    arg {number=6}{call=--extcap-capture-filter}{display=Capture filter}{type=string}{default=not host hardcore}
+    {tooltip=The capture filter}
+
+To capture:
+
+    sshdump --extcap-interface=ssh --fifo=/tmp/ssh.pcapng --capture --remote-host 192.168.1.10
+    --remote-username user --extcap-capture-filter "not port 22"
+
+NOTE: To stop capturing CTRL+C/kill/terminate application.
+
+=head1 SEE ALSO
+
+wireshark(1), tshark(1), dumpcap(1), extcap(4)
+
+=head1 NOTES
+
+B<Sshdump> is part of the B<Wireshark> distribution.  The latest version
+of B<Wireshark> can be found at L<https://www.wireshark.org>.
+
+HTML versions of the Wireshark project man pages are available at:
+L<https://www.wireshark.org/docs/man-pages>.
+
+=head1 AUTHORS
+
+  Original Author
+  -------- ------
+  Dario Lombardo             <lomato[AT]gmail.com>
diff --git a/extcap/sshdump.c b/extcap/sshdump.c
new file mode 100644 (file)
index 0000000..736e06e
--- /dev/null
@@ -0,0 +1,850 @@
+/* sshdump.c
+ * sshdump is extcap tool used to capture data using a remote ssh host
+ *
+ * Copyright 2015, Dario Lombardo
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib/gstdio.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libssh/libssh.h>
+
+#ifdef HAVE_ARPA_INET_H
+       #include <arpa/inet.h>
+#endif
+
+#include "log.h"
+
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#ifndef HAVE_GETOPT_LONG
+       #include "wsutil/wsgetopt.h"
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       #ifdef HAVE_WINDOWS_H
+               #include <windows.h>
+       #endif
+
+       #include <ws2tcpip.h>
+
+       #ifdef HAVE_WINSOCK2_H
+               #include <winsock2.h>
+       #endif
+
+       #include <process.h>
+
+       #define socket_handle_t SOCKET
+#else
+/*
+ * UN*X, or Windows pretending to be UN*X with the aid of Cygwin.
+ */
+#define closesocket(socket)  close(socket)
+#define socket_handle_t int
+#define INVALID_SOCKET (-1)
+#define SOCKET_ERROR (-1)
+#endif
+
+#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__) || defined(__linux__)
+#define USE_GETIFADDRS 1
+#include <ifaddrs.h>
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#define SSHDUMP_VERSION_MAJOR 1U
+#define SSHDUMP_VERSION_MINOR 0U
+#define SSHDUMP_VERSION_RELEASE 0U
+
+#define SSH_EXTCAP_INTERFACE "ssh"
+#define SSH_READ_BLOCK_SIZE 256
+
+static gboolean verbose = FALSE;
+
+enum {
+       OPT_HELP = 1,
+       OPT_VERSION,
+       OPT_VERBOSE,
+       OPT_LIST_INTERFACES,
+       OPT_LIST_DLTS,
+       OPT_INTERFACE,
+       OPT_CONFIG,
+       OPT_CAPTURE,
+       OPT_FIFO,
+       OPT_EXTCAP_FILTER,
+       OPT_REMOTE_HOST,
+       OPT_REMOTE_PORT,
+       OPT_REMOTE_USERNAME,
+       OPT_REMOTE_PASSWORD,
+       OPT_REMOTE_INTERFACE,
+       OPT_REMOTE_CAPTURE_BIN,
+       OPT_REMOTE_FILTER,
+       OPT_SSHKEY,
+       OPT_SSHKEY_PASSPHRASE
+};
+
+static struct option longopts[] = {
+/* Generic application options */
+       { "help", no_argument, NULL, OPT_HELP},
+       { "version", no_argument, NULL, OPT_VERSION},
+       { "verbose", optional_argument, NULL, OPT_VERBOSE},
+       { "extcap-interfaces", no_argument, NULL, OPT_LIST_INTERFACES},
+       { "extcap-dlts", no_argument, NULL, OPT_LIST_DLTS},
+       { "extcap-interface", required_argument, NULL, OPT_INTERFACE},
+       { "extcap-config", no_argument, NULL, OPT_CONFIG},
+       { "extcap-capture-filter", required_argument, NULL, OPT_EXTCAP_FILTER},
+       { "capture", no_argument, NULL, OPT_CAPTURE},
+       { "fifo", required_argument, NULL, OPT_FIFO},
+       { "remote-host", required_argument, NULL, OPT_REMOTE_HOST},
+       { "remote-port", required_argument, NULL, OPT_REMOTE_PORT},
+       { "remote-username", required_argument, NULL, OPT_REMOTE_USERNAME},
+       { "remote-password", required_argument, NULL, OPT_REMOTE_PASSWORD},
+       { "remote-interface", required_argument, NULL, OPT_REMOTE_INTERFACE},
+       { "remote-capture-bin", required_argument, NULL, OPT_REMOTE_CAPTURE_BIN},
+       { "remote-filter", required_argument, NULL, OPT_REMOTE_FILTER},
+       { "sshkey", required_argument, NULL, OPT_SSHKEY},
+       { "sshkey-passphrase", required_argument, NULL, OPT_SSHKEY_PASSPHRASE},
+       { 0, 0, 0, 0}
+};
+
+#define verbose_print(...) { if (verbose) g_print(__VA_ARGS__); }
+#define errmsg_print(...) { g_print(__VA_ARGS__); g_print("\n"); }
+
+static char* local_interfaces_to_filter(unsigned int remote_port);
+
+static void ssh_cleanup(ssh_session sshs, ssh_channel channel)
+{
+       if (channel) {
+               ssh_channel_send_eof(channel);
+               ssh_channel_close(channel);
+               ssh_channel_free(channel);
+       }
+
+       if (sshs) {
+               ssh_disconnect(sshs);
+               ssh_free(sshs);
+       }
+}
+
+static ssh_session create_ssh_connection(const char* hostname, const unsigned int port, const char* username,
+       const char* password, const char* sshkey_path, const char* sshkey_passphrase)
+{
+       ssh_session sshs;
+
+       /* Open session and set options */
+       sshs = ssh_new();
+       if (sshs == NULL) {
+               errmsg_print("Can't create ssh session");
+               return NULL;
+       }
+
+       if (!hostname)
+               return NULL;
+
+       if (ssh_options_set(sshs, SSH_OPTIONS_HOST, hostname)) {
+               errmsg_print("Can't set the hostname: %s\n", hostname);
+               goto failure;
+       }
+
+       if (port != 0) {
+               if (ssh_options_set(sshs, SSH_OPTIONS_PORT, &port)) {
+                       errmsg_print("Can't set the port: %d\n", port);
+                       goto failure;
+               }
+       }
+
+       if (!username)
+               username = g_get_user_name();
+
+       if (ssh_options_set(sshs, SSH_OPTIONS_USER, username)) {
+               errmsg_print("Can't set the username: %s\n", username);
+               goto failure;
+       }
+
+       verbose_print("Opening ssh connection to %s@%s:%u\n", username, hostname, port);
+
+       /* Connect to server */
+       if (ssh_connect(sshs) != SSH_OK) {
+               errmsg_print("Error connecting to %s@%s:%u (%s)\n", username, hostname, port,
+                       ssh_get_error(sshs));
+               goto failure;
+       }
+
+#ifdef HAVE_LIBSSH_USERAUTH_AGENT
+       verbose_print("Connecting using ssh-agent...");
+       /* Try to authenticate using ssh agent */
+       if (ssh_userauth_agent(sshs, NULL) == SSH_AUTH_SUCCESS) {
+               verbose_print("done\n");
+               return sshs;
+       }
+       verbose_print("failed\n");
+#endif
+
+       /* If a public key path has been provided, try to authenticate using it */
+       if (sshkey_path) {
+               ssh_key pkey = ssh_key_new();
+               int ret;
+
+               verbose_print("Connecting using public key in %s...", sshkey_path);
+               ret = ssh_pki_import_privkey_file(sshkey_path, sshkey_passphrase, NULL, NULL, &pkey);
+
+               if (ret == SSH_OK) {
+                       if (ssh_userauth_publickey(sshs, NULL, pkey) == SSH_AUTH_SUCCESS) {
+                               verbose_print("done\n");
+                               ssh_key_free(pkey);
+                               return sshs;
+                       }
+               }
+               ssh_key_free(pkey);
+               verbose_print("failed (%s)\n", ssh_get_error(sshs));
+       }
+
+       /* Try to authenticate using standard public key */
+       verbose_print("Connecting using standard public key...");
+       if (ssh_userauth_publickey_auto(sshs, NULL, NULL) == SSH_AUTH_SUCCESS) {
+               verbose_print("done\n");
+               return sshs;
+       }
+       verbose_print("failed\n");
+
+       /* If a password has been provided and all previous attempts failed, try to use it */
+       if (password) {
+               verbose_print("Connecting using password...");
+               if (ssh_userauth_password(sshs, username, password) == SSH_AUTH_SUCCESS) {
+                       verbose_print("done\n");
+                       return sshs;
+               }
+               verbose_print("failed\n");
+       }
+
+       verbose_print("Can't find a valid authentication. Disconnecting.\n");
+
+       /* All authentication failed. Disconnect and return */
+       ssh_disconnect(sshs);
+
+failure:
+       ssh_free(sshs);
+       return NULL;
+}
+
+static void ssh_loop_read(ssh_channel channel, int fd)
+{
+       int nbytes;
+       char buffer[SSH_READ_BLOCK_SIZE];
+
+       /* read from stdin until data are available */
+       do {
+               nbytes = ssh_channel_read(channel, buffer, SSH_READ_BLOCK_SIZE, 0);
+               if (write(fd, buffer, nbytes) != nbytes) {
+                       errmsg_print("ERROR reading: %s\n", g_strerror(errno));
+                       return;
+               }
+       } while(nbytes > 0);
+
+       /* read loop finished... maybe something wrong happened. Read from stderr */
+       do {
+               nbytes = ssh_channel_read(channel, buffer, SSH_READ_BLOCK_SIZE, 1);
+               if (write(STDERR_FILENO, buffer, nbytes) != nbytes) {
+                       return;
+               }
+       } while(nbytes > 0);
+
+       if (ssh_channel_send_eof(channel) != SSH_OK)
+               return;
+}
+
+static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_bin, const char* iface, const char* cfilter)
+{
+       gchar* cmdline;
+       ssh_channel channel;
+       char* quoted_bin;
+       char* quoted_iface;
+       char* default_filter;
+       char* quoted_filter;
+       unsigned int remote_port = 22;
+
+       if (!capture_bin)
+               capture_bin = "dumpcap";
+
+       if (!iface)
+               iface = "eth0";
+
+       channel = ssh_channel_new(sshs);
+       if (!channel)
+               return NULL;
+
+       if (ssh_channel_open_session(channel) != SSH_OK) {
+               ssh_channel_free(channel);
+               return NULL;
+       }
+
+       ssh_options_get_port(sshs, &remote_port);
+
+       /* escape parameters to go save with the shell */
+       quoted_bin = g_shell_quote(capture_bin);
+       quoted_iface = g_shell_quote(iface);
+       default_filter = local_interfaces_to_filter(remote_port);
+       if (!cfilter)
+               cfilter = default_filter;
+       quoted_filter = g_shell_quote(cfilter);
+
+       cmdline = g_strdup_printf("%s -i %s -P -w - -f %s", quoted_bin, quoted_iface, quoted_filter);
+
+       verbose_print("Running: %s\n", cmdline);
+       if (ssh_channel_request_exec(channel, cmdline) != SSH_OK) {
+               ssh_channel_close(channel);
+               ssh_channel_free(channel);
+               channel = NULL;
+       }
+
+       g_free(quoted_bin);
+       g_free(quoted_iface);
+       g_free(default_filter);
+       g_free(quoted_filter);
+       g_free(cmdline);
+
+       return channel;
+}
+
+static int ssh_open_remote_connection(const char* hostname, const unsigned int port, const char* username, const char* password,
+       const char* sshkey, const char* sshkey_passphrase, const char* iface, const char* cfilter, const char* capture_bin,
+       const char* fifo)
+{
+       ssh_session sshs;
+       ssh_channel channel;
+       int fd;
+
+       if (!g_strcmp0(fifo, "-")) {
+               /* use stdout */
+               fd = STDOUT_FILENO;
+       } else {
+               /* Open or create the output file */
+               fd = open(fifo, O_WRONLY);
+               if (fd == -1) {
+                       fd = open(fifo, O_WRONLY | O_CREAT, 0640);
+                       if (fd == -1) {
+                               errmsg_print("Error creating output file: %s\n", g_strerror(errno));
+                               return EXIT_FAILURE;
+                       }
+               }
+       }
+
+       sshs = create_ssh_connection(hostname, port, username, password, sshkey, sshkey_passphrase);
+
+       if (!sshs)
+               return EXIT_FAILURE;
+
+       channel = run_ssh_command(sshs, capture_bin, iface, cfilter);
+       if (!channel)
+               return EXIT_FAILURE;
+
+       /* read from channel and write into fd */
+       ssh_loop_read(channel, fd);
+
+       /* clean up and exit */
+       ssh_cleanup(sshs, channel);
+
+       return EXIT_SUCCESS;
+}
+
+static void help(const char* binname)
+{
+       g_print("Help\n");
+       g_print(" Usage:\n");
+       g_print(" %s --extcap-interfaces\n", binname);
+       g_print(" %s --extcap-interface=INTERFACE --extcap-dlts\n", binname);
+       g_print(" %s --extcap-interface=INTERFACE --extcap-config\n", binname);
+       g_print(" %s --extcap-interface=INTERFACE --remote-host myhost --remote-port 22222 "
+               "--remote-username myuser --remote-interface eth2 --remote-capture-bin /bin/dumpcap "
+               "--fifo=FILENAME --capture\n", binname);
+       g_print("\n\n");
+       g_print("  --help: print this help\n");
+       g_print("  --version: print the version\n");
+       g_print("  --verbose: print more messages\n");
+       g_print("  --extcap-interfaces: list the interfaces\n");
+       g_print("  --extcap-interface <iface>: specify the interface\n");
+       g_print("  --extcap-dlts: list the DTLs for an interface\n");
+       g_print("  --extcap-config: list the additional configuration for an interface\n");
+       g_print("  --extcap-capture-filter <filter>: the capture filter\n");
+       g_print("  --capture: run the capture\n");
+       g_print("  --fifo <file>: dump data to file or fifo\n");
+       g_print("  --remote-host <host>: the remote SSH host\n");
+       g_print("  --remote-port <port>: the remote SSH port (default: 22)\n");
+       g_print("  --remote-username <username>: the remote SSH username (default: the current user)\n");
+       g_print("  --remote-password <password>: the remote SSH password. If not specified, ssh-agent and ssh-key are used\n");
+       g_print("  --sshkey <public key path>: the path of the ssh key\n");
+       g_print("  --sshkey-passphrase <public key passphrase>: the passphrase to unlock public ssh\n");
+       g_print("  --remote-interface <iface>: the remote capture interface (default: eth0)\n");
+       g_print("  --remote-capture-bin <capture bin>: the remote dumcap binary (default: dumpcap\n");
+       g_print("  --remote-filter <filter>: a filter for remote capture (default: don't listen on local local interfaces IPs)\n");
+}
+
+static int list_interfaces(void)
+{
+       g_print("interface {value=%s}{display=SSH remote capture}\n", SSH_EXTCAP_INTERFACE);
+       return EXIT_SUCCESS;
+}
+
+static int list_dlts(const char *interface)
+{
+       if (!interface) {
+               g_print("ERROR: No interface specified.\n");
+               return EXIT_FAILURE;
+       }
+
+       if (g_strcmp0(interface, SSH_EXTCAP_INTERFACE)) {
+               g_print("ERROR: interface must be %s\n", SSH_EXTCAP_INTERFACE);
+               return EXIT_FAILURE;
+       }
+
+       g_print("dlt {number=147}{name=%s}{display=Remote capture dependant DLT}\n", SSH_EXTCAP_INTERFACE);
+       return EXIT_SUCCESS;
+}
+
+
+static char* local_interfaces_to_filter(unsigned int remote_port)
+{
+#ifdef USE_GETIFADDRS
+       struct ifaddrs* ifap;
+       struct ifaddrs* ifa;
+       GString* interfaces;
+       char* filter = NULL;
+       int family;
+       char ip[INET6_ADDRSTRLEN];
+
+       if (getifaddrs(&ifap)) {
+               return NULL;
+       }
+
+       interfaces = g_string_new(NULL);
+
+       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr == NULL)
+                       continue;
+
+               family = ifa->ifa_addr->sa_family;
+
+               memset(&ip, 0x0, INET6_ADDRSTRLEN);
+
+               switch (family) {
+                       case AF_INET:
+                               {
+                                       struct sockaddr_in *addr4 = (struct sockaddr_in *)ifa->ifa_addr;
+                                       inet_ntop(family, (char *)&addr4->sin_addr, ip, sizeof(ip));
+                                       break;
+                               }
+
+                       case AF_INET6:
+                               {
+                                       struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+                                       inet_ntop(family, (char *)&addr6->sin6_addr, ip, sizeof(ip));
+                                       break;
+                               }
+
+                       default:
+                               break;
+               }
+
+               /* skip loopback addresses */
+               if (!g_strcmp0(ip, "127.0.0.1") || !g_strcmp0(ip, "::1"))
+                       continue;
+
+               if (*ip) {
+                       if (interfaces->len)
+                               g_string_append(interfaces, " or ");
+                       g_string_append_printf(interfaces, "host %s", ip);
+               }
+       }
+       freeifaddrs(ifap);
+
+       if (interfaces->len)
+               filter = g_strdup_printf("not ((%s) and port %u)", interfaces->str, remote_port);
+       g_string_free(interfaces, TRUE);
+
+       return filter;
+#else
+       return NULL;
+#endif
+}
+
+static int list_config(char *interface, unsigned int remote_port)
+{
+       unsigned inc = 0;
+       char* ipfilter;
+
+       if (!interface) {
+               g_fprintf(stderr, "ERROR: No interface specified.\n");
+               return EXIT_FAILURE;
+       }
+
+       if (g_strcmp0(interface, SSH_EXTCAP_INTERFACE)) {
+               errmsg_print("ERROR: interface must be %s\n", SSH_EXTCAP_INTERFACE);
+               return EXIT_FAILURE;
+       }
+
+       ipfilter = local_interfaces_to_filter(remote_port);
+       if (!ipfilter)
+               return EXIT_FAILURE;
+
+       g_print("arg {number=%u}{call=--remote-host}{display=Remote SSH server address}"
+               "{type=string}{tooltip=The remote SSH host. It can be both "
+               "an IP address or a hostname}\n", inc++);
+       g_print("arg {number=%u}{call=--remote-port}{display=Remote SSH server port}"
+               "{type=unsigned}{default=22}{tooltip=The remote SSH host port (1-65535)}"
+               "{range=1,65535}\n", inc++);
+       g_print("arg {number=%u}{call=--remote-username}{display=Remote SSH server username}"
+               "{type=string}{default=%s}{tooltip=The remote SSH username. If not provided, "
+               "the current user will be used}\n", inc++, g_get_user_name());
+       g_print("arg {number=%u}{call=--remote-password}{display=Remote SSH server password}"
+               "{type=string}{tooltip=The SSH password, used when other methods (SSH agent "
+               "or key files) are unavailable.}\n", inc++);
+       g_print("arg {number=%u}{call=--sshkey}{display=Path to SSH private key}"
+               "{type=fileselect}{tooltip=The path on the local filesystem of the private ssh key}\n",
+               inc++);
+       g_print("arg {number=%u}{call--sshkey-passphrase}{display=SSH key passphrase}\n"
+               "{type=string}{tooltip=Passphrase to unlock the SSH private key}\n",
+               inc++);
+       g_print("arg {number=%u}{call=--remote-interface}{display=Remote interface}"
+               "{type=string}{default=eth0}{tooltip=The remote network interface used for capture"
+               "}\n", inc++);
+       g_print("arg {number=%u}{call=--remote-capture-bin}{display=Remote capture binary}"
+               "{type=string}{default=dumpcap}{tooltip=The remote dumpcap binary used "
+               "for capture.}\n", inc++);
+       g_print("arg {number=%u}{call=--remote-filter}{display=Remote capture filter}"
+               "{type=string}{default=%s}{tooltip=The remote capture filter}\n", inc++, ipfilter);
+
+       g_free(ipfilter);
+
+       return EXIT_SUCCESS;
+}
+
+static char* concat_filters(const char* extcap_filter, const char* remote_filter)
+{
+       if (!extcap_filter && remote_filter)
+               return g_strdup(remote_filter);
+
+       if (!remote_filter && extcap_filter)
+               return g_strdup(extcap_filter);
+
+       if (!remote_filter && !extcap_filter)
+               return NULL;
+
+       return g_strdup_printf("(%s) and (%s)", extcap_filter, remote_filter);
+}
+
+#ifdef _WIN32
+BOOLEAN IsHandleRedirected(DWORD handle)
+{
+       HANDLE h = GetStdHandle(handle);
+       if (h) {
+               BY_HANDLE_FILE_INFORMATION fi;
+               if (GetFileInformationByHandle(h, &fi)) {
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+static void attach_parent_console()
+{
+       BOOL outRedirected, errRedirected;
+
+       outRedirected = IsHandleRedirected(STD_OUTPUT_HANDLE);
+       errRedirected = IsHandleRedirected(STD_ERROR_HANDLE);
+
+       if (outRedirected && errRedirected) {
+               /* Both standard output and error handles are redirected.
+                * There is no point in attaching to parent process console.
+                */
+               return;
+       }
+
+       if (AttachConsole(ATTACH_PARENT_PROCESS) == 0) {
+               /* Console attach failed. */
+               return;
+       }
+
+       /* Console attach succeeded */
+       if (outRedirected == FALSE) {
+               freopen("CONOUT$", "w", stdout);
+       }
+
+       if (errRedirected == FALSE) {
+               freopen("CONOUT$", "w", stderr);
+       }
+}
+#endif
+
+int main(int argc, char **argv)
+{
+       int result;
+       int option_idx = 0;
+       int do_list_interfaces = 0;
+       int do_config = 0;
+       int do_capture = 0;
+       int i;
+       char* interface = NULL;
+       char* remote_host = NULL;
+       unsigned int remote_port = 22;
+       char* remote_username = NULL;
+       char* remote_password = NULL;
+       int do_dlts = 0;
+       char* fifo = NULL;
+       char* remote_interface = NULL;
+       char* remote_capture_bin = NULL;
+       char* extcap_filter = NULL;
+       char* sshkey = NULL;
+       char* sshkey_passphrase = NULL;
+       char* remote_filter = NULL;
+
+#ifdef _WIN32
+       WSADATA wsaData;
+
+       attach_parent_console();
+#endif  /* _WIN32 */
+
+       opterr = 0;
+       optind = 0;
+
+       if (argc == 1) {
+               help(argv[0]);
+               return EXIT_FAILURE;
+       }
+
+       for (i = 0; i < argc; i++) {
+               verbose_print("%s ", argv[i]);
+       }
+       verbose_print("\n");
+
+       while ((result = getopt_long(argc, argv, ":", longopts, &option_idx)) != -1) {
+
+               switch (result) {
+
+               case OPT_HELP:
+                       help(argv[0]);
+                       return EXIT_SUCCESS;
+
+               case OPT_VERBOSE:
+                       verbose = TRUE;
+                       break;
+
+               case OPT_VERSION:
+                       g_print("%u.%u.%u\n", SSHDUMP_VERSION_MAJOR, SSHDUMP_VERSION_MINOR, SSHDUMP_VERSION_RELEASE);
+                       return EXIT_SUCCESS;
+
+               case OPT_LIST_INTERFACES:
+                       do_list_interfaces = 1;
+                       break;
+
+               case OPT_LIST_DLTS:
+                       do_dlts = 1;
+                       break;
+
+               case OPT_INTERFACE:
+                       if (interface)
+                               g_free(interface);
+                       interface = g_strdup(optarg);
+                       break;
+
+               case OPT_CONFIG:
+                       do_config = 1;
+                       break;
+
+               case OPT_CAPTURE:
+                       do_capture = 1;
+                       break;
+
+               case OPT_FIFO:
+                       if (fifo)
+                               g_free(fifo);
+                       fifo = g_strdup(optarg);
+                       break;
+
+               case OPT_REMOTE_HOST:
+                       if (remote_host)
+                               g_free(remote_host);
+                       remote_host = g_strdup(optarg);
+                       break;
+
+               case OPT_REMOTE_PORT:
+                       remote_port = (unsigned int)strtoul(optarg, NULL, 10);
+                       if (remote_port > 65535 || remote_port == 0) {
+                               g_print("Invalid port: %s\n", optarg);
+                               return EXIT_FAILURE;
+                       }
+                       break;
+
+               case OPT_REMOTE_USERNAME:
+                       if (remote_username)
+                               g_free(remote_username);
+                       remote_username = g_strdup(optarg);
+                       break;
+
+               case OPT_REMOTE_PASSWORD:
+                       if (remote_password)
+                               g_free(remote_password);
+                       remote_password = g_strdup(optarg);
+                       memset(optarg, 'X', strlen(optarg));
+                       break;
+
+               case OPT_SSHKEY:
+                       if (sshkey)
+                               g_free(sshkey);
+                       sshkey = g_strdup(optarg);
+                       break;
+
+               case OPT_SSHKEY_PASSPHRASE:
+                       if (sshkey_passphrase)
+                               g_free(sshkey_passphrase);
+                       sshkey_passphrase = g_strdup(optarg);
+                       memset(optarg, 'X', strlen(optarg));
+                       break;
+
+               case OPT_REMOTE_INTERFACE:
+                       if (remote_interface)
+                               g_free(remote_interface);
+                       remote_interface = g_strdup(optarg);
+                       break;
+
+               case OPT_REMOTE_CAPTURE_BIN:
+                       if (remote_capture_bin)
+                               g_free(remote_capture_bin);
+                       remote_capture_bin = g_strdup(optarg);
+                       break;
+
+               case OPT_EXTCAP_FILTER:
+                       if (extcap_filter)
+                               g_free(extcap_filter);
+                       extcap_filter = g_strdup(optarg);
+                       break;
+
+               case OPT_REMOTE_FILTER:
+                       if (remote_filter)
+                               g_free(remote_filter);
+                       remote_filter = g_strdup(optarg);
+                       break;
+
+               case ':':
+                       /* missing option argument */
+                       g_print("Option '%s' requires an argument\n", argv[optind - 1]);
+                       break;
+
+               default:
+                       g_print("Invalid option: %s\n", argv[optind - 1]);
+                       return EXIT_FAILURE;
+               }
+       }
+
+       if (optind != argc) {
+               g_print("Unexpected extra option: %s\n", argv[optind]);
+               return EXIT_FAILURE;
+       }
+
+       if (do_list_interfaces)
+               return list_interfaces();
+
+       if (do_config)
+               return list_config(interface, remote_port);
+
+       if (do_dlts)
+               return list_dlts(interface);
+
+#ifdef _WIN32
+       result = WSAStartup(MAKEWORD(1,1), &wsaData);
+       if (result != 0) {
+               if (verbose)
+                       errmsg_print("ERROR: WSAStartup failed with error: %d\n", result);
+               return 1;
+       }
+#endif  /* _WIN32 */
+
+       if (do_capture) {
+               char* filter;
+               int ret = 0;
+               if (!fifo) {
+                       errmsg_print("ERROR: No FIFO or file specified\n");
+                       return 1;
+               }
+               if (g_strcmp0(interface, SSH_EXTCAP_INTERFACE)) {
+                       errmsg_print("ERROR: invalid interface\n");
+                       return 1;
+               }
+               if (!remote_host) {
+                       errmsg_print("Missing parameter: --remote-host");
+                       return 1;
+               }
+               filter = concat_filters(extcap_filter, remote_filter);
+               ret = ssh_open_remote_connection(remote_host, remote_port, remote_username,
+                       remote_password, sshkey, sshkey_passphrase, remote_interface,
+                       filter, remote_capture_bin, fifo);
+               g_free(filter);
+               return ret;
+       }
+
+       verbose_print("You should not come here... maybe some parameter missing?\n");
+       return 1;
+}
+
+
+#ifdef _WIN32
+int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+               LPSTR lpCmdLine, int nCmdShow) {
+       return main(__argc, __argv);
+}
+#endif
+
+/*
+ * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=4 noexpandtab:
+ * :indentSize=4:tabSize=4:noTabs=false:
+ */
index 8e638eb3d087f084c96dbc948726a96a6a801804..20eeca8142cc78cecc8159852104297a5317eaef 100755 (executable)
@@ -60,6 +60,7 @@ binary_list="
        text2pcap
        tshark
        extcap/androiddump
+       extcap/sshdump
 "
 cs_binary_list=
 
index 0890b02af7de62a210968a3e21e577175bd8fbc2..1b5125b9741bf9fcc7ede001164995a6186e50f1 100644 (file)
@@ -36,6 +36,9 @@ DOC=../../doc/ws.css                          \
        $(STAGING_DIR)/README.txt               \
        $(STAGING_DIR)/README.windows.txt
 
+;WIP: uncomment and add to the above when sshdump on windows will be ready to go
+;../../doc/sshdump.html
+
 GPL=../../COPYING
 HELP=$(STAGING_DIR)/help/capture_filters.txt \
        $(STAGING_DIR)/help/capturing.txt \
index e72e759c66fb7c53aff7d0a2557c3b60ba923c5a..a7081411d14c480e764d535efd3c3d4442d9e848 100755 (executable)
@@ -127,6 +127,8 @@ SetShellVarContext all
 
 Push "${EXECUTABLE_MARKER}"
 Push "androiddump"
+;WIP: uncomment when sshdump on windows will be ready to go
+;Push "sshdump"
 Push "dumpcap"
 Push "${PROGRAM_NAME}"
 Push "tshark"
@@ -178,6 +180,8 @@ Delete "$INSTDIR\etc\gtk-2.0\*.*"
 Delete "$INSTDIR\etc\gtk-3.0\*.*"
 Delete "$INSTDIR\etc\pango\*.*"
 Delete "$INSTDIR\extcap\androiddump.*"
+;WIP: uncomment when sshdump on windows will be ready to go
+;Delete "$INSTDIR\extcap\sshdump.*"
 Delete "$INSTDIR\help\*.*"
 Delete "$INSTDIR\iconengines\*.*"
 Delete "$INSTDIR\imageformats\*.*"
index 2d37a77d3c62766b0d921982138218a52a266f64..613318b37ad75a6865174892e3cf1744eda79f98 100644 (file)
@@ -1055,6 +1055,15 @@ SetOutPath $INSTDIR\extcap
 File "${STAGING_DIR}\extcap\androiddump.exe"
 SectionEnd
 
+;WIP: uncomment this section when sshdump on windows will be ready to go
+;Section /o "Sshdump" SecSshdumpinfos
+;-------------------------------------------
+;SetOutPath $INSTDIR
+;File "${STAGING_DIR}\sshdump.html"
+;SetOutPath $INSTDIR\extcap
+;File "${STAGING_DIR}\extcap\sshdump.exe"
+;SectionEnd
+
 SectionGroupEnd ; "Tools"
 
 !ifdef USER_GUIDE_DIR
@@ -1101,6 +1110,8 @@ SectionEnd
 
   !insertmacro MUI_DESCRIPTION_TEXT ${SecToolsGroup} "Additional command line based tools."
   !insertmacro MUI_DESCRIPTION_TEXT ${SecAndroiddumpinfos} "Provide capture interfaces from Android devices"
+;WIP: uncomment this section when sshdump on windows will be ready to go
+;!insertmacro MUI_DESCRIPTION_TEXT ${SecSshdumpinfos} "Provide remote capture through SSH"
   !insertmacro MUI_DESCRIPTION_TEXT ${SecEditCap} "Copy packets to a new file, optionally trimmming packets, omitting them, or saving to a different format."
   !insertmacro MUI_DESCRIPTION_TEXT ${SecText2Pcap} "Read an ASCII hex dump and write the data into a libpcap-style capture file."
   !insertmacro MUI_DESCRIPTION_TEXT ${SecMergecap} "Combine multiple saved capture files into a single output file"