diff options
author | Dario Lombardo <lomato@gmail.com> | 2015-11-19 11:30:44 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2015-11-19 15:29:18 +0000 |
commit | d6da95231ee790fd884ca2a41fe59aa9b05ccde9 (patch) | |
tree | 521b455286bad8276f270cb69fd4bb53192643dd | |
parent | 1a841483e9df85f913ece0286a6e0d4f97a859c2 (diff) |
extcap: add sshdump.
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>
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | CMakeLists.txt | 53 | ||||
-rw-r--r-- | CMakeOptions.txt | 1 | ||||
-rw-r--r-- | Makefile.am | 21 | ||||
-rw-r--r-- | Makefile.common | 4 | ||||
-rw-r--r-- | Makefile.nmake | 44 | ||||
-rw-r--r-- | acinclude.m4 | 37 | ||||
-rw-r--r-- | cmake/modules/FindLIBSSH.cmake | 101 | ||||
-rw-r--r-- | cmakeconfig.h.in | 6 | ||||
-rw-r--r-- | config.nmake | 19 | ||||
-rw-r--r-- | configure.ac | 71 | ||||
-rw-r--r-- | debian/wireshark-common.manpages | 1 | ||||
-rw-r--r-- | doc/Makefile.am | 13 | ||||
-rw-r--r-- | doc/Makefile.nmake | 18 | ||||
-rw-r--r-- | doc/extcap.pod | 2 | ||||
-rw-r--r-- | doc/sshdump.pod | 212 | ||||
-rw-r--r-- | extcap/sshdump.c | 850 | ||||
-rwxr-xr-x | packaging/macosx/osx-app.sh | 1 | ||||
-rw-r--r-- | packaging/nsis/Makefile.nmake | 3 | ||||
-rwxr-xr-x | packaging/nsis/uninstall.nsi | 4 | ||||
-rw-r--r-- | packaging/nsis/wireshark.nsi | 11 |
21 files changed, 1463 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore index 0004e49e55..0b4efeb72e 100644 --- a/.gitignore +++ b/.gitignore @@ -101,6 +101,7 @@ randpkt rawshark reordercap reassemble_test +sshdump stamp-h1 text2pcap tfshark diff --git a/CMakeLists.txt b/CMakeLists.txt index 7827725ad5..6a82046a64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}") diff --git a/CMakeOptions.txt b/CMakeOptions.txt index 4f2440c5ac..b547e74343 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -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) diff --git a/Makefile.am b/Makefile.am index e3a12dbce5..ebce8cc270 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/Makefile.common b/Makefile.common index 0321fc5e5c..1f0fe02200 100644 --- a/Makefile.common +++ b/Makefile.common @@ -99,6 +99,10 @@ rawshark_SOURCES = \ androiddump_SOURCES = \ extcap/androiddump.c +# sshdump specifics +sshdump_SOURCES = \ + extcap/sshdump.c + # text2pcap specifics text2pcap_SOURCES = \ pcapio.c \ diff --git a/Makefile.nmake b/Makefile.nmake index cb1043bc24..63fc01354b 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -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 diff --git a/acinclude.m4 b/acinclude.m4 index 4220fb86c5..89a77016a1 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 index 0000000000..db13825d89 --- /dev/null +++ b/cmake/modules/FindLIBSSH.cmake @@ -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() diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in index dfc7e3290c..81812f1f94 100644 --- a/cmakeconfig.h.in +++ b/cmakeconfig.h.in @@ -64,6 +64,12 @@ /* 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 diff --git a/config.nmake b/config.nmake index 700f28023a..2619486457 100644 --- a/config.nmake +++ b/config.nmake @@ -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 diff --git a/configure.ac b/configure.ac index 4bd21bf75e..524c861485 100644 --- a/configure.ac +++ b/configure.ac @@ -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" diff --git a/debian/wireshark-common.manpages b/debian/wireshark-common.manpages index f91eb8e0f2..b78326dcd2 100644 --- a/debian/wireshark-common.manpages +++ b/debian/wireshark-common.manpages @@ -1,4 +1,5 @@ obj-*/androiddump.1 +obj-*/sshdump.1 obj-*/editcap.1 obj-*/extcap.4 obj-*/mergecap.1 diff --git a/doc/Makefile.am b/doc/Makefile.am index 8f00fdfd49..1c4381ec23 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -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 \ diff --git a/doc/Makefile.nmake b/doc/Makefile.nmake index dfe2710cf4..35e114b37c 100644 --- a/doc/Makefile.nmake +++ b/doc/Makefile.nmake @@ -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" \ diff --git a/doc/extcap.pod b/doc/extcap.pod index 9795beb256..d267ec28c7 100644 --- a/doc/extcap.pod +++ b/doc/extcap.pod @@ -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 index 0000000000..6defdf1d74 --- /dev/null +++ b/doc/sshdump.pod @@ -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 index 0000000000..736e06e98f --- /dev/null +++ b/extcap/sshdump.c @@ -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: + */ diff --git a/packaging/macosx/osx-app.sh b/packaging/macosx/osx-app.sh index 8e638eb3d0..20eeca8142 100755 --- a/packaging/macosx/osx-app.sh +++ b/packaging/macosx/osx-app.sh @@ -60,6 +60,7 @@ binary_list=" text2pcap tshark extcap/androiddump + extcap/sshdump " cs_binary_list= diff --git a/packaging/nsis/Makefile.nmake b/packaging/nsis/Makefile.nmake index 0890b02af7..1b5125b974 100644 --- a/packaging/nsis/Makefile.nmake +++ b/packaging/nsis/Makefile.nmake @@ -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 \ diff --git a/packaging/nsis/uninstall.nsi b/packaging/nsis/uninstall.nsi index e72e759c66..a7081411d1 100755 --- a/packaging/nsis/uninstall.nsi +++ b/packaging/nsis/uninstall.nsi @@ -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\*.*" diff --git a/packaging/nsis/wireshark.nsi b/packaging/nsis/wireshark.nsi index 2d37a77d3c..613318b37a 100644 --- a/packaging/nsis/wireshark.nsi +++ b/packaging/nsis/wireshark.nsi @@ -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" |