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>
This commit is contained in:
Dario Lombardo 2015-11-19 11:30:44 +01:00 committed by Anders Broman
parent 1a841483e9
commit d6da95231e
21 changed files with 1463 additions and 10 deletions

1
.gitignore vendored
View File

@ -101,6 +101,7 @@ randpkt
rawshark
reordercap
reassemble_test
sshdump
stamp-h1
text2pcap
tfshark

View File

@ -656,6 +656,9 @@ endif()
set(PACKAGELIST ${PACKAGELIST} HtmlViewer)
set(PACKAGELIST ${PACKAGELIST} LIBSSH)
set(LIBSSH_OPTIONS "0.6")
if(ENABLE_PCAP)
set(PACKAGELIST ${PACKAGELIST} PCAP)
endif()
@ -869,6 +872,9 @@ endif()
if(HAVE_LIBGEOIP)
set(HAVE_GEOIP 1)
endif()
if(LIBSSH_FOUND)
set(HAVE_LIBSSH 1)
endif()
if(HAVE_LIBCARES)
set(HAVE_C_ARES 1)
endif()
@ -1039,6 +1045,14 @@ if(ENABLE_EXTCAP)
set(EXTCAP_DIR "${ABSOLUTE_CMAKE_INSTALL_LIBDIR}/${CPACK_PACKAGE_NAME}/extcap/")
endif()
if(LIBSSH_FOUND)
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LIBSSH_LIBRARIES})
CHECK_FUNCTION_EXISTS(ssh_userauth_agent LIBSSH_USERAUTH_AGENT_FOUND)
if(LIBSSH_USERAUTH_AGENT_FOUND)
set(HAVE_SSH_USERAUTH_AGENT 1)
endif()
endif()
# Location of our plugins. PLUGIN_DIRECTORY should allow running
# from the build directory similar to DATAFILE_DIR above.
if(ENABLE_PLUGINS)
@ -1168,6 +1182,7 @@ endforeach()
include(FeatureSummary)
#SET_FEATURE_INFO(NAME DESCRIPTION [URL [COMMENT] ])
SET_FEATURE_INFO(SBC "SBC Codec for Bluetooth A2DP stream playing" "www: http://git.kernel.org/cgit/bluetooth/sbc.git" )
SET_FEATURE_INFO(LIBSSH "libssh is library for ssh connections and it is needed to build sshdump" "www: https://www.libssh.org/get-it/" )
FEATURE_SUMMARY(WHAT ALL)
@ -1254,6 +1269,7 @@ set(INSTALL_DIRS
set(INSTALL_FILES
${CMAKE_BINARY_DIR}/androiddump.html
${CMAKE_BINARY_DIR}/sshdump.html
${CMAKE_BINARY_DIR}/AUTHORS-SHORT
${CMAKE_BINARY_DIR}/capinfos.html
${CMAKE_BINARY_DIR}/captype.html
@ -1305,6 +1321,7 @@ set(MAN1_FILES
${CMAKE_BINARY_DIR}/randpkt.1
${CMAKE_BINARY_DIR}/rawshark.1
${CMAKE_BINARY_DIR}/reordercap.1
${CMAKE_BINARY_DIR}/sshdump.1
${CMAKE_BINARY_DIR}/text2pcap.1
${CMAKE_BINARY_DIR}/tshark.1
${CMAKE_BINARY_DIR}/wireshark.1
@ -1405,6 +1422,13 @@ if(WIN32)
"${_dll_output_dir}"
)
endif(GEOIP_FOUND)
if (LIBSSH_FOUND)
add_custom_command(TARGET copy_cli_dlls PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${LIBSSH_DLL_DIR}/${LIBSSH_DLL}"
"${_dll_output_dir}"
)
endif(LIBSSH_FOUND)
if(GCRYPT_FOUND)
foreach( _dll ${GCRYPT_DLLS} )
add_custom_command(TARGET copy_cli_dlls PRE_BUILD
@ -1861,7 +1885,7 @@ macro(set_extra_executable_properties _executable _folder)
endmacro()
macro(set_extcap_executable_properties _executable)
set_target_properties(androiddump PROPERTIES FOLDER "Executables/Extcaps")
set_target_properties(${_executable} PROPERTIES FOLDER "Executables/Extcaps")
set(PROGLIST ${PROGLIST} ${_executable})
@ -2309,6 +2333,28 @@ if(BUILD_androiddump)
install(TARGETS androiddump RUNTIME DESTINATION ${EXTCAP_DIR})
endif()
if(BUILD_sshdump AND LIBSSH_FOUND)
set(sshdump_LIBS
${GLIB2_LIBRARIES}
${CMAKE_DL_LIBS}
${LIBSSH_LIBRARIES}
)
if (WIN32)
set(sshdump_LIBS wsutil ${sshdump_LIBS})
endif()
set(sshdump_FILES
extcap/sshdump.c
)
add_executable(sshdump WIN32 ${sshdump_FILES})
set_extcap_executable_properties(sshdump)
target_link_libraries(sshdump ${sshdump_LIBS})
target_include_directories(sshdump PUBLIC ${LIBSSH_INCLUDE_DIR})
install(TARGETS sshdump RUNTIME DESTINATION ${EXTCAP_DIR})
elseif (BUILD_sshdump)
#message( WARNING "Cannot find libssh, cannot build sshdump" )
endif()
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_BINARY_DIR}/AUTHORS-SHORT
COMMAND ${PERL_EXECUTABLE}
@ -2430,6 +2476,7 @@ pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/mergecap 1 )
pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/randpkt 1 )
pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/rawshark 1 )
pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/reordercap 1 )
pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/sshdump 1 )
pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/text2pcap 1 )
pod2manhtml( ${CMAKE_SOURCE_DIR}/doc/tshark 1 )
pod2manhtml( ${CMAKE_BINARY_DIR}/wireshark 1 )
@ -2452,6 +2499,7 @@ add_custom_target(
randpkt.html
rawshark.html
reordercap.html
sshdump.html
text2pcap.html
tshark.html
wireshark.html
@ -2472,6 +2520,7 @@ set(CLEAN_FILES
${editcap_FILES}
${dumpcap_FILES}
${androiddump_FILES}
${sshdump_FILES}
)
if (WERROR_COMMON_FLAGS)
@ -2607,7 +2656,7 @@ else ()
if (NOT "${HARDENING_CHECK_EXECUTABLE}" STREQUAL "HARDENING_CHECK_EXECUTABLE-NOTFOUND")
foreach(_prog ${PROGLIST})
get_target_property(_prog_dir ${_prog} RUNTIME_OUTPUT_DIRECTORY)
if ("${_prog_dir}" STREQUAL "_prog_dir-NOTFOUND")
if (${_prog_dir} STREQUAL "_prog_dir-NOTFOUND")
set(_prog_dir "${CMAKE_BINARY_DIR}/run")
endif()
set(_prog_paths ${_prog_paths} "${_prog_dir}/${_prog}")

View File

@ -15,6 +15,7 @@ option(BUILD_captype "Build captype" ON)
option(BUILD_randpkt "Build randpkt" ON)
option(BUILD_dftest "Build dftest" ON)
option(BUILD_androiddump "Build androiddump" ON)
option(BUILD_sshdump "Build sshdump" ON)
option(AUTOGEN_dcerpc "Autogenerate DCE RPC dissectors" OFF)
option(AUTOGEN_pidl "Autogenerate pidl dissectors" OFF)

View File

@ -43,11 +43,12 @@ bin_PROGRAMS = \
@reordercap_bin@ \
@rawshark_bin@ \
@androiddump_bin@ \
@sshdump_bin@ \
@echld_test_bin@
EXTRA_PROGRAMS = wireshark-gtk wireshark tshark tfshark capinfos captype editcap \
mergecap dftest randpkt text2pcap dumpcap reordercap rawshark androiddump \
echld_test
sshdump echld_test
#
# Wireshark configuration files are put in $(pkgdatadir).
@ -547,6 +548,23 @@ androiddump_LDADD = \
androiddump_CFLAGS = $(AM_CLEAN_CFLAGS)
if ENABLE_STATIC
sshdump_LDFLAGS = -Wl,-static -all-static
else
sshdump_LDFLAGS = -export-dynamic
endif
# Libraries and plugin flags with which to link sshdump.
sshdump_LDADD = \
wiretap/libwiretap.la \
wsutil/libwsutil.la \
@GLIB_LIBS@ \
@LIBSSH_LIBS@ \
@SOCKET_LIBS@
sshdump_CFLAGS = $(AM_CLEAN_CFLAGS)
# Libraries with which to link text2pcap.
text2pcap_LDADD = \
wsutil/libwsutil.la \
@ -1322,6 +1340,7 @@ EXTRA_DIST = \
cmake/modules/FindSETCAP.cmake \
cmake/modules/FindSH.cmake \
cmake/modules/FindSMI.cmake \
cmake/modules/FindLIBSSH.cmake \
cmake/modules/FindWinSparkle.cmake \
cmake/modules/FindWireshark.cmake \
cmake/modules/FindWSWinLibs.cmake \

View File

@ -99,6 +99,10 @@ rawshark_SOURCES = \
androiddump_SOURCES = \
extcap/androiddump.c
# sshdump specifics
sshdump_SOURCES = \
extcap/sshdump.c
# text2pcap specifics
text2pcap_SOURCES = \
pcapio.c \

View File

@ -42,7 +42,7 @@ GENERATED_CFLAGS=\
/I. /Iwiretap $(GLIB_CFLAGS) \
$(ZLIB_CFLAGS) /I$(PCAP_DIR)\include $(AIRPCAP_CFLAGS) \
$(C_ARES_CFLAGS) $(ADNS_CFLAGS) $(GNUTLS_CFLAGS) \
$(SMI_CFLAGS) $(GEOIP_CFLAGS) $(WINSPARKLE_CFLAGS)
$(SMI_CFLAGS) $(GEOIP_CFLAGS) $(LIBSSH_CFLAGS) $(WINSPARKLE_CFLAGS)
CFLAGS=$(WARNINGS_ARE_ERRORS) $(GENERATED_CFLAGS)
@ -182,6 +182,12 @@ androiddump_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \
wsutil\libwsutil.lib \
$(GLIB_LIBS)
sshdump_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \
wsock32.lib user32.lib \
wsutil\libwsutil.lib \
$(LIBSSH_LIBS) \
$(GLIB_LIBS)
dumpcap_LIBS= \
wsock32.lib user32.lib \
caputils\libcaputils.lib \
@ -214,6 +220,10 @@ EXECUTABLES=$(PROGRAM_NAME_GTK).exe tshark.exe tfshark.exe rawshark.exe \
capinfos.exe captype.exe editcap.exe mergecap.exe text2pcap.exe \
randpkt.exe reordercap.exe dumpcap.exe androiddump.exe dftest.exe
!IFDEF LIBSSH_DIR
EXECUTABLES += sshdump.exe
!ENDIF
!IFDEF QT5_BASE_DIR
EXECUTABLES=$(EXECUTABLES) $(PROGRAM_NAME).exe
!ENDIF
@ -439,6 +449,17 @@ androiddump.exe : $(LIBS_CHECK) config.h androiddump.obj wsutil\libwsutil.lib wi
mt.exe -nologo -manifest "androiddump.exe.manifest" -outputresource:androiddump.exe;1
!ENDIF
!IFDEF LIBSSH_DIR
sshdump.exe : $(LIBS_CHECK) config.h sshdump.obj wsutil\libwsutil.lib wiretap\wiretap-$(WTAP_VERSION).lib
@echo Linking $@
$(LINK) @<<
/OUT:sshdump.exe $(conflags) $(conlibsdll) $(LDFLAGS) /SUBSYSTEM:WINDOWS sshdump.obj $(sshdump_LIBS)
<<
!IFDEF MANIFEST_INFO_REQUIRED
mt.exe -nologo -manifest "sshdump.exe.manifest" -outputresource:sshdump.exe;1
!ENDIF
!ENDIF
dumpcap.exe : $(LIBS_CHECK) config.h $(dumpcap_OBJECTS) caputils wsutil\libwsutil.lib image\dumpcap.res
@echo Linking $@
$(LINK) @<<
@ -485,6 +506,7 @@ config.h : config.h.win32 config.nmake
-e "s/@HAVE_SMI@/$(SMI_CONFIG)/" \
-e "s/@HAVE_GEOIP@/$(GEOIP_CONFIG)/" \
-e "s/@HAVE_GEOIP_V6@/$(GEOIP_V6_CONFIG)/" \
-e "s/@HAVE_LIBSSH/$(LIBSSH_CONFIG)/" \
-e "s/@HAVE_SOFTWARE_UPDATE@/$(WINSPARKLE_CONFIG)/" \
-e "s/@INET6@/$(INET6_CONFIG)/" \
-e "s/@HAVE_NTDDNDIS_H@/$(NTDDNDIS_CONFIG)/" \
@ -517,6 +539,7 @@ SMI_DIR = $(SMI_DIR:\=/)
KFW_DIR = $(KFW_DIR:\=/)
LUA_DIR = $(LUA_DIR:\=/)
GEOIP_DIR = $(GEOIP_DIR:\=/)
LIBSSH_DIR = $(LIBSSH_DIR:\=/)
WINSPARKLE_DIR = $(WINSPARKLE_DIR:\=/)
GCC_DLL = $(GCC_DLL)
@ -573,6 +596,9 @@ text2pcap-scanner.obj : text2pcap-scanner.c
androiddump.obj : extcap/androiddump.c
$(CC) $(CFLAGS) -Fd.\ -c $?
sshdump.obj : extcap/sshdump.c
$(CC) $(CFLAGS) -Fd.\ -c $?
test-programs:
cd epan
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake test-programs
@ -581,7 +607,7 @@ test-programs:
clean-local:
rm -f $(wireshark_gtk_OBJECTS) $(tshark_OBJECTS) $(tfshark_OBJECTS) $(dumpcap_OBJECTS) $(rawshark_OBJECTS) \
$(EXECUTABLES) *.nativecodeanalysis.xml *.pdb *.sbr *.exe.manifest \
androiddump.obj \
androiddump.obj sshdump.obj \
capinfos.obj capinfos.exp capinfos.lib \
captype.obj captype.exp captype.lib \
editcap.obj editcap.exp editcap.lib \
@ -1088,6 +1114,12 @@ process_libs:
GeoIP-$(GEOIP_PKG)-$(WIRESHARK_TARGET_PLATFORM)ws.zip \
"$(DOWNLOAD_TAG)" "$(WIRESHARK_TARGET_PLATFORM)"
!ENDIF
!IFDEF LIBSSH_DIR
@$(SH) $(WIN_SETUP) "$(WIN_SETUP_OPT)" "$(WIRESHARK_LIB_DIR)" \
libssh-$(LIBSSH_PKG)-$(WIRESHARK_TARGET_PLATFORM)ws \
libssh-$(LIBSSH_PKG)-$(WIRESHARK_TARGET_PLATFORM)ws.zip \
"$(DOWNLOAD_TAG)" "$(WIRESHARK_TARGET_PLATFORM)"
!ENDIF
!IFDEF WINSPARKLE_DIR
@$(SH) $(WIN_SETUP) "$(WIN_SETUP_OPT)" "$(WIRESHARK_LIB_DIR)" \
. \
@ -1184,6 +1216,7 @@ clean_setup:
rm -r -f AirPcap_Devpack_4_1_0_1622
rm -r -f GeoIP-1.4.5ws
rm -r -f GeoIP-1.*-win??ws
rm -r -f libssh-0.7.2
rm -r -f WinSparkle-0.3-44-g2c8d9d3-win??ws
rm -r -f WpdPack
cd "$(MAKEDIR)"
@ -1234,9 +1267,13 @@ install-generated-files: doc
if not exist $(INSTALL_DIR)\extcap mkdir $(INSTALL_DIR)\extcap
if exist androiddump.exe xcopy androiddump.exe $(INSTALL_DIR)\extcap /d
if exist androiddump.pdb xcopy androiddump.pdb $(INSTALL_DIR)\extcap /d
if exist sshdump.exe xcopy sshdump.exe $(INSTALL_DIR)\extcap /d
if exist sshdump.pdb xcopy sshdump.pdb $(INSTALL_DIR)\extcap /d
if not exist $(INSTALL_DIR_QT)\extcap mkdir $(INSTALL_DIR_QT)\extcap
if exist androiddump.exe xcopy androiddump.exe $(INSTALL_DIR_QT)\extcap /d
if exist androiddump.pdb xcopy androiddump.pdb $(INSTALL_DIR_QT)\extcap /d
if exist sshdump.exe xcopy sshdump.exe $(INSTALL_DIR_QT)\extcap /d
if exist sshdump.pdb xcopy sshdump.pdb $(INSTALL_DIR_QT)\extcap /d
if exist capinfos.exe xcopy capinfos.exe $(INSTALL_DIR) /d
if exist capinfos.pdb xcopy capinfos.pdb $(INSTALL_DIR) /d
if exist captype.exe xcopy captype.exe $(INSTALL_DIR) /d
@ -1463,6 +1500,9 @@ install-all: install-generated-files
!IFDEF GEOIP_DIR
xcopy "$(GEOIP_DIR)\bin\libGeoip-1.dll" $(INSTALL_DIR) /d
!ENDIF
!IFDEF LIBSSH_DIR
xcopy "$(LIBSSH_DIR)\bin\libssh.dll" $(INSTALL_DIR) /d
!ENDIF
!IFDEF WINSPARKLE_DIR
xcopy "$(WINSPARKLE_DIR)\WinSparkle.dll" $(INSTALL_DIR) /d
!ENDIF

View File

@ -1476,6 +1476,43 @@ AC_DEFUN([AC_WIRESHARK_GEOIP_CHECK],
fi
])
#
# AC_WIRESHARK_LIBSSH_CHECK
#
AC_DEFUN([AC_WIRESHARK_LIBSSH_CHECK],
[
want_libssh=defaultyes
if test "x$want_libssh" = "xdefaultyes"; then
want_libssh=yes
if test "x$ac_cv_enable_usr_local" = "xyes" ; then
withval=/usr/local
if test -d "$withval"; then
AC_WIRESHARK_ADD_DASH_L(LDFLAGS, ${withval}/lib)
fi
fi
fi
if test "x$want_libssh" = "xyes"; then
AC_CHECK_LIB(ssh, ssh_new,
[
LIBSSH_LIBS=-lssh
AC_DEFINE(HAVE_LIBSSH, 1, [Define to use libssh library])
have_good_libssh=yes
],,
)
AC_CHECK_LIB(ssh, ssh_userauth_agent,
[
LIBSSH_LIBS=-lssh
AC_DEFINE(HAVE_SSH_USERAUTH_AGENT, 1, [Libssh library has ssh_userauth_agent])
have_ssh_userauth_agent=yes
],,
)
else
AC_MSG_RESULT(not required)
fi
])
#AC_WIRESHARK_LDFLAGS_CHECK
#
# $1 : ldflag(s) to test

View File

@ -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()

View File

@ -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

View File

@ -431,6 +431,13 @@ GNUTLS_PKG=3.2.15-2.7
GPGERROR_DLL=libgpg-error-0.dll
GCC_DLL=libgcc_s_sjlj-1.dll
# Optional: libssh library is required for sshdump support
#
# If you don't have libssh, comment this line out so that LIBSSH_DIR
# isn't defined.
#
#LIBSSH_DIR=$(WIRESHARK_LIB_DIR)\libssh-0.7.2
#
# Optional: the KFW library enables kerberos/sasl/dcerpc decryption.
#
@ -1686,6 +1693,18 @@ GNUTLS_CONFIG=
LIBGCRYPT_CONFIG=
!ENDIF
!IFDEF LIBSSH_DIR
LIBSSH_CFLAGS=/I$(LIBSSH_DIR)\include
LIBSSH_LIBS=$(LIBSSH_DIR)\lib\ssh.lib
# Nmake uses carets to escape special characters
LIBSSH_CONFIG=^#define HAVE_LIBSSH 1
LIBSSH_VERSION=^#define HAVE_LIBSSH 1
!else
LIBSSH_CFLAGS=
LIBSSH_LIBS=
LIBSSH_CONFIG=
!ENDIF
!IFDEF LUA_DIR
LUA_CFLAGS=/I$(LUA_DIR)\include
LUA_LIBS=$(LUA_DIR)\lua52.lib

