Compare commits

..

141 Commits

Author SHA1 Message Date
Andreas Schneider
62f7eaf156 misc: Updated the changelog. 2010-09-05 17:57:48 +02:00
Andreas Schneider
2462b0fbc7 build: Increase version number. 2010-09-05 17:54:03 +02:00
Andreas Schneider
c05666245c build: Fixed a wrong if statement.
(cherry picked from commit 461dde231c)
2010-09-05 13:13:01 +02:00
Andreas Schneider
6db13f776f build: Fixed build with gcc 3.4.
The -fvisibility=hidden flag is broken in gcc 3.4. This fixes the build
on CentOS, bug #74.
2010-09-05 13:00:51 +02:00
Andreas Schneider
0980117c52 build: Fixed checking for printf function on Windows. 2010-09-02 11:50:59 +02:00
Andreas Schneider
3d66164545 poll: Fixed the Windows build on Vista and newer. 2010-09-01 23:31:06 +02:00
Aris Adamantiadis
c087e8704d Fixes bug #99
returns error when no cryptographic context is available
2010-08-28 23:38:53 +02:00
Andreas Schneider
e5801287da poll: Fixed the ssh_poll_(init/cleanup) functions. 2010-08-25 23:12:27 +02:00
Andreas Schneider
5b9d92c36f poll: Fixed the usage of WSAPoll() on Windows.
This should fix ticket #101.
2010-08-25 23:12:27 +02:00
Andreas Schneider
edc6b2cef2 poll: Added a cleanup function to free the ws2_32 library. 2010-08-25 23:12:26 +02:00
Aris Adamantiadis
9590a643ab Fixed "@deprecated" in doxygen 2010-08-20 12:59:42 +02:00
Aris Adamantiadis
bec9bc1222 Changed SSH_SUCCESS to SSH_OK 2010-08-20 12:58:48 +02:00
Aris Adamantiadis
b3067e362c Obsoletes ssh_auth_list, comment ssh_userauth_list
Conflicts:

	libssh/auth.c
2010-08-19 19:53:16 +02:00
Andreas Schneider
5f99fed07c build: Fixed some mingw warnings. 2010-07-24 21:36:00 +02:00
Andreas Schneider
9973de535e priv: Fixed a mingw build bug. 2010-07-24 10:10:33 +02:00
Aris Adamantiadis
a7d9f4addd Correctly handle failed opened channels 2010-07-19 22:50:15 +02:00
Aris Adamantiadis
a4f4fa3058 Fixed keepalive problem on older openssh servers 2010-07-16 23:04:54 +02:00
Aris Adamantiadis
a9c4877d84 New example for port forwarding 2010-07-16 22:45:12 +02:00
Andreas Schneider
284466632e build: InstallRequiredSystemLibraries isn't needed. 2010-07-16 08:58:32 +02:00
Andreas Schneider
aa8381999a build: Fixed the NSIS build. 2010-07-13 17:49:01 +02:00
Andreas Schneider
ac54a26c5d build: Fixed the Windows build.
We have to include stdio.h for the printf function before we can do
anything.
2010-07-13 17:27:52 +02:00
Andreas Schneider
fd53ebc7b6 build: Define values for printf functions. 2010-07-13 17:25:48 +02:00
Andreas Schneider
df2436b4a6 build: Don't test for big endian on Windows.
Visual Studio 2010 has problems running the test.
2010-07-13 16:08:43 +02:00
Andreas Schneider
7029d2f4b8 build: Fixed the Windows preprocessor macros and defines. 2010-07-13 15:10:19 +02:00
Andreas Schneider
3c9c358385 build: Set a default zlib search path for windows. 2010-07-13 14:03:54 +02:00
Andreas Schneider
82d1627cad build: Set a default openssl search path for windows. 2010-07-13 14:03:25 +02:00
Andreas Schneider
641e89b14a build: Fixed typo. 2010-07-13 13:25:20 +02:00
Andreas Schneider
3a61d55f27 build: Added a check for NSIS. 2010-07-13 13:19:06 +02:00
Andreas Schneider
c4d1d8b684 build: Increase version numbers. 2010-07-13 10:15:22 +02:00
Andreas Schneider
10e27f26be build: Updated ChangeLog. 2010-07-12 09:48:22 +02:00
Andreas Schneider
9791bc3eeb poll: Added poll constants for Windows.
WSAPoll uses different constanst values as the POSIX implementation,
what else ...
2010-07-09 09:46:57 +02:00
Andreas Schneider
4ad7828797 options: Added option to bind a client to an ip address.
Thanks to Donatello Boccaforno <donatello.boccaforno@gmail.com>.
2010-07-07 12:40:49 +02:00
Aris Adamantiadis
af8315b9ce Fixed ssh_socket_poll behaviour 2010-07-07 10:00:09 +02:00
Andreas Schneider
94fdcf7a2a socket: Fixed ssh_socket_poll().
If we don't have date to read or write, leave ssh_socket_poll().
2010-07-06 23:18:16 +02:00
Andreas Schneider
59a95fc3a7 poll: FD_SETSIZE is only for the count value of FD_SET on Windows. 2010-07-06 00:40:19 +02:00
Andreas Schneider
c1729c36d9 socket: Fixed a prototype. 2010-06-25 16:20:38 +02:00
Andreas Schneider
23efab0f8f socket: Fixed conflicting types. 2010-06-24 20:05:10 +02:00
Andreas Schneider
e50752a925 poll: Another attempt to get bsd_poll() working correctly. 2010-06-24 09:17:39 +02:00
Andreas Schneider
fd45c1b36b poll: Fixed building with poll-emulation on UNIX. 2010-06-24 09:16:58 +02:00
Andreas Schneider
5080671581 agent: Use the our poll typedef. 2010-06-24 09:14:07 +02:00
Andreas Schneider
e67fafd60f poll: Added a comment to the bsd_poll() implementation. 2010-06-22 14:45:08 +02:00
Andreas Schneider
a2a98fb5bc poll: Handle FD_SETSIZE in bsd_poll(). 2010-06-22 14:44:54 +02:00
Andreas Schneider
e2480fbaba poll: Fixed a comparsion. 2010-06-22 14:43:09 +02:00
Andreas Schneider
23e6b36209 poll: Fixed a typo. 2010-06-21 15:41:58 +02:00
Andreas Schneider
541b38b772 poll: Check if maxfd has been set. 2010-06-20 21:16:29 +02:00
Andreas Schneider
a85a4cc192 connect: Fixed some socket build warnings on windows. 2010-06-18 12:43:12 +02:00
Andreas Schneider
54ef77123a server: Fixed types and checks of fd's. 2010-06-17 13:36:14 +02:00
Andreas Schneider
4c679fd8a6 poll: Fixed type of the fd variables and use SSH_INVALID_SOCKET. 2010-06-17 13:35:40 +02:00
Andreas Schneider
21d918c68a client: Fixed fd type and checks. 2010-06-17 13:33:52 +02:00
Andreas Schneider
544fc28e6b channel: Fixed the type of the max fd variable in ssh_channel_select(). 2010-06-17 13:32:14 +02:00
Andreas Schneider
601081ebb6 agent: Use ssh_poll in agent code. 2010-06-17 13:31:35 +02:00
Andreas Schneider
22d975a24b socket: Fixed checks for max fd. 2010-06-17 13:18:23 +02:00
Andreas Schneider
aeb9f3e389 poll: Fixed brackets. 2010-06-17 12:02:06 +02:00
Andreas Schneider
d3a4e01137 poll: Fixed another wrong invalid fd check in bsd_poll. 2010-06-17 11:49:28 +02:00
Andreas Schneider
a1b9ae5048 poll: Some code cleanup for easier debugging. 2010-06-17 11:23:58 +02:00
Andreas Schneider
a375ebe29b poll: Fixed a malfunction with wrong max fd value check. 2010-06-17 11:23:50 +02:00
Andreas Schneider
b2f49a6a93 config: Use ssh log and error functions for problems. 2010-06-03 16:46:17 +02:00
Andreas Schneider
99fb5987ce socket: Fixed signed values which could be seen as an unary operator. 2010-06-02 10:14:53 +02:00
Andreas Schneider
be389dd644 socket: According to execle(2) environ shouldn't be const. 2010-06-01 21:47:15 +02:00
Andreas Schneider
a6a7922dbd Update Changelog. 2010-05-31 19:36:32 +02:00
Aris Adamantiadis
608e81bc00 Fix warning for snprintf 2010-05-31 11:52:36 +03:00
Aris Adamantiadis
7e17838c0b Fix unclean null termination in ~ expending 2010-05-31 11:50:52 +03:00
Andreas Schneider
84f6945a9c Increased version numbers. 2010-05-30 11:26:11 +02:00
Andreas Schneider
3ae187dbe7 misc: Make sure the expanded string is null-terminated. 2010-05-30 11:00:38 +02:00
Andreas Schneider
26989ab001 session: Fixed setting up default identity files. 2010-05-28 10:47:37 +02:00
Andreas Schneider
5b2e39cd79 options: Make sure that we have always have default options set. 2010-05-21 10:21:03 +02:00
Andreas Schneider
13af149ef9 options: Set the local username if still not set. 2010-05-21 10:19:06 +02:00
Andreas Schneider
3453cafd95 keyfiles: Fixed possible problem with known_hosts path. 2010-05-21 10:03:13 +02:00
Andreas Schneider
fa65fd3dd1 cmake: Fixed doxygen. 2010-05-18 00:32:43 +02:00
Andreas Schneider
ec5fa5cc06 doxygen: Fixed latex pdf generation. 2010-05-18 00:08:01 +02:00
Andreas Schneider
8577688174 Updated changelog file. 2010-05-17 23:41:15 +02:00
Andreas Schneider
31462a4d72 sftp: Fixed sftp_chown. 2010-05-17 23:38:21 +02:00
Aris Adamantiadis
fd2ff2d29c Fix sftp_rename on sftp3 2010-05-17 20:05:22 +02:00
Aris Adamantiadis
0b09bd900f Typos in last patch 2010-05-14 12:49:24 +02:00
Aris Adamantiadis
abc61fa1cc Fix build on VC7 2010-05-14 12:46:17 +02:00
Aris Adamantiadis
e94bff02ba Respond to keepalives/global requests 2010-05-12 21:58:09 +02:00
Andreas Schneider
3671c61023 build: Fixed build.
I've added a non-existent kex header, sorry.
2010-05-12 19:36:40 +02:00
Andreas Schneider
2702f3ea3f Fixed building libssh with DEBUG_CRYPTO. 2010-05-12 19:25:34 +02:00
Andreas Schneider
4abd0522b4 Increment version and soversion numbers. 2010-05-12 19:00:07 +02:00
Andreas Schneider
62b6eb4436 Updated ChangeLog entries for 0.4.3. 2010-05-12 18:59:29 +02:00
Andreas Schneider
4b7eba1eda Added runtime detection of WSAPoll().
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-05-12 18:44:09 +02:00
Andreas Schneider
9970b1fd7d Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR. 2010-05-12 13:57:54 +02:00
Andreas Schneider
d703f51861 Fixed windows include files in pcap support. 2010-05-12 13:39:00 +02:00
Andreas Schneider
a009702cd6 Fixed Windows build warnings. 2010-05-12 13:11:33 +02:00
Andreas Schneider
ed268e5948 Fixed Windows build. 2010-05-12 13:11:33 +02:00
Andreas Schneider
10b4654ad5 Added a select(2) based poll-emulation if poll(2) is not available. 2010-05-12 13:11:33 +02:00
Andreas Schneider
9d7fc9d50b Use the new expand functions.
This implements escape chars for IdentityFile in ssh_config and reads
the system ssh_config.
2010-05-11 09:52:06 +02:00
Andreas Schneider
b8bc3a6582 Added a function to expand an escaped string. 2010-05-11 09:44:29 +02:00
Andreas Schneider
07e8d8f1f2 Added a function to expand the tilde from a path. 2010-05-11 09:44:13 +02:00
Aris Adamantiadis
34a927716a Added code to test proxycommand 2010-05-10 22:40:28 +02:00
Aris Adamantiadis
bae4090715 Backport of the proxycommand feature 2010-05-10 22:32:52 +02:00
Andreas Schneider
403ded1e97 Use configure checks to define vsnprintf and strncpy. 2010-05-10 15:53:57 +02:00
Andreas Schneider
6fd8de3376 Added configure checks for _vsnprintf_s and strncpy. 2010-05-10 15:53:46 +02:00
Andreas Schneider
5fe99f8b09 Fixed building libssh with VC9. 2010-05-10 14:41:20 +02:00
Patrick Spendrin
af155db080 Move ssh_hostport to a location which is global accessible.
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-05-10 10:48:13 +02:00
Patrick Spendrin
df5a94d445 The lower function doesn't have the prefix.
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2010-05-10 10:48:03 +02:00
Andreas Schneider
4bfe7f024c Added more defines to use secure VC functions. 2010-05-10 10:45:51 +02:00
Aris Adamantiadis
99ea177eea oops, this file was not intended to be commited 2010-05-07 13:03:35 +02:00
Aris Adamantiadis
476630841f Match hashed [host]:port format knownhosts 2010-05-07 13:02:28 +02:00
Aris Adamantiadis
7f59662cad knownhosts writing cherry-pick
Conflicts:

	libssh/keyfiles.c
	tests/unittests/CMakeLists.txt
2010-05-07 12:58:56 +02:00
Aris Adamantiadis
e9d6b15926 First implementation of known_hosts with port read
Conflicts:

	include/libssh/misc.h
	libssh/keyfiles.c
	libssh/misc.c
2010-05-07 12:55:33 +02:00
Aris Adamantiadis
6885d32c05 Added ssh_privatekey_type public function 2010-04-28 11:51:02 +02:00
Aris Adamantiadis
e5c2af6316 Fix doublefree happening after a negociation error 2010-04-14 20:56:22 +02:00
Aris Adamantiadis
08a1bebb58 Do not compile aes*-ctr with <=OpenSSL 0.9.7b 2010-04-14 20:43:06 +02:00
Aris Adamantiadis
6195b133bf Fix missing string_data() in crypto debug code 2010-04-14 18:24:23 +02:00
Aris Adamantiadis
6e65abbe63 Fix vsnprintf symbol on older VS2003 compiler 2010-04-06 22:58:43 +02:00
Aris Adamantiadis
bda836d744 Fix building on win32/vs7 2010-04-06 22:23:43 +02:00
Andreas Schneider
c8c2647555 Fixed a typo. 2010-04-04 15:55:49 +02:00
Andreas Schneider
4ad74765f6 Removed the unneeded dependency to doxygen. 2010-04-04 15:00:59 +02:00
Andreas Schneider
b1f93f600e Fixed documentation of ssh_bind_options_set. 2010-04-04 14:07:54 +02:00
Andreas Schneider
28edbe1ef5 Added an improved version of UseDoxygen.cmake which handles trac doc. 2010-04-04 14:07:43 +02:00
Andreas Schneider
75cf66a3ee Added a doxygen configuration for trac. 2010-04-04 14:04:38 +02:00
Andreas Schneider
5021ed3074 Fixed config parsing wich has overwritten user specified values. 2010-04-04 14:02:09 +02:00
Andreas Schneider
3773366a25 Fixed blocking bug in channel_poll.
This is a backport from 514ab6eed2.
2010-04-03 23:29:01 +02:00
Aris Adamantiadis
c6fab4bf84 Fix openssl detection in cmake 2010-03-29 23:06:20 +02:00
Aris Adamantiadis
7d1dcb0dff Fix file inclusion with VS2003 2010-03-29 22:23:47 +02:00
Aris Adamantiadis
d7c1384df0 Fix exec example which has broken read usage 2010-03-28 21:49:17 +02:00
Aris Adamantiadis
d2bb97c1c6 Fixes the broken algorithm choice for server 2010-03-28 21:43:13 +02:00
Aris Adamantiadis
3b6098597d Fix crash when no callback is defined 2010-03-28 21:19:12 +02:00
Andreas Schneider
964d8fdc11 Fixed build warnings on Windows. 2010-03-25 16:47:45 +01:00
Andreas Schneider
5d339aa9e2 Fixed a build warning in ssh_userauth_autopubkey. 2010-03-25 15:32:28 +01:00
Andreas Schneider
af7f69c515 Fixed spelling. 2010-03-25 13:55:50 +01:00
Andreas Schneider
ea92d5b230 Added comments to the so version to increment it correctly in future. 2010-03-25 13:24:59 +01:00
Andreas Schneider
f096e031ed Fixed a typo that we don't export all symbols. 2010-03-25 09:52:05 +01:00
Andreas Schneider
a8be476ea9 Build examples only on the Linux plattform. 2010-03-17 10:09:38 +01:00
Andreas Schneider
b9f65b5740 Added changelog entries for version 0.4.2. 2010-03-15 19:33:49 +01:00
Andreas Schneider
99a58eb325 Increase version number to 0.4.2. 2010-03-15 19:33:11 +01:00
Andreas Schneider
ed1cba705c Fixed a memory leak in ssh_try_publickey_from_file. 2010-03-13 15:00:19 +01:00
Andreas Schneider
0b13a6d265 Added missing SSH_OPTIONS_FD option. 2010-03-13 14:21:57 +01:00
Andreas Schneider
74c0201219 Remove support for SSHv1 Cipher variable. 2010-03-13 13:09:23 +01:00
Andreas Schneider
83c51d1c13 Fixed and added support for several identity files. 2010-03-06 12:33:27 +01:00
Andreas Schneider
c712d30311 Rename ssh_list_add to ssh_list_append. 2010-03-06 12:29:03 +01:00
Andreas Schneider
2144049c7d Added a prepend function for ssh_list. 2010-03-06 12:29:03 +01:00
Aris Adamantiadis
9dd86859e8 renamed ssh_list_get_head to ssh_list_pop_head 2010-03-06 12:28:56 +01:00
Andreas Schneider
810fbfb620 Fixed sftp_parse_longname() on Windows.
There is no strndup function on Windows.
2010-03-02 14:16:21 +01:00
Aris Adamantiadis
370d072eba Fix a race condition bug in ssh_scp_close() 2010-03-01 20:00:29 +01:00
Aris Adamantiadis
56dfa69fc9 Send back replies to openssh's keepalives 2010-03-01 18:41:59 +01:00
Aris Adamantiadis
672f8412f0 Fixed documentation in scp code 2010-02-26 18:49:15 +01:00
Andreas Schneider
83ff1ffcc3 Added printout of owner and group in the sftp example. 2010-02-24 00:26:20 +01:00
Andreas Schneider
fb35153b49 Fixed longname parsing, this only workings with readdir. 2010-02-24 00:25:38 +01:00
Andreas Schneider
7539200773 Added owner and group information in sftp attributes.
Parse the longname which is the output of 'ls -l' and set the owner and
group if we are talking to an openssh server.
2010-02-23 22:52:56 +01:00
52 changed files with 3665 additions and 795 deletions

View File

@@ -6,15 +6,20 @@ cmake_minimum_required(VERSION 2.6.0)
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION "0.4.0")
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "4")
set(APPLICATION_VERSION_PATCH "1")
set(APPLICATION_VERSION_PATCH "6")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}${APPLICATION_VERSION_MINOR}${APPLICATION_VERSION_PATCH}")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
set(LIBRARY_VERSION "4.0.1")
# SOVERSION scheme: CURRENT.AGE.REVISION
# If there was an incompatible interface change:
# Increment CURRENT. Set AGE and REVISION to 0
# If there was a compatible interface change:
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.1.3")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
@@ -47,12 +52,12 @@ if (WITH_GCRYPT)
endif (NOT GCRYPT_FOUND)
else (WITH_GCRYPT)
find_package(OpenSSL)
if (NOT CRYPTO_FOUND)
if (NOT OPENSSL_FOUND)
find_package(GCrypt)
if (NOT GCRYPT_FOUND)
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
endif (NOT GCRYPT_FOUND)
endif (NOT CRYPTO_FOUND)
endif (NOT OPENSSL_FOUND)
endif(WITH_GCRYPT)
# config.h checks
@@ -67,7 +72,7 @@ add_subdirectory(libssh)
# build samples
include_directories(${CMAKE_SOURCE_DIR}/include)
if (UNIX AND NOT WIN32)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_subdirectory(examples)
endif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif (UNIX AND NOT WIN32)

View File

@@ -13,7 +13,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
### versions
set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "4")
set(CPACK_PACKAGE_VERSION_PATCH "1")
set(CPACK_PACKAGE_VERSION_PATCH "6")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
@@ -22,16 +22,21 @@ set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if (WIN32)
set(CPACK_GENERATOR "ZIP")
### nsis generator
set(CPACK_GENERATOR "NSIS")
### nsis generator
find_package(NSIS)
if (HAVE_NSIS)
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
endif (HAVE_NSIS)
endif (WIN32)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh")
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION})
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")

View File

@@ -1,6 +1,68 @@
ChangeLog
==========
version 0.4.6 (released 2010-09-03)
* Added a cleanup function to free the ws2_32 library.
* Fixed build with gcc 3.4.
* Fixed the Windows build on Vista and newer.
* Fixed the usage of WSAPoll() on Windows.
* Fixed "@deprecated" in doxygen
* Fixed some mingw warnings.
* Fixed handling of opened channels.
* Fixed keepalive problem on older openssh servers.
* Fixed testing for big endian on Windows.
* Fixed the Windows preprocessor macros and defines.
version 0.4.5 (released 2010-07-13)
* Added option to bind a client to an ip address.
* Fixed the ssh socket polling function.
* Fixed Windows related bugs in bsd_poll().
* Fixed serveral build warnings.
version 0.4.4 (released 2010-06-01)
* Fixed a bug in the expand function for escape sequences.
* Fixed a bug in the tilde expand function.
* Fixed a bug in setting the options.
version 0.4.3 (released 2010-05-18)
* Added global/keepalive responses.
* Added runtime detection of WSAPoll().
* Added a select(2) based poll-emulation if poll(2) is not available.
* Added a function to expand an escaped string.
* Added a function to expand the tilde from a path.
* Added a proxycommand support.
* Added ssh_privatekey_type public function
* Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR.
* Fixed sftp_chown.
* Fixed sftp_rename on protocol version 3.
* Fixed a blocking bug in channel_poll.
* Fixed config parsing wich has overwritten user specified values.
* Fixed hashed [host]:port format in knownhosts
* Fixed Windows build.
* Fixed doublefree happening after a negociation error.
* Fixed aes*-ctr with <= OpenSSL 0.9.7b.
* Fixed some documentation.
* Fixed exec example which has broken read usage.
* Fixed broken algorithm choice for server.
* Fixed a typo that we don't export all symbols.
* Removed the unneeded dependency to doxygen.
* Build examples only on the Linux plattform.
version 0.4.2 (released 2010-03-15)
* Added owner and group information in sftp attributes.
* Added missing SSH_OPTIONS_FD option.
* Added printout of owner and group in the sftp example.
* Added a prepend function for ssh_list.
* Added send back replies to openssh's keepalives.
* Fixed documentation in scp code
* Fixed longname parsing, this only workings with readdir.
* Fixed and added support for several identity files.
* Fixed sftp_parse_longname() on Windows.
* Fixed a race condition bug in ssh_scp_close()
* Remove config support for SSHv1 Cipher variable.
* Rename ssh_list_add to ssh_list_append.
* Rename ssh_list_get_head to ssh_list_pop_head
version 0.4.1 (released 2010-02-13)
* Added support for aes128-ctr, aes192-ctr and aes256-ctr encryption.
* Added an example for exec.

View File

@@ -1,4 +1,5 @@
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
@@ -16,20 +17,39 @@ set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${CMAKE_BINARY_DIR})
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
if(CMAKE_COMPILER_IS_GNUC)
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
endif(CMAKE_COMPILER_IS_GNUC)
function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
execute_process(
COMMAND
${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} -dumpversion
OUTPUT_VARIABLE _COMPILER_VERSION
)
string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
_COMPILER_VERSION ${_COMPILER_VERSION})
set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
endfunction()
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
compiler_dumpversion(GNUCC_VERSION)
if (NOT GNUCC_VERSION EQUAL 34)
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
endif (NOT GNUCC_VERSION EQUAL 34)
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
# HEADER FILES
check_include_file(argp.h HAVE_ARGP_H)
check_include_file(pty.h HAVE_PTY_H)
check_include_file(terminos.h HAVE_TERMIOS_H)
if (WIN32)
check_include_file(wspiapi.h HAVE_WSPIAPI_H)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H)
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
message(STATUS "WARNING: Without wspiapi.h (or dependencies), this build will only work on Windows XP and newer versions")
endif (NOT HAVE_WSPIAPI_H)
check_include_file(ws2tcpip.h HAVE_WS2TCPIP_H)
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
if (NOT HAVE_WS2TCPIP_H)
message(ERROR "WARNING: Does not have ws2tcpip.h or winsock2.h")
endif (NOT HAVE_WS2TCPIP_H)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
@@ -49,6 +69,17 @@ check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
# FUNCTIONS
check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(vsnprintf HAVE_VSNPRINTF)
check_function_exists(snprintf HAVE_SNPRINTF)
if (WIN32)
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
check_function_exists(_snprintf HAVE__SNPRINTF)
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
endif (WIN32)
if (UNIX)
# libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
@@ -82,9 +113,9 @@ endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
# LIBRARIES
if (CRYPTO_FOUND)
if (OPENSSL_FOUND)
set(HAVE_LIBCRYPTO 1)
endif (CRYPTO_FOUND)
endif (OPENSSL_FOUND)
if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1)
@@ -104,4 +135,6 @@ if (WITH_DEBUG_CALLTRACE)
endif (WITH_DEBUG_CALLTRACE)
# ENDIAN
test_big_endian(WORDS_BIGENDIAN)
if (NOT WIN32)
test_big_endian(WORDS_BIGENDIAN)
endif (NOT WIN32)

View File

@@ -0,0 +1,31 @@
# - Try to find NSIS
# Once done this will define
#
# NSIS_FOUND - system has NSIS
# NSIS_MAKE - NSIS creator executable
#
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (NSIS_MAKE)
# in cache already
set(NSIS_FOUND TRUE)
elseif (NSIS_MAKE)
find_program(NSIS_MAKE
NAMES
makensis
PATHS
${_NSIS_DIR}
${_NSIS_DIR}/Bin
$ENV{PROGRAMFILES}/NSIS
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
mark_as_advanced(NSIS_MAKE)
endif (NSIS_MAKE)

View File

@@ -18,6 +18,10 @@ if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
# in cache already
set(OPENSSL_FOUND TRUE)
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
if (WIN32)
set(_OPENSSL_DIR $ENV{PROGRAMFILES}/OpenSSL)
endif (WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
@@ -34,6 +38,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
openssl/ssl.h
PATHS
${_OPENSSL_DIR}/include
${_OPENSSL_INCLUDEDIR}
/usr/include
/usr/local/include
@@ -49,6 +54,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
ssl
libssl
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
@@ -64,6 +70,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
ssleay32
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
@@ -79,6 +86,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
ssleay32MD
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
@@ -99,6 +107,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
libeay
libeay32
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/lib
/usr/lib

View File

@@ -18,11 +18,15 @@ if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
# in cache already
set(ZLIB_FOUND TRUE)
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
if (WIN32)
set(_ZLIB_DIR $ENV{PROGRAMFILES}/GnuWin32)
endif (WIN32)
find_path(ZLIB_INCLUDE_DIR
NAMES
zlib.h
PATHS
${_ZLIB_DIR}/include
/usr/include
/usr/local/include
/opt/local/include
@@ -36,6 +40,7 @@ else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
zlib
zlib1
PATHS
${_ZLIB_DIR}/lib
/usr/lib
/usr/local/lib
/opt/local/lib

View File

@@ -1,127 +1,100 @@
# -helper macro to add a "doc" target with CMake build system.
# and configure doxy.config.in to doxy.config
# - Run Doxygen
#
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
# Creates .chm windows help file if MS HTML help workshop
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
# is installed with its DLLs in PATH.
# Adds a doxygen target that runs doxygen to generate the html
# and optionally the LaTeX API documentation.
# The doxygen target is added to the doc target as dependency.
# i.e.: the API documentation is built with:
# make doc
#
# USAGE: INCLUDE IN PROJECT
#
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# include(UseDoxygen)
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
#
#
# Please note, that the tools, e.g.:
# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
# must be in path.
# Variables you may define are:
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
#
# Note about Visual Studio Projects:
# MSVS has its own path environment which may differ from the shell.
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
#
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
#
# author Jan Woetzel 2004-2006
# www.mip.informatik.uni-kiel.de/~jw
#
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
FIND_PACKAGE(Doxygen)
macro(usedoxygen_set_default name value)
if(NOT DEFINED "${name}")
set("${name}" "${value}")
endif()
endmacro()
IF (DOXYGEN_FOUND)
find_package(Doxygen)
# click+jump in Emacs and Visual Studio (for doxy.config) (jw)
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
if(DOXYGEN_FOUND)
find_file(DOXYFILE_IN
NAMES
doxy.config.in
PATHS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_ROOT}/Modules/
NO_DEFAULT_PATH)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
endif()
# we need latex for doxygen because of the formulas
FIND_PACKAGE(LATEX)
IF (NOT LATEX_COMPILER)
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
ENDIF (NOT LATEX_COMPILER)
IF (NOT MAKEINDEX_COMPILER)
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
ENDIF (NOT MAKEINDEX_COMPILER)
IF (NOT DVIPS_CONVERTER)
MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
ENDIF (NOT DVIPS_CONVERTER)
FIND_PROGRAM(DOXYGEN_DOT_EXECUTABLE_PATH NAMES dot)
IF (DOXYGEN_DOT_EXECUTABLE_PATH)
SET(DOXYGEN_DOT_FOUND "YES")
ENDIF (DOXYGEN_DOT_EXECUTABLE_PATH)
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
# use (configured) doxy.config from (out of place) BUILD tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
# use static hand-edited doxy.config from SOURCE tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# using template doxy.config.in
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# failed completely...
MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)")
ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
set(DOXYFILE_LATEX FALSE)
set(DOXYFILE_PDFLATEX FALSE)
set(DOXYFILE_DOT FALSE)
# create a windows help .chm file using hhc.exe
# HTMLHelp DLL must be in path!
# fallback: use hhw.exe interactively
IF (WIN32)
FIND_PACKAGE(HTMLHelp)
IF (HTML_HELP_COMPILER)
SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\doc\\html\\index.hhp")
STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} )
# MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}")
ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE})
ADD_DEPENDENCIES (winhelp doc)
IF (NOT TARGET_DOC_SKIP_INSTALL)
# install windows help?
# determine useful name for output file
# should be project and version unique to allow installing
# multiple projects into one global directory
IF (EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
IF (PROJECT_NAME)
SET(OUT "${PROJECT_NAME}")
ELSE (PROJECT_NAME)
SET(OUT "Documentation") # default
ENDIF(PROJECT_NAME)
IF (${PROJECT_NAME}_VERSION_MAJOR)
SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}")
IF (${PROJECT_NAME}_VERSION_MINOR)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}")
IF (${PROJECT_NAME}_VERSION_PATCH)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}")
ENDIF(${PROJECT_NAME}_VERSION_PATCH)
ENDIF(${PROJECT_NAME}_VERSION_MINOR)
ENDIF(${PROJECT_NAME}_VERSION_MAJOR)
# keep suffix
SET(OUT "${OUT}.chm")
#MESSAGE("DBG ${PROJECT_BINARY_DIR}/doc/html/index.chm \n${OUT}")
# create target used by install and package commands
INSTALL(FILES "${PROJECT_BINARY_DIR}/doc/html/index.chm"
DESTINATION "doc"
RENAME "${OUT}"
)
ENDIF(EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
ENDIF(NOT TARGET_DOC_SKIP_INSTALL)
find_package(LATEX)
if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
set(DOXYFILE_LATEX TRUE)
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
ENDIF(HTML_HELP_COMPILER)
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}")
ENDIF (WIN32)
ENDIF(DOXYGEN_FOUND)
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
if(PDFLATEX_COMPILER)
set(DOXYFILE_PDFLATEX TRUE)
endif()
if(DOXYGEN_DOT_EXECUTABLE)
set(DOXYFILE_DOT TRUE)
endif()
add_custom_command(TARGET doxygen
POST_BUILD
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
endif()
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
endif()
get_target_property(DOC_TARGET doc TYPE)
if(NOT DOC_TARGET)
add_custom_target(doc)
endif()
add_dependencies(doc doxygen)
endif()

View File

@@ -37,6 +37,37 @@
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1
/* Define to 1 if you have the `_snprintf' function. */
#cmakedefine HAVE__SNPRINTF 1
/* Define to 1 if you have the `_snprintf_s' function. */
#cmakedefine HAVE__SNPRINTF_S 1
/* Define to 1 if you have the `vsnprintf' function. */
#cmakedefine HAVE_VSNPRINTF 1
/* Define to 1 if you have the `_vsnprintf' function. */
#cmakedefine HAVE__VSNPRINTF 1
/* Define to 1 if you have the `_vsnprintf_s' function. */
#cmakedefine HAVE__VSNPRINTF_S 1
/* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1
/* Define to 1 if you have the `_snprintf' function. */
#cmakedefine HAVE__SNPRINTF 1
/* Define to 1 if you have the `_snprintf_s' function. */
#cmakedefine HAVE__SNPRINTF_S 1
/* Define to 1 if you have the `strncpy' function. */
#cmakedefine HAVE_STRNCPY 1
/* Define to 1 if you have the `cfmakeraw' function. */
#cmakedefine HAVE_CFMAKERAW 1
@@ -94,17 +125,3 @@
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#cmakedefine WORDS_BIGENDIAN 1
/************************* MS Windows ***************************/
#ifdef _WIN32
# ifdef _MSC_VER
/* On Microsoft compilers define inline to __inline on all others use inline */
# undef inline
# define inline __inline
# undef strdup
# define strdup _strdup
# endif // _MSC_VER
#endif /* _WIN32 */

1
doc/TracFooter.html Normal file
View File

@@ -0,0 +1 @@
<!-- Doxygen TracFooter -->

4
doc/TracHeader.html Normal file
View File

@@ -0,0 +1,4 @@
<!-- Doxygen TracHeader -->
<style>@import url(/chrome/site/doxygen.css);</style>
<style>@import url(/chrome/site/tabs.css);</style>
<!-- /Doxygen TracHeader -->

View File

@@ -918,7 +918,7 @@ FORMULA_FONTSIZE = 10
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
GENERATE_LATEX = @DOXYFILE_LATEX@
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be

1546
doc/doxy.trac.in Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -15,11 +15,14 @@ add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
add_executable(scp_download scp_download.c ${examples_SRCS})
add_executable(samplessh sample.c ${examples_SRCS})
add_executable(exec exec.c ${examples_SRCS})
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS}

View File

@@ -7,7 +7,7 @@
int main(void) {
ssh_session session;
ssh_channel channel;
ssh_buffer buf;
char buf[4096];
int rc;
session = connect_ssh("localhost", NULL, 0);
@@ -38,24 +38,14 @@ int main(void) {
return 1;
}
if (channel_is_open(channel)) {
while (channel_poll(channel, 0) >= 0) {
buf = buffer_new();
rc = channel_read_buffer(channel, buf, 0, 0);
if (rc < 0) {
buffer_free(buf);
channel_close(channel);
ssh_disconnect(session);
ssh_finalize();
return 1;
do {
if (channel_is_open(channel)) {
rc = channel_read(channel, buf, sizeof(buf), 0);
if(rc > 0){
fwrite(buf,1,rc,stdout);
}
printf("%s\n", (char *) buffer_get(buf));
buffer_free(buf);
}
}
} while(rc > 0);
channel_send_eof(channel);
channel_close(channel);

View File

@@ -46,6 +46,8 @@ struct termios terminal;
char *pcap_file=NULL;
#endif
char *proxycommand;
static int auth_callback(const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata) {
char *answer = NULL;
@@ -95,6 +97,9 @@ static void usage(){
" -r : use RSA to verify host public key\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
#endif
#ifndef _WIN32
" -T proxycommand : command to execute as a socket proxy\n"
#endif
,
ssh_version(0));
@@ -106,12 +111,17 @@ static int opts(int argc, char **argv){
// for(i=0;i<argc;i++)
// printf("%d : %s\n",i,argv[i]);
/* insert your own arguments here */
while((i=getopt(argc,argv,"P:"))!=-1){
while((i=getopt(argc,argv,"T:P:"))!=-1){
switch(i){
#ifdef WITH_PCAP
case 'P':
pcap_file=optarg;
break;
#endif
#ifndef _WIN32
case 'T':
proxycommand=optarg;
break;
#endif
default:
fprintf(stderr,"unknown option %c\n",optopt);
@@ -432,7 +442,10 @@ static int client(ssh_session session){
return -1;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
if (proxycommand != NULL){
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
return -1;
}
ssh_options_parse_config(session, NULL);
if(ssh_connect(session)){

View File

@@ -152,10 +152,12 @@ static void do_sftp(ssh_session session){
}
/* reading the whole directory, file by file */
while((file=sftp_readdir(sftp,dir))){
fprintf(stderr, "%30s(%.8o) : %.5d.%.5d : %.10llu bytes\n",
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
file->name,
file->permissions,
file->owner,
file->uid,
file->group,
file->gid,
(long long unsigned int) file->size);
sftp_attributes_free(file);

247
examples/sshnetcat.c Normal file
View File

@@ -0,0 +1,247 @@
/*
Copyright 2010 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <fcntl.h>
#include "examples_common.h"
char *host;
const char *desthost="localhost";
const char *port="22";
#ifdef WITH_PCAP
#include <libssh/pcap.h>
char *pcap_file=NULL;
#endif
static void usage(){
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1);
}
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"P:"))!=-1){
switch(i){
#ifdef WITH_PCAP
case 'P':
pcap_file=optarg;
break;
#endif
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage();
}
}
if(optind < argc)
host=argv[optind++];
if(optind < argc)
desthost=argv[optind++];
if(optind < argc)
port=argv[optind++];
if(host==NULL)
usage();
return 0;
}
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[4096];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof=0;
int maxfd;
int ret;
while(channel){
do{
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
FD_SET(ssh_get_fd(session),&fds);
maxfd=ssh_get_fd(session)+1;
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
channel_write(channel,buffer,lus);
else {
eof=1;
channel_send_eof(channel);
}
}
if(channel && channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(outchannels[0]){
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
lus=channel_read(channel,buffer,sizeof(buffer),0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=channels[0]=NULL;
} else
write(1,buffer,lus);
}
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
lus=channel_read(channel,buffer,sizeof(buffer),1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=channels[0]=NULL;
} else
write(2,buffer,lus);
}
}
if(channel && channel_is_closed(channel)){
channel_free(channel);
channel=NULL;
}
} while (ret==EINTR || ret==SSH_EINTR);
}
}
static void forwarding(ssh_session session){
ssh_channel channel;
int r;
channel=channel_new(session);
r=channel_open_forward(channel,desthost,atoi(port),"localhost",22);
if(r<0) {
printf("error forwarding port : %s\n",ssh_get_error(session));
return;
}
select_loop(session,channel);
}
static int client(ssh_session session){
int auth=0;
char *banner;
int state;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
ssh_options_parse_config(session, NULL);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
return -1;
}
state=verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
auth=authenticate_console(session);
if(auth != SSH_AUTH_SUCCESS){
return -1;
}
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
forwarding(session);
return 0;
}
#ifdef WITH_PCAP
ssh_pcap_file pcap;
void set_pcap(ssh_session session);
void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
void cleanup_pcap(void);
void cleanup_pcap(){
ssh_pcap_file_free(pcap);
pcap=NULL;
}
#endif
int main(int argc, char **argv){
ssh_session session;
session = ssh_new();
if(ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr, "error parsing command line :%s\n",
ssh_get_error(session));
usage();
}
opts(argc,argv);
#ifdef WITH_PCAP
set_pcap(session);
#endif
client(session);
ssh_disconnect(session);
ssh_free(session);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize();
return 0;
}

View File

@@ -79,7 +79,7 @@
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 4
#define LIBSSH_VERSION_MICRO 1
#define LIBSSH_VERSION_MICRO 6
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -119,10 +119,16 @@ typedef struct ssh_string_struct* ssh_string;
/* Socket type */
#ifdef _WIN32
#define socket_t SOCKET
#else
#ifndef socket_t
typedef SOCKET socket_t;
#endif /* socket_t */
#else /* _WIN32 */
#ifndef socket_t
typedef int socket_t;
#endif
#endif /* _WIN32 */
#define SSH_INVALID_SOCKET ((socket_t) -1)
/* the offsets of methods */
enum ssh_kex_types_e {
@@ -231,7 +237,7 @@ enum {
/** Only rare and noteworthy events
*/
SSH_LOG_RARE,
/** High level protocol informations
/** High level protocol information
*/
SSH_LOG_PROTOCOL,
/** Lower level protocol infomations, packet level
@@ -252,6 +258,7 @@ enum ssh_options_e {
SSH_OPTIONS_USER,
SSH_OPTIONS_SSH_DIR,
SSH_OPTIONS_IDENTITY,
SSH_OPTIONS_ADD_IDENTITY,
SSH_OPTIONS_KNOWNHOSTS,
SSH_OPTIONS_TIMEOUT,
SSH_OPTIONS_TIMEOUT_USEC,
@@ -263,7 +270,9 @@ enum ssh_options_e {
SSH_OPTIONS_CIPHERS_C_S,
SSH_OPTIONS_CIPHERS_S_C,
SSH_OPTIONS_COMPRESSION_C_S,
SSH_OPTIONS_COMPRESSION_S_C
SSH_OPTIONS_COMPRESSION_S_C,
SSH_OPTIONS_PROXYCOMMAND,
SSH_OPTIONS_BINDADDR
};
enum {
@@ -335,10 +344,14 @@ LIBSSH_API void privatekey_free(ssh_private_key prv);
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
int type, const char *passphrase);
LIBSSH_API void publickey_free(ssh_public_key key);
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
ssh_string pubkey, int type);
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
int *type);
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type);
LIBSSH_API int ssh_auth_list(ssh_session session);
LIBSSH_API char *ssh_basename (const char *path);
@@ -383,6 +396,9 @@ LIBSSH_API int ssh_pcap_file_close(ssh_pcap_file pcap);
LIBSSH_API void ssh_pcap_file_free(ssh_pcap_file pcap);
LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void);
LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
LIBSSH_API int ssh_privatekey_type(ssh_private_key privatekey);
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
LIBSSH_API int ssh_scp_accept_request(ssh_scp scp);
LIBSSH_API int ssh_scp_close(ssh_scp scp);

View File

@@ -25,8 +25,12 @@
/* in misc.c */
/* gets the user home dir. */
char *ssh_get_user_home_dir(void);
char *ssh_get_local_username(ssh_session session);
int ssh_file_readaccess_ok(const char *file);
char *ssh_path_expand_tilde(const char *d);
char *ssh_path_expand_escape(ssh_session session, const char *s);
/* macro for byte ordering */
uint64_t ntohll(uint64_t);
#define htonll(x) ntohll(x)
@@ -46,14 +50,12 @@ struct ssh_iterator {
struct ssh_list *ssh_list_new(void);
void ssh_list_free(struct ssh_list *list);
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
int ssh_list_add(struct ssh_list *list, const void *data);
int ssh_list_append(struct ssh_list *list, const void *data);
int ssh_list_prepend(struct ssh_list *list, const void *data);
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator);
char *ssh_hostport(const char *host, int port);
/** @brief fetch the head element of a list and remove it from list
* @param list the ssh_list to use
* @return the first element of the list
*/
const void *_ssh_list_get_head(struct ssh_list *list);
const void *_ssh_list_pop_head(struct ssh_list *list);
#define ssh_iterator_value(type, iterator)\
((type)((iterator)->data))
@@ -61,9 +63,9 @@ const void *_ssh_list_get_head(struct ssh_list *list);
/** @brief fetch the head element of a list and remove it from list
* @param type type of the element to return
* @param list the ssh_list to use
* @return the first element of the list
* @return the first element of the list, or NULL if the list is empty
*/
#define ssh_list_get_head(type, ssh_list)\
((type)_ssh_list_get_head(ssh_list))
#define ssh_list_pop_head(type, ssh_list)\
((type)_ssh_list_pop_head(ssh_list))
#endif /* MISC_H_ */

View File

@@ -38,9 +38,48 @@ typedef struct ssh_pollfd_struct {
short revents; /* returned events */
} ssh_pollfd_t;
typedef unsigned long int nfds_t;
#ifdef _WIN32
#ifndef POLLRDNORM
#define POLLRDNORM 0x0100
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0x0200
#endif
#ifndef POLLIN
#define POLLIN (POLLRDNORM | POLLRDBAND)
#endif
#ifndef POLLPRI
#define POLLPRI 0x0400
#endif
#ifndef POLLWRNORM
#define POLLWRNORM 0x0010
#endif
#ifndef POLLOUT
#define POLLOUT (POLLWRNORM)
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0x0020
#endif
#ifndef POLLERR
#define POLLERR 0x0001
#endif
#ifndef POLLHUP
#define POLLHUP 0x0002
#endif
#ifndef POLLNVAL
#define POLLNVAL 0x0004
#endif
#else /* _WIN32 */
/* poll.c */
#ifndef POLLIN
# define POLLIN 0x001 /* There is data to read. */
#define POLLIN 0x001 /* There is data to read. */
#endif
#ifndef POLLPRI
#define POLLPRI 0x002 /* There is urgent data to read. */
@@ -59,9 +98,24 @@ typedef struct ssh_pollfd_struct {
#define POLLNVAL 0x020 /* Invalid polling request. */
#endif
typedef unsigned long int nfds_t;
#ifndef POLLRDNORM
#define POLLRDNORM 0x040 /* mapped to read fds_set */
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0x080 /* mapped to exception fds_set */
#endif
#ifndef POLLWRNORM
#define POLLWRNORM 0x100 /* mapped to write fds_set */
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0x200 /* mapped to write fds_set */
#endif
#endif /* WIN32 */
#endif /* HAVE_POLL */
void ssh_poll_init(void);
void ssh_poll_cleanup(void);
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout);
typedef struct ssh_poll_ctx_struct *ssh_poll_ctx;
typedef struct ssh_poll_handle_struct *ssh_poll_handle;
@@ -77,7 +131,7 @@ typedef struct ssh_poll_handle_struct *ssh_poll_handle;
* @return 0 on success, < 0 if you removed the poll object from
* it's poll context.
*/
typedef int (*ssh_poll_callback)(ssh_poll_handle p, int fd, int revents,
typedef int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd, int revents,
void *userdata);

View File

@@ -32,18 +32,72 @@
#include "config.h"
#ifdef _MSC_VER
#define snprintf _snprintf
/** Imitate define of inttypes.h */
#define PRIdS "Id"
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define strtoull _strtoui64
#define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
#else
#ifdef _WIN32
/* Imitate define of inttypes.h */
# ifndef PRIdS
# define PRIdS "Id"
# endif
# ifdef _MSC_VER
# include <stdio.h>
/* On Microsoft compilers define inline to __inline on all others use inline */
# undef inline
# define inline __inline
# undef strdup
# define strdup _strdup
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# define strtoull _strtoui64
# define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
# define usleep(X) Sleep(((X)+1000)/1000)
# undef strtok_r
# define strtok_r strtok_s
# if defined(HAVE__SNPRINTF_S)
# undef snprintf
# define snprintf(d, n, ...) _snprintf_s((d), (n), _TRUNCATE, __VA_ARGS__)
# else /* HAVE__SNPRINTF_S */
# if defined(HAVE__SNPRINTF)
# undef snprintf
# define snprintf _snprintf
# else /* HAVE__SNPRINTF */
# if !defined(HAVE_SNPRINTF)
# error "no snprintf compatible function found"
# endif /* HAVE_SNPRINTF */
# endif /* HAVE__SNPRINTF */
# endif /* HAVE__SNPRINTF_S */
# if defined(HAVE__VSNPRINTF_S)
# undef vsnprintf
# define vsnprintf(s, n, f, v) _vsnprintf_s((s), (n), _TRUNCATE, (f), (v))
# else /* HAVE__VSNPRINTF_S */
# if defined(HAVE__VSNPRINTF)
# undef vsnprintf
# define vsnprintf _vsnprintf
# else
# if !defined(HAVE_VSNPRINTF)
# error "No vsnprintf compatible function found"
# endif /* HAVE_VSNPRINTF */
# endif /* HAVE__VSNPRINTF */
# endif /* HAVE__VSNPRINTF_S */
# ifndef HAVE_STRNCPY
# define strncpy(d, s, n) strncpy_s((d), (n), (s), _TRUNCATE)
# endif
# endif /* _MSC_VER */
#else /* _WIN32 */
#include <unistd.h>
#define PRIdS "zd"
#endif
#endif /* _WIN32 */
#include "libssh/libssh.h"
#include "libssh/callbacks.h"
@@ -222,8 +276,8 @@ int gettimeofday(struct timeval *__p, void *__t);
/* options.c */
char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir);
int ssh_options_set_algo(ssh_session session, int algo, const char *list);
int ssh_options_apply(ssh_session session);
/** Free memory space */
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)

View File

@@ -61,9 +61,13 @@ LIBSSH_API ssh_bind ssh_bind_new(void);
/**
* @brief Set the opitons for the current SSH server bind.
*
* @param ssh_bind The ssh server bind to use.
* @param sshbind The ssh server bind to use.
*
* @param options The option structure to set.
* @param type The option type to set.
*
* @param value The option value to set.
*
* @return 0 on success, < 0 on error.
*/
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
enum ssh_bind_options_e type, const void *value);

View File

@@ -102,9 +102,9 @@ struct ssh_session_struct {
#endif
char *username;
char *host;
char *bindaddr; /* TODO: check if needed */
char *bindaddr; /* bind the client to an ip addr */
char *xbanner; /* TODO: looks like it is not needed */
char *identity;
struct ssh_list *identity;
char *sshdir;
char *knownhosts;
char *wanted_methods[10];
@@ -114,8 +114,9 @@ struct ssh_session_struct {
socket_t fd;
int ssh2;
int ssh1;
char *ProxyCommand;
};
int ssh_handle_packets(ssh_session session);
void ssh_global_request_handle(ssh_session session);
#endif /* SESSION_H_ */

View File

@@ -149,17 +149,16 @@ struct sftp_status_message_struct {
char *langmsg;
};
/* don't worry much of these aren't really used */
struct sftp_attributes_struct {
char *name;
char *longname; /* some weird stuff */
char *longname; /* ls -l output on openssh, not reliable else */
uint32_t flags;
uint8_t type;
uint64_t size;
uint32_t uid;
uint32_t gid;
char *owner;
char *group;
char *owner; /* set if openssh and version 4 */
char *group; /* set if openssh and version 4 */
uint32_t permissions;
uint64_t atime64;
uint32_t atime;

View File

@@ -30,6 +30,7 @@ struct socket *ssh_socket_new(ssh_session session);
void ssh_socket_free(struct socket *s);
void ssh_socket_set_fd(struct socket *s, socket_t fd);
socket_t ssh_socket_get_fd(struct socket *s);
void ssh_socket_cleanup(void);
#ifndef _WIN32
int ssh_socket_unix(struct socket *s, const char *path);
#endif
@@ -38,7 +39,7 @@ int ssh_socket_read(struct socket *s, void *buffer, int len);
int ssh_socket_write(struct socket *s,const void *buffer, int len);
int ssh_socket_is_open(struct socket *s);
int ssh_socket_fd_isset(struct socket *s, fd_set *set);
void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max);
void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd);
int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len);
int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len);
int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len);
@@ -52,4 +53,10 @@ int ssh_socket_get_status(struct socket *s);
int ssh_socket_data_available(struct socket *s);
int ssh_socket_data_writable(struct socket *s);
#ifndef _WIN32
void ssh_execute_command(const char *command, socket_t in, socket_t out);
socket_t ssh_socket_connect_proxycommand(ssh_session session,
const char *command);
#endif
#endif /* SOCKET_H_ */

View File

@@ -70,6 +70,11 @@ typedef HMAC_CTX* HMACCTX;
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
#include <openssl/bn.h>
#include <openssl/opensslv.h>
#define OPENSSL_0_9_7b 0x0090702fL
#if (OPENSSL_VERSION_NUMBER <= OPENSSL_0_9_7b)
#define BROKEN_AES_CTR
#endif
typedef BIGNUM* bignum;
typedef BN_CTX* bignum_CTX;

View File

@@ -43,7 +43,7 @@ if (HAVE_LIBSOCKET)
)
endif (HAVE_LIBSOCKET)
if (CRYPTO_LIBRARY)
if (OPENSSL_LIBRARIES)
set(LIBSSH_PRIVATE_INCLUDE_DIRS
${LIBSSH_PRIVATE_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIRS}
@@ -51,9 +51,9 @@ if (CRYPTO_LIBRARY)
set(LIBSSH_LINK_LIBRARIES
${LIBSSH_LINK_LIBRARIES}
${CRYPTO_LIBRARY}
${OPENSSL_LIBRARIES}
)
endif (CRYPTO_LIBRARY)
endif (OPENSSL_LIBRARIES)
if (GCRYPT_LIBRARY)
set(LIBSSH_PRIVATE_INCLUDE_DIRS

View File

@@ -41,7 +41,6 @@
#include <string.h>
#include <stdio.h>
#include <poll.h>
#include <unistd.h>
#ifndef _WIN32
@@ -54,6 +53,7 @@
#include "libssh/buffer.h"
#include "libssh/session.h"
#include "libssh/keys.h"
#include "libssh/poll.h"
/* macro to check for "agent failure" message */
#define agent_failed(x) \
@@ -85,8 +85,8 @@ static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
char *b = buf;
size_t pos = 0;
ssize_t res;
struct pollfd pfd;
int fd = ssh_socket_get_fd(s);
ssh_pollfd_t pfd;
socket_t fd = ssh_socket_get_fd(s);
pfd.fd = fd;
pfd.events = do_read ? POLLIN : POLLOUT;
@@ -107,7 +107,7 @@ static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
#else
if (errno == EAGAIN) {
#endif
(void) poll(&pfd, 1, -1);
(void) ssh_poll(&pfd, 1, -1);
continue;
}
return 0;

View File

@@ -35,6 +35,7 @@
#include "libssh/buffer.h"
#include "libssh/agent.h"
#include "libssh/keyfiles.h"
#include "libssh/misc.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/keys.h"
@@ -169,24 +170,33 @@ static int wait_auth_status(ssh_session session, int kbdint) {
return rc;
}
/**
* @brief retrieves available authentication methods for this session
* @deprecated
* @see ssh_userauth_list
*/
int ssh_auth_list(ssh_session session) {
if (session == NULL) {
return -1;
}
return session->auth_methods;
return ssh_userauth_list(session, NULL);
}
/**
* @brief retrieves available authentication methods for this session
* @param[in] session the SSH session
* @param[in] username set to NULL
* @returns A bitfield of values SSH_AUTH_METHOD_NONE, SSH_AUTH_METHOD_PASSWORD,
SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED,
SSH_AUTH_METHOD_INTERACTIVE.
@warning Other reserved flags may appear in future versions.
*/
int ssh_userauth_list(ssh_session session, const char *username) {
if (session == NULL || username == NULL) {
if (session == NULL) {
return SSH_AUTH_ERROR;
}
if (session->auth_methods == 0) {
ssh_userauth_none(session, username);
}
return ssh_auth_list(session);
return session->auth_methods;
}
/* use the "none" authentication question */
@@ -224,7 +234,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -330,7 +340,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -442,7 +452,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -560,7 +570,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -687,7 +697,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return rc;
}
@@ -756,42 +766,6 @@ error:
return rc;
}
#ifdef _MSC_VER
static const char privKey_1[] = "SSH_DIR/identity";
static const char pubKey_1[] = "SSH_DIR/identity.pub";
static const char privKey_2[] = "SSH_DIR/id_dsa";
static const char pubKey_2[] = "SSH_DIR/id_dsa.pub";
static const char privKey_3[] = "SSH_DIR/id_rsa";
static const char pubKey_3[] = "SSH_DIR/id_rsa.pub";
/** Used different var to allow const char[] declaration */
static struct ssh_keys_struct keytab[] = {
{ privKey_1, pubKey_1},
{ privKey_2, pubKey_2},
{ privKey_3, pubKey_3},
{0}
};
#else
/* This requires GCC extensions */
static struct ssh_keys_struct keytab[] = {
{
.privatekey = "SSH_DIR/identity",
.publickey = "SSH_DIR/identity.pub"
},
{
.privatekey = "SSH_DIR/id_dsa",
.publickey = "SSH_DIR/id_dsa.pub",
},
{
.privatekey = "SSH_DIR/id_rsa",
.publickey = "SSH_DIR/id_rsa.pub",
},
{
.privatekey = NULL,
.publickey = NULL
}
};
#endif
/**
* @brief Tries to automaticaly authenticate with public key and "none"
*
@@ -812,16 +786,12 @@ static struct ssh_keys_struct keytab[] = {
*
* @see ssh_userauth_kbdint()
* @see ssh_userauth_password()
* @see ssh_options_set()
*/
int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
struct ssh_public_key_struct *publickey;
ssh_string pubkey;
struct ssh_iterator *it;
ssh_private_key privkey;
char *privkeyfile = NULL;
char *id = NULL;
size_t size;
unsigned int i = 0;
ssh_public_key pubkey;
ssh_string pubkey_string;
int type = 0;
int rc;
@@ -837,142 +807,159 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
/* Try authentication with ssh-agent first */
#ifndef _WIN32
if (agent_is_running(session)) {
char *privkey_file = NULL;
ssh_log(session, SSH_LOG_RARE,
"Trying to authenticate with SSH agent keys as user: %s",
session->username);
for (publickey = agent_get_first_ident(session, &privkeyfile);
publickey != NULL;
publickey = agent_get_next_ident(session, &privkeyfile)) {
for (pubkey = agent_get_first_ident(session, &privkey_file);
pubkey != NULL;
pubkey = agent_get_next_ident(session, &privkey_file)) {
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkeyfile);
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkey_file);
pubkey = publickey_to_string(publickey);
if (pubkey) {
rc = ssh_userauth_offer_pubkey(session, NULL, publickey->type, pubkey);
string_free(pubkey);
pubkey_string = publickey_to_string(pubkey);
if (pubkey_string) {
rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string);
string_free(pubkey_string);
if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
leave_function();
return rc;
} else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_PACKET, "Public key refused by server\n");
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server");
SAFE_FREE(privkey_file);
publickey_free(pubkey);
continue;
}
ssh_log(session, SSH_LOG_RARE, "Public key accepted");
/* pubkey accepted by server ! */
rc = ssh_userauth_agent_pubkey(session, NULL, publickey);
rc = ssh_userauth_agent_pubkey(session, NULL, pubkey);
if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
leave_function();
return rc;
} else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_RARE,
"Server accepted public key but refused the signature\n"
"It might be a bug of libssh\n");
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
"Server accepted public key but refused the signature ;"
" It might be a bug of libssh");
SAFE_FREE(privkey_file);
publickey_free(pubkey);
continue;
}
/* auth success */
ssh_log(session, SSH_LOG_RARE, "Authentication using %s success\n",
privkeyfile);
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success",
privkey_file);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
leave_function();
return SSH_AUTH_SUCCESS;
} /* if pubkey */
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
} /* for each privkey */
} /* if agent is running */
#endif
size = ARRAY_SIZE(keytab);
if (session->identity) {
ssh_log(session, SSH_LOG_RARE,
"Trying identity file %s\n", session->identity);
id = malloc(strlen(session->identity) + 1 + 4);
if (id == NULL) {
leave_function();
return SSH_AUTH_ERROR;
}
sprintf(id, "%s.pub", session->identity);
for (it = ssh_list_get_iterator(session->identity);
it != NULL;
it = it->next) {
const char *privkey_file = it->data;
int privkey_open = 0;
keytab[size - 1].privatekey = session->identity;
keytab[size - 1].publickey = id;
}
privkey = NULL;
for (i = 0, pubkey = try_publickey_from_file(session, keytab[i],
&privkeyfile, &type);
i < size;
pubkey = try_publickey_from_file(session, keytab[i++],
&privkeyfile, &type)) {
if (pubkey == NULL) {
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file);
rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type);
if (rc == 1) {
char *publickey_file;
size_t len;
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_RARE,
"Reading private key %s failed (bad passphrase ?)",
privkey_file);
leave_function();
return SSH_AUTH_ERROR;
}
privkey_open = 1;
pubkey = publickey_from_privatekey(privkey);
if (pubkey == NULL) {
privatekey_free(privkey);
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
pubkey_string = publickey_to_string(pubkey);
type = pubkey->type;
publickey_free(pubkey);
if (pubkey_string == NULL) {
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
len = strlen(privkey_file) + 5;
publickey_file = malloc(len);
if (publickey_file == NULL) {
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
snprintf(publickey_file, len, "%s.pub", privkey_file);
rc = ssh_publickey_to_file(session, publickey_file, pubkey_string, type);
if (rc < 0) {
ssh_log(session, SSH_LOG_PACKET,
"Could not write public key to file: %s", publickey_file);
}
SAFE_FREE(publickey_file);
} else if (rc < 0) {
continue;
}
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey);
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string);
if (rc == SSH_AUTH_ERROR){
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
string_free(pubkey_string);
ssh_log(session, SSH_LOG_RARE, "Publickey authentication error");
leave_function();
return rc;
} else {
if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_RARE, "Publickey refused by server");
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server");
string_free(pubkey_string);
continue;
}
}
/* Public key accepted by server! */
ssh_log(session, SSH_LOG_RARE, "Trying to read privatekey %s", privkeyfile);
privkey = privatekey_from_file(session, privkeyfile, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS,
"Reading private key %s failed (bad passphrase ?)",
privkeyfile);
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
continue; /* continue the loop with other pubkey */
if (!privkey_open) {
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s",
privkey_file);
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_RARE,
"Reading private key %s failed (bad passphrase ?)",
privkey_file);
string_free(pubkey_string);
continue; /* continue the loop with other pubkey */
}
}
rc = ssh_userauth_pubkey(session, NULL, pubkey, privkey);
rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey);
if (rc == SSH_AUTH_ERROR) {
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
string_free(pubkey_string);
privatekey_free(privkey);
leave_function();
return rc;
@@ -980,39 +967,26 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_FUNCTIONS,
"The server accepted the public key but refused the signature");
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
string_free(pubkey_string);
privatekey_free(privkey);
continue;
}
}
/* auth success */
ssh_log(session, SSH_LOG_RARE,
"Successfully authenticated using %s", privkeyfile);
string_free(pubkey);
ssh_log(session, SSH_LOG_PROTOCOL,
"Successfully authenticated using %s", privkey_file);
string_free(pubkey_string);
privatekey_free(privkey);
SAFE_FREE(privkeyfile);
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
leave_function();
return SSH_AUTH_SUCCESS;
}
/* at this point, pubkey is NULL and so is privkeyfile */
ssh_log(session, SSH_LOG_FUNCTIONS,
"Tried every public key, none matched");
ssh_set_error(session,SSH_NO_ERROR,"No public key matched");
if (id) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
leave_function();
return SSH_AUTH_DENIED;
@@ -1370,7 +1344,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
/* first time we call. we must ask for a challenge */
if (user == NULL) {
if ((user = session->username) == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
leave_function();
return SSH_AUTH_ERROR;
} else {
@@ -1402,7 +1376,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
/*
* If we are at this point, it ss because session->kbdint exists.
* It means the user has set some informations there we need to send
* It means the user has set some information there we need to send
* the server and then we need to ack the status (new questions or ok
* pass in).
*/

View File

@@ -165,8 +165,10 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
type_c, channel->local_channel);
if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) {
leave_function();
return -1;
if(session->in_packet.type != SSH2_MSG_CHANNEL_OPEN_FAILURE) {
leave_function();
return -1;
}
}
switch(session->in_packet.type) {
@@ -552,6 +554,15 @@ static void channel_rcv_request(ssh_session session) {
return;
}
if(strcmp(request,"keepalive@openssh.com")==0){
SAFE_FREE(request);
ssh_log(session, SSH_LOG_PROTOCOL,"Responding to Openssh's keepalive");
buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_FAILURE);
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel));
packet_send(session);
leave_function();
return;
}
/* TODO call message_handle since it handles channel requests as messages */
/* *but* reset buffer before !! */
@@ -566,7 +577,7 @@ static void channel_rcv_request(ssh_session session) {
/*
* channel_handle() is called by packet_wait(), for example when there is
* channel informations to handle.
* channel information to handle.
*/
void channel_handle(ssh_session session, int type){
enter_function();
@@ -785,7 +796,7 @@ void channel_free(ssh_channel channel) {
*
* @param channel The channel to send the eof to.
*
* @return SSH_SUCCESS on success\n
* @return SSH_OK on success\n
* SSH_ERROR on error\n
*
* @see channel_close()
@@ -828,7 +839,7 @@ error:
*
* @param channel The channel to close.
*
* @return SSH_SUCCESS on success\n
* @return SSH_OK on success\n
* SSH_ERROR on error
*
* @see channel_free()
@@ -1107,7 +1118,7 @@ error:
*
* @param row The number of rows.
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*/
int channel_request_pty_size(ssh_channel channel, const char *terminal,
int col, int row) {
@@ -1158,7 +1169,7 @@ error:
*
* @param channel The channel to send the request.
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @see channel_request_pty_size()
*/
@@ -1219,7 +1230,7 @@ error:
*
* @param channel The channel to send the request.
*
* @returns SSH_SUCCESS on success, SSH_ERROR on error.
* @returns SSH_OK on success, SSH_ERROR on error.
*/
int channel_request_shell(ssh_channel channel) {
#ifdef WITH_SSH1
@@ -1237,7 +1248,7 @@ int channel_request_shell(ssh_channel channel) {
*
* @param subsys The subsystem to request (for example "sftp").
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @warning You normally don't have to call it for sftp, see sftp_new().
*/
@@ -1585,7 +1596,7 @@ error:
*
* @param value The value to set.
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @warning Some environement variables may be refused by security reasons.
* */
@@ -1636,7 +1647,7 @@ error:
* @param cmd The command to execute
* (e.g. "ls ~/ -al | grep -i reports").
*
* @return SSH_SUCCESS on success, SSH_ERROR on error.
* @return SSH_OK on success, SSH_ERROR on error.
*
* @see channel_request_shell()
*/
@@ -1686,7 +1697,7 @@ error:
* @param signal The signal to send (without SIG prefix)
* (e.g. "TERM" or "KILL").
*
* @return SSH_SUCCESS on success, SSH_ERROR on error (including attempt to send signal via SSH-v1 session).
* @return SSH_OK on success, SSH_ERROR on error (including attempt to send signal via SSH-v1 session).
*
*/
int channel_request_send_signal(ssh_channel channel, const char *signal) {
@@ -1809,7 +1820,7 @@ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
}
if (count == 0) {
/* write the ful buffer informations */
/* write the ful buffer information */
if (buffer_add_data(buffer, buffer_get_rest(stdbuf),
buffer_get_rest_len(stdbuf)) < 0) {
leave_function();
@@ -1998,9 +2009,10 @@ int channel_poll(ssh_channel channel, int is_stderr){
stdbuf = channel->stderr_buffer;
}
while (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) {
if (ssh_handle_packets(channel->session) <= 0) {
break;
if (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) {
if (ssh_handle_packets(channel->session) == SSH_ERROR) {
leave_function();
return SSH_ERROR;
}
}
@@ -2140,7 +2152,7 @@ static int count_ptrs(ssh_channel *ptrs) {
*
* @param timeout Timeout as defined by select(2).
*
* @return SSH_SUCCESS operation successful\n
* @return SSH_OK operation successful\n
* SSH_EINTR select(2) syscall was interrupted, relaunch the function
*/
int channel_select(ssh_channel *readchans, ssh_channel *writechans,
@@ -2150,7 +2162,7 @@ int channel_select(ssh_channel *readchans, ssh_channel *writechans,
fd_set rset;
fd_set wset;
fd_set eset;
int fdmax = -1;
socket_t max_fd = SSH_INVALID_SOCKET;
int rc;
int i;
@@ -2218,24 +2230,24 @@ int channel_select(ssh_channel *readchans, ssh_channel *writechans,
for (i = 0; readchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) {
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &fdmax);
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &max_fd);
}
}
for (i = 0; writechans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) {
ssh_socket_fd_set(writechans[i]->session->socket, &wset, &fdmax);
ssh_socket_fd_set(writechans[i]->session->socket, &wset, &max_fd);
}
}
for (i = 0; exceptchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) {
ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &fdmax);
ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &max_fd);
}
}
/* Here we go */
rc = select(fdmax, &rset, &wset, &eset, timeout);
rc = select(max_fd, &rset, &wset, &eset, timeout);
/* Leave if select was interrupted */
if (rc == EINTR) {
SAFE_FREE(rchans);

View File

@@ -26,6 +26,9 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/ssh1.h"
#include "libssh/buffer.h"

View File

@@ -296,6 +296,7 @@ static int dh_handshake(ssh_session session) {
goto error;
}
session->dh_server_signature = signature;
signature=NULL; /* ownership changed */
if (dh_build_k(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
rc = SSH_ERROR;
@@ -400,10 +401,6 @@ error:
string_burn(f);
string_free(f);
}
if(pubkey != NULL){
string_burn(pubkey);
string_free(pubkey);
}
if(signature != NULL){
string_burn(signature);
string_free(signature);
@@ -484,7 +481,8 @@ int ssh_service_request(ssh_session session, const char *service) {
int ssh_connect(ssh_session session) {
int ssh1 = 0;
int ssh2 = 0;
int fd = -1;
socket_t fd = SSH_INVALID_SOCKET;
int ret;
if (session == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
@@ -500,18 +498,31 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
if (session->fd == -1 && session->host == NULL) {
if (session->fd == SSH_INVALID_SOCKET && session->host == NULL &&
session->ProxyCommand == NULL) {
ssh_set_error(session, SSH_FATAL, "Hostname required");
leave_function();
return SSH_ERROR;
}
if (session->fd != -1) {
ret = ssh_options_apply(session);
if (ret < 0) {
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
leave_function();
return SSH_ERROR;
}
if (session->fd != SSH_INVALID_SOCKET) {
fd = session->fd;
#ifndef _WIN32
} else if (session->ProxyCommand != NULL) {
fd=ssh_socket_connect_proxycommand(session, session->ProxyCommand);
#endif
} else {
fd = ssh_connect_host(session, session->host, session->bindaddr,
session->port, session->timeout, session->timeout_usec);
}
if (fd < 0) {
if (fd == SSH_INVALID_SOCKET) {
leave_function();
return SSH_ERROR;
}
@@ -699,7 +710,7 @@ error:
const char *ssh_copyright(void) {
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2008 Aris Adamantiadis "
"(aris@0xbadc0de.be) Distributed under the LGPL, please refer to COPYING"
"file for informations about your rights";
"file for information about your rights";
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -35,11 +35,11 @@ enum ssh_config_opcode_e {
SOC_PORT,
SOC_USERNAME,
SOC_IDENTITY,
SOC_CIPHER,
SOC_CIPHERS,
SOC_COMPRESSION,
SOC_TIMEOUT,
SOC_PROTOCOL
SOC_PROTOCOL,
SOC_PROXYCOMMAND
};
struct ssh_config_keyword_table_s {
@@ -53,11 +53,11 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "port", SOC_PORT },
{ "user", SOC_USERNAME },
{ "identityfile", SOC_IDENTITY },
{ "cipher", SOC_CIPHER },
{ "ciphers", SOC_CIPHERS },
{ "compression", SOC_COMPRESSION },
{ "connecttimeout", SOC_TIMEOUT },
{ "protocol", SOC_PROTOCOL },
{ "proxycommand", SOC_PROXYCOMMAND },
{ NULL, SOC_UNSUPPORTED }
};
@@ -199,21 +199,25 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
}
break;
case SOC_PORT:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
if (session->port == 22) {
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
}
}
break;
case SOC_USERNAME:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_USER, p);
if (session->username == NULL) {
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_USER, p);
}
}
break;
case SOC_IDENTITY:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_IDENTITY, p);
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
}
break;
case SOC_CIPHERS:
@@ -272,11 +276,19 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &i);
}
break;
case SOC_PROXYCOMMAND:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
}
break;
case SOC_UNSUPPORTED:
fprintf(stderr, "Unsupported option: %s, line: %d\n", keyword, count);
ssh_log(session, SSH_LOG_RARE, "Unsupported option: %s, line: %d\n",
keyword, count);
break;
default:
fprintf(stderr, "ERROR - unimplemented opcode: %d\n", opcode);
ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d\n",
opcode);
SAFE_FREE(x);
return -1;
break;

View File

@@ -390,6 +390,7 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
fd_set *readfds, struct timeval *timeout) {
struct timeval zerotime;
fd_set localset, localset2;
socket_t f;
int rep;
int set;
int i;
@@ -430,8 +431,8 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
/* Look into the localset for active fd */
set = 0;
for (i = 0; (i < maxfd) && !set; i++) {
if (FD_ISSET(i, &localset)) {
for (f = 0; (f < maxfd) && !set; f++) {
if (FD_ISSET(f, &localset)) {
set = 1;
}
}
@@ -493,9 +494,9 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
outchannels[j] = NULL;
FD_ZERO(&localset2);
for (i = 0; i < maxfd; i++) {
if (FD_ISSET(i, readfds) && FD_ISSET(i, &localset)) {
FD_SET(i, &localset2);
for (f = 0; f < maxfd; f++) {
if (FD_ISSET(f, readfds) && FD_ISSET(i, &localset)) {
FD_SET(f, &localset2);
}
}

View File

@@ -831,8 +831,11 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
if (session == NULL || hash == NULL) {
return -1;
}
*hash = NULL;
if (session->current_crypto == NULL ||
session->current_crypto->server_pubkey == NULL){
ssh_set_error(session,SSH_FATAL,"No current cryptographic context");
}
h = malloc(sizeof(unsigned char *) * MD5_DIGEST_LEN);
if (h == NULL) {

View File

@@ -65,6 +65,7 @@ int ssh_init(void) {
int ssh_finalize(void) {
ssh_regex_finalize();
ssh_crypto_finalize();
ssh_socket_cleanup();
#ifdef HAVE_LIBGCRYPT
gcry_control(GCRYCTL_TERM_SECMEM);
#elif defined HAVE_LIBCRYPTO

View File

@@ -40,6 +40,7 @@
#include "libssh/wrapper.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/string.h"
#ifdef HAVE_LIBGCRYPT
#define BLOWFISH "blowfish-cbc,"
@@ -52,10 +53,15 @@
#define BLOWFISH ""
#endif
#ifdef HAVE_OPENSSL_AES_H
#ifdef BROKEN_AES_CTR
#define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
#else
#define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
#endif /* BROKEN_AES_CTR */
#else
#define AES ""
#endif
#define DES "3des-cbc"
#endif
@@ -194,48 +200,48 @@ char **space_tokenize(const char *chain){
return tokens;
}
/* find_matching gets 2 parameters : a list of available objects (in_d), separated by colons,*/
/* and a list of prefered objects (what_d) */
/* find_matching gets 2 parameters : a list of available objects (available_d), separated by colons,*/
/* and a list of preferred objects (preferred_d) */
/* it will return a strduped pointer on the first prefered object found in the available objects list */
char *ssh_find_matching(const char *in_d, const char *what_d){
char ** tok_in, **tok_what;
int i_in, i_what;
char *ssh_find_matching(const char *available_d, const char *preferred_d){
char ** tok_available, **tok_preferred;
int i_avail, i_pref;
char *ret;
if ((in_d == NULL) || (what_d == NULL)) {
if ((available_d == NULL) || (preferred_d == NULL)) {
return NULL; /* don't deal with null args */
}
tok_in = tokenize(in_d);
if (tok_in == NULL) {
tok_available = tokenize(available_d);
if (tok_available == NULL) {
return NULL;
}
tok_what = tokenize(what_d);
if (tok_what == NULL) {
SAFE_FREE(tok_in[0]);
SAFE_FREE(tok_in);
tok_preferred = tokenize(preferred_d);
if (tok_preferred == NULL) {
SAFE_FREE(tok_available[0]);
SAFE_FREE(tok_available);
}
for(i_what=0; tok_what[i_what] ; ++i_what){
for(i_in=0; tok_in[i_in]; ++i_in){
if(!strcmp(tok_in[i_in],tok_what[i_what])){
for(i_pref=0; tok_preferred[i_pref] ; ++i_pref){
for(i_avail=0; tok_available[i_avail]; ++i_avail){
if(!strcmp(tok_available[i_avail],tok_preferred[i_pref])){
/* match */
ret=strdup(tok_in[i_in]);
ret=strdup(tok_available[i_avail]);
/* free the tokens */
free(tok_in[0]);
free(tok_what[0]);
free(tok_in);
free(tok_what);
free(tok_available[0]);
free(tok_preferred[0]);
free(tok_available);
free(tok_preferred);
return ret;
}
}
}
free(tok_in[0]);
free(tok_what[0]);
free(tok_in);
free(tok_what);
free(tok_available[0]);
free(tok_preferred[0]);
free(tok_available);
free(tok_preferred);
return NULL;
}
@@ -487,8 +493,8 @@ static int build_session_id1(ssh_session session, ssh_string servern,
}
#ifdef DEBUG_CRYPTO
ssh_print_hexa("host modulus",hostn->string,string_len(hostn));
ssh_print_hexa("server modulus",servern->string,string_len(servern));
ssh_print_hexa("host modulus",string_data(hostn),string_len(hostn));
ssh_print_hexa("server modulus",string_data(servern),string_len(servern));
#endif
md5_update(md5,string_data(hostn),string_len(hostn));
md5_update(md5,string_data(servern),string_len(servern));

View File

@@ -677,7 +677,7 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
switch (type) {
case TYPE_DSS:
if (passphrase == NULL) {
if (session->callbacks->auth_function) {
if (session->callbacks && session->callbacks->auth_function) {
auth_cb = session->callbacks->auth_function;
auth_ud = session->callbacks->userdata;
@@ -780,6 +780,20 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
return privkey;
}
/**
* @brief returns the type of a private key
* @param privatekey[in] the private key handle
* @returns one of TYPE_RSA,TYPE_DSS,TYPE_RSA1
* @returns 0 if the type is unknown
* @see privatekey_from_file
* @see ssh_userauth_offer_pubkey
*/
int ssh_privatekey_type(ssh_private_key privatekey){
if (privatekey==NULL)
return 0;
return privatekey->type;
}
/* same that privatekey_from_file() but without any passphrase things. */
ssh_private_key _privatekey_from_file(void *session, const char *filename,
int type) {
@@ -887,6 +901,79 @@ void privatekey_free(ssh_private_key prv) {
SAFE_FREE(prv);
}
/**
* @brief Write a public key to a file.
*
* @param[in] session The ssh session to use.
*
* @param[in] file The filename to write the key into.
*
* @param[in] pubkey The public key to write.
*
* @param[in] type The type of the public key.
*
* @return 0 on success, -1 on error.
*/
int ssh_publickey_to_file(ssh_session session, const char *file,
ssh_string pubkey, int type) {
FILE *fp;
char *user;
char buffer[1024];
char host[256];
unsigned char *pubkey_64;
size_t len;
int rc;
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
if (pubkey_64 == NULL) {
return -1;
}
user = ssh_get_local_username(session);
if (user == NULL) {
SAFE_FREE(pubkey_64);
return -1;
}
rc = gethostname(host, sizeof(host));
if (rc < 0) {
SAFE_FREE(user);
SAFE_FREE(pubkey_64);
return -1;
}
snprintf(buffer, sizeof(buffer), "%s %s %s@%s\n",
ssh_type_to_char(type),
pubkey_64,
user,
host);
SAFE_FREE(pubkey_64);
SAFE_FREE(user);
ssh_log(session, SSH_LOG_RARE, "Trying to write public key file: %s", file);
ssh_log(session, SSH_LOG_PACKET, "public key file content: %s", buffer);
fp = fopen(file, "w+");
if (fp == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Error opening %s: %s", file, strerror(errno));
return -1;
}
len = strlen(buffer);
if (fwrite(buffer, len, 1, fp) != 1 || ferror(fp)) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Unable to write to %s", file);
fclose(fp);
unlink(file);
return -1;
}
fclose(fp);
return 0;
}
/** \brief Retrieve a public key from a file
* \param session the SSH session
* \param filename Filename of the key
@@ -964,10 +1051,85 @@ ssh_string publickey_from_file(ssh_session session, const char *filename,
return str;
}
/**
* @brief Try to read the public key from a given file.
*
* @param[in] session The ssh session to use.
*
* @param[in] keyfile The name of the private keyfile.
*
* @param[out] publickey A ssh_string to store the public key.
*
* @param[out] type A pointer to an integer to store the type.
*
* @return 0 on success, -1 on error or the private key doesn't
* exist, 1 if the public key doesn't exist.
*/
int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type) {
char *pubkey_file;
size_t len;
ssh_string pubkey_string;
int pubkey_type;
if (session == NULL || keyfile == NULL || publickey == NULL || type == NULL) {
return -1;
}
if (session->sshdir == NULL) {
if (ssh_options_apply(session) < 0) {
return -1;
}
}
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", keyfile);
if (!ssh_file_readaccess_ok(keyfile)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", keyfile);
return -1;
}
len = strlen(keyfile) + 5;
pubkey_file = malloc(len);
if (pubkey_file == NULL) {
return -1;
}
snprintf(pubkey_file, len, "%s.pub", keyfile);
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s",
pubkey_file);
if (!ssh_file_readaccess_ok(pubkey_file)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s",
pubkey_file);
SAFE_FREE(pubkey_file);
return 1;
}
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
/*
* We are sure both the private and public key file is readable. We return
* the public as a string, and the private filename as an argument
*/
pubkey_string = publickey_from_file(session, pubkey_file, &pubkey_type);
if (pubkey_string == NULL) {
ssh_log(session, SSH_LOG_PACKET,
"Wasn't able to open public key file %s: %s",
pubkey_file,
ssh_get_error(session));
SAFE_FREE(pubkey_file);
return -1;
}
SAFE_FREE(pubkey_file);
*publickey = pubkey_string;
*type = pubkey_type;
return 0;
}
ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab,
char **privkeyfile, int *type) {
char *public;
char *private;
const char *priv;
const char *pub;
char *new;
@@ -983,26 +1145,20 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
}
if (session->sshdir == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
return NULL;
}
}
/* are them readable ? */
public=dir_expand_dup(session,pub,1);
private=dir_expand_dup(session,priv,1);
//snprintf(public, sizeof(public), "%s/%s", session->sshdir, pub);
//snprintf(private, sizeof(private), "%s/%s", session->sshdir, priv);
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", public);
if (!ssh_file_readaccess_ok(public)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", public);
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
if (!ssh_file_readaccess_ok(pub)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
goto error;
}
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", private);
if (!ssh_file_readaccess_ok(private)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", private);
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
if (!ssh_file_readaccess_ok(priv)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
goto error;
}
@@ -1012,26 +1168,24 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
* We are sure both the private and public key file is readable. We return
* the public as a string, and the private filename as an argument
*/
pubkey = publickey_from_file(session, public, type);
pubkey = publickey_from_file(session, pub, type);
if (pubkey == NULL) {
ssh_log(session, SSH_LOG_PACKET,
"Wasn't able to open public key file %s: %s",
public,
pub,
ssh_get_error(session));
goto error;
}
new = realloc(*privkeyfile, strlen(private) + 1);
new = realloc(*privkeyfile, strlen(priv) + 1);
if (new == NULL) {
string_free(pubkey);
goto error;
}
strcpy(new, private);
strcpy(new, priv);
*privkeyfile = new;
error:
SAFE_FREE(public);
SAFE_FREE(private);
return pubkey;
}
@@ -1396,7 +1550,6 @@ static int match_hashed_host(ssh_session session, const char *host,
* if host key is accepted\n
* SSH_SERVER_ERROR: Some error happened
*
* \see ssh_options_set()
* \see ssh_get_pubkey_hash()
*
* \bug There is no current way to remove or modify an entry into the known
@@ -1406,6 +1559,7 @@ int ssh_is_server_known(ssh_session session) {
FILE *file = NULL;
char **tokens;
char *host;
char *hostport;
const char *type;
int match;
int ret = SSH_SERVER_NOT_KNOWN;
@@ -1413,7 +1567,7 @@ int ssh_is_server_known(ssh_session session) {
enter_function();
if (session->knownhosts == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file");
leave_function();
@@ -1429,8 +1583,11 @@ int ssh_is_server_known(ssh_session session) {
}
host = lowercase(session->host);
if (host == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space!");
hostport = ssh_hostport(host,session->port);
if (host == NULL || hostport == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(host);
SAFE_FREE(hostport);
leave_function();
return SSH_SERVER_ERROR;
}
@@ -1444,10 +1601,15 @@ int ssh_is_server_known(ssh_session session) {
break;
}
match = match_hashed_host(session, host, tokens[0]);
if (match == 0){
match = match_hostname(hostport, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hostname(host, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hashed_host(session, hostport, tokens[0]);
}
if (match) {
/* We got a match. Now check the key type */
if (strcmp(session->current_crypto->server_pubkey_type, type) != 0) {
@@ -1478,6 +1640,7 @@ int ssh_is_server_known(ssh_session session) {
} while (1);
SAFE_FREE(host);
SAFE_FREE(hostport);
if (file != NULL) {
fclose(file);
}
@@ -1487,10 +1650,15 @@ int ssh_is_server_known(ssh_session session) {
return ret;
}
/** You generaly use it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN
* \brief write the current server as known in the known hosts file. This will create the known hosts file if it does not exist.
* \param session ssh session
* \return 0 on success, -1 on error
/**
* @brief Write the current server as known in the known hosts file.
*
* This will create the known hosts file if it does not exist. You generaly use
* it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN.
*
* @param[in] session The ssh session to use.
*
* @return SSH_OK on success, SSH_ERROR on error.
*/
int ssh_write_knownhost(ssh_session session) {
ssh_string pubkey = session->current_crypto->server_pubkey;
@@ -1498,19 +1666,30 @@ int ssh_write_knownhost(ssh_session session) {
char buffer[4096] = {0};
FILE *file;
char *dir;
char *host;
char *hostport;
size_t len = 0;
if (session->knownhosts == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) {
ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file");
return -1;
}
}
if (session->host == NULL) {
ssh_set_error(session, SSH_FATAL,
"Cannot write host in known hosts if the hostname is unknown");
return -1;
"Can't write host in known hosts if the hostname isn't known");
return SSH_ERROR;
}
host = lowercase(session->host);
/* If using a nonstandard port, save the host in the [host]:port format */
if(session->port != 22){
hostport = ssh_hostport(host,session->port);
SAFE_FREE(host);
host=hostport;
hostport=NULL;
}
if (session->knownhosts == NULL) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file");
return -1;
}
}
/* Check if ~/.ssh exists and create it if not */
@@ -1534,6 +1713,7 @@ int ssh_write_knownhost(ssh_session session) {
ssh_set_error(session, SSH_FATAL,
"Couldn't open known_hosts file %s for appending: %s",
session->knownhosts, strerror(errno));
SAFE_FREE(host);
return -1;
}
@@ -1553,6 +1733,7 @@ int ssh_write_knownhost(ssh_session session) {
key = publickey_from_string(session, pubkey);
if (key == NULL) {
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1561,6 +1742,7 @@ int ssh_write_knownhost(ssh_session session) {
if (sexp == NULL) {
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1568,6 +1750,7 @@ int ssh_write_knownhost(ssh_session session) {
if (e == NULL) {
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1576,6 +1759,7 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key);
bignum_free(e);
fclose(file);
SAFE_FREE(host);
return -1;
}
n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1584,6 +1768,7 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key);
bignum_free(e);
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1608,12 +1793,13 @@ int ssh_write_knownhost(ssh_session session) {
#endif
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
snprintf(buffer, sizeof(buffer),
"%s %d %s %s\n",
session->host,
host,
rsa_size << 3,
e_string,
n_string);
@@ -1633,18 +1819,19 @@ int ssh_write_knownhost(ssh_session session) {
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
if (pubkey_64 == NULL) {
fclose(file);
SAFE_FREE(host);
return -1;
}
snprintf(buffer, sizeof(buffer),
"%s %s %s\n",
session->host,
host,
session->current_crypto->server_pubkey_type,
pubkey_64);
SAFE_FREE(pubkey_64);
}
SAFE_FREE(host);
len = strlen(buffer);
if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
fclose(file);

View File

@@ -36,6 +36,7 @@
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
#include "libssh/string.h"
/** \addtogroup ssh_auth
* @{
@@ -130,9 +131,9 @@ ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
#endif /* HAVE_LIBCRYPTO */
#ifdef DEBUG_CRYPTO
ssh_print_hexa("p", p->string, string_len(p));
ssh_print_hexa("q", q->string, string_len(q));
ssh_print_hexa("g", g->string, string_len(g));
ssh_print_hexa("p", string_data(p), string_len(p));
ssh_print_hexa("q", string_data(q), string_len(q));
ssh_print_hexa("g", string_data(g), string_len(g));
#endif
string_burn(p);
@@ -206,8 +207,8 @@ ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
#endif
#ifdef DEBUG_CRYPTO
ssh_print_hexa("e", e->string, string_len(e));
ssh_print_hexa("n", n->string, string_len(n));
ssh_print_hexa("e", string_data(e), string_len(e));
ssh_print_hexa("n", string_data(n), string_len(n));
#endif
string_burn(e);
@@ -974,8 +975,8 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#endif
#ifdef DEBUG_CRYPTO
ssh_print_hexa("r", rs->string, 20);
ssh_print_hexa("s", rs->string + 20, 20);
ssh_print_hexa("r", string_data(rs), 20);
ssh_print_hexa("s", (const unsigned char *)string_data(rs) + 20, 20);
#endif
string_free(rs);
@@ -1024,7 +1025,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#ifdef DEBUG_CRYPTO
ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len);
ssh_print_hexa("RSA signature", e->string, len);
ssh_print_hexa("RSA signature", string_data(e), len);
#endif
#ifdef HAVE_LIBGCRYPT

View File

@@ -867,7 +867,7 @@ void message_handle(ssh_session session, uint32_t type){
if(!session->ssh_message_list){
session->ssh_message_list=ssh_list_new();
}
ssh_list_add(session->ssh_message_list,msg);
ssh_list_append(session->ssh_message_list,msg);
}
}

View File

@@ -35,6 +35,7 @@
#ifdef _WIN32
#define _WIN32_IE 0x0501 //SHGetSpecialFolderPath
#include <winsock2.h> // Must be the first to include
#include <ws2tcpip.h>
#include <shlobj.h>
#include <direct.h>
#else
@@ -46,6 +47,7 @@
#include "libssh/priv.h"
#include "libssh/misc.h"
#include "libssh/session.h"
#ifdef HAVE_LIBGCRYPT
#define GCRYPT_STRING "/gnutls"
@@ -145,6 +147,20 @@ int ssh_file_readaccess_ok(const char *file) {
}
#endif
char *ssh_hostport(const char *host, int port){
char *dest;
size_t len;
if(host==NULL)
return NULL;
/* 3 for []:, 5 for 65536 and 1 for nul */
len=strlen(host) + 3 + 5 + 1;
dest=malloc(len);
if(dest==NULL)
return NULL;
snprintf(dest,len,"[%s]:%d",host,port);
return dest;
}
uint64_t ntohll(uint64_t a) {
#ifdef WORDS_BIGENDIAN
return a;
@@ -158,6 +174,52 @@ uint64_t ntohll(uint64_t a) {
#endif
}
#ifdef _WIN32
char *ssh_get_local_username(ssh_session session) {
DWORD size = 0;
char *user;
/* get the size */
GetUserName(NULL, &size);
user = malloc(size);
if (user == NULL) {
ssh_set_error_oom(session);
return NULL;
}
if (GetUserName(user, &size)) {
return user;
}
return NULL;
}
#else
char *ssh_get_local_username(ssh_session session) {
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
char *name;
int rc;
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Couldn't retrieve information for current user!");
return NULL;
}
name = strdup(pwd.pw_name);
if (name == NULL) {
ssh_set_error_oom(session);
return NULL;
}
return name;
}
#endif
/**
* @brief Check if libssh is the required version or get the version
* string.
@@ -222,7 +284,7 @@ static struct ssh_iterator *ssh_iterator_new(const void *data){
return iterator;
}
int ssh_list_add(struct ssh_list *list,const void *data){
int ssh_list_append(struct ssh_list *list,const void *data){
struct ssh_iterator *iterator=ssh_iterator_new(data);
if(!iterator)
return SSH_ERROR;
@@ -237,6 +299,25 @@ int ssh_list_add(struct ssh_list *list,const void *data){
return SSH_OK;
}
int ssh_list_prepend(struct ssh_list *list, const void *data){
struct ssh_iterator *it = ssh_iterator_new(data);
if (it == NULL) {
return SSH_ERROR;
}
if (list->end == NULL) {
/* list is empty */
list->root = list->end = it;
} else {
/* set as new root */
it->next = list->root;
list->root = it;
}
return SSH_OK;
}
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
struct ssh_iterator *ptr,*prev;
prev=NULL;
@@ -261,7 +342,14 @@ void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
SAFE_FREE(iterator);
}
const void *_ssh_list_get_head(struct ssh_list *list){
/** @internal
* @brief Removes the top element of the list and returns the data value attached
* to it
* @param list the ssh_list
* @returns pointer to the element being stored in head, or
* NULL if the list is empty.
*/
const void *_ssh_list_pop_head(struct ssh_list *list){
struct ssh_iterator *iterator=list->root;
const void *data;
if(!list->root)
@@ -406,5 +494,155 @@ int ssh_mkdir(const char *pathname, mode_t mode) {
return r;
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */
/**
* @brief Expand a directory starting with a tilde '~'
*
* @param[in] session The ssh session to use.
*
* @param[in] d The directory to expand.
*
* @return The expanded directory, NULL on error.
*/
char *ssh_path_expand_tilde(const char *d) {
char *h, *r;
const char *p;
size_t ld;
size_t lh = 0;
if (d[0] != '~') {
return strdup(d);
}
d++;
/* handle ~user/path */
p = strchr(d, '/');
if (p != NULL && p > d) {
#ifdef _WIN32
return strdup(d);
#else
struct passwd *pw;
size_t s = p - d;
char u[128];
if (s > sizeof(u)) {
return NULL;
}
memcpy(u, d, s);
u[s] = '\0';
pw = getpwnam(u);
if (pw == NULL) {
return NULL;
}
ld = strlen(p);
h = strdup(pw->pw_dir);
#endif
} else {
ld = strlen(d);
p = (char *) d;
h = ssh_get_user_home_dir();
}
if (h == NULL) {
return NULL;
}
lh = strlen(h);
r = malloc(ld + lh + 1);
if (r == NULL) {
return NULL;
}
if (lh > 0) {
memcpy(r, h, lh);
}
memcpy(r + lh, p, ld + 1);
return r;
}
char *ssh_path_expand_escape(ssh_session session, const char *s) {
#define MAX_BUF_SIZE 4096
char host[NI_MAXHOST];
char buf[MAX_BUF_SIZE];
char *r, *x = NULL;
const char *p;
size_t i, l;
if (strlen(s) > MAX_BUF_SIZE) {
ssh_set_error(session, SSH_FATAL, "string to expand too long");
return NULL;
}
r = ssh_path_expand_tilde(s);
if (r == NULL) {
ssh_set_error_oom(session);
return NULL;
}
p = r;
buf[0] = '\0';
for (i = 0; *p != '\0'; p++) {
if (*p != '%') {
buf[i] = *p;
i++;
if (i > MAX_BUF_SIZE) {
return NULL;
}
buf[i] = '\0';
continue;
}
p++;
if (*p == '\0') {
break;
}
switch (*p) {
case 'd':
x = strdup(session->sshdir);
break;
case 'u':
x = ssh_get_local_username(session);
break;
case 'l':
if (gethostname(host, sizeof(host) == 0)) {
x = strdup(host);
}
break;
case 'h':
x = strdup(session->host);
break;
case 'r':
x = strdup(session->username);
break;
default:
ssh_set_error(session, SSH_FATAL,
"Wrong escape sequence detected");
return NULL;
}
if (x == NULL) {
ssh_set_error_oom(session);
return NULL;
}
i += strlen(x);
if (i > MAX_BUF_SIZE) {
ssh_set_error(session, SSH_FATAL,
"String too long");
return NULL;
}
l = strlen(buf);
strcat(buf + l, x);
buf[i] = '\0';
SAFE_FREE(x);
}
free(r);
return strdup(buf);
#undef MAX_BUF_SIZE
}
/* @} */
/* vim: set ts=4 sw=4 et cindent: */

View File

@@ -83,10 +83,29 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
}
if (src->identity) {
new->identity = strdup(src->identity);
struct ssh_iterator *it;
new->identity = ssh_list_new();
if (new->identity == NULL) {
return -1;
}
it = ssh_list_get_iterator(src->identity);
while (it) {
char *id;
int rc;
id = strdup((char *) it->data);
if (id == NULL) {
return -1;
}
rc = ssh_list_append(new->identity, id);
if (rc < 0) {
return -1;
}
it = it->next;
}
}
if (src->sshdir) {
@@ -124,29 +143,6 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
return 0;
}
#ifndef _WIN32
static char *get_username_from_uid(ssh_session session, uid_t uid){
struct passwd *pwd = NULL;
char *name;
pwd = getpwuid(uid);
if (pwd == NULL) {
ssh_set_error(session, SSH_FATAL, "uid %d doesn't exist !", uid);
return NULL;
}
name = strdup(pwd->pw_name);
if (name == NULL) {
ssh_set_error_oom(session);
return NULL;
}
return name;
}
#endif
int ssh_options_set_algo(ssh_session session, int algo,
const char *list) {
if (!verify_existing_algo(algo, list)) {
@@ -166,58 +162,6 @@ int ssh_options_set_algo(ssh_session session, int algo,
return 0;
}
char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) {
char *new;
if (value[0] == '~' && value[1] == '/') {
char *homedir = ssh_get_user_home_dir();
size_t lv, lh;
if (homedir == NULL) {
return NULL;
}
lv = strlen(value + 1);
lh = strlen(homedir);
new = malloc(lv + lh + 1);
if (new == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(homedir);
return NULL;
}
memcpy(new, homedir, lh);
SAFE_FREE(homedir);
memcpy(new + lh, value + 1, lv + 1);
return new;
}
if (allowsshdir && strncmp(value, "SSH_DIR/", 8) == 0) {
size_t lv, ls;
if (session->sshdir == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0)
return NULL;
}
value += 7;
lv = strlen(value);
ls = strlen(session->sshdir);
new = malloc(lv + ls + 1);
if (new == NULL) {
ssh_set_error_oom(session);
return NULL;
}
memcpy(new, session->sshdir, ls);
memcpy(new + ls, value, lv + 1);
return new;
}
new = strdup(value);
if (new == NULL) {
ssh_set_error_oom(session);
return NULL;
}
return new;
}
/**
* @brief This function can set all possible ssh options.
*
@@ -243,6 +187,9 @@ char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) {
* set the hostname as the hostname is used as a key in
* the known_host mechanism.
*
* - SSH_OPTIONS_BINDADDR:
* The address to bind the client to (string).
*
* - SSH_OPTIONS_USER:
* The username for authentication (string).\n
* \n
@@ -366,6 +313,10 @@ char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) {
* Set the compression to use for server to client
* communication (string, "none" or "zlib").
*
* - SSH_OPTIONS_PROXYCOMMAND:
* Set the command to be executed in order to connect to
* server.
*
* @param value The value to set. This is a generic pointer and the
* datatype which is used should be set according to the
* type set.
@@ -376,6 +327,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
const void *value) {
char *p, *q;
long int i;
int rc;
if (session == NULL) {
return -1;
@@ -439,30 +391,35 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->port = i & 0xffff;
}
break;
case SSH_OPTIONS_FD:
if (value == NULL) {
session->fd = -1;
} else {
socket_t *x = (socket_t *) value;
session->fd = *x & 0xffff;
}
break;
case SSH_OPTIONS_BINDADDR:
if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
q = strdup(value);
if (q == NULL) {
return -1;
}
SAFE_FREE(session->bindaddr);
session->bindaddr = q;
break;
case SSH_OPTIONS_USER:
SAFE_FREE(session->username);
if (value == NULL) { /* set default username */
#ifdef _WIN32
DWORD size = 0;
GetUserName(NULL, &size); //Get Size
q = malloc(size);
if (q == NULL) {
ssh_set_error_oom(session);
return -1;
}
if (GetUserName(q, &size)) {
session->username = q;
} else {
SAFE_FREE(q);
return -1;
}
#else /* _WIN32 */
q = get_username_from_uid(session, getuid());
q = ssh_get_local_username(session);
if (q == NULL) {
return -1;
}
session->username = q;
#endif /* _WIN32 */
} else { /* username provided */
session->username = strdup(value);
if (session->username == NULL) {
@@ -474,43 +431,47 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
case SSH_OPTIONS_SSH_DIR:
if (value == NULL) {
SAFE_FREE(session->sshdir);
/* TODO: why ~/.ssh/ instead of ~/.ssh ? */
session->sshdir = dir_expand_dup(session, "~/.ssh/", 0);
session->sshdir = ssh_path_expand_tilde("~/.ssh/");
if (session->sshdir == NULL) {
return -1;
}
} else {
SAFE_FREE(session->sshdir);
session->sshdir = dir_expand_dup(session, value, 0);
session->sshdir = ssh_path_expand_tilde(value);
if (session->sshdir == NULL) {
return -1;
}
}
break;
case SSH_OPTIONS_IDENTITY:
case SSH_OPTIONS_ADD_IDENTITY:
if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
SAFE_FREE(session->identity);
session->identity = dir_expand_dup(session, value, 1);
if (session->identity == NULL) {
q = strdup(value);
if (q == NULL) {
return -1;
}
rc = ssh_list_prepend(session->identity, q);
if (rc < 0) {
return -1;
}
break;
case SSH_OPTIONS_KNOWNHOSTS:
if (value == NULL) {
SAFE_FREE(session->knownhosts);
session->knownhosts = dir_expand_dup(session,
"SSH_DIR/known_hosts", 1);
if (session->sshdir == NULL) {
return -1;
}
session->knownhosts = ssh_path_expand_escape(session, "%d/known_hosts");
if (session->knownhosts == NULL) {
return -1;
}
} else {
SAFE_FREE(session->knownhosts);
session->knownhosts = dir_expand_dup(session, value, 1);
session->knownhosts = strdup(value);
if (session->knownhosts == NULL) {
return -1;
}
@@ -618,8 +579,21 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
return -1;
}
break;
case SSH_OPTIONS_PROXYCOMMAND:
if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
} else {
SAFE_FREE(session->ProxyCommand);
q = strdup(value);
if (q == NULL) {
return -1;
}
session->ProxyCommand = q;
}
break;
default:
ssh_set_error(session, SSH_REQUEST_DENIED, "Unkown ssh option %d", type);
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return -1;
break;
}
@@ -833,7 +807,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
}
break;
default:
ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unkown ssh option %d", type);
ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return -1;
break;
}
@@ -1056,19 +1030,91 @@ int ssh_options_parse_config(ssh_session session, const char *filename) {
return -1;
}
if (session->sshdir == NULL) {
r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
if (r < 0) {
ssh_set_error_oom(session);
return -1;
}
}
/* set default filename */
if (filename == NULL) {
expanded_filename = dir_expand_dup(session, "SSH_DIR/config", 1);
expanded_filename = ssh_path_expand_escape(session, "%d/config");
} else {
expanded_filename = dir_expand_dup(session, filename, 1);
expanded_filename = ssh_path_expand_escape(session, filename);
}
if (expanded_filename == NULL)
if (expanded_filename == NULL) {
return -1;
}
r = ssh_config_parse_file(session, expanded_filename);
if (r < 0) {
goto out;
}
if (filename == NULL) {
r = ssh_config_parse_file(session, "/etc/ssh/ssh_config");
}
out:
free(expanded_filename);
return r;
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */
int ssh_options_apply(ssh_session session) {
struct ssh_iterator *it;
char *tmp;
int rc;
if (session->sshdir == NULL) {
rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
if (rc < 0) {
return -1;
}
}
if (session->username == NULL) {
rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL);
if (rc < 0) {
return -1;
}
}
if (session->knownhosts == NULL) {
tmp = ssh_path_expand_escape(session, "%d/known_hosts");
} else {
tmp = ssh_path_expand_escape(session, session->knownhosts);
}
if (tmp == NULL) {
return -1;
}
free(session->knownhosts);
session->knownhosts = tmp;
if (session->ProxyCommand != NULL) {
tmp = ssh_path_expand_escape(session, session->ProxyCommand);
if (tmp == NULL) {
return -1;
}
free(session->ProxyCommand);
session->ProxyCommand = tmp;
}
for (it = ssh_list_get_iterator(session->identity);
it != NULL;
it = it->next) {
char *id = (char *) it->data;
tmp = ssh_path_expand_escape(session, id);
if (tmp == NULL) {
return -1;
}
free(id);
it->data = tmp;
}
return 0;
}
/* @} */
/* vim: set ts=4 sw=4 et cindent: */

View File

@@ -693,6 +693,9 @@ void packet_parse(ssh_session session) {
case SSH2_MSG_CHANNEL_OPEN:
message_handle(session,type);
return;
case SSH2_MSG_GLOBAL_REQUEST:
ssh_global_request_handle(session);
return;
default:
ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type);
}
@@ -779,6 +782,7 @@ static int packet_wait2(ssh_session session, int type, int blocking) {
ssh_log(session, SSH_LOG_PACKET, "received disconnect packet");
leave_function();
return SSH_ERROR;
case SSH2_MSG_GLOBAL_REQUEST:
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:

View File

@@ -30,7 +30,9 @@
#ifdef WITH_PCAP
#include <stdio.h>
#ifndef _WIN32
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/time.h>
#include <sys/socket.h>
#endif
@@ -91,7 +93,7 @@ struct ssh_pcap_context_struct {
ssh_session session;
ssh_pcap_file file;
int connected;
/* All of these informations are useful to generate
/* All of these information are useful to generate
* the dummy IP and TCP packets
*/
uint32_t ipsource;

View File

@@ -3,6 +3,7 @@
*
* This file is part of the SSH Library
*
* Copyright (c) 2009-2010 by Andreas Schneider <mail@cynapses.org>
* Copyright (c) 2003-2009 by Aris Adamantiadis
* Copyright (c) 2009 Aleksandar Kanchev
*
@@ -24,8 +25,6 @@
* vim: ts=2 sw=2 et cindent
*/
/* This code is based on glib's gpoll */
#include "config.h"
#include <errno.h>
@@ -60,177 +59,217 @@ struct ssh_poll_ctx_struct {
#ifdef HAVE_POLL
#include <poll.h>
void ssh_poll_init(void) {
return;
}
void ssh_poll_cleanup(void) {
return;
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return poll((struct pollfd *) fds, nfds, timeout);
}
#else /* HAVE_POLL */
typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int);
static poll_fn ssh_poll_emu;
#include <sys/types.h>
#ifdef _WIN32
#if 0
/* defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) */
#include <winsock2.h>
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return WSAPoll(fds, nfds, timeout);
}
#else /* _WIN32_WINNT */
#ifndef STRICT
#define STRICT
#endif
#endif /* STRICT */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <errno.h>
#include <winsock2.h>
static int poll_rest (HANDLE *handles, int nhandles,
ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
DWORD ready;
ssh_pollfd_t *f;
int recursed_result;
if (nhandles == 0) {
/* No handles to wait for, just the timeout */
if (timeout == INFINITE) {
ready = WAIT_FAILED;
} else {
SleepEx(timeout, 1);
ready = WAIT_TIMEOUT;
}
} else {
/* Wait for just handles */
ready = WaitForMultipleObjectsEx(nhandles, handles, FALSE, timeout, TRUE);
#if 0
if (ready == WAIT_FAILED) {
fprintf(stderr, "WaitForMultipleObjectsEx failed: %d\n", GetLastError());
}
#if (_WIN32_WINNT < 0x0600)
typedef struct ssh_pollfd_struct WSAPOLLFD;
#endif
}
if (ready == WAIT_FAILED) {
return -1;
} else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) {
return 0;
} else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles) {
for (f = fds; f < &fds[nfds]; f++) {
if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) {
f->revents = f->events;
}
typedef int (WSAAPI* WSAPoll_FunctionType)(WSAPOLLFD fdarray[],
ULONG nfds,
INT timeout
);
static WSAPoll_FunctionType wsa_poll;
int win_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
if (wsa_poll) {
return (wsa_poll)(fds, nfds, timeout);
}
/*
* If no timeout and polling several handles, recurse to poll
* the rest of them.
*/
if (timeout == 0 && nhandles > 1) {
/* Remove the handle that fired */
int i;
if (ready < nhandles - 1) {
for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
handles[i-1] = handles[i];
}
}
nhandles--;
recursed_result = poll_rest(handles, nhandles, fds, nfds, 0);
if (recursed_result < 0) {
return -1;
}
return recursed_result + 1;
}
return 1;
}
return 0;
return SOCKET_ERROR;
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
ssh_pollfd_t *f;
int nhandles = 0;
int rc = -1;
#define WS2_LIBRARY "ws2_32.dll"
static HINSTANCE hlib;
#else /* _WIN32 */
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/time.h>
#endif /* _WIN32 */
/*
* This is a poll(2)-emulation using select for systems not providing a native
* poll implementation.
*
* Keep in mind that select is terribly inefficient. The interface is simply not
* meant to be used with maximum descriptor value greater, say, 32 or so. With
* a value as high as 1024 on Linux you'll pay dearly in every single call.
* poll() will be orders of magnitude faster.
*/
static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
fd_set readfds, writefds, exceptfds;
struct timeval tv, *ptv;
socket_t max_fd;
int rc;
nfds_t i;
if (fds == NULL) {
errno = EFAULT;
return -1;
errno = EFAULT;
return -1;
}
if (nfds >= MAXIMUM_WAIT_OBJECTS) {
errno = EINVAL;
return -1;
}
FD_ZERO (&readfds);
FD_ZERO (&writefds);
FD_ZERO (&exceptfds);
for (f = fds; f < &fds[nfds]; f++) {
if (f->fd > 0) {
int i;
/*
* Don't add the same handle several times into the array, as
* docs say that is not allowed, even if it actually does seem
* to work.
*/
for (i = 0; i < nhandles; i++) {
if (handles[i] == (HANDLE) f->fd) {
break;
}
/* compute fd_sets and find largest descriptor */
for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
if (fds[i].fd == SSH_INVALID_SOCKET) {
continue;
}
if (i == nhandles) {
if (nhandles == MAXIMUM_WAIT_OBJECTS) {
#ifndef _WIN32
if (fds[i].fd >= FD_SETSIZE) {
rc = -1;
break;
} else {
handles[nhandles++] = (HANDLE) f->fd;
}
}
}
#endif
if (fds[i].events & (POLLIN | POLLRDNORM)) {
FD_SET (fds[i].fd, &readfds);
}
if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
FD_SET (fds[i].fd, &writefds);
}
if (fds[i].events & (POLLPRI | POLLRDBAND)) {
FD_SET (fds[i].fd, &exceptfds);
}
if (fds[i].fd > max_fd &&
(fds[i].events & (POLLIN | POLLOUT | POLLPRI |
POLLRDNORM | POLLRDBAND |
POLLWRNORM | POLLWRBAND))) {
max_fd = fds[i].fd;
rc = 0;
}
}
if (timeout == -1) {
timeout = INFINITE;
if (max_fd == SSH_INVALID_SOCKET || rc == -1) {
errno = EINVAL;
return -1;
}
if (nhandles > 1) {
/*
* First check if one or several of them are immediately
* available.
*/
rc = poll_rest(handles, nhandles, fds, nfds, 0);
/*
* If not, and we have a significant timeout, poll again with
* timeout then. Note that this will return indication for only
* one event, or only for messages. We ignore timeouts less than
* ten milliseconds as they are mostly pointless on Windows, the
* MsgWaitForMultipleObjectsEx() call will timeout right away
* anyway.
*/
if (rc == 0 && (timeout == INFINITE || timeout >= 10)) {
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
}
if (timeout < 0) {
ptv = NULL;
} else {
/*
* Just polling for one thing, so no need to check first if
* available immediately
*/
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
ptv = &tv;
if (timeout == 0) {
tv.tv_sec = 0;
tv.tv_usec = 0;
} else {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
}
}
rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
if (rc < 0) {
for (f = fds; f < &fds[nfds]; f++) {
f->revents = 0;
}
errno = EBADF;
return -1;
}
for (rc = 0, i = 0; i < nfds; i++)
if (fds[i].fd >= 0) {
fds[i].revents = 0;
if (FD_ISSET(fds[i].fd, &readfds)) {
int save_errno = errno;
char data[64] = {0};
int ret;
/* support for POLLHUP */
ret = recv(fds[i].fd, data, 64, MSG_PEEK);
#ifdef _WIN32
if ((ret == -1) &&
(errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
errno == WSAECONNABORTED || errno == WSAENETRESET)) {
#else
if ((ret == -1) &&
(errno == ESHUTDOWN || errno == ECONNRESET ||
errno == ECONNABORTED || errno == ENETRESET)) {
#endif
fds[i].revents |= POLLHUP;
} else {
fds[i].revents |= fds[i].events & (POLLIN | POLLRDNORM);
}
errno = save_errno;
}
if (FD_ISSET(fds[i].fd, &writefds)) {
fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND);
}
if (FD_ISSET(fds[i].fd, &exceptfds)) {
fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND);
}
if (fds[i].revents & ~POLLHUP) {
rc++;
}
} else {
fds[i].revents = POLLNVAL;
}
return rc;
}
#endif /* _WIN32_WINNT */
void ssh_poll_init(void) {
ssh_poll_emu = bsd_poll;
#ifdef _WIN32
hlib = LoadLibrary(WS2_LIBRARY);
if (hlib != NULL) {
wsa_poll = (WSAPoll_FunctionType) (void *) GetProcAddress(hlib, "WSAPoll");
}
#endif /* _WIN32 */
if (wsa_poll != NULL) {
ssh_poll_emu = bsd_poll;
}
}
void ssh_poll_cleanup(void) {
ssh_poll_emu = bsd_poll;
#ifdef _WIN32
wsa_poll = NULL;
FreeLibrary(hlib);
hlib = NULL;
#endif /* _WIN32 */
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return (ssh_poll_emu)(fds, nfds, timeout);
}
#endif /* HAVE_POLL */
/**
@@ -403,7 +442,7 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
used = ctx->polls_used;
for (i = 0; i < used; ) {
ssh_poll_handle p = ctx->pollptrs[i];
int fd = ctx->pollfds[i].fd;
socket_t fd = ctx->pollfds[i].fd;
/* force poll object removal */
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) {
@@ -451,7 +490,7 @@ static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size) {
* @return 0 on success, < 0 on error
*/
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
int fd;
socket_t fd;
if (p->ctx != NULL) {
/* already attached to a context */
@@ -530,7 +569,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
i++;
} else {
ssh_poll_handle p = ctx->pollptrs[i];
int fd = ctx->pollfds[i].fd;
socket_t fd = ctx->pollfds[i].fd;
int revents = ctx->pollfds[i].revents;
if (p->cb(p, fd, revents, p->cb_data) < 0) {

View File

@@ -26,11 +26,18 @@
#include "libssh/priv.h"
#include "libssh/scp.h"
/** @defgroup ssh_scp SSH-scp
* @brief SCP protocol over SSH functions
* @addtogroup ssh_scp
* @{
*/
/** @brief Creates a new scp session
* @param session the SSH session to use
* @param mode one of SSH_SCP_WRITE or SSH_SCP_READ, depending if you need to drop files remotely or read them.
* It is not possible to combine read and write.
* @param location The directory in which write or read will be done. Any push or pull will be relative
* to this place
* @returns NULL if the creation was impossible.
* @returns a ssh_scp handle if it worked.
*/
@@ -110,11 +117,22 @@ int ssh_scp_init(ssh_scp scp){
}
int ssh_scp_close(ssh_scp scp){
char buffer[128];
int err;
if(scp->channel != NULL){
if(channel_send_eof(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
/* avoid situations where data are buffered and
* not yet stored on disk. This can happen if the close is sent
* before we got the EOF back
*/
while(!channel_is_eof(scp->channel)){
err=channel_read(scp->channel,buffer,sizeof(buffer),0);
if(err==SSH_ERROR)
break;
}
if(channel_close(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
@@ -138,6 +156,7 @@ void ssh_scp_free(ssh_scp scp){
}
/** @brief creates a directory in a scp in sink mode
* @param scp the scp handle.
* @param dirname Name of the directory being created.
* @param mode Unix permissions for the new directory, e.g. 0755.
* @returns SSH_OK if the directory was created.
@@ -203,6 +222,7 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){
/** @brief initializes the sending of a file to a scp in sink mode
* @param scp the scp handle.
* @param filename Name of the file being sent. It should not contain any path indicator
* @param size Exact size in bytes of the file being sent.
* @param mode Unix permissions for the new file, e.g. 0644
@@ -285,6 +305,7 @@ int ssh_scp_response(ssh_scp scp, char **response){
}
/** @brief Write into a remote scp file
* @param scp the scp handle.
* @param buffer the buffer to write
* @param len the number of bytes to write
* @returns SSH_OK the write was successful
@@ -331,6 +352,7 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
/**
* @brief reads a string on a channel, terminated by '\n'
* @param scp the scp handle.
* @param buffer pointer to a buffer to place the string
* @param len size of the buffer in bytes. If the string is bigger
* than len-1, only len-1 bytes are read and the string
@@ -455,6 +477,7 @@ int ssh_scp_pull_request(ssh_scp scp){
/**
* @brief denies the transfer of a file or creation of a directory
* coming from the remote party
* @param scp the scp handle.
* @param reason nul-terminated string with a human-readable explanation
* of the deny
* @returns SSH_OK the message was sent
@@ -481,6 +504,7 @@ int ssh_scp_deny_request(ssh_scp scp, const char *reason){
/**
* @brief accepts transfer of a file or creation of a directory
* coming from the remote party
* @param scp the scp handle.
* @returns SSH_OK the message was sent
* @returns SSH_ERROR Error sending the message, or sending it in a bad state
*/
@@ -503,6 +527,7 @@ int ssh_scp_accept_request(ssh_scp scp){
}
/** @brief Read from a remote scp file
* @param scp the scp handle.
* @param buffer Destination buffer
* @param size Size of the buffer
* @returns Number of bytes read
@@ -585,7 +610,7 @@ int ssh_scp_integer_mode(const char *mode){
/** @brief Converts a unix mode into a scp string one.
* @param mode mode to convert, e.g. 420 or 0644
* @retuns pointer to a malloc'ed string containing the scp mode,
* @returns pointer to a malloc'ed string containing the scp mode,
* e.g. "0644".
*/
char *ssh_scp_string_mode(int mode){
@@ -601,3 +626,6 @@ char *ssh_scp_string_mode(int mode){
const char *ssh_scp_request_get_warning(ssh_scp scp){
return scp->warning;
}
/** @} */

View File

@@ -129,7 +129,7 @@ ssh_bind ssh_bind_new(void) {
return NULL;
}
ZERO_STRUCTP(ptr);
ptr->bindfd = -1;
ptr->bindfd = SSH_INVALID_SOCKET;
ptr->bindport= 22;
ptr->log_verbosity = 0;
@@ -138,7 +138,7 @@ ssh_bind ssh_bind_new(void) {
int ssh_bind_listen(ssh_bind sshbind) {
const char *host;
int fd;
socket_t fd;
if (ssh_init() < 0) {
return -1;
@@ -185,10 +185,10 @@ void ssh_bind_fd_toaccept(ssh_bind sshbind) {
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
ssh_private_key dsa = NULL;
ssh_private_key rsa = NULL;
int fd = -1;
socket_t fd = SSH_INVALID_SOCKET;
int i;
if (sshbind->bindfd < 0) {
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL,
"Can't accept new clients on a not bound socket.");
return SSH_ERROR;
@@ -219,7 +219,7 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
}
fd = accept(sshbind->bindfd, NULL, NULL);
if (fd < 0) {
if (fd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL,
"Accepting a new connection: %s",
strerror(errno));
@@ -284,7 +284,7 @@ void ssh_bind_free(ssh_bind sshbind){
close(sshbind->bindfd);
#endif
}
sshbind->bindfd = -1;
sshbind->bindfd = SSH_INVALID_SOCKET;
/* options */
SAFE_FREE(sshbind->banner);
@@ -871,7 +871,7 @@ int ssh_execute_message_callbacks(ssh_session session){
if(!session->ssh_message_list)
return SSH_OK;
if(session->ssh_message_callback){
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list)) != NULL){
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
ret=session->ssh_message_callback(session,msg);
if(ret==1){
ret = ssh_message_reply_default(msg);
@@ -880,7 +880,7 @@ int ssh_execute_message_callbacks(ssh_session session){
}
}
} else {
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list)) != NULL){
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
ret = ssh_message_reply_default(msg);
if(ret != SSH_OK)
return ret;

View File

@@ -32,7 +32,8 @@
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#define FIRST_CHANNEL 42 // why not ? it helps to find bugs.
/** \defgroup ssh_session SSH Session
@@ -46,6 +47,8 @@
*/
ssh_session ssh_new(void) {
ssh_session session;
char *id;
int rc;
session = malloc(sizeof (struct ssh_session_struct));
if (session == NULL) {
@@ -95,6 +98,39 @@ ssh_session ssh_new(void) {
goto err;
}
#endif /* _WIN32 */
session->identity = ssh_list_new();
if (session->identity == NULL) {
goto err;
}
id = strdup("%d/id_rsa");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
id = strdup("%d/id_dsa");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
id = strdup("%d/identity");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
return session;
err:
@@ -155,19 +191,30 @@ void ssh_free(ssh_session session) {
privatekey_free(session->rsa_key);
if(session->ssh_message_list){
ssh_message msg;
while((msg=ssh_list_get_head(ssh_message ,session->ssh_message_list))
while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
!= NULL){
ssh_message_free(msg);
}
ssh_list_free(session->ssh_message_list);
}
if (session->identity) {
char *id;
for (id = ssh_list_pop_head(char *, session->identity);
id != NULL;
id = ssh_list_pop_head(char *, session->identity)) {
SAFE_FREE(id);
}
ssh_list_free(session->identity);
}
/* options */
SAFE_FREE(session->username);
SAFE_FREE(session->host);
SAFE_FREE(session->identity);
SAFE_FREE(session->sshdir);
SAFE_FREE(session->knownhosts);
SAFE_FREE(session->ProxyCommand);
for (i = 0; i < 10; i++) {
if (session->wanted_methods[i]) {
@@ -363,5 +410,32 @@ int ssh_get_version(ssh_session session) {
return session->version;
}
/**
* @internal
* @handle a SSH_MSG_GLOBAL_REQUEST packet
* @param session the SSH session
*/
void ssh_global_request_handle(ssh_session session){
ssh_string type;
char *type_c;
uint32_t needreply;
type=buffer_get_ssh_string(session->in_buffer);
buffer_get_u32(session->in_buffer,&needreply);
if(type==NULL)
return;
type_c=string_to_char(type);
if(!type_c)
return;
ssh_log(session, SSH_LOG_PROTOCOL,
"Received SSH_GLOBAL_REQUEST %s (wantreply=%d)",type_c,needreply);
SAFE_FREE(type_c);
string_free(type);
if(needreply != 0){
buffer_add_u8(session->out_buffer,SSH2_MSG_REQUEST_FAILURE);
packet_send(session);
}
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -25,9 +25,11 @@
/* This file contains code written by Nick Zitzmann */
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -1111,6 +1113,54 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
return attr;
}
enum sftp_longname_field_e {
SFTP_LONGNAME_PERM = 0,
SFTP_LONGNAME_FIXME,
SFTP_LONGNAME_OWNER,
SFTP_LONGNAME_GROUP,
SFTP_LONGNAME_SIZE,
SFTP_LONGNAME_DATE,
SFTP_LONGNAME_TIME,
SFTP_LONGNAME_NAME,
};
static char *sftp_parse_longname(const char *longname,
enum sftp_longname_field_e longname_field) {
const char *p, *q;
size_t len, field = 0;
char *x;
p = longname;
/* Find the beginning of the field which is specified by sftp_longanme_field_e. */
while(field != longname_field) {
if(isspace(*p)) {
field++;
p++;
while(*p && isspace(*p)) {
p++;
}
} else {
p++;
}
}
q = p;
while (! isspace(*q)) {
q++;
}
/* There is no strndup on windows */
len = q - p + 1;
x = malloc(len);
if (x == NULL) {
return NULL;
}
snprintf(x, len, "%s", p);
return x;
}
/* sftp version 0-3 code. It is different from the v4 */
/* maybe a paste of the draft is better than the code */
/*
@@ -1157,6 +1207,19 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
break;
}
string_free(longname);
/* Set owner and group if we talk to openssh and have the longname */
if (ssh_get_openssh_version(sftp->session)) {
attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER);
if (attr->owner == NULL) {
break;
}
attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP);
if (attr->group == NULL) {
break;
}
}
}
if (buffer_get_u32(buf, &flags) != sizeof(uint32_t)) {
@@ -1254,6 +1317,8 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
string_free(attr->extended_data);
SAFE_FREE(attr->name);
SAFE_FREE(attr->longname);
SAFE_FREE(attr->owner);
SAFE_FREE(attr->group);
SAFE_FREE(attr);
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure");
@@ -2276,8 +2341,9 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, oldpath) < 0 ||
buffer_add_ssh_string(buffer, newpath) < 0 ||
/* POSIX rename atomically replaces newpath, we should do the same */
buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0) {
/* POSIX rename atomically replaces newpath, we should do the same
* only available on >=v4 */
sftp->version>=4 ? (buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0):0) {
ssh_set_error_oom(sftp->session);
buffer_free(buffer);
string_free(oldpath);
@@ -2419,7 +2485,8 @@ int sftp_chown(sftp_session sftp, const char *file, uid_t owner, gid_t group) {
attr.uid = owner;
attr.gid = group;
attr.flags = SSH_FILEXFER_ATTR_OWNERGROUP;
attr.flags = SSH_FILEXFER_ATTR_UIDGID;
return sftp_setstat(sftp, file, &attr);
}

View File

@@ -27,11 +27,13 @@
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
extern char **environ;
#endif
#include "libssh/priv.h"
#include "libssh/socket.h"
@@ -39,6 +41,7 @@
#include "libssh/poll.h"
#include "libssh/session.h"
/** \defgroup ssh_socket SSH Sockets
* \addtogroup ssh_socket
* @{
@@ -68,10 +71,21 @@ int ssh_socket_init(void) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1;
}
#endif
ssh_poll_init();
return 0;
}
/*
/**
* @brief Cleanup the socket system.
*/
void ssh_socket_cleanup(void) {
ssh_poll_cleanup();
}
/**
* \internal
* \brief creates a new Socket object
*/
@@ -82,7 +96,7 @@ struct socket *ssh_socket_new(ssh_session session) {
if (s == NULL) {
return NULL;
}
s->fd = -1;
s->fd = SSH_INVALID_SOCKET;
s->last_errno = -1;
s->session = session;
s->in_buffer = buffer_new();
@@ -124,20 +138,20 @@ int ssh_socket_unix(struct socket *s, const char *path) {
snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);
s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s->fd < 0) {
if (s->fd == SSH_INVALID_SOCKET) {
return -1;
}
if (fcntl(s->fd, F_SETFD, 1) == -1) {
close(s->fd);
s->fd = -1;
s->fd = SSH_INVALID_SOCKET;
return -1;
}
if (connect(s->fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) {
close(s->fd);
s->fd = -1;
s->fd = SSH_INVALID_SOCKET;
return -1;
}
@@ -157,7 +171,7 @@ void ssh_socket_close(struct socket *s){
close(s->fd);
s->last_errno = errno;
#endif
s->fd=-1;
s->fd = SSH_INVALID_SOCKET;
}
}
@@ -179,7 +193,7 @@ socket_t ssh_socket_get_fd(struct socket *s) {
* \brief returns nonzero if the socket is open
*/
int ssh_socket_is_open(struct socket *s) {
return s->fd != -1;
return s->fd != SSH_INVALID_SOCKET;
}
/* \internal
@@ -237,22 +251,22 @@ static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer,
* \brief returns nonzero if the current socket is in the fd_set
*/
int ssh_socket_fd_isset(struct socket *s, fd_set *set) {
if(s->fd == -1) {
if(s->fd == SSH_INVALID_SOCKET) {
return 0;
}
return FD_ISSET(s->fd,set);
}
/* \internal
* \brief sets the current fd in a fd_set and updates the fd_max
* \brief sets the current fd in a fd_set and updates the max_fd
*/
void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max) {
if (s->fd == -1)
void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd) {
if (s->fd == SSH_INVALID_SOCKET)
return;
FD_SET(s->fd,set);
if (s->fd >= *fd_max) {
*fd_max = s->fd + 1;
if (s->fd >= 0 && s->fd != SSH_INVALID_SOCKET) {
*max_fd = s->fd + 1;
}
}
@@ -435,7 +449,7 @@ int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len
if (ssh_socket_is_open(session->socket)) {
r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer));
} else {
r =- 1;
r = -1;
}
if (r <= 0) {
@@ -482,13 +496,15 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
if (!s->data_to_write) {
fd->events |= POLLOUT;
}
/* Make the call, and listen for errors */
rc = ssh_poll(fd, 1, 0);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno));
leave_function();
return -1;
/* do not do poll if fd->events is empty, we already know the response */
if(fd->events != 0){
/* Make the call, and listen for errors */
rc = ssh_poll(fd, 1, 0);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno));
leave_function();
return -1;
}
}
if (!s->data_to_read) {
@@ -542,7 +558,7 @@ int ssh_socket_nonblocking_flush(struct socket *s) {
buffer_get_rest_len(s->out_buffer));
} else {
/* write failed */
w =- 1;
w = -1;
}
if (w < 0) {
@@ -658,6 +674,54 @@ int ssh_socket_get_status(struct socket *s) {
return r;
}
#ifndef _WIN32
/**
* @internal
* @brief executes a command and redirect input and outputs
* @param command command to execute
* @param in input file descriptor
* @param out output file descriptor
*/
void ssh_execute_command(const char *command, socket_t in, socket_t out){
const char *args[]={"/bin/sh","-c",command,NULL};
/* redirect in and out to stdin, stdout and stderr */
dup2(in, 0);
dup2(out,1);
dup2(out,2);
close(in);
close(out);
execve(args[0],(char * const *)args,(char * const *)environ);
exit(1);
}
/**
* @internal
* @brief Open a socket on a ProxyCommand
* This call will always be nonblocking.
* @param s socket to connect.
* @param command Command to execute.
* @returns SSH_OK socket is being connected.
* @returns SSH_ERROR error while executing the command.
*/
socket_t ssh_socket_connect_proxycommand(ssh_session session,
const char *command){
socket_t fd[2];
int pid;
enter_function();
socketpair(AF_UNIX,SOCK_STREAM,0,fd);
pid = fork();
if(pid == 0){
ssh_execute_command(command,fd[1],fd[1]);
}
close(fd[1]);
ssh_log(session,SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",fd[0],fd[1]);
return fd[0];
}
#endif /* _WIN32 */
/** @}
*/
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -614,6 +614,11 @@ static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out,
AES_cbc_encrypt(in, out, len, cipher->key, IV, AES_DECRYPT);
}
#ifndef BROKEN_AES_CTR
/* OpenSSL until 0.9.7c has a broken AES_ctr128_encrypt implementation which
* increments the counter from 2^64 instead of 1. It's better not to use it
*/
/** @internal
* @brief encrypts/decrypts data with stream cipher AES_ctr128. 128 bits is actually
* the size of the CTR counter and incidentally the blocksize, but not the keysize.
@@ -631,6 +636,7 @@ static void aes_ctr128_encrypt(struct crypto_struct *cipher, void *in, void *out
*/
AES_ctr128_encrypt(in, out, len, cipher->key, IV, tmp_buffer, &num);
}
#endif /* BROKEN_AES_CTR */
#endif /* HAS_AES */
#ifdef HAS_DES
@@ -722,6 +728,7 @@ static struct crypto_struct ssh_ciphertab[] = {
},
#endif /* HAS_BLOWFISH */
#ifdef HAS_AES
#ifndef BROKEN_AES_CTR
{
"aes128-ctr",
16,
@@ -755,6 +762,7 @@ static struct crypto_struct ssh_ciphertab[] = {
aes_ctr128_encrypt,
aes_ctr128_encrypt
},
#endif /* BROKEN_AES_CTR */
{
"aes128-cbc",
16,
@@ -1001,7 +1009,8 @@ int crypt_set_algorithms_server(ssh_session session){
/* out */
server = session->server_kex.methods[SSH_CRYPT_S_C];
client = session->client_kex.methods[SSH_CRYPT_S_C];
match = ssh_find_matching(client, server);
/* That's the client algorithms that are more important */
match = ssh_find_matching(server,client);
if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
@@ -1030,7 +1039,7 @@ int crypt_set_algorithms_server(ssh_session session){
/* in */
client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_kex.methods[SSH_CRYPT_S_C];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
free(match);
@@ -1058,7 +1067,7 @@ int crypt_set_algorithms_server(ssh_session session){
/* compression */
client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_kex.methods[SSH_CRYPT_C_S];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling C->S compression");
session->next_crypto->do_compress_in=1;
@@ -1067,7 +1076,7 @@ int crypt_set_algorithms_server(ssh_session session){
client=session->client_kex.methods[SSH_CRYPT_S_C];
server=session->server_kex.methods[SSH_CRYPT_S_C];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling S->C compression\n");
session->next_crypto->do_compress_out=1;
@@ -1076,7 +1085,7 @@ int crypt_set_algorithms_server(ssh_session session){
server=session->server_kex.methods[SSH_HOSTKEYS];
client=session->client_kex.methods[SSH_HOSTKEYS];
match=ssh_find_matching(client,server);
match=ssh_find_matching(server,client);
if(match && !strcmp(match,"ssh-dss"))
session->hostkeys=TYPE_DSS;
else if(match && !strcmp(match,"ssh-rsa"))