aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDario Lombardo <lomato@gmail.com>2015-11-19 11:30:44 +0100
committerAnders Broman <a.broman58@gmail.com>2015-11-19 15:29:18 +0000
commitd6da95231ee790fd884ca2a41fe59aa9b05ccde9 (patch)
tree521b455286bad8276f270cb69fd4bb53192643dd
parent1a841483e9df85f913ece0286a6e0d4f97a859c2 (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--.gitignore1
-rw-r--r--CMakeLists.txt53
-rw-r--r--CMakeOptions.txt1
-rw-r--r--Makefile.am21
-rw-r--r--Makefile.common4
-rw-r--r--Makefile.nmake44
-rw-r--r--acinclude.m437
-rw-r--r--cmake/modules/FindLIBSSH.cmake101
-rw-r--r--cmakeconfig.h.in6
-rw-r--r--config.nmake19
-rw-r--r--configure.ac71
-rw-r--r--debian/wireshark-common.manpages1
-rw-r--r--doc/Makefile.am13
-rw-r--r--doc/Makefile.nmake18
-rw-r--r--doc/extcap.pod2
-rw-r--r--doc/sshdump.pod212
-rw-r--r--extcap/sshdump.c850
-rwxr-xr-xpackaging/macosx/osx-app.sh1
-rw-r--r--packaging/nsis/Makefile.nmake3
-rwxr-xr-xpackaging/nsis/uninstall.nsi4
-rw-r--r--packaging/nsis/wireshark.nsi11
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"