View File

@ -2331,6 +2331,37 @@ fi
AC_SUBST(androiddump_bin)
AC_SUBST(androiddump_man)
dnl sshdump check
AC_MSG_CHECKING(whether to build sshdump)
AC_ARG_ENABLE(sshdump,
AC_HELP_STRING( [--enable-sshdump],
[build sshdump @<:@default=yes@:>@]),
sshdump=$enableval,enable_sshdump=yes)
if test "x$enable_sshdump" = "xyes" ; then
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
if test "x$enable_sshdump" = "xyes" ; then
if test "x$have_good_libssh" = "xyes" ; then
sshdump_bin="sshdump\$(EXEEXT)"
sshdump_man="sshdump.1"
else
echo "Can't find libssh. Disabling sshdump."
enable_sshdump=no
sshdump_bin=""
sshdump_man=""
fi
else
sshdump_bin=""
sshdump_man=""
fi
AC_SUBST(sshdump_bin)
AC_SUBST(sshdump_man)
# Enable/disable echld
AC_ARG_ENABLE(echld,
AC_HELP_STRING( [--enable-echld],
@ -2816,6 +2847,31 @@ else
fi
AC_SUBST(GEOIP_LIBS)
dnl LIBSSH Check
LIBSSH=''
AC_MSG_CHECKING(whether to use the libssh library if available)
AC_ARG_WITH(ssh,
AC_HELP_STRING( [--with-libssh@<:@=DIR@:>@],
[use libssh (located in directory DIR, if supplied) @<:@default=yes, if present@:>@]),
[
if test "x$withval" = "xno"; then
want_libssh=no
elif test "x$withval" = "xyes"; then
want_libssh=yes
elif test -d "$withval"; then
want_libssh=yes
AC_WIRESHARK_ADD_DASH_L(LDFLAGS, ${withval}/lib)
fi
])
if test "x$want_libssh" = "xno"; then
AC_MSG_RESULT(no)
else
AC_MSG_RESULT(yes)
AC_WIRESHARK_LIBSSH_CHECK
fi
AC_SUBST(LIBSSH_LIBS)
#
# Define WS_MSVC_NORETURN appropriately for declarations of routines that
# never return (just like Charlie on the MTA).
@ -3377,6 +3433,18 @@ else
geoip_message="no"
fi
if test "x$have_good_libssh" = "xyes" ; then
libssh_message="yes"
else
libssh_message="no"
fi
if test "x$have_ssh_userauth_agent" = "xyes" ; then
ssh_userauth_agent_message="yes"
else
ssh_userauth_agent_message="no"
fi
echo ""
echo "The Wireshark package has been configured with the following options."
echo " Build wireshark : $enable_wireshark_qt$qt_lib_message"
@ -3394,6 +3462,7 @@ echo " Build randpkt : $enable_randpkt"
echo " Build dftest : $enable_dftest"
echo " Build rawshark : $enable_rawshark"
echo " Build androiddump : $enable_androiddump"
echo " Build sshdump : $enable_sshdump"
echo " Build echld : $have_echld"
echo ""
echo " Save files as pcap-ng by default : $enable_pcap_ng_default"
@ -3418,6 +3487,8 @@ echo " Use IPv6 name resolution : $enable_ipv6"
echo " Use gnutls library : $tls_message"
echo " Use POSIX capabilities library : $libcap_message"
echo " Use GeoIP library : $geoip_message"
echo " Use libssh library : $libssh_message"
echo " Have ssh_userauth_agent : $ssh_userauth_agent_message"
echo " Use nl library : $libnl_message"
echo " Use SBC codec library : $have_sbc"
#echo " Use GResource : $have_gresource"

View File

@ -1,4 +1,5 @@
obj-*/androiddump.1
obj-*/sshdump.1
obj-*/editcap.1
obj-*/extcap.4
obj-*/mergecap.1

View File

@ -71,7 +71,8 @@ man1_MANS = \
@rawshark_man@ \
@dftest_man@ \
@randpkt_man@ \
@androiddump_man@
@androiddump_man@ \
@sshdump_man@
man4_MANS = @wiresharkfilter_man@
man_MANS =
@ -83,7 +84,7 @@ noinst_DATA = asn2deb.1 asn2deb.html idl2deb.1 idl2deb.html idl2wrs.1 idl2wrs.ht
pkgdata_DATA = AUTHORS-SHORT $(top_srcdir)/docbook/ws.css wireshark.html \
tshark.html wireshark-filter.html capinfos.html editcap.html \
mergecap.html reordercap.html text2pcap.html dumpcap.html androiddump.html \
rawshark.html dftest.html randpkt.html
sshdump.html rawshark.html dftest.html randpkt.html
#
# Build the short version of the authors file for the about dialog
@ -212,6 +213,13 @@ androiddump.html: androiddump.pod ../config.h $(top_srcdir)/docbook/ws.css
--noindex \
$(srcdir)/androiddump.pod > androiddump.html
sshdump.html: sshdump.pod ../config.h $(top_srcdir)/docbook/ws.css
$(AM_V_POD2HTML)$(POD2HTML) \
--title="sshdump - The Wireshark Network Analyzer $(VERSION)" \
--css=$(POD_CSS_URL) \
--noindex \
$(srcdir)/sshdump.pod > sshdump.html
rawshark.html: rawshark.pod ../config.h $(top_srcdir)/docbook/ws.css
$(AM_V_POD2HTML)$(POD2HTML) \
--title="rawshark - The Wireshark Network Analyzer $(VERSION)" \
@ -293,6 +301,7 @@ EXTRA_DIST = \
rawshark.pod \
reordercap.pod \
sgml.doc.template \
sshdump.pod \
text2pcap.pod \
tshark.pod \
wireshark-filter.pod \

View File

@ -26,12 +26,13 @@ include ../config.nmake
doc: wireshark.html tshark.html wireshark-filter.html capinfos.html \
editcap.html idl2wrs.html mergecap.html reordercap.html \
text2pcap.html dumpcap.html androiddump.html rawshark.html dftest.html randpkt.html \
text2pcap.html dumpcap.html androiddump.html sshdump.html rawshark.html \
dftest.html randpkt.html \
idl2deb.html asn2deb.html extcap.html
man: wireshark.1 tshark.1 wireshark-filter.4 capinfos.1 \
editcap.1 idl2wrs.1 mergecap.1 reordercap.1 \
text2pcap.1 dumpcap.1 androiddump.1 rawshark.1 dftest.1 randpkt.1 \
text2pcap.1 dumpcap.1 androiddump.1 sshdump.1 rawshark.1 dftest.1 randpkt.1 \
idl2deb.1 asn2deb.1 extcap.4
wireshark.pod: wireshark.pod.template AUTHORS-SHORT-FORMAT
@ -235,6 +236,19 @@ androiddump.html: androiddump.pod ../config.h ws.css
--noindex \
androiddump.pod > androiddump.html
sshdump.1: sshdump.pod ../config.h
$(POD2MAN) \
--center="The Wireshark Network Analyzer" \
--release=$(VERSION) \
sshdump.pod > sshdump.1
sshdump.html: sshdump.pod ../config.h ws.css
$(POD2HTML) \
--title="sshdump - The Wireshark Network Analyzer $(VERSION)" \
--css=ws.css \
--noindex \
sshdump.pod > sshdump.html
rawshark.1: rawshark.pod ../config.h
$(POD2MAN) \
--center="The Wireshark Network Analyzer" \

View File

@ -96,7 +96,7 @@ Example 3:
=head1 SEE ALSO
wireshark(1), tshark(1), dumpcap(1), androiddump(1)
wireshark(1), tshark(1), dumpcap(1), androiddump(1), sshdump(1)
=head1 NOTES

212
doc/sshdump.pod Normal file
View File

@ -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>

850
extcap/sshdump.c Normal file
View File

@ -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:
*/

View File

@ -60,6 +60,7 @@ binary_list="
text2pcap
tshark
extcap/androiddump
extcap/sshdump
"
cs_binary_list=

View File

@ -36,6 +36,9 @@ DOC=../../doc/ws.css \
$(STAGING_DIR)/README.txt \
$(STAGING_DIR)/README.windows.txt
;WIP: uncomment and add to the above when sshdump on windows will be ready to go
;../../doc/sshdump.html
GPL=../../COPYING
HELP=$(STAGING_DIR)/help/capture_filters.txt \
$(STAGING_DIR)/help/capturing.txt \

View File

@ -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\*.*"

View File

@ -1055,6 +1055,15 @@ SetOutPath $INSTDIR\extcap
File "${STAGING_DIR}\extcap\androiddump.exe"
SectionEnd
;WIP: uncomment this section when sshdump on windows will be ready to go
;Section /o "Sshdump" SecSshdumpinfos
;-------------------------------------------
;SetOutPath $INSTDIR
;File "${STAGING_DIR}\sshdump.html"
;SetOutPath $INSTDIR\extcap
;File "${STAGING_DIR}\extcap\sshdump.exe"
;SectionEnd
SectionGroupEnd ; "Tools"
!ifdef USER_GUIDE_DIR
@ -1101,6 +1110,8 @@ SectionEnd
!insertmacro MUI_DESCRIPTION_TEXT ${SecToolsGroup} "Additional command line based tools."
!insertmacro MUI_DESCRIPTION_TEXT ${SecAndroiddumpinfos} "Provide capture interfaces from Android devices"
;WIP: uncomment this section when sshdump on windows will be ready to go
;!insertmacro MUI_DESCRIPTION_TEXT ${SecSshdumpinfos} "Provide remote capture through SSH"
!insertmacro MUI_DESCRIPTION_TEXT ${SecEditCap} "Copy packets to a new file, optionally trimmming packets, omitting them, or saving to a different format."
!insertmacro MUI_DESCRIPTION_TEXT ${SecText2Pcap} "Read an ASCII hex dump and write the data into a libpcap-style capture file."
!insertmacro MUI_DESCRIPTION_TEXT ${SecMergecap} "Combine multiple saved capture files into a single output file"