Compare commits

...

104 Commits

Author SHA1 Message Date
Andreas Schneider
39802b31fe build: Set libssh version to 0.5.1. 2011-08-09 14:47:33 +02:00
Andreas Schneider
e5a2aef1bf build: Updated ChangeLog. 2011-08-09 14:46:26 +02:00
Einar Floystad Dorum
edb03bd224 Fixed ssh_scp_write so it works when doing recursive copy
There where two issues with ssh_scp_write:
1) It did not write a status message after the last write and OpenSSH
   would then give up after the write finished.
2) OpenSSH would sometimes write a status message, after near ends write.
   If scp_write didn't handle it, and subsequent status message. The remote
   window would shrink to zero and ssh_channel_write would start returning 0.

Signed-off-by: Einar Floystad Dorum <einarfd@mailthief.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 01c4b713dc)
2011-08-08 15:28:08 +02:00
rofl0r
1204f43ea9 client: Fix another source of endless wait.
(cherry picked from commit 35686b4822)
2011-08-07 12:47:23 +02:00
rofl0r
b542bc9e4e channels: Fix an endless loop in case of a channel_open error.
(cherry picked from commit 7ccd9c31b3)
2011-08-07 12:47:17 +02:00
rofl0r
61a97ccede session: Fix timeout handling.
-2 now means to use the timeout specified in options. It wasn't used
earlier and poll only knows -1 and 0 anyway for special meanings.
(cherry picked from commit af85337f5f)
2011-08-07 12:47:09 +02:00
rofl0r
a1ef27c0b8 channels: Fix checking for fatal errors.
We need this that we don't end up in and infinite poll loop.
(cherry picked from commit 563fbe4de8)

Conflicts:

	src/poll.c
2011-08-07 12:46:47 +02:00
rofl0r
fb8f2cd11b channels: Fix ssh_channel_from_local()
It only worked if the first channel in the list was equivalent to we
were looking for.
(cherry picked from commit 39f962c91e)
2011-08-07 12:46:06 +02:00
rofl0r
1d8a9ddf84 misc: Fix ssh_timeout_update().
(cherry picked from commit c31cac93f3)
2011-08-07 12:45:54 +02:00
Andreas Schneider
bea66b6476 examples: Fix permissions of the file we copy.
Thanks to Baptiste Marchand.
(cherry picked from commit 15ebbad146)
2011-08-03 22:23:51 +02:00
Andreas Schneider
a8111934d5 channels: Set the max packet size to 32768.
(cherry picked from commit 790b62bca5)
2011-08-03 22:20:52 +02:00
Aris Adamantiadis
f201e983b0 Workaround ssh_get_user_home_dir on LDAP users 2011-07-13 12:04:04 +02:00
Andreas Schneider
81332e1e27 build: Fix libssh_threads pkg-config.
(cherry picked from commit 269c9fed354f3a8adbc54fccba6287d5b1f166e3)
2011-06-15 18:26:33 +02:00
Andreas Schneider
ea84f50603 cmake: Added pkg-config support for libssh_treads.
(cherry picked from commit 583a7f933a)
2011-06-14 13:47:51 +02:00
Andreas Schneider
ccc94e7ab6 packet: Don't (de)compress empty buffers.
This fixes bug #50.
(cherry picked from commit fb0f125351)
2011-06-11 13:16:21 +02:00
Aris Adamantiadis
4c05be0c1b Fix compilation without server and sftp modes
(cherry picked from commit 809b3adeba)
2011-06-09 12:16:07 +02:00
Andreas Schneider
a493a90c59 build: Check for ntohll().
This function is available on AIX.
(cherry picked from commit 640e3830f2)
2011-06-06 18:57:50 +02:00
Andreas Schneider
4a18df8574 string: Added missing include.
(cherry picked from commit 3fa801a929)
2011-06-06 18:57:11 +02:00
Andreas Schneider
cfa74c1dc6 string: Added missing errno.
(cherry picked from commit d536cc4f39)
2011-06-06 18:51:12 +02:00
milo
de706de8c3 Check for NULL pointers in string.c
(cherry picked from commit 4230509e80)
2011-06-06 18:50:11 +02:00
Andreas Schneider
71fa0dc6bb cmake: Fix static .lib overwriting on Windows.
(cherry picked from commit 1880ef54d2)
2011-06-01 14:53:29 +02:00
Andreas Schneider
914a2d8e41 cmake: Prepare for release. 2011-05-30 12:36:54 +02:00
Andreas Schneider
956b64d348 session: Fix return code of ssh_blocking_flush().
(cherry picked from commit 3c21281bf0)
2011-05-28 18:35:21 +02:00
Aris Adamantiadis
91489cd378 remove "0.5.0 is dev" in the doc
(cherry picked from commit 3bc46c3bf0)
2011-05-27 14:20:02 +02:00
Aris Adamantiadis
615bc3b8f7 Forgot a cast to remove warnings
(cherry picked from commit ac167c9077)
2011-05-27 14:19:54 +02:00
Aris Adamantiadis
5b645419fd Fix bug #5, channel_read_nonblocking that blocks 2011-05-27 14:19:42 +02:00
Mark Riordan
c436e07022 Fix memory leak when compression is used
Signed-off-by: Mark Riordan <mriordan@ipswitch.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dcea8db6b2)
2011-05-27 11:47:26 +02:00
Andreas Schneider
188fb37801 sftp: Reset eof on seek operations.
This fixes bug #48.
(cherry picked from commit c483418b82)
2011-05-26 11:27:35 +02:00
Andreas Schneider
44fed3eb9b misc: Fix compilation on Windows.
(cherry picked from commit ba03388031)
2011-05-26 11:20:25 +02:00
Andreas Schneider
36abd82a7e cmake: Fix detection of clock_gettime. 2011-05-25 22:13:28 +02:00
Aris Adamantiadis
fd6d0b6897 Replace clock_gettime with gettimeofday when missing
(cherry picked from commit 65282841e2)
2011-05-25 22:00:00 +02:00
Aris Adamantiadis
09b0018b93 Introduced ssh_timeout_elapsed functions
Functions to mesure elapsed time before and after a serie of
calls. Introduces a dependancy to clock_gettime() and librt,
hope this doesn't break anything. Porting to gettimeofday() should
not be too hard.
(cherry picked from commit 59f7647cd9)
2011-05-25 21:59:51 +02:00
Andreas Schneider
2624e603d4 Revert "Use BIO* in _privatekey_from_file [Oliver Stöneberg]"
This reverts commit da8356b477.
2011-05-19 19:47:29 +02:00
Oliver Stöneberg
fd61eda16d keyfiles: Move FILE* into HAVE_LIBGCRYPT code.
(cherry picked from commit c7c563eb8ad01ab5750b5ea4e72031ebd298651c)
2011-05-17 21:00:02 +02:00
Oliver Stöneberg
a6dda5fefd keyfiles: Use BIO* in _privatekey_from_file().
(cherry picked from commit 82df5dc2083a6f7234d1545bd671ee1b5b4680b6)
2011-05-17 20:59:55 +02:00
Oliver Stöneberg
da8356b477 Use BIO* in _privatekey_from_file [Oliver Stöneberg]
_privatekey_from_file: moved FILE* into HAVE_LIBGCRYPT code / added missing #ifdef's to default case of switch [Oliver Stöneberg]
2011-05-17 20:57:58 +02:00
Oliver Stöneberg
e5fb20c17b socket: Fixed use-after-free.
When s->callbacks->exception() was called in ssh_socket_pollcallback()
we had a use after free bug.
(cherry picked from commit 9866763789)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
c472bd7437 keyfiles: Fixed compilation without defines.
This fixes cppcheck issues.
(cherry picked from commit 7f0761885c)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
8796756ae5 tests: Fixed some cppcheck warnings.
(cherry picked from commit e3311d03db)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
9c8f285a98 examples: Use the right cleanup functions.
(cherry picked from commit 525324b2f9)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
8154e24027 channel: Fixed potential use-after-free in ssh_channel_get_exit_status().
If ssh_channel_get_exit_status() is called more than once and the
connection closed.
(cherry picked from commit 4e153aed8a)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
629cfbccc4 connect: Set timeout on connect
This also fixes error handling in ssh_poll_ctx_dopoll() and
ssh_handle_packets(), so it won't loop forever on an actual timeout.
(cherry picked from commit 671a982739)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
c5990791db poll: Removed WSAPoll() support.
It was causing too many issues and the poll emulation is quite stable.
(cherry picked from commit f4f4ce37f0)
2011-05-17 20:57:38 +02:00
Oliver Stöneberg
16241938af doc: Small update to auth.c documentation.
(cherry picked from commit 12b61a6266)
2011-05-17 20:57:38 +02:00
Andreas Schneider
6a8cb38dd3 channel: Improve the request signal documentation.
(cherry picked from commit 32cd45612b)
2011-05-15 13:44:11 +02:00
Oliver Stöneberg
bac2227ee2 Updated privatekey_from_file() to use BIO* as well [Oliver Stöneberg] 2011-05-02 19:46:54 +02:00
Oliver Stöneberg
dcb50cc0c8 Use BIO* in _privatekey_from_file [Oliver Stöneberg]
_privatekey_from_file: moved FILE* into HAVE_LIBGCRYPT code / added missing #ifdef's to default case of switch [Oliver Stöneberg]
2011-05-02 19:17:38 +02:00
milo
f503c4a3e1 Delay the check for kbdint->answers in kbdint_send()
(cherry picked from commit 32ba5204b7)
2011-05-02 18:04:56 +02:00
milo
a56c925da9 Fix segfault when ssh_userauth_kbdint_setanswer() has not been called
(cherry picked from commit b6e712e934)
2011-05-02 17:47:00 +02:00
milo
833cc00014 [socket] fix a segfault at disconnect
(cherry picked from commit 7d2064c289)
2011-05-02 17:41:51 +02:00
milo
09e8cf33d7 [messages] don't queue messages if callback present
(cherry picked from commit 1979c14aac)
2011-05-02 17:40:05 +02:00
milo
a03bb2fbf7 [poll] avoid infinite loop in ssh_poll_ctx_free()
(cherry picked from commit 8092541603)
2011-05-02 17:39:28 +02:00
milo
bb784ec6be [channels] Added ssh_channel_window_size() and avoided reentrancy in channel_write_common()
(cherry picked from commit 7ba0938846)
2011-05-02 17:35:34 +02:00
Andreas Schneider
996c00c81c keyfiles: Fixed the build. 2011-05-01 21:04:55 +02:00
Oliver Stöneberg
30bdca07e9 init: Some initialization fixes.
- Check result of ssh_init() in privatekey_from_base64()
- Moved code from ssh_finalize() to appropriate subroutines
- Only initialize sockets once (caused mismatch of WSAStartup() and
  WSACleanup() calls and potential usage of bsd_poll when win_poll
  should be used)
2011-05-01 19:43:57 +02:00
Oliver Stöneberg
b4b49cf3f6 socket: Fixed poll input event.
(cherry picked from commit 040a543f57)
2011-05-01 19:43:01 +02:00
Oliver Stöneberg
189796e94f examples: Removed unnecessary \n from ssh_log() calls in samplessh.
(cherry picked from commit a73459171b)
2011-05-01 19:42:13 +02:00
Oliver Stöneberg
2431c7d925 examples: Fixed memory leak in samplessh when using commands.
(cherry picked from commit c3849a3cfd)
2011-05-01 19:42:01 +02:00
Andreas Schneider
fc9c61714f poll: Fix poll input events.
bug#38
2011-04-15 19:17:40 +02:00
Andreas Schneider
e096658df3 examples: Fix some memory leaks.
(cherry picked from commit 644145a88c)
2011-04-15 19:06:24 +02:00
Andreas Schneider
b1d58c5454 Fix assertion with Visual Studio because of %zu.
(cherry picked from commit ef658b4bef)
2011-04-15 19:03:02 +02:00
Mark Riordan
ced66eb11f scp: Fix potential infinite loop in ssh_scp_close
Signed-off-by: Mark Riordan <mriordan@ipswitch.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5939cfe78a)
2011-04-14 14:19:15 +02:00
Andreas Schneider
1b44daddf6 examples: Call correct functions on exit.
(cherry picked from commit 3e7d4534ce)
2011-04-14 14:19:08 +02:00
Aris Adamantiadis
a309c1b38e Fixed missing CRYPTO_cleanup_all_ex_data() in ssh_finalize
(cherry picked from commit 934252d6ca)
2011-04-14 13:40:42 +02:00
Andreas Schneider
e56aaf5f44 wrapper: Fixed a possible NULL pointer dereference.
(cherry picked from commit 94e7d345a7)
2011-04-14 10:18:37 +02:00
Andreas Schneider
632cee4426 server: Fixed a possible NULL pointer dereference.
(cherry picked from commit 7e4916cefc)
2011-04-14 10:18:34 +02:00
Oliver Stöneberg
af25fc35d1 build: Fixed some VS2010 problems.
(cherry picked from commit 166ee451c5)
2011-04-11 11:19:26 +02:00
Oliver Stöneberg
db49b84a44 keys: Fixed issues reported by cppcheck.
(cherry picked from commit 46475dfa2f)
2011-04-11 11:19:18 +02:00
Andreas Schneider
c5f4b8c1c7 cmake: Fixed a typo.
(cherry picked from commit 7150cabafa)
2011-04-08 11:06:16 +02:00
Mark Riordan
6a0daddd8f sftp: Fixed double-free in sftp_unlink().
(cherry picked from commit 29bb718a93)
2011-04-08 11:00:04 +02:00
Aris Adamantiadis
af997b221d Fixed doc of ssh_userauth_list()
(cherry picked from commit 1c062b22bf)
2011-03-28 13:36:51 +02:00
Aris Adamantiadis
9d6855702e Change session state after receiving a Disconnect
(cherry picked from commit 4bc9c96e4e)
2011-03-28 13:36:44 +02:00
Andreas Schneider
daf256e15f cpack: Raise version number. 2011-03-23 08:51:06 +01:00
Aris Adamantiadis
0eddcb4424 Fix the ssh_message_retrieve problem by anihilation 2011-03-23 08:49:34 +01:00
Aris Adamantiadis
b7f6794e03 Implement ssh_blocking_flush()
Based on code from Jan Willamowius
(cherry picked from commit dff4e4e6d3)
2011-03-23 08:49:26 +01:00
Andreas Schneider
cd9fc88151 doc: Improve the doc of ssh_bind_set_callbacks.
(cherry picked from commit 7daa81f3aa)
2011-03-09 18:33:49 +01:00
Andreas Schneider
fbe0f37e1b doc: Improved documentation for server options.
(cherry picked from commit 6754c34711)
2011-03-09 18:33:42 +01:00
Andreas Schneider
c496194614 messages: Added missing config.h include. 2011-03-01 14:08:01 +01:00
Andreas Schneider
ca639ceb63 legacy: Added missing channel_write_stderr. 2011-02-23 12:39:25 +01:00
Andreas Schneider
e85537aac4 legacy: Fixed the symbol export. 2011-02-23 12:32:02 +01:00
milo
e839c9cae6 Reverse commit 076dfb82 for the server side
(cherry picked from commit 32e23a25da)
2011-02-19 10:38:15 +01:00
Andreas Schneider
100e94c18e channel: Fixed uninitialized use of session. 2011-02-19 10:24:57 +01:00
Andreas Schneider
e7f7b4e499 server: Fixed logging function name.
(cherry picked from commit ac8276c70e)
2011-02-18 20:57:37 +01:00
Bernhard R. Link
eca8b53868 channel: Improve ssh_channel_open_reverse_forward documentation.
(cherry picked from commit 23b3c46fd6)
2011-02-18 18:01:45 +01:00
Andreas Schneider
b8767be373 channels: set error for new NULL pointer checks
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8a83990c16)
2011-02-18 18:01:45 +01:00
Bernhard R. Link
9658eade0b socket: Set errors on return.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 071b0034db)
2011-02-18 17:54:43 +01:00
Bernhard R. Link
689536ec92 channels: Set errors on return.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7ae59c571a)
2011-02-18 17:54:34 +01:00
Bernhard R. Link
3ff2999228 bind: Set errors on return.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b1db0e54ad)
2011-02-18 17:54:28 +01:00
Andreas Schneider
4f65104ecc misc: Fixed ssh_is_ipaddr_v4() on Windows.
(cherry picked from commit eea1df3574)
2011-02-13 17:39:18 +01:00
Andreas Schneider
242e1c342c build: Try to fix the build on Solaris.
(cherry picked from commit 9baa491b0b)
2011-02-13 17:39:11 +01:00
Andreas Schneider
935e3b70ae misc: Added working ssh_is_ipaddr for Windows.
(cherry picked from commit cd30a1d4b1)
2011-02-13 12:30:52 +01:00
Andreas Schneider
8d1bfb5a85 tests: Fixed misc and isipaddr test on Windows.
(cherry picked from commit ca941d6985)
2011-02-13 12:30:46 +01:00
Andreas Schneider
2ac664968d torture: Fixed torture on Windows.
(cherry picked from commit cbcd5668f5)
2011-02-13 12:30:33 +01:00
Andreas Schneider
1199ad8f47 misc: Fixed ssh_is_ipaddr on FreeBSD.
(cherry picked from commit d1ddec00d9)
2011-02-13 12:30:17 +01:00
Bernhard R. Link
c12559f8f6 always set error when returning error in auth.c
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 637fc7ea59)
2011-02-12 20:15:07 +01:00
Andreas Schneider
840e1abcdc tests: Added ipv6 tests.
(cherry picked from commit 5d4bd5a21d)
2011-02-12 19:22:02 +01:00
Andreas Schneider
e3594ba0ec tests: Fixed torture_isipaddr.
(cherry picked from commit e8c3f55751)
2011-02-12 19:22:02 +01:00
Andreas Schneider
0d07dc5355 srv_sftp: Set error messages in sftp_get_client_message().
(cherry picked from commit 4d38b4c848)
2011-02-12 19:22:01 +01:00
Andreas Schneider
4170258595 connect: Use ssh_is_ipaddr instead of regex.
(cherry picked from commit 768fbdd92e)
2011-02-12 19:22:01 +01:00
Andreas Schneider
dacfc41d21 misc: Added ssh_is_ipaddr() function.
(cherry picked from commit b313fa944a)
2011-02-12 19:22:01 +01:00
Aris Adamantiadis
5158877b72 Connect: Test the new isipaddr() function
(cherry picked from commit 7acc2fa607)
2011-02-12 19:21:42 +01:00
Bernhard R. Link
a785ba3c4d use ssh_log instead of fprintf in ssh_config_parse_file
ssh_config_parse_file calls "fprintf(stderr," directly thus ignoring
a set log callback. Replacing the print with a call to ssh_log should
fix this.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8d9d46ca66)
2011-02-12 19:21:17 +01:00
Bernhard R. Link
92dbd4eca2 ssh_connect_host_nonblocking returns SSH_EINTR, not E_INTR, so update documentation
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8e0e4d8fb3)
2011-02-12 19:21:16 +01:00
Bernhard R. Link
a7144c5b6b proper prototypes
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8b51d29363)
2011-02-12 19:21:16 +01:00
56 changed files with 1315 additions and 396 deletions

View File

@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "5")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION_PATCH "1")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.2.0")
set(LIBRARY_VERSION "4.2.1")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
@@ -78,9 +78,11 @@ add_subdirectory(src)
# pkg-config file
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
DESTINATION
${LIB_INSTALL_DIR}/pkgconfig
COMPONENT

View File

@@ -12,8 +12,8 @@ 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 "90")
set(CPACK_PACKAGE_VERSION_MINOR "5")
set(CPACK_PACKAGE_VERSION_PATCH "1")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")

View File

@@ -1,7 +1,22 @@
ChangeLog
==========
version 0.5.0 (released xxxx-xx-xx)
version 0.5.1 (released 2011-08-09)
* Added checks for NULL pointers in string.c.
* Set the channel max packet size to 32768.
* Don't (de)compress empty buffers.
* Fixed ssh_scp_write so it works when doing recursive copy.
* Fixed another source of endless wait.
* Fixed an endless loop in case of a channel_open error.
* Fixed session timeout handling.
* Fixed ssh_channel_from_local() loop.
* Fixed permissions of scp example when we copy a file.
* Workaround ssh_get_user_home_dir on LDAP users.
* Added pkg-config support for libssh_threads.
* Fixed compilation without server and sftp modes.
* Fix static .lib overwriting on Windows.
version 0.5.0 (released 2011-06-01)
* Added ssh_ prefix to all functions.
* Added complete Windows support.
* Added improved server support.
@@ -10,6 +25,8 @@ version 0.5.0 (released xxxx-xx-xx)
* Added a multiplatform ssh_getpass() function.
* Added a tutorial.
* Added a lot of documentation.
* Fixed a lot of bugs.
* Fixed several memory leaks.
version 0.4.8 (released 2011-01-15)
* Fixed memory leaks in session signing.

View File

@@ -43,7 +43,8 @@ endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
# 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)
check_include_file(termios.h HAVE_TERMIOS_H)
if (WIN32)
check_include_file(wspiapi.h HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H)
@@ -91,23 +92,34 @@ if (UNIX)
if (HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET)
# libresolv
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
if (HAVE_LIBRESOLV)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
endif (HAVE_LIBRESOLV)
check_library_exists(rt nanosleep "" HAVE_LIBRT)
# libnsl/inet_pton (Solaris)
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
if (HAVE_LIBNSL)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
endif (HAVE_LIBNSL)
# librt
if (HAVE_LIBRT)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT)
check_library_exists(rt nanosleep "" HAVE_LIBRT)
endif (NOT LINUX)
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT)
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(regcomp HAVE_REGCOMP)
check_function_exists(ntohll HAVE_NTOHLL)
endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")

View File

@@ -77,6 +77,12 @@
/* Define to 1 if you have the `regcomp' function. */
#cmakedefine HAVE_REGCOMP 1
/* Define to 1 if you have the `clock_gettime' function. */
#cmakedefine HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the `ntohll' function. */
#cmakedefine HAVE_NTOHLL 1
/*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */

View File

@@ -22,8 +22,8 @@ This tutorial concentrates for its main part on the "client" side of libssh.
To learn how to accept incoming SSH connexions (how to write a SSH server),
you'll have to jump to the end of this document.
This tutorial describes libssh version 0.5.0. This version is the development
version and is *not* published yet. However, the examples should work with
This tutorial describes libssh version 0.5.0. This version is a little different
from the 0.4.X series. However, the examples should work with
little changes on versions like 0.4.2 and later.

View File

@@ -157,7 +157,7 @@ int authenticate_console(ssh_session session){
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
free(banner);
ssh_string_free_char(banner);
}
return rc;

View File

@@ -32,22 +32,25 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
if(user != NULL){
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
ssh_free(session);
return NULL;
}
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
if(verify_knownhost(session)<0){
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
auth=authenticate_console(session);
@@ -59,5 +62,6 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
}
ssh_disconnect(session);
ssh_free(session);
return NULL;
}

View File

@@ -13,6 +13,7 @@ int main(void) {
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
ssh_finalize();
return 1;
}
@@ -20,6 +21,7 @@ int main(void) {
if (channel == NULL) {
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 1;
}
@@ -48,7 +50,9 @@ int main(void) {
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
failed:
@@ -56,6 +60,7 @@ failed:
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 1;
}

View File

@@ -48,7 +48,7 @@ int verify_knownhost(ssh_session session){
case SSH_SERVER_KNOWN_CHANGED:
fprintf(stderr,"Host key for server changed : server's one is now :\n");
ssh_print_hexa("Public key hash",hash, hlen);
free(hash);
ssh_clean_pubkey_hash(&hash);
fprintf(stderr,"For security reason, connection will be stopped\n");
return -1;
case SSH_SERVER_FOUND_OTHER:
@@ -65,20 +65,23 @@ int verify_knownhost(ssh_session session){
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
free(hexa);
ssh_string_free_char(hexa);
if (fgets(buf, sizeof(buf), stdin) == NULL) {
ssh_clean_pubkey_hash(&hash);
return -1;
}
if(strncasecmp(buf,"yes",3)!=0){
ssh_clean_pubkey_hash(&hash);
return -1;
}
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
ssh_clean_pubkey_hash(&hash);
return -1;
}
if(strncasecmp(buf,"yes",3)==0){
if (ssh_write_knownhost(session) < 0) {
free(hash);
ssh_clean_pubkey_hash(&hash);
fprintf(stderr, "error %s\n", strerror(errno));
return -1;
}
@@ -86,10 +89,10 @@ int verify_knownhost(ssh_session session){
break;
case SSH_SERVER_ERROR:
free(hash);
ssh_clean_pubkey_hash(&hash);
fprintf(stderr,"%s",ssh_get_error(session));
return -1;
}
free(hash);
ssh_clean_pubkey_hash(&hash);
return 0;
}

View File

@@ -182,7 +182,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
fd=fileno(src->file);
fstat(fd,&s);
size=s.st_size;
mode = s.st_mode & S_IFMT;
mode = s.st_mode & ~S_IFMT;
filename=ssh_basename(src->path);
} else {
size=0;

View File

@@ -16,7 +16,7 @@ program.
#include <libssh/libsshpp.hpp>
int main(int argc, const char **argv){
ssh::Session session,s2;
ssh::Session session;
try {
if(argc>1)
session.setOption(SSH_OPTIONS_HOST,argv[1]);
@@ -24,10 +24,10 @@ int main(int argc, const char **argv){
session.setOption(SSH_OPTIONS_HOST,"localhost");
session.connect();
session.userauthAutopubkey();
session.disconnect();
} catch (ssh::SshException e){
std::cout << "Error during connection : ";
std::cout << e.getError() << std::endl;
}
//s2=session;
return 0;
}

View File

@@ -246,7 +246,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
// we already looked for input from stdin. Now, we are looking for input from the channel
if(channel && ssh_channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=NULL;
@@ -261,8 +261,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
@@ -280,8 +280,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
@@ -338,7 +338,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=NULL;
@@ -353,8 +353,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
@@ -372,8 +372,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
@@ -431,8 +431,11 @@ static void batch_shell(ssh_session session){
ssh_channel channel;
char buffer[1024];
int i,s=0;
for(i=0;i<MAXCMD && cmds[i];++i)
for(i=0;i<MAXCMD && cmds[i];++i) {
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
free(cmds[i]);
cmds[i] = NULL;
}
channel=ssh_channel_new(session);
ssh_channel_open_session(channel);
if(ssh_channel_request_exec(channel,buffer)){

View File

@@ -64,16 +64,21 @@ static void create_files(ssh_session session){
}
if(ssh_channel_open_session(channel) != SSH_OK){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
while(!ssh_channel_is_eof(channel)){
ssh_channel_read(channel,buffer,1,1);
if (write(1,buffer,1) < 0) {
fprintf(stderr, "Error writing to buffer\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
}
@@ -91,6 +96,7 @@ static int fetch_files(ssh_session session){
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
if(ssh_scp_init(scp) != SSH_OK){
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
ssh_scp_free(scp);
return -1;
}
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
@@ -108,12 +114,16 @@ static int fetch_files(ssh_session session){
r=ssh_scp_read(scp,buffer,sizeof(buffer));
if(r==SSH_ERROR){
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
}
printf("done\n");
break;
case SSH_ERROR:
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
case SSH_SCP_REQUEST_WARNING:
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
@@ -134,6 +144,8 @@ static int fetch_files(ssh_session session){
}
} while (1);
end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0;
}
@@ -147,6 +159,7 @@ int main(int argc, char **argv){
create_files(session);
fetch_files(session);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
}

View File

@@ -86,7 +86,7 @@ LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filen
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 ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
LIBSSH_API void string_burn(ssh_string str);
LIBSSH_API ssh_string string_copy(ssh_string str);
LIBSSH_API void *string_data(ssh_string str);

View File

@@ -79,7 +79,7 @@
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 5
#define LIBSSH_VERSION_MICRO 0
#define LIBSSH_VERSION_MICRO 1
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -323,6 +323,7 @@ enum ssh_scp_request_types {
SSH_SCP_REQUEST_WARNING
};
LIBSSH_API int ssh_blocking_flush(ssh_session session, int timeout);
LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms);
LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows);
LIBSSH_API int ssh_channel_close(ssh_channel channel);
@@ -356,6 +357,7 @@ LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechan
timeval * timeout);
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel);
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type);

View File

@@ -31,6 +31,8 @@ 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);
int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2);
int ssh_is_ipaddr_v4(const char *str);
int ssh_is_ipaddr(const char *str);
/* macro for byte ordering */
uint64_t ntohll(uint64_t);
@@ -48,6 +50,11 @@ struct ssh_iterator {
const void *data;
};
struct ssh_timestamp {
long seconds;
long useconds;
};
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);
@@ -70,4 +77,8 @@ const void *_ssh_list_pop_head(struct ssh_list *list);
#define ssh_list_pop_head(type, ssh_list)\
((type)_ssh_list_pop_head(ssh_list))
void ssh_timestamp_init(struct ssh_timestamp *ts);
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
#endif /* MISC_H_ */

View File

@@ -172,8 +172,6 @@ void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callback
void ssh_packet_set_default_callbacks(ssh_session session);
void ssh_packet_process(ssh_session session, uint8_t type);
/* connect.c */
int ssh_regex_init(void);
void ssh_regex_finalize(void);
socket_t ssh_connect_host(ssh_session session, const char *host,const char
*bind_addr, int port, long timeout, long usec);
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,

View File

@@ -87,10 +87,63 @@ LIBSSH_API ssh_bind ssh_bind_new(void);
*
* @param sshbind The ssh server bind to configure.
*
* @param type Option to set up.
* @param value Value to set.
* @returns SSH_OK No error.
* @returns SSH_ERROR Invalid option or parameter.
* @param type The option type to set. This could be one of the
* following:
*
* - SSH_BIND_OPTIONS_BINDADDR
* The ip address to bind (const char *).
*
* - SSH_BIND_OPTIONS_BINDPORT
* The port to bind (unsigned int).
*
* - SSH_BIND_OPTIONS_BINDPORT_STR
* The port to bind (const char *).
*
* - SSH_BIND_OPTIONS_HOSTKEY
* This specifies the file containing the private host key used
* by SSHv1. (const char *).
*
* - SSH_BIND_OPTIONS_DSAKEY
* This specifies the file containing the private host dsa key
* used by SSHv2. (const char *).
*
* - SSH_BIND_OPTIONS_RSAKEY
* This specifies the file containing the private host dsa key
* used by SSHv2. (const char *).
*
* - SSH_BIND_OPTIONS_BANNER
* That the server banner (version string) for SSH.
* (const char *).
*
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
* Set the session logging verbosity (int).\n
* \n
* The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown.
* - SSH_LOG_NOLOG: No logging
* - SSH_LOG_RARE: Rare conditions or warnings
* - SSH_LOG_ENTRY: API-accessible entrypoints
* - SSH_LOG_PACKET: Packet id and size
* - SSH_LOG_FUNCTIONS: Function entering and leaving
*
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
* Set the session logging verbosity (const char *).\n
* \n
* The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown.
* - SSH_LOG_NOLOG: No logging
* - SSH_LOG_RARE: Rare conditions or warnings
* - SSH_LOG_ENTRY: API-accessible entrypoints
* - SSH_LOG_PACKET: Packet id and size
* - SSH_LOG_FUNCTIONS: Function entering and leaving
* \n
* See the corresponding numbers in libssh.h.
*
* @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.
*
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
*/
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
enum ssh_bind_options_e type, const void *value);
@@ -104,6 +157,26 @@ LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
*/
LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o);
/**
* @brief Set the callback for this bind.
*
* @param[in] sshbind The bind to set the callback on.
*
* @param[in] callbacks An already set up ssh_bind_callbacks instance.
*
* @param[in] userdata A pointer to private data to pass to the callbacks.
*
* @return SSH_OK on success, SSH_ERROR if an error occured.
*
* @code
* struct ssh_callbacks_struct cb = {
* .userdata = data,
* .auth_function = my_auth_function
* };
* ssh_callbacks_init(&cb);
* ssh_bind_set_callbacks(session, &cb);
* @endcode
*/
LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
void *userdata);
@@ -230,6 +303,8 @@ LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
/* deprecated functions */
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
const void *data, uint32_t len);
#ifdef __cplusplus
}

View File

@@ -53,6 +53,7 @@ void ssh_socket_set_write_wontblock(ssh_socket s);
void ssh_socket_set_read_wontblock(ssh_socket s);
void ssh_socket_set_except(ssh_socket s);
int ssh_socket_get_status(ssh_socket s);
int ssh_socket_buffered_write_bytes(ssh_socket s);
int ssh_socket_data_available(ssh_socket s);
int ssh_socket_data_writable(ssh_socket s);

5
libssh_threads.pc.cmake Normal file
View File

@@ -0,0 +1,5 @@
Name: ${APPLICATION_NAME}_threads
Description: The SSH Library Thread Extension
Version: ${APPLICATION_VERSION}
Libs: -L${LIB_INSTALL_DIR} -lssh_threads
Cflags: -I${INCLUDE_INSTALL_DIR}

View File

@@ -184,6 +184,11 @@ install(
if (WITH_STATIC_LIB)
add_library(${LIBSSH_STATIC_LIBRARY} STATIC ${libssh_SRCS})
if (MSVC)
set(OUTPUT_SUFFIX static)
else (MSVC)
set(OUTPUT_SUFFIX )
endif (MSVC)
set_target_properties(
${LIBSSH_STATIC_LIBRARY}
PROPERTIES
@@ -193,6 +198,8 @@ if (WITH_STATIC_LIB)
${LIBRARY_SOVERSION}
OUTPUT_NAME
ssh
ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
)
if (WIN32)
@@ -208,7 +215,7 @@ if (WITH_STATIC_LIB)
TARGETS
${LIBSSH_STATIC_LIBRARY}
DESTINATION
${LIB_INSTALL_DIR}
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
COMPONENT
libraries
)

View File

@@ -62,23 +62,23 @@
* again is necessary
*/
static int ask_userauth(ssh_session session) {
int rc = 0;
int rc = 0;
enter_function();
do {
rc=ssh_service_request(session,"ssh-userauth");
if(ssh_is_blocking(session)){
if(rc==SSH_AGAIN)
ssh_handle_packets(session,-1);
} else {
/* nonblocking */
ssh_handle_packets(session,0);
rc=ssh_service_request(session,"ssh-userauth");
break;
}
} while(rc==SSH_AGAIN);
leave_function();
return rc;
enter_function();
do {
rc = ssh_service_request(session,"ssh-userauth");
if (ssh_is_blocking(session)) {
if(rc == SSH_AGAIN)
ssh_handle_packets(session, -2);
} else {
/* nonblocking */
ssh_handle_packets(session, 0);
rc = ssh_service_request(session, "ssh-userauth");
break;
}
} while (rc == SSH_AGAIN);
leave_function();
return rc;
}
/**
@@ -254,7 +254,7 @@ static int wait_auth_status(ssh_session session) {
enter_function();
if(ssh_is_blocking(session)){
if(ssh_handle_packets_termination(session,-1,auth_status_termination,
if(ssh_handle_packets_termination(session, -2, auth_status_termination,
session) == SSH_ERROR){
leave_function();
return SSH_AUTH_ERROR;
@@ -308,7 +308,7 @@ int ssh_auth_list(ssh_session session) {
/**
* @brief retrieves available authentication methods for this session
* @param[in] session the SSH session
* @param[in] username set to NULL
* @param[in] username Deprecated, 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.
@@ -345,7 +345,7 @@ int ssh_userauth_list(ssh_session session, const char *username) {
* SSH_AUTH_DENIED: Authentication failed: use another method\n
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
* have to use another method\n
* SSH_AUTH_SUCCESS: Authentication success
* SSH_AUTH_SUCCESS: Authentication success\n
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
* later.
*/
@@ -384,6 +384,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
}
if (user == NULL) {
ssh_set_error_oom(session);
leave_function();
return rc;
}
@@ -415,10 +416,12 @@ int ssh_userauth_none(ssh_session session, const char *username) {
method = ssh_string_from_char("none");
if (method == NULL) {
ssh_set_error_oom(session);
goto error;
}
service = ssh_string_from_char("ssh-connection");
if (service == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -519,6 +522,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
}
if (user == NULL) {
ssh_set_error_oom(session);
leave_function();
return rc;
}
@@ -531,14 +535,17 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection");
if (service == NULL) {
ssh_set_error_oom(session);
goto error;
}
method = ssh_string_from_char("publickey");
if (method == NULL) {
ssh_set_error_oom(session);
goto error;
}
algo = ssh_string_from_char(ssh_type_to_char(type));
if (algo == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -549,6 +556,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
buffer_add_u8(session->out_buffer, 0) < 0 ||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(session->out_buffer, publickey) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -640,6 +648,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
}
if (user == NULL) {
ssh_set_error_oom(session);
leave_function();
return rc;
}
@@ -652,24 +661,32 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection");
if (service == NULL) {
ssh_set_error_oom(session);
goto error;
}
method = ssh_string_from_char("publickey");
if (method == NULL) {
ssh_set_error_oom(session);
goto error;
}
algo = ssh_string_from_char(ssh_type_to_char(privatekey->type));
if (algo == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (publickey == NULL) {
pk = publickey_from_privatekey(privatekey);
if (pk == NULL) {
/* most likely oom, and publickey_from_privatekey does not
* return any more information */
ssh_set_error_oom(session);
goto error;
}
pkstr = publickey_to_string(pk);
publickey_free(pk);
if (pkstr == NULL) {
/* same as above */
ssh_set_error_oom(session);
goto error;
}
}
@@ -682,6 +699,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
buffer_add_u8(session->out_buffer, 1) < 0 ||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(session->out_buffer, (publickey == NULL ? pkstr : publickey)) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -694,6 +712,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
sign = ssh_do_sign(session,session->out_buffer, privatekey);
if (sign) {
if (buffer_add_ssh_string(session->out_buffer,sign) < 0) {
ssh_set_error_oom(session);
goto error;
}
ssh_string_free(sign);
@@ -737,7 +756,9 @@ error:
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
* have to use another method.\n
* SSH_AUTH_SUCCESS: Authentication successful.
* SSH_AUTH_SUCCESS: Authentication successful.\n
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
* later.
*
* @see publickey_from_file()
* @see privatekey_from_file()
@@ -756,6 +777,7 @@ int ssh_userauth_privatekey_file(ssh_session session, const char *username,
pubkeyfile = malloc(strlen(filename) + 1 + 4);
if (pubkeyfile == NULL) {
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
@@ -837,6 +859,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
}
if (user == NULL) {
ssh_set_error_oom(session);
leave_function();
return rc;
}
@@ -849,18 +872,22 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection");
if (service == NULL) {
ssh_set_error_oom(session);
goto error;
}
method = ssh_string_from_char("publickey");
if (method == NULL) {
ssh_set_error_oom(session);
goto error;
}
algo = ssh_string_from_char(ssh_type_to_char(publickey->type));
if (algo == NULL) {
ssh_set_error_oom(session);
goto error;
}
key = publickey_to_string(publickey);
if (key == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -872,6 +899,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
buffer_add_u8(session->out_buffer, 1) < 0 ||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(session->out_buffer, key) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -879,6 +907,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
if (sign) {
if (buffer_add_ssh_string(session->out_buffer, sign) < 0) {
ssh_set_error_oom(session);
goto error;
}
ssh_string_free(sign);
@@ -929,7 +958,7 @@ error:
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
* have to use another method.\n
* SSH_AUTH_SUCCESS: Authentication successful.
* SSH_AUTH_SUCCESS: Authentication successful.\n
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
* later.
*
@@ -968,6 +997,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
}
if (user == NULL) {
ssh_set_error_oom(session);
leave_function();
return rc;
}
@@ -1000,14 +1030,17 @@ int ssh_userauth_password(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection");
if (service == NULL) {
ssh_set_error_oom(session);
goto error;
}
method = ssh_string_from_char("password");
if (method == NULL) {
ssh_set_error_oom(session);
goto error;
}
pwd = ssh_string_from_char(password);
if (pwd == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -1017,6 +1050,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
buffer_add_u8(session->out_buffer, 0) < 0 ||
buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1374,18 +1408,22 @@ static int kbdauth_init(ssh_session session, const char *user,
usr = ssh_string_from_char(user);
if (usr == NULL) {
ssh_set_error_oom(session);
goto error;
}
sub = (submethods ? ssh_string_from_char(submethods) : ssh_string_from_char(""));
if (sub == NULL) {
ssh_set_error_oom(session);
goto error;
}
service = ssh_string_from_char("ssh-connection");
if (service == NULL) {
ssh_set_error_oom(session);
goto error;
}
method = ssh_string_from_char("keyboard-interactive");
if (method == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -1395,6 +1433,7 @@ static int kbdauth_init(ssh_session session, const char *user,
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
buffer_add_u32(session->out_buffer, 0) < 0 ||
buffer_add_ssh_string(session->out_buffer, sub) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1562,23 +1601,30 @@ static int kbdauth_send(ssh_session session) {
enter_function();
if(session==NULL || session->kbdint == NULL) {
return rc;
}
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE) < 0 ||
buffer_add_u32(session->out_buffer,
htonl(session->kbdint->nprompts)) < 0) {
ssh_set_error_oom(session);
goto error;
}
for (i = 0; i < session->kbdint->nprompts; i++) {
if (session->kbdint->answers[i]) {
if (session->kbdint->answers && session->kbdint->answers[i]) {
answer = ssh_string_from_char(session->kbdint->answers[i]);
} else {
answer = ssh_string_from_char("");
}
if (answer == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_ssh_string(session->out_buffer, answer) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1622,7 +1668,9 @@ error:
* have to use another method\n
* SSH_AUTH_SUCCESS: Authentication success\n
* SSH_AUTH_INFO: The server asked some questions. Use
* ssh_userauth_kbdint_getnprompts() and such.
* ssh_userauth_kbdint_getnprompts() and such.\n
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
* later.
*
* @see ssh_userauth_kbdint_getnprompts()
* @see ssh_userauth_kbdint_getname()
@@ -1635,7 +1683,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
int rc = SSH_AUTH_ERROR;
if (session->version == 1) {
/* No keyb-interactive for ssh1 */
ssh_set_error(session, SSH_NO_ERROR, "No keyboard-interactive for ssh1");
return SSH_AUTH_DENIED;
}
@@ -1688,8 +1736,12 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
* @returns The number of prompts.
*/
int ssh_userauth_kbdint_getnprompts(ssh_session session) {
if(session==NULL || session->kbdint == NULL)
return SSH_ERROR;
if(session==NULL)
return SSH_ERROR;
if(session->kbdint == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return SSH_ERROR;
}
return session->kbdint->nprompts;
}
@@ -1704,8 +1756,12 @@ int ssh_userauth_kbdint_getnprompts(ssh_session session) {
* @returns The name of the message block. Do not free it.
*/
const char *ssh_userauth_kbdint_getname(ssh_session session) {
if(session==NULL || session->kbdint == NULL)
if(session==NULL)
return NULL;
if(session->kbdint == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return NULL;
}
return session->kbdint->name;
}
@@ -1721,8 +1777,12 @@ const char *ssh_userauth_kbdint_getname(ssh_session session) {
*/
const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
if(session==NULL || session->kbdint == NULL)
return NULL;
if(session==NULL)
return NULL;
if(session->kbdint == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return NULL;
}
return session->kbdint->instruction;
}
@@ -1744,9 +1804,14 @@ const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
*/
const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
char *echo) {
if(session==NULL || session->kbdint == NULL)
if(session==NULL)
return NULL;
if (i > session->kbdint->nprompts) {
if(session->kbdint == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return NULL;
}
if (i > session->kbdint->nprompts) {
ssh_set_error_invalid(session, __FUNCTION__);
return NULL;
}
@@ -1773,14 +1838,18 @@ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
*/
int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
const char *answer) {
if (session == NULL || answer == NULL || session->kbdint == NULL ||
if (session == NULL)
return -1;
if (answer == NULL || session->kbdint == NULL ||
i > session->kbdint->nprompts) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
if (session->kbdint->answers == NULL) {
session->kbdint->answers = malloc(sizeof(char*) * session->kbdint->nprompts);
if (session->kbdint->answers == NULL) {
ssh_set_error_oom(session);
return -1;
}
memset(session->kbdint->answers, 0, sizeof(char *) * session->kbdint->nprompts);
@@ -1793,6 +1862,7 @@ int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
session->kbdint->answers[i] = strdup(answer);
if (session->kbdint->answers[i] == NULL) {
ssh_set_error_oom(session);
return -1;
}

View File

@@ -38,7 +38,7 @@ static int wait_auth1_status(ssh_session session) {
enter_function();
/* wait for a packet */
while(session->auth_state == SSH_AUTH_STATE_NONE)
if (ssh_handle_packets(session,-1) != SSH_OK)
if (ssh_handle_packets(session, -2) != SSH_OK)
break;
ssh_log(session,SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state);
leave_function();

View File

@@ -160,6 +160,7 @@ int ssh_bind_listen(ssh_bind sshbind) {
socket_t fd;
if (ssh_init() < 0) {
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
return -1;
}
@@ -185,28 +186,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
return 0;
}
/**
* @brief set the bind callbacks for ssh_bind
* @code
* struct ssh_callbacks_struct cb = {
* .userdata = data,
* .auth_function = my_auth_function
* };
* ssh_callbacks_init(&cb);
* ssh_set_callbacks(session, &cb);
* @endcode
* @param sshbind the ssh_bind structure to set
* @param callbacks a ssh_bind_callbacks instance already set up. Do
* use ssh_callbacks_init() to initialize it.
* @param userdata userdata to be used with each callback called
* within callbacks.
* @returns SSH_OK on success,
* SSH_ERROR on error.
*/
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
void *userdata){
if (sshbind == NULL || callbacks == NULL) {
if (sshbind == NULL) {
return SSH_ERROR;
}
if (callbacks == NULL) {
ssh_set_error_invalid(sshbind, __FUNCTION__);
return SSH_ERROR;
}
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
@@ -378,6 +364,8 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
ssh_socket_free(session->socket);
session->socket = ssh_socket_new(session);
if (session->socket == NULL) {
/* perhaps it may be better to copy the error from session to sshbind */
ssh_set_error_oom(sshbind);
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;

View File

@@ -48,6 +48,14 @@
#define WINDOWBASE 128000
#define WINDOWLIMIT (WINDOWBASE/2)
/*
* All implementations MUST be able to process packets with an
* uncompressed payload length of 32768 bytes or less and a total packet
* size of 35000 bytes or less.
*/
#define CHANNEL_MAX_PACKET 32768
#define CHANNEL_INITIAL_WINDOW 64000
/**
* @defgroup libssh_channel The SSH channel functions
* @ingroup libssh
@@ -71,18 +79,21 @@ ssh_channel ssh_channel_new(ssh_session session) {
channel = malloc(sizeof(struct ssh_channel_struct));
if (channel == NULL) {
ssh_set_error_oom(session);
return NULL;
}
memset(channel,0,sizeof(struct ssh_channel_struct));
channel->stdout_buffer = ssh_buffer_new();
if (channel->stdout_buffer == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(channel);
return NULL;
}
channel->stderr_buffer = ssh_buffer_new();
if (channel->stderr_buffer == NULL) {
ssh_set_error_oom(session);
ssh_buffer_free(channel->stdout_buffer);
SAFE_FREE(channel);
return NULL;
@@ -243,6 +254,7 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
type = ssh_string_from_char(type_c);
if (type == NULL) {
ssh_set_error_oom(session);
leave_function();
return err;
}
@@ -252,6 +264,7 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
buffer_add_u32(session->out_buffer, htonl(channel->local_channel)) < 0 ||
buffer_add_u32(session->out_buffer, htonl(channel->local_window)) < 0 ||
buffer_add_u32(session->out_buffer, htonl(channel->local_maxpacket)) < 0) {
ssh_set_error_oom(session);
ssh_string_free(type);
leave_function();
return err;
@@ -261,6 +274,7 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
if (payload != NULL) {
if (buffer_add_buffer(session->out_buffer, payload) < 0) {
ssh_set_error_oom(session);
leave_function();
return err;
}
@@ -278,7 +292,11 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
/* Todo: fix this into a correct loop */
/* wait until channel is opened by server */
while(channel->state == SSH_CHANNEL_STATE_NOT_OPEN){
ssh_handle_packets(session,-1);
ssh_handle_packets(session, -2);
if (session->session_state == SSH_SESSION_STATE_ERROR) {
err = SSH_ERROR;
break;
}
}
if(channel->state == SSH_CHANNEL_STATE_OPEN)
err=SSH_OK;
@@ -286,24 +304,25 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
return err;
}
/* get ssh channel from local session? */
/* return channel with corresponding local id, or NULL if not found */
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id) {
ssh_channel initchan = session->channels;
ssh_channel channel;
ssh_channel initchan = session->channels;
ssh_channel channel = initchan;
/* We assume we are always the local */
if (initchan == NULL) {
return NULL;
}
for (channel = initchan; channel->local_channel != id;
channel=channel->next) {
if (channel->next == initchan) {
return NULL;
for (;;) {
if (channel == NULL) {
return NULL;
}
if (channel->local_channel == id) {
return channel;
}
if (channel->next == initchan) {
return NULL;
}
channel = channel->next;
}
}
return channel;
return NULL;
}
/**
@@ -331,6 +350,7 @@ static int grow_window(ssh_session session, ssh_channel channel, int minimumsize
if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_WINDOW_ADJUST) < 0 ||
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0 ||
buffer_add_u32(session->out_buffer, htonl(new_window - channel->local_window)) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -467,7 +487,7 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
len = ssh_string_len(str);
ssh_log(session, SSH_LOG_PROTOCOL,
"Channel receiving %zu bytes data in %d (local win=%d remote win=%d)",
"Channel receiving %" PRIdS " bytes data in %d (local win=%d remote win=%d)",
len,
is_stderr,
channel->local_window,
@@ -476,7 +496,7 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
/* What shall we do in this case? Let's accept it anyway */
if (len > channel->local_window) {
ssh_log(session, SSH_LOG_RARE,
"Data packet too big for our window(%zu vs %d)",
"Data packet too big for our window(%" PRIdS " vs %d)",
len,
channel->local_window);
}
@@ -799,7 +819,18 @@ SSH_PACKET_CALLBACK(channel_rcv_request) {
*/
int channel_default_bufferize(ssh_channel channel, void *data, int len,
int is_stderr) {
ssh_session session = channel->session;
ssh_session session;
if(channel == NULL) {
return -1;
}
session = channel->session;
if(data == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
ssh_log(session, SSH_LOG_RARE,
"placing %d bytes into channel buffer (stderr=%d)", len, is_stderr);
@@ -814,6 +845,7 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
}
if (buffer_add_data(channel->stdout_buffer, data, len) < 0) {
ssh_set_error_oom(session);
ssh_buffer_free(channel->stdout_buffer);
channel->stdout_buffer = NULL;
return -1;
@@ -829,6 +861,7 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
}
if (buffer_add_data(channel->stderr_buffer, data, len) < 0) {
ssh_set_error_oom(session);
ssh_buffer_free(channel->stderr_buffer);
channel->stderr_buffer = NULL;
return -1;
@@ -857,7 +890,11 @@ int ssh_channel_open_session(ssh_channel channel) {
}
#endif
return channel_open(channel,"session",64000,32000,NULL);
return channel_open(channel,
"session",
CHANNEL_INITIAL_WINDOW,
CHANNEL_MAX_PACKET,
NULL);
}
/**
@@ -869,11 +906,12 @@ int ssh_channel_open_session(ssh_channel channel) {
*
* @param[in] remoteport The remote port.
*
* @param[in] sourcehost The source host (your local computer). It's optional
* and for logging purpose.
* @param[in] sourcehost The numeric IP address of the machine from where the
* connection request originates. This is mostly for
* logging purposes.
*
* @param[in] localport The source port (your local computer). It's optional
* and for logging purpose.
* @param[in] localport The port on the host from where the connection
* originated. This is mostly for logging purposes.
*
* @return SSH_OK on success, SSH_ERROR if an error occured.
*
@@ -883,39 +921,59 @@ int ssh_channel_open_session(ssh_channel channel) {
*/
int ssh_channel_open_forward(ssh_channel channel, const char *remotehost,
int remoteport, const char *sourcehost, int localport) {
ssh_session session = channel->session;
ssh_session session;
ssh_buffer payload = NULL;
ssh_string str = NULL;
int rc = SSH_ERROR;
if (channel == NULL) {
return rc;
}
session = channel->session;
enter_function();
if(remotehost == NULL || sourcehost == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return rc;
}
payload = ssh_buffer_new();
if (payload == NULL) {
ssh_set_error_oom(session);
goto error;
}
str = ssh_string_from_char(remotehost);
if (str == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_ssh_string(payload, str) < 0 ||
buffer_add_u32(payload,htonl(remoteport)) < 0) {
ssh_set_error_oom(session);
goto error;
}
ssh_string_free(str);
str = ssh_string_from_char(sourcehost);
if (str == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_ssh_string(payload, str) < 0 ||
buffer_add_u32(payload,htonl(localport)) < 0) {
ssh_set_error_oom(session);
goto error;
}
rc = channel_open(channel, "direct-tcpip", 64000, 32000, payload);
rc = channel_open(channel,
"direct-tcpip",
CHANNEL_INITIAL_WINDOW,
CHANNEL_MAX_PACKET,
payload);
error:
ssh_buffer_free(payload);
@@ -988,9 +1046,11 @@ int ssh_channel_send_eof(ssh_channel channel){
enter_function();
if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_EOF) < 0) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_u32(session->out_buffer,htonl(channel->remote_channel)) < 0) {
ssh_set_error_oom(session);
goto error;
}
rc = packet_send(session);
@@ -1040,6 +1100,7 @@ int ssh_channel_close(ssh_channel channel){
if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_CLOSE) < 0 ||
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1064,15 +1125,28 @@ error:
int channel_write_common(ssh_channel channel, const void *data,
uint32_t len, int is_stderr) {
ssh_session session = channel->session;
ssh_session session;
int origlen = len;
size_t effectivelen;
/* handle the max packet len from remote side, be nice */
/* 10 bytes for the headers */
size_t maxpacketlen = channel->remote_maxpacket - 10;
size_t maxpacketlen;
if(channel == NULL || data == NULL) {
return -1;
}
session = channel->session;
if(data == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
enter_function();
/*
* Handle the max packet len from remote side, be nice
* 10 bytes for the headers
*/
maxpacketlen = channel->remote_maxpacket - 10;
if (channel->local_eof) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't write to channel %d:%d after EOF was sent",
@@ -1102,15 +1176,12 @@ int channel_write_common(ssh_channel channel, const void *data,
"Remote window is %d bytes. going to write %d bytes",
channel->remote_window,
len);
ssh_log(session, SSH_LOG_PROTOCOL,
"Waiting for a growing window message...");
/* What happens when the channel window is zero? */
while(channel->remote_window == 0) {
/* parse every incoming packet */
if (ssh_handle_packets(session,-1) == SSH_ERROR) {
leave_function();
return SSH_ERROR;
}
if(channel->remote_window == 0) {
/* nothing can be written */
ssh_log(session, SSH_LOG_PROTOCOL,
"Wait for a growing window message...");
return 0;
}
effectivelen = len > channel->remote_window ? channel->remote_window : len;
} else {
@@ -1121,16 +1192,19 @@ int channel_write_common(ssh_channel channel, const void *data,
SSH2_MSG_CHANNEL_EXTENDED_DATA : SSH2_MSG_CHANNEL_DATA) < 0 ||
buffer_add_u32(session->out_buffer,
htonl(channel->remote_channel)) < 0) {
ssh_set_error_oom(session);
goto error;
}
/* stderr message has an extra field */
if (is_stderr &&
buffer_add_u32(session->out_buffer, htonl(SSH2_EXTENDED_DATA_STDERR)) < 0) {
ssh_set_error_oom(session);
goto error;
}
/* append payload data */
if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
buffer_add_data(session->out_buffer, data, effectivelen) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1156,6 +1230,10 @@ error:
return SSH_ERROR;
}
uint32_t ssh_channel_window_size(ssh_channel channel) {
return channel->remote_window;
}
/**
* @brief Blocking write on a channel.
*
@@ -1313,6 +1391,7 @@ static int channel_request(ssh_channel channel, const char *request,
req = ssh_string_from_char(request);
if (req == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -1320,6 +1399,7 @@ static int channel_request(ssh_channel channel, const char *request,
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0 ||
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
ssh_set_error_oom(session);
goto error;
}
ssh_string_free(req);
@@ -1327,6 +1407,7 @@ static int channel_request(ssh_channel channel, const char *request,
if (buffer != NULL) {
if (buffer_add_data(session->out_buffer, buffer_get_rest(buffer),
buffer_get_rest_len(buffer)) < 0) {
ssh_set_error_oom(session);
goto error;
}
}
@@ -1344,7 +1425,12 @@ static int channel_request(ssh_channel channel, const char *request,
return SSH_OK;
}
while(channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING){
ssh_handle_packets(session,-1);
ssh_handle_packets(session, -2);
if(session->session_state == SSH_SESSION_STATE_ERROR) {
channel->request_state = SSH_CHANNEL_REQ_STATE_ERROR;
break;
}
}
/* we received something */
switch (channel->request_state){
@@ -1409,11 +1495,13 @@ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
#endif
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(session);
goto error;
}
term = ssh_string_from_char(terminal);
if (term == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -1424,6 +1512,7 @@ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
buffer_add_u32(buffer, 0) < 0 ||
buffer_add_u32(buffer, htonl(1)) < 0 || /* Add a 0byte string */
buffer_add_u8(buffer, 0) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1481,6 +1570,7 @@ int ssh_channel_change_pty_size(ssh_channel channel, int cols, int rows) {
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -1488,6 +1578,7 @@ int ssh_channel_change_pty_size(ssh_channel channel, int cols, int rows) {
buffer_add_u32(buffer, htonl(rows)) < 0 ||
buffer_add_u32(buffer, 0) < 0 ||
buffer_add_u32(buffer, 0) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1533,15 +1624,18 @@ int ssh_channel_request_subsystem(ssh_channel channel, const char *subsys) {
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
subsystem = ssh_string_from_char(subsys);
if (subsystem == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_ssh_string(buffer, subsystem) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -1601,11 +1695,13 @@ int ssh_channel_request_x11(ssh_channel channel, int single_connection, const ch
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
p = ssh_string_from_char(protocol ? protocol : "MIT-MAGIC-COOKIE-1");
if (p == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -1615,6 +1711,7 @@ int ssh_channel_request_x11(ssh_channel channel, int single_connection, const ch
c = generate_cookie();
}
if (c == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -1622,6 +1719,7 @@ int ssh_channel_request_x11(ssh_channel channel, int single_connection, const ch
buffer_add_ssh_string(buffer, p) < 0 ||
buffer_add_ssh_string(buffer, c) < 0 ||
buffer_add_u32(buffer, htonl(screen_number)) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -1649,7 +1747,7 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
for (t = timeout_ms; t >= 0; t -= 50)
{
ssh_handle_packets(session,50);
ssh_handle_packets(session, 50);
if (session->ssh_message_list) {
iterator = ssh_list_get_iterator(session->ssh_message_list);
@@ -1674,6 +1772,7 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
}
}
ssh_set_error(session, SSH_NO_ERROR, "No channel request of this type from server");
return NULL;
}
@@ -1771,12 +1870,14 @@ static int global_request(ssh_session session, const char *request,
}
req = ssh_string_from_char(request);
if (req == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 ||
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
ssh_set_error_oom(session);
goto error;
}
ssh_string_free(req);
@@ -1785,6 +1886,7 @@ static int global_request(ssh_session session, const char *request,
if (buffer != NULL) {
if (buffer_add_data(session->out_buffer, buffer_get_rest(buffer),
buffer_get_rest_len(buffer)) < 0) {
ssh_set_error_oom(session);
goto error;
}
}
@@ -1802,7 +1904,7 @@ static int global_request(ssh_session session, const char *request,
return SSH_OK;
}
while(session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING){
rc=ssh_handle_packets(session,-1);
rc=ssh_handle_packets(session, -2);
if(rc==SSH_ERROR){
session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR;
break;
@@ -1863,16 +1965,19 @@ int ssh_forward_listen(ssh_session session, const char *address, int port, int *
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(session);
goto error;
}
addr = ssh_string_from_char(address ? address : "");
if (addr == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_ssh_string(buffer, addr) < 0 ||
buffer_add_u32(buffer, htonl(port)) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1922,16 +2027,19 @@ int ssh_forward_cancel(ssh_session session, const char *address, int port) {
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(session);
goto error;
}
addr = ssh_string_from_char(address ? address : "");
if (addr == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_ssh_string(buffer, addr) < 0 ||
buffer_add_u32(buffer, htonl(port)) < 0) {
ssh_set_error_oom(session);
goto error;
}
@@ -1963,25 +2071,30 @@ int ssh_channel_request_env(ssh_channel channel, const char *name, const char *v
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
str = ssh_string_from_char(name);
if (str == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_ssh_string(buffer, str) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
ssh_string_free(str);
str = ssh_string_from_char(value);
if (str == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_ssh_string(buffer, str) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -2033,15 +2146,18 @@ int ssh_channel_request_exec(ssh_channel channel, const char *cmd) {
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
command = ssh_string_from_char(cmd);
if (command == NULL) {
goto error;
ssh_set_error_oom(channel->session);
}
if (buffer_add_ssh_string(buffer, command) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -2061,10 +2177,26 @@ error:
* In such a case this request will be silently ignored.
* Only SSH-v2 is supported (I'm not sure about SSH-v1).
*
* OpenSSH doesn't support signals yet, see:
* https://bugzilla.mindrot.org/show_bug.cgi?id=1424
*
* @param[in] channel The channel to send signal.
*
* @param[in] sig The signal to send (without SIG prefix)
* (e.g. "TERM" or "KILL").
* \n\n
* SIGABRT -> ABRT \n
* SIGALRM -> ALRM \n
* SIGFPE -> FPE \n
* SIGHUP -> HUP \n
* SIGILL -> ILL \n
* SIGINT -> INT \n
* SIGKILL -> KILL \n
* SIGPIPE -> PIPE \n
* SIGQUIT -> QUIT \n
* SIGSEGV -> SEGV \n
* SIGTERM -> TERM \n
* SIGUSR1 -> USR1 \n
* SIGUSR2 -> USR2 \n
*
* @return SSH_OK on success, SSH_ERROR if an error occured
* (including attempts to send signal via SSH-v1 session).
@@ -2082,15 +2214,18 @@ int ssh_channel_request_send_signal(ssh_channel channel, const char *sig) {
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
encoded_signal = ssh_string_from_char(sig);
if (encoded_signal == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_ssh_string(buffer, encoded_signal) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -2142,7 +2277,10 @@ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
leave_function();
return r;
}
buffer_add_data(buffer,buffer_tmp,r);
if(buffer_add_data(buffer,buffer_tmp,r) < 0){
ssh_set_error_oom(session);
r = SSH_ERROR;
}
leave_function();
return r;
}
@@ -2150,7 +2288,7 @@ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
leave_function();
return 0;
}
ssh_handle_packets(channel->session, -1);
ssh_handle_packets(channel->session, -2);
} while (r == 0);
}
while(total < count){
@@ -2163,7 +2301,11 @@ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
leave_function();
return total;
}
buffer_add_data(buffer,buffer_tmp,r);
if(buffer_add_data(buffer,buffer_tmp,r) < 0){
ssh_set_error_oom(session);
leave_function();
return SSH_ERROR;
}
total += r;
}
leave_function();
@@ -2244,7 +2386,7 @@ int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_std
break;
}
ssh_handle_packets(session,-1);
ssh_handle_packets(session, -2);
}
len = buffer_get_rest_len(stdbuf);
@@ -2288,7 +2430,7 @@ int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_std
int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
int is_stderr) {
ssh_session session = channel->session;
uint32_t to_read;
int to_read;
int rc;
enter_function();
@@ -2300,8 +2442,8 @@ int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count
return to_read; /* may be an error code */
}
if (to_read > count) {
to_read = count;
if (to_read > (int)count) {
to_read = (int)count;
}
rc = ssh_channel_read(channel, dest, to_read, is_stderr);
@@ -2334,7 +2476,7 @@ int ssh_channel_poll(ssh_channel channel, int is_stderr){
}
if (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) {
if (ssh_handle_packets(channel->session,0)==SSH_ERROR) {
if (ssh_handle_packets(channel->session, 0)==SSH_ERROR) {
leave_function();
return SSH_ERROR;
}
@@ -2379,9 +2521,9 @@ int ssh_channel_get_exit_status(ssh_channel channel) {
return -1;
}
while (channel->remote_eof == 0 || channel->exit_status == -1) {
while ((channel->remote_eof == 0 || channel->exit_status == -1) && channel->session->alive) {
/* Parse every incoming packet */
if (ssh_handle_packets(channel->session,-1) != SSH_OK) {
if (ssh_handle_packets(channel->session, -2) != SSH_OK) {
return -1;
}
/* XXX We should actually wait for a close packet and not a close
@@ -2416,7 +2558,7 @@ static int channel_protocol_select(ssh_channel *rchans, ssh_channel *wchans,
chan = rchans[i];
while (ssh_channel_is_open(chan) && ssh_socket_data_available(chan->session->socket)) {
ssh_handle_packets(chan->session,-1);
ssh_handle_packets(chan->session, -2);
}
if ((chan->stdout_buffer && buffer_get_rest_len(chan->stdout_buffer) > 0) ||
@@ -2659,30 +2801,39 @@ int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost
payload = ssh_buffer_new();
if (payload == NULL) {
ssh_set_error_oom(session);
goto error;
}
str = ssh_string_from_char(remotehost);
if (str == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_ssh_string(payload, str) < 0 ||
buffer_add_u32(payload,htonl(remoteport)) < 0) {
ssh_set_error_oom(session);
goto error;
}
ssh_string_free(str);
str = ssh_string_from_char(sourcehost);
if (str == NULL) {
ssh_set_error_oom(session);
goto error;
}
if (buffer_add_ssh_string(payload, str) < 0 ||
buffer_add_u32(payload,htonl(localport)) < 0) {
ssh_set_error_oom(session);
goto error;
}
rc = channel_open(channel, "forwarded-tcpip", 64000, 32000, payload);
rc = channel_open(channel,
"forwarded-tcpip",
CHANNEL_INITIAL_WINDOW,
CHANNEL_MAX_PACKET,
payload);
error:
ssh_buffer_free(payload);
@@ -2717,10 +2868,12 @@ int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status) {
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_u32(buffer, ntohl(exit_status)) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
@@ -2754,6 +2907,15 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig, i
ssh_string tmp = NULL;
int rc = SSH_ERROR;
if(channel == NULL) {
return rc;
}
if(sig == NULL || errmsg == NULL || lang == NULL) {
ssh_set_error_invalid(channel->session, __FUNCTION__);
return rc;
}
#ifdef WITH_SSH1
if (channel->version == 1) {
return SSH_ERROR; // TODO: Add support for SSH-v1 if possible.
@@ -2762,36 +2924,44 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig, i
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
tmp = ssh_string_from_char(sig);
if (tmp == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_ssh_string(buffer, tmp) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_u8(buffer, core?1:0) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
ssh_string_free(tmp);
tmp = ssh_string_from_char(errmsg);
if (tmp == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_ssh_string(buffer, tmp) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}
ssh_string_free(tmp);
tmp = ssh_string_from_char(lang);
if (tmp == NULL) {
ssh_set_error_oom(channel->session);
goto error;
}
if (buffer_add_ssh_string(buffer, tmp) < 0) {
ssh_set_error_oom(channel->session);
goto error;
}

View File

@@ -232,7 +232,7 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
}
ssh_log(session, SSH_LOG_PROTOCOL,
"Adding %zu bytes data in %d",
"Adding %" PRIdS " bytes data in %d",
ssh_string_len(str), is_stderr);
if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str),

View File

@@ -673,8 +673,6 @@ int ssh_connect(ssh_session session) {
} else {
ret=ssh_socket_connect(session->socket, session->host, session->port,
session->bindaddr);
/*, session->timeout * 1000 + session->timeout_usec); */
}
if (ret == SSH_ERROR) {
leave_function();
@@ -686,11 +684,21 @@ int ssh_connect(ssh_session session) {
session->alive = 1;
ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
pending:
session->pending_call_state=SSH_PENDING_CALL_CONNECT;
if(ssh_is_blocking(session))
ssh_handle_packets_termination(session,-1,ssh_connect_termination,session);
session->pending_call_state=SSH_PENDING_CALL_CONNECT;
if(ssh_is_blocking(session)) {
int timeout = (session->timeout * 1000) + (session->timeout_usec / 1000);
if (timeout == 0) {
timeout = 10 * 1000;
}
ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual timeout : %d", timeout);
ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
if(!ssh_connect_termination(session)){
ssh_set_error(session,SSH_FATAL,"Timeout connecting to %s",session->host);
session->session_state = SSH_SESSION_STATE_ERROR;
}
}
else
ssh_handle_packets_termination(session,0,ssh_connect_termination, session);
ssh_handle_packets_termination(session, 0, ssh_connect_termination, session);
ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
leave_function();

View File

@@ -327,9 +327,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
return 0;
}
if (session->log_verbosity) {
fprintf(stderr, "Reading configuration data from %s\n", filename);
}
ssh_log(session, SSH_LOG_RARE, "Reading configuration data from %s", filename);
parsing = 1;
while (fgets(line, sizeof(line), f)) {

View File

@@ -21,12 +21,17 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libssh/libssh.h"
#include "libssh/misc.h"
#ifdef _WIN32
/*
* Only use Windows API functions available on Windows 2000 SP4 or later.
@@ -78,14 +83,6 @@
#error "Your system must have getaddrinfo()"
#endif
#ifdef HAVE_REGCOMP
/* don't declare gnu extended regexp's */
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE
#endif
#include <regex.h>
#endif /* HAVE_REGCOMP */
#ifdef _WIN32
void ssh_sock_set_nonblocking(socket_t sock) {
u_long nonblocking = 1;
@@ -118,53 +115,6 @@ void ssh_sock_set_blocking(socket_t sock) {
#endif /* _WIN32 */
#ifdef HAVE_REGCOMP
#define IPEXPR "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
static regex_t *ip_regex = NULL;
/** @internal
* @brief initializes and compile the regexp to be used for IP matching
* @returns -1 on error (and error message is set)
* @returns 0 on success
*/
int ssh_regex_init(){
if(ip_regex==NULL){
int err;
regex_t *regex=malloc(sizeof (regex_t));
ZERO_STRUCTP(regex);
err = regcomp(regex, IPEXPR, REG_EXTENDED | REG_NOSUB);
if(err != 0){
char buffer[128];
regerror(err,regex,buffer,sizeof(buffer));
fprintf(stderr,"Error while compiling regular expression : %s\n",buffer);
SAFE_FREE(regex);
return -1;
}
ip_regex=regex;
}
return 0;
}
/** @internal
* @brief clean up the IP regexp
*/
void ssh_regex_finalize(){
if(ip_regex){
regfree(ip_regex);
SAFE_FREE(ip_regex);
}
}
#else /* HAVE_REGCOMP */
int ssh_regex_init(){
return 0;
}
void ssh_regex_finalize(){
}
#endif
static int ssh_connect_socket_close(socket_t s){
#ifdef _WIN32
return closesocket(s);
@@ -194,13 +144,13 @@ static int getai(ssh_session session, const char *host, int port, struct addrinf
hints.ai_flags=AI_NUMERICSERV;
#endif
}
#ifdef HAVE_REGCOMP
if(regexec(ip_regex,host,0,NULL,0) == 0){
if (ssh_is_ipaddr(host)) {
/* this is an IP address */
ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
hints.ai_flags |= AI_NUMERICHOST;
}
#endif
return getaddrinfo(host, service, &hints, ai);
}
@@ -472,7 +422,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
*
* @param[in] timeout A timeout for the select.
*
* @return -1 if an error occured. E_INTR if it was interrupted, in
* @return -1 if an error occured. SSH_EINTR if it was interrupted, in
* that case, just restart it.
*
* @warning libssh is not threadsafe here. That means that if a signal is caught

View File

@@ -140,6 +140,7 @@ int ssh_crypto_init(void) {
}
bignum_bin2bn(p_value, P_LEN, p);
OpenSSL_add_all_algorithms();
#endif
ssh_crypto_initialized = 1;
@@ -154,8 +155,13 @@ void ssh_crypto_finalize(void) {
g = NULL;
bignum_free(p);
p = NULL;
#ifdef HAVE_LIBGCRYPT
gcry_control(GCRYCTL_TERM_SECMEM);
#elif defined HAVE_LIBCRYPTO
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
#endif
ssh_crypto_initialized=0;
}
}

View File

@@ -57,8 +57,6 @@ int ssh_init(void) {
return -1;
if(ssh_socket_init())
return -1;
if(ssh_regex_init())
return -1;
return 0;
}
@@ -73,18 +71,12 @@ int ssh_init(void) {
@returns 0 otherwise
*/
int ssh_finalize(void) {
ssh_threads_finalize();
ssh_regex_finalize();
ssh_crypto_finalize();
ssh_socket_cleanup();
#ifdef HAVE_LIBGCRYPT
gcry_control(GCRYCTL_TERM_SECMEM);
#elif defined HAVE_LIBCRYPTO
EVP_cleanup();
#endif
#ifdef _WIN32
WSACleanup();
#endif
/* It is important to finalize threading after CRYPTO because
* it still depends on it */
ssh_threads_finalize();
return 0;
}

View File

@@ -761,7 +761,7 @@ SSH_PACKET_CALLBACK(ssh_packet_publickey1){
}
bits = ssh_string_len(enc_session) * 8 - 7;
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session",
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %" PRIdS " bytes encrypted session",
bits, ssh_string_len(enc_session));
bits = htons(bits);
/* the encrypted mpint */
@@ -814,14 +814,14 @@ int ssh_get_kex1(ssh_session session) {
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
/* Here the callback is called */
while(session->session_state==SSH_SESSION_STATE_INITIAL_KEX){
ssh_handle_packets(session,-1);
ssh_handle_packets(session, -2);
}
if(session->session_state==SSH_SESSION_STATE_ERROR)
goto error;
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS");
/* Waiting for SSH_SMSG_SUCCESS */
while(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){
ssh_handle_packets(session,-1);
ssh_handle_packets(session, -2);
}
if(session->session_state==SSH_SESSION_STATE_ERROR)
goto error;

View File

@@ -677,11 +677,15 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
#elif defined HAVE_LIBCRYPTO
DSA *dsa = NULL;
RSA *rsa = NULL;
BIO *bio = NULL;
#endif
/* TODO Implement to read both DSA and RSA at once. */
/* needed for openssl initialization */
ssh_init();
if (ssh_init() < 0) {
return NULL;
}
ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
file = fopen(filename,"r");
if (file == NULL) {
@@ -690,6 +694,15 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
return NULL;
}
#ifdef HAVE_LIBCRYPTO
bio = BIO_new_file(filename,"r");
if (bio == NULL) {
fclose(file);
ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
return NULL;
}
#endif
ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
filename, passphrase ? "true" : "false",
session->callbacks && session->callbacks->auth_function ? "true" : "false");
@@ -726,15 +739,16 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO
if (session->callbacks && session->callbacks->auth_function) {
dsa = PEM_read_DSAPrivateKey(file, NULL, pem_get_password, session);
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, pem_get_password, session);
} else { /* authcb */
/* openssl uses its own callback to get the passphrase here */
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, NULL);
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
} /* authcb */
} else { /* passphrase */
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, (void *) passphrase);
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
}
BIO_free(bio);
fclose(file);
if (dsa == NULL) {
ssh_set_error(session, SSH_FATAL,
@@ -766,15 +780,16 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
ssh_set_error(session,SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO
if (session->callbacks && session->callbacks->auth_function) {
rsa = PEM_read_RSAPrivateKey(file, NULL, pem_get_password, session);
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, pem_get_password, session);
} else { /* authcb */
/* openssl uses its own callback to get the passphrase here */
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
} /* authcb */
} else { /* passphrase */
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, (void *) passphrase);
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
}
BIO_free(bio);
fclose(file);
if (rsa == NULL) {
@@ -786,6 +801,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
}
break;
default:
#ifdef HAVE_LIBCRYPTO
BIO_free(bio);
#endif
fclose(file);
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
return NULL;
@@ -828,22 +846,31 @@ enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey){
ssh_private_key _privatekey_from_file(void *session, const char *filename,
int type) {
ssh_private_key privkey = NULL;
FILE *file = NULL;
#ifdef HAVE_LIBGCRYPT
FILE *file = NULL;
gcry_sexp_t dsa = NULL;
gcry_sexp_t rsa = NULL;
int valid;
#elif defined HAVE_LIBCRYPTO
DSA *dsa = NULL;
RSA *rsa = NULL;
BIO *bio = NULL;
#endif
#ifdef HAVE_LIBGCRYPT
file = fopen(filename,"r");
if (file == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Error opening %s: %s", filename, strerror(errno));
return NULL;
}
#elif defined HAVE_LIBCRYPTO
bio = BIO_new_file(filename,"r");
if (bio == NULL) {
ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
return NULL;
}
#endif
switch (type) {
case SSH_KEYTYPE_DSS:
@@ -855,14 +882,16 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
if (!valid) {
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, NULL);
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
fclose(file);
BIO_free(bio);
if (dsa == NULL) {
ssh_set_error(session, SSH_FATAL,
"Parsing private key %s: %s",
filename, ERR_error_string(ERR_get_error(), NULL));
#else
{
#endif
return NULL;
}
@@ -876,19 +905,26 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
if (!valid) {
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
fclose(file);
BIO_free(bio);
if (rsa == NULL) {
ssh_set_error(session, SSH_FATAL,
"Parsing private key %s: %s",
filename, ERR_error_string(ERR_get_error(), NULL));
#else
{
#endif
return NULL;
}
break;
default:
#ifdef HAVE_LIBGCRYPT
fclose(file);
#elif defined HAVE_LIBCRYPTO
BIO_free(bio);
#endif
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
return NULL;
}

View File

@@ -597,7 +597,9 @@ error:
ssh_string_free(n);
return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
}
#endif
#ifdef HAVE_LIBGCRYPT
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
@@ -665,7 +667,9 @@ error:
ssh_string_free(n);
return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
}
#endif
/**
* @brief Convert a public_key object into a a SSH string.

View File

@@ -24,7 +24,9 @@
* compatibility
*/
#include <libssh/libssh.h>
#include "config.h"
#include <libssh/priv.h>
#include <libssh/server.h>
#include <libssh/buffer.h>
@@ -240,4 +242,18 @@ char *string_to_char(ssh_string str){
int ssh_accept(ssh_session session) {
return ssh_handle_key_exchange(session);
}
int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) {
return ssh_channel_write(channel, data, len);
}
/** @deprecated
* @brief Interface previously exported by error.
*/
ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype){
(void) packettype;
ssh_set_error(session, SSH_FATAL, "ssh_message_retrieve: obsolete libssh call");
return NULL;
}
#endif /* WITH_SERVER */

View File

@@ -21,6 +21,8 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
@@ -67,6 +69,51 @@ static ssh_message ssh_message_new(ssh_session session){
return msg;
}
#ifndef WITH_SERVER
/* Reduced version of the reply default that only reply with
* SSH_MSG_UNIMPLEMENTED
*/
static int ssh_message_reply_default(ssh_message msg) {
ssh_log(msg->session, SSH_LOG_FUNCTIONS, "Reporting unknown packet");
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_UNIMPLEMENTED) < 0)
goto error;
if (buffer_add_u32(msg->session->out_buffer,
htonl(msg->session->recv_seq-1)) < 0)
goto error;
return packet_send(msg->session);
error:
return SSH_ERROR;
}
#endif
static int ssh_execute_message_callback(ssh_session session, ssh_message msg) {
int ret;
if(session->ssh_message_callback != NULL) {
ret = session->ssh_message_callback(session, msg,
session->ssh_message_callback_data);
if(ret == 1) {
ret = ssh_message_reply_default(msg);
ssh_message_free(msg);
if(ret != SSH_OK) {
return ret;
}
} else {
ssh_message_free(msg);
}
} else {
ret = ssh_message_reply_default(msg);
ssh_message_free(msg);
if(ret != SSH_OK) {
return ret;
}
}
return SSH_OK;
}
/**
* @internal
*
@@ -77,12 +124,16 @@ static ssh_message ssh_message_new(ssh_session session){
* @param[in] message The message to add to the queue.
*/
void ssh_message_queue(ssh_session session, ssh_message message){
if(message){
if(session->ssh_message_list == NULL){
session->ssh_message_list=ssh_list_new();
if(message) {
if(session->ssh_message_list == NULL) {
if(session->ssh_message_callback != NULL) {
ssh_execute_message_callback(session, message);
return;
}
session->ssh_message_list = ssh_list_new();
}
ssh_list_append(session->ssh_message_list, message);
}
ssh_list_append(session->ssh_message_list, message);
}
}
/**
@@ -130,7 +181,7 @@ ssh_message ssh_message_get(ssh_session session) {
session->ssh_message_list = ssh_list_new();
}
do {
if (ssh_handle_packets(session,-1) == SSH_ERROR) {
if (ssh_handle_packets(session, -2) == SSH_ERROR) {
leave_function();
return NULL;
}

View File

@@ -22,14 +22,22 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#ifndef _WIN32
/* This is needed for a standard getpwuid_r on opensolaris */
#define _POSIX_PTHREAD_SEMANTICS
#include <pwd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include "config.h"
#ifndef HAVE_CLOCK_GETTIME
#include <sys/time.h>
#endif /* HAVE_CLOCK_GETTIME */
#endif /* _WIN32 */
#include <limits.h>
#include <stdio.h>
#include <string.h>
@@ -37,6 +45,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <time.h>
#ifdef _WIN32
@@ -136,7 +145,7 @@ char *ssh_get_local_username(ssh_session session) {
/* get the size */
GetUserName(NULL, &size);
user = malloc(size);
user = (char *) malloc(size);
if (user == NULL) {
ssh_set_error_oom(session);
return NULL;
@@ -148,6 +157,49 @@ char *ssh_get_local_username(ssh_session session) {
return NULL;
}
int ssh_is_ipaddr_v4(const char *str) {
struct sockaddr_storage ss;
int sslen = sizeof(ss);
int rc = SOCKET_ERROR;
/* WSAStringToAddressA thinks that 0.0.0 is a valid IP */
if (strlen(str) < 7) {
return 0;
}
rc = WSAStringToAddressA((LPSTR) str,
AF_INET,
NULL,
(struct sockaddr*)&ss,
&sslen);
if (rc == 0) {
return 1;
}
return 0;
}
int ssh_is_ipaddr(const char *str) {
int rc = SOCKET_ERROR;
if (strchr(str, ':')) {
struct sockaddr_storage ss;
int sslen = sizeof(ss);
/* TODO link-local (IP:v6:addr%ifname). */
rc = WSAStringToAddressA((LPSTR) str,
AF_INET6,
NULL,
(struct sockaddr*)&ss,
&sslen);
if (rc == 0) {
return 1;
}
}
return ssh_is_ipaddr_v4(str);
}
#else /* _WIN32 */
#ifndef NSS_BUFLEN_PASSWD
@@ -163,7 +215,8 @@ char *ssh_get_user_home_dir(void) {
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
return NULL;
szPath=getenv("HOME");
return szPath ? strdup(szPath) : NULL;
}
szPath = strdup(pwd.pw_dir);
@@ -203,20 +256,51 @@ char *ssh_get_local_username(ssh_session session) {
return name;
}
int ssh_is_ipaddr_v4(const char *str) {
int rc = -1;
struct in_addr dest;
rc = inet_pton(AF_INET, str, &dest);
if (rc > 0) {
return 1;
}
return 0;
}
int ssh_is_ipaddr(const char *str) {
int rc = -1;
if (strchr(str, ':')) {
struct in6_addr dest6;
/* TODO link-local (IP:v6:addr%ifname). */
rc = inet_pton(AF_INET6, str, &dest6);
if (rc > 0) {
return 1;
}
}
return ssh_is_ipaddr_v4(str);
}
#endif /* _WIN32 */
#ifndef HAVE_NTOHLL
uint64_t ntohll(uint64_t a) {
#ifdef WORDS_BIGENDIAN
return a;
#else
#else /* WORDS_BIGENDIAN */
uint32_t low = (uint32_t)(a & 0xffffffff);
uint32_t high = (uint32_t)(a >> 32);
low = ntohl(low);
high = ntohl(high);
return ((((uint64_t) low) << 32) | ( high));
#endif
#endif /* WORDS_BIGENDIAN */
}
#endif /* HAVE_NTOHLL */
char *ssh_lowercase(const char* str) {
char *new, *p;
@@ -779,6 +863,99 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
return 0;
}
/* try the Monotonic clock if possible for perfs reasons */
#ifdef _POSIX_MONOTONIC_CLOCK
#define CLOCK CLOCK_MONOTONIC
#else
#define CLOCK CLOCK_REALTIME
#endif
/**
* @internal
* @brief initializes a timestamp to the current time
* @param[out] ts pointer to an allocated ssh_timestamp structure
*/
void ssh_timestamp_init(struct ssh_timestamp *ts){
#ifdef HAVE_CLOCK_GETTIME
struct timespec tp;
clock_gettime(CLOCK, &tp);
ts->useconds = tp.tv_nsec / 1000;
#else
struct timeval tp;
gettimeofday(&tp, NULL);
ts->useconds = tp.tv_usec;
#endif
ts->seconds = tp.tv_sec;
}
#undef CLOCK
/**
* @internal
* @brief gets the time difference between two timestamps in ms
* @param[in] old older value
* @param[in] new newer value
* @returns difference in milliseconds
*/
static int ssh_timestamp_difference(struct ssh_timestamp *old,
struct ssh_timestamp *new){
long seconds, usecs, msecs;
seconds = new->seconds - old->seconds;
usecs = new->useconds - old->useconds;
if (usecs < 0){
seconds--;
usecs += 1000000;
}
msecs = seconds * 1000 + usecs/1000;
return msecs;
}
/**
* @internal
* @brief Checks if a timeout is elapsed, in function of a previous
* timestamp and an assigned timeout
* @param[in] ts pointer to an existing timestamp
* @param[in] timeout timeout in milliseconds. Negative values mean infinite
* timeout
* @returns 1 if timeout is elapsed
* 0 otherwise
*/
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) {
struct ssh_timestamp now;
if(timeout < 0)
return 0; // -1 means infinite timeout
if(timeout == 0)
return 1; // 0 means no timeout
ssh_timestamp_init(&now);
if(ssh_timestamp_difference(ts,&now) >= timeout)
return 1;
else
return 0;
}
/**
* @brief updates a timeout value so it reflects the remaining time
* @param[in] ts pointer to an existing timestamp
* @param[in] timeout timeout in milliseconds. Negative values mean infinite
* timeout
* @returns remaining time in milliseconds, 0 if elapsed, -1 if never,
* -2 if option-set-timeout.
*/
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout){
struct ssh_timestamp now;
int ms, ret;
if (timeout <= 0) {
return timeout;
}
ssh_timestamp_init(&now);
ms = ssh_timestamp_difference(ts,&now);
if(ms < 0)
ms = 0;
ret = timeout - ms;
return ret >= 0 ? ret: 0;
}
/** @} */
/* vim: set ts=4 sw=4 et cindent: */

View File

@@ -255,7 +255,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
"After padding, %d bytes left in buffer",
buffer_get_rest_len(session->in_buffer));
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if (session->current_crypto && session->current_crypto->do_compress_in) {
if (session->current_crypto
&& session->current_crypto->do_compress_in
&& buffer_get_rest_len(session->in_buffer)) {
ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ...");
if (decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN) < 0) {
goto error;
@@ -457,7 +459,9 @@ static int packet_send2(ssh_session session) {
"Writing on the wire a packet having %u bytes before", currentlen);
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if (session->current_crypto && session->current_crypto->do_compress_out) {
if (session->current_crypto
&& session->current_crypto->do_compress_out
&& buffer_get_rest_len(session->out_buffer)) {
ssh_log(session, SSH_LOG_PACKET, "Compressing out_buffer ...");
if (compress_buffer(session,session->out_buffer) < 0) {
goto error;

View File

@@ -125,7 +125,7 @@ struct ssh_pcap_file_struct {
ssh_pcap_file ssh_pcap_file_new(){
struct ssh_pcap_file_struct *pcap;
pcap = malloc(sizeof(struct ssh_pcap_file_struct));
pcap = (struct ssh_pcap_file_struct *) malloc(sizeof(struct ssh_pcap_file_struct));
if (pcap == NULL) {
return NULL;
}
@@ -228,7 +228,7 @@ void ssh_pcap_file_free(ssh_pcap_file pcap){
*/
ssh_pcap_context ssh_pcap_context_new(ssh_session session){
ssh_pcap_context ctx=malloc(sizeof(struct ssh_pcap_context_struct));
ssh_pcap_context ctx = (struct ssh_pcap_context_struct *) malloc(sizeof(struct ssh_pcap_context_struct));
if(ctx==NULL){
ssh_set_error_oom(session);
return NULL;

View File

@@ -105,29 +105,6 @@ static poll_fn ssh_poll_emu;
#include <time.h>
#include <windows.h>
#include <winsock2.h>
#if (_WIN32_WINNT < 0x0600)
typedef struct ssh_pollfd_struct WSAPOLLFD;
#endif
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)((WSAPOLLFD *) fds, nfds, timeout);
}
return SOCKET_ERROR;
}
#define WS2_LIBRARY "ws2_32.dll"
static HINSTANCE hlib;
#else /* _WIN32 */
#include <sys/select.h>
#include <sys/socket.h>
@@ -261,30 +238,10 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
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;
} else {
ssh_poll_emu = win_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) {
@@ -298,8 +255,9 @@ int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
*
* @param fd Socket that will be polled.
* @param events Poll events that will be monitored for the socket. i.e.
* POLLIN, POLLPRI, POLLOUT, POLLERR, POLLHUP, POLLNVAL
* POLLIN, POLLPRI, POLLOUT
* @param cb Function to be called if any of the events are set.
*
* @param userdata Userdata to be passed to the callback function. NULL if
* not needed.
*
@@ -490,8 +448,13 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
socket_t fd = ctx->pollfds[i].fd;
/* force poll object removal */
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) {
used = ctx->polls_used;
if (p->cb && p->cb(p, fd, POLLERR, p->cb_data) < 0) {
if(ctx->polls_used < used) {
used = ctx->polls_used;
} else {
/* nothing to do */
i++;
}
} else {
i++;
}
@@ -622,6 +585,7 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) {
* the poll() function.
* @returns SSH_OK No error.
* SSH_ERROR Error happened during the poll.
* SSH_AGAIN Timeout occured
*/
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
@@ -636,19 +600,24 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
if(rc < 0)
rc=SSH_ERROR;
if(rc <= 0)
return rc;
return SSH_ERROR;
if (rc == 0)
return SSH_AGAIN;
used = ctx->polls_used;
for (i = 0; i < used && rc > 0; ) {
if (!ctx->pollfds[i].revents) {
i++;
} else {
int ret;
p = ctx->pollptrs[i];
fd = ctx->pollfds[i].fd;
revents = ctx->pollfds[i].revents;
if (p->cb(p, fd, revents, p->cb_data) < 0) {
if (p->cb && (ret = p->cb(p, fd, revents, p->cb_data)) < 0) {
if (ret == -2) {
return -1;
}
/* the poll was removed, reload the used counter and start again */
used = ctx->polls_used;
i=0;

View File

@@ -148,7 +148,7 @@ int ssh_scp_close(ssh_scp scp){
*/
while(!ssh_channel_is_eof(scp->channel)){
err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0);
if(err==SSH_ERROR)
if(err==SSH_ERROR || err==0)
break;
}
if(ssh_channel_close(scp->channel) == SSH_ERROR){
@@ -380,8 +380,8 @@ int ssh_scp_response(ssh_scp scp, char **response){
*/
int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
int w;
//int r;
//uint8_t code;
int r;
uint8_t code;
if(scp==NULL)
return SSH_ERROR;
if(scp->state != SSH_SCP_WRITE_WRITING){
@@ -400,19 +400,27 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
//return=channel_get_exit_status(scp->channel);
return SSH_ERROR;
}
/* Far end sometimes send a status message, which we need to read
* and handle */
r = ssh_channel_poll(scp->channel,0);
if(r > 0){
r = ssh_channel_read(scp->channel, &code, 1, 0);
if(r == SSH_ERROR){
return SSH_ERROR;
}
if(code == 1 || code == 2){
ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Error: status code %i received", code);
return SSH_ERROR;
}
}
/* Check if we arrived at end of file */
if(scp->processed == scp->filelen) {
/* r=channel_read(scp->channel,&code,1,0);
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
code = 0;
w = ssh_channel_write(scp->channel, &code, 1);
if(w == SSH_ERROR){
scp->state = SSH_SCP_ERROR;
return SSH_ERROR;
}
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
*/
scp->processed=scp->filelen=0;
scp->state=SSH_SCP_WRITE_INITED;
}

View File

@@ -104,7 +104,7 @@ static int server_set_kex(ssh_session session) {
}
}
server->methods = malloc(10 * sizeof(char **));
server->methods = (char **) malloc(10 * sizeof(char **));
if (server->methods == NULL) {
return -1;
}
@@ -479,8 +479,8 @@ int ssh_handle_key_exchange(ssh_session session) {
* loop until SSH_SESSION_STATE_BANNER_RECEIVED or
* SSH_SESSION_STATE_ERROR
*/
ssh_handle_packets(session,-1);
ssh_log(session,SSH_LOG_PACKET, "ssh_accept: Actual state : %d",
ssh_handle_packets(session, -2);
ssh_log(session,SSH_LOG_PACKET, "ssh_handle_key_exchange: Actual state : %d",
session->session_state);
}
@@ -616,10 +616,13 @@ static int ssh_message_service_request_reply_default(ssh_message msg) {
int ssh_message_service_reply_success(ssh_message msg) {
struct ssh_string_struct *service;
ssh_session session=msg->session;
ssh_session session;
if (msg == NULL) {
return SSH_ERROR;
}
session = msg->session;
ssh_log(session, SSH_LOG_PACKET,
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {

View File

@@ -297,6 +297,40 @@ int ssh_is_blocking(ssh_session session){
return (session->flags&SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
}
/**
* @brief Blocking flush of the outgoing buffer
* @param[in] session The SSH session
* @param[in] timeout Set an upper limit on the time for which this function
* will block, in milliseconds. Specifying a negative value
* means an infinite timeout. This parameter is passed to
* the poll() function.
* @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
* SSH_ERROR otherwise.
*/
int ssh_blocking_flush(ssh_session session, int timeout){
ssh_socket s;
struct ssh_timestamp ts;
int rc = SSH_OK;
if(session==NULL)
return SSH_ERROR;
enter_function();
s=session->socket;
ssh_timestamp_init(&ts);
while (ssh_socket_buffered_write_bytes(s) > 0 && session->alive) {
rc=ssh_handle_packets(session, timeout);
if(ssh_timeout_elapsed(&ts,timeout)){
rc=SSH_AGAIN;
break;
}
timeout = ssh_timeout_update(&ts, timeout);
}
leave_function();
return rc;
}
/**
* @brief Check if we are connected.
*
@@ -370,6 +404,17 @@ void ssh_set_fd_except(ssh_session session) {
ssh_socket_set_except(session->socket);
}
static int ssh_make_milliseconds(long sec, long usec) {
int res = usec ? (usec / 1000) : 0;
res += (sec * 1000);
if (res == 0) {
res = 10 * 1000; /* use a reasonable default value in case
* SSH_OPTIONS_TIMEOUT is not set in options. */
}
return res;
}
/**
* @internal
*
@@ -381,33 +426,56 @@ void ssh_set_fd_except(ssh_session session) {
* @param[in] session The session handle to use.
*
* @param[in] timeout Set an upper limit on the time for which this function
* will block, in milliseconds. Specifying a negative value
* means an infinite timeout. This parameter is passed to
* the poll() function.
* will block, in milliseconds. Specifying -1
* means an infinite timeout.
* Specifying -2 means to use the timeout specified in
* options. 0 means poll will return immediately. This
* parameter is passed to the poll() function.
*
* @return SSH_OK on success, SSH_ERROR otherwise.
*/
int ssh_handle_packets(ssh_session session, int timeout) {
ssh_poll_handle spoll_in,spoll_out;
ssh_poll_ctx ctx;
if(session==NULL || session->socket==NULL)
return SSH_ERROR;
enter_function();
spoll_in=ssh_socket_get_poll_handle_in(session->socket);
spoll_out=ssh_socket_get_poll_handle_out(session->socket);
ctx=ssh_poll_get_ctx(spoll_in);
if(ctx==NULL){
ctx=ssh_poll_get_default_ctx(session);
ssh_poll_ctx_add(ctx,spoll_in);
if(spoll_in != spoll_out)
ssh_poll_ctx_add(ctx,spoll_out);
}
ssh_poll_ctx_dopoll(ctx,timeout);
leave_function();
if (session->session_state != SSH_SESSION_STATE_ERROR)
return SSH_OK;
else
return SSH_ERROR;
ssh_poll_handle spoll_in,spoll_out;
ssh_poll_ctx ctx;
int tm = timeout;
int rc;
if (session == NULL || session->socket == NULL) {
return SSH_ERROR;
}
enter_function();
spoll_in = ssh_socket_get_poll_handle_in(session->socket);
spoll_out = ssh_socket_get_poll_handle_out(session->socket);
if (session->server) {
ssh_poll_add_events(spoll_in, POLLIN);
}
ctx = ssh_poll_get_ctx(spoll_in);
if (!ctx) {
ctx = ssh_poll_get_default_ctx(session);
ssh_poll_ctx_add(ctx, spoll_in);
if (spoll_in != spoll_out) {
ssh_poll_ctx_add(ctx, spoll_out);
}
}
if (timeout == -2) {
tm = ssh_make_milliseconds(session->timeout, session->timeout_usec);
}
rc = ssh_poll_ctx_dopoll(ctx, tm);
if (rc == SSH_ERROR) {
session->session_state = SSH_SESSION_STATE_ERROR;
}
leave_function();
if (session->session_state == SSH_SESSION_STATE_ERROR) {
return SSH_ERROR;
}
return SSH_OK;
}
/**
@@ -432,17 +500,19 @@ int ssh_handle_packets(ssh_session session, int timeout) {
int ssh_handle_packets_termination(ssh_session session, int timeout,
ssh_termination_function fct, void *user){
int ret = SSH_ERROR;
struct ssh_timestamp ts;
ssh_timestamp_init(&ts);
while(!fct(user)){
ret = ssh_handle_packets(session, timeout);
if(ret == SSH_ERROR)
return SSH_ERROR;
if(timeout == 0){
if(fct(user))
return SSH_OK;
else
return SSH_AGAIN;
if(fct(user)) {
return SSH_OK;
} else if (ssh_timeout_elapsed(&ts, timeout)) {
return SSH_AGAIN;
}
/* TODO: verify that total timeout has not expired and then return SSH_AGAIN */
timeout = ssh_timeout_update(&ts,timeout);
}
return ret;
}
@@ -552,6 +622,7 @@ SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){
ssh_socket_close(session->socket);
session->alive = 0;
session->session_state= SSH_SESSION_STATE_ERROR;
/* TODO: handle a graceful disconnect */
return SSH_PACKET_USED;
}

View File

@@ -1817,7 +1817,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
if (ssh_string_len(datastring) > count) {
ssh_set_error(sftp->session, SSH_FATAL,
"Received a too big DATA packet from sftp server: "
"%zu and asked for %zu",
"%" PRIdS " and asked for %" PRIdS,
ssh_string_len(datastring), count);
ssh_string_free(datastring);
return -1;
@@ -1938,7 +1938,7 @@ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){
if (ssh_string_len(datastring) > size) {
ssh_set_error(sftp->session, SSH_FATAL,
"Received a too big DATA packet from sftp server: "
"%zu and asked for %u",
"%" PRIdS " and asked for %u",
ssh_string_len(datastring), size);
ssh_string_free(datastring);
sftp_leave_function();
@@ -2054,6 +2054,7 @@ int sftp_seek(sftp_file file, uint32_t new_offset) {
}
file->offset = new_offset;
file->eof = 0;
return 0;
}
@@ -2064,6 +2065,7 @@ int sftp_seek64(sftp_file file, uint64_t new_offset) {
}
file->offset = new_offset;
file->eof = 0;
return 0;
}
@@ -2080,6 +2082,7 @@ uint64_t sftp_tell64(sftp_file file) {
/* Rewinds the position of the file pointer to the beginning of the file.*/
void sftp_rewind(sftp_file file) {
file->offset = 0;
file->eof = 0;
}
/* code written by Nick */
@@ -2109,10 +2112,12 @@ int sftp_unlink(sftp_session sftp, const char *file) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1;
}
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) {
ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1;
}
ssh_string_free(filename);
ssh_buffer_free(buffer);
@@ -2846,7 +2851,7 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path) {
ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support sftp_statvfs",sftp->version);
return NULL;
}
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);

View File

@@ -37,6 +37,7 @@
#include "libssh/misc.h"
sftp_client_message sftp_get_client_message(sftp_session sftp) {
ssh_session session = sftp->session;
sftp_packet packet;
sftp_client_message msg;
ssh_buffer payload;
@@ -44,12 +45,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
msg = malloc(sizeof (struct sftp_client_message_struct));
if (msg == NULL) {
ssh_set_error_oom(session);
return NULL;
}
ZERO_STRUCTP(msg);
packet = sftp_packet_read(sftp);
if (packet == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -65,6 +68,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_READDIR:
msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -72,6 +76,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_READ:
msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -81,12 +86,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_WRITE:
msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
buffer_get_u64(payload, &msg->offset);
msg->data = buffer_get_ssh_string(payload);
if (msg->data == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -98,12 +105,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_REALPATH:
tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp);
if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -112,17 +121,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_SYMLINK:
tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp);
if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->data = buffer_get_ssh_string(payload);
if (msg->data == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -131,17 +143,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_SETSTAT:
tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->filename=ssh_string_to_char(tmp);
ssh_string_free(tmp);
if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->attr = sftp_parse_attr(sftp, payload, 0);
if (msg->attr == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -149,11 +164,13 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_FSETSTAT:
msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->attr = sftp_parse_attr(sftp, payload, 0);
if (msg->attr == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -162,12 +179,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_STAT:
tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp);
if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
@@ -178,31 +197,38 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_OPEN:
tmp=buffer_get_ssh_string(payload);
if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp);
if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
buffer_get_u32(payload,&msg->flags);
msg->attr = sftp_parse_attr(sftp, payload, 0);
if (msg->attr == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
case SSH_FXP_FSTAT:
msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg);
return NULL;
}
buffer_get_u32(payload, &msg->flags);
break;
default:
fprintf(stderr, "Received unhandled sftp message %d\n", msg->type);
ssh_set_error(sftp->session, SSH_FATAL,
"Received unhandled sftp message %d\n", msg->type);
sftp_client_message_free(msg);
return NULL;
}
msg->flags = ntohl(msg->flags);

View File

@@ -91,6 +91,8 @@ struct ssh_socket_struct {
ssh_poll_handle poll_out;
};
static int sockets_initialized = 0;
static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len);
static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
uint32_t len);
@@ -100,16 +102,20 @@ static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
* \brief inits the socket system (windows specific)
*/
int ssh_socket_init(void) {
if (sockets_initialized == 0) {
#ifdef _WIN32
struct WSAData wsaData;
struct WSAData wsaData;
/* Initiates use of the Winsock DLL by a process. */
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1;
}
/* Initiates use of the Winsock DLL by a process. */
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1;
}
#endif
ssh_poll_init();
ssh_poll_init();
sockets_initialized = 1;
}
return 0;
}
@@ -118,7 +124,13 @@ int ssh_socket_init(void) {
* @brief Cleanup the socket system.
*/
void ssh_socket_cleanup(void) {
if (sockets_initialized == 1) {
ssh_poll_cleanup();
#ifdef _WIN32
WSACleanup();
#endif
sockets_initialized = 0;
}
}
@@ -131,6 +143,7 @@ ssh_socket ssh_socket_new(ssh_session session) {
s = malloc(sizeof(struct ssh_socket_struct));
if (s == NULL) {
ssh_set_error_oom(session);
return NULL;
}
s->fd_in = SSH_INVALID_SOCKET;
@@ -140,11 +153,13 @@ ssh_socket ssh_socket_new(ssh_session session) {
s->session = session;
s->in_buffer = ssh_buffer_new();
if (s->in_buffer == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(s);
return NULL;
}
s->out_buffer=ssh_buffer_new();
if (s->out_buffer == NULL) {
ssh_set_error_oom(session);
ssh_buffer_free(s->in_buffer);
SAFE_FREE(s);
return NULL;
@@ -215,7 +230,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
/* Check if we are in a connecting state */
if(s->state==SSH_SOCKET_CONNECTING){
s->state=SSH_SOCKET_ERROR;
getsockopt(fd,SOL_SOCKET,SO_ERROR,(void *)&err,&errlen);
getsockopt(fd,SOL_SOCKET,SO_ERROR,(char *)&err,&errlen);
s->last_errno=err;
ssh_socket_close(s);
if(s->callbacks && s->callbacks->connected)
@@ -231,20 +246,34 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
s->read_wontblock=1;
r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer));
if(r<0){
if(p != NULL)
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
if(p != NULL) {
ssh_poll_remove_events(p, POLLIN);
}
if(s->callbacks && s->callbacks->exception){
s->callbacks->exception(
SSH_SOCKET_EXCEPTION_ERROR,
s->last_errno,s->callbacks->userdata);
/* p may have been freed, so don't use it
* anymore in this function */
p = NULL;
return -2;
}
}
if(r==0){
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
if(p != NULL) {
ssh_poll_remove_events(p, POLLIN);
}
if(p != NULL) {
ssh_poll_remove_events(p, POLLIN);
}
if(s->callbacks && s->callbacks->exception){
s->callbacks->exception(
SSH_SOCKET_EXCEPTION_EOF,
0,s->callbacks->userdata);
/* p may have been freed, so don't use it
* anymore in this function */
p = NULL;
return -2;
}
}
if(r>0){
@@ -255,6 +284,9 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
buffer_get_rest_len(s->in_buffer),
s->callbacks->userdata);
buffer_pass_bytes(s->in_buffer,r);
/* p may have been freed, so don't use it
* anymore in this function */
p = NULL;
}
}
}
@@ -267,7 +299,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
if(s->state == SSH_SOCKET_CONNECTING){
ssh_log(s->session,SSH_LOG_PACKET,"Received POLLOUT in connecting state");
s->state = SSH_SOCKET_CONNECTED;
ssh_poll_set_events(p,POLLOUT | POLLIN | POLLERR);
ssh_poll_set_events(p,POLLOUT | POLLIN);
ssh_sock_set_blocking(ssh_socket_get_fd_in(s));
if(s->callbacks && s->callbacks->connected)
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
@@ -275,7 +307,9 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
}
/* So, we can write data */
s->write_wontblock=1;
ssh_poll_remove_events(p,POLLOUT);
if(p != NULL) {
ssh_poll_remove_events(p, POLLOUT);
}
/* If buffered data is pending, write it */
if(buffer_get_rest_len(s->out_buffer) > 0){
@@ -340,16 +374,24 @@ int ssh_socket_unix(ssh_socket s, const char *path) {
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == SSH_INVALID_SOCKET) {
ssh_set_error(s->session, SSH_FATAL,
"Error from socket(AF_UNIX, SOCK_STREAM, 0): %s",
strerror(errno));
return -1;
}
if (fcntl(fd, F_SETFD, 1) == -1) {
ssh_set_error(s->session, SSH_FATAL,
"Error from fcntl(fd, F_SETFD, 1): %s",
strerror(errno));
close(fd);
return -1;
}
if (connect(fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) {
ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s",
strerror(errno));
close(fd);
return -1;
}
@@ -544,6 +586,7 @@ int ssh_socket_write(ssh_socket s, const void *buffer, int len) {
enter_function();
if(len > 0) {
if (buffer_add_data(s->out_buffer, buffer, len) < 0) {
ssh_set_error_oom(s->session);
return SSH_ERROR;
}
ssh_socket_nonblocking_flush(s);
@@ -632,6 +675,18 @@ int ssh_socket_data_writable(ssh_socket s) {
return s->write_wontblock;
}
/** @internal
* @brief returns the number of outgoing bytes currently buffered
* @param s the socket
* @returns numbers of bytes buffered, or 0 if the socket isn't connected
*/
int ssh_socket_buffered_write_bytes(ssh_socket s){
if(s==NULL || s->out_buffer == NULL)
return 0;
return buffer_get_rest_len(s->out_buffer);
}
int ssh_socket_get_status(ssh_socket s) {
int r = 0;
@@ -665,8 +720,11 @@ int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bin
socket_t fd;
ssh_session session=s->session;
enter_function();
if(s->state != SSH_SOCKET_NONE)
if(s->state != SSH_SOCKET_NONE) {
ssh_set_error(s->session, SSH_FATAL,
"ssh_socket_connect called on socket not unconnected");
return SSH_ERROR;
}
fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port);
ssh_log(session,SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd);
if(fd == SSH_INVALID_SOCKET)
@@ -744,7 +802,7 @@ int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
s->state=SSH_SOCKET_CONNECTED;
s->fd_is_socket=0;
/* POLLOUT is the event to wait for in a nonblocking connect */
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLIN | POLLERR);
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLIN);
ssh_poll_set_events(ssh_socket_get_poll_handle_out(s),POLLOUT);
if(s->callbacks && s->callbacks->connected)
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);

View File

@@ -21,6 +21,7 @@
* MA 02111-1307, USA.
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -91,8 +92,15 @@ int ssh_string_fill(struct ssh_string_struct *s, const void *data, size_t len) {
* @note The nul byte is not copied nor counted in the ouput string.
*/
struct ssh_string_struct *ssh_string_from_char(const char *what) {
struct ssh_string_struct *ptr = NULL;
size_t len = strlen(what);
struct ssh_string_struct *ptr;
size_t len;
if(what == NULL) {
errno = EINVAL;
return NULL;
}
len = strlen(what);
ptr = malloc(4 + len);
if (ptr == NULL) {
@@ -133,7 +141,7 @@ size_t ssh_string_len(struct ssh_string_struct *s) {
char *ssh_string_to_char(struct ssh_string_struct *s) {
size_t len;
char *new;
if(s==NULL)
if(s==NULL || s->string == NULL)
return NULL;
len = ntohl(s->size) + 1;
new = malloc(len);
@@ -164,7 +172,12 @@ void ssh_string_free_char(char *s) {
* @return Newly allocated copy of the string, NULL on error.
*/
struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) {
struct ssh_string_struct *new = malloc(ntohl(s->size) + 4);
struct ssh_string_struct *new;
if(s == NULL || s->string == NULL) {
return NULL;
}
new = malloc(ntohl(s->size) + 4);
if (new == NULL) {
return NULL;

View File

@@ -92,7 +92,7 @@ static void libcrypto_lock_callback(int mode, int i, const char *file, int line)
}
}
static int libcrypto_thread_init(){
static int libcrypto_thread_init(void){
int n=CRYPTO_num_locks();
int i;
if(user_callbacks == &ssh_threads_noop)
@@ -109,7 +109,7 @@ static int libcrypto_thread_init(){
return SSH_OK;
}
static void libcrypto_thread_finalize(){
static void libcrypto_thread_finalize(void){
int n=CRYPTO_num_locks();
int i;
if (libcrypto_mutexes==NULL)

View File

@@ -86,6 +86,12 @@ install(
if (WITH_STATIC_LIB)
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS})
if (MSVC)
set(OUTPUT_SUFFIX static)
else (MSVC)
set(OUTPUT_SUFFIX )
endif (MSVC)
set_target_properties(
${LIBSSH_THREADS_STATIC_LIBRARY}
PROPERTIES
@@ -93,15 +99,26 @@ if (WITH_STATIC_LIB)
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
COMPILE_FLAGS
"-DLIBSSH_STATIC"
OUTPUT_NAME
ssh_threads
ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
)
if (WIN32)
set_target_properties(
${LIBSSH_THREADS_STATIC_LIBRARY}
PROPERTIES
COMPILE_FLAGS
"-DLIBSSH_STATIC"
)
endif (WIN32)
install(
TARGETS
${LIBSSH_THREADS_STATIC_LIBRARY}
DESTINATION
${LIB_INSTALL_DIR}
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
COMPONENT
libraries
)

View File

@@ -38,6 +38,10 @@
#include <stdio.h>
#include <string.h>
#ifdef WITH_LIBZ
#include <zlib.h>
#endif
#include "libssh/priv.h"
#include "libssh/session.h"
#include "libssh/crypto.h"
@@ -82,7 +86,7 @@ static void cipher_free(struct crypto_struct *cipher) {
}
struct ssh_crypto_struct *crypto_new(void) {
struct ssh_crypto_struct *crypto;
struct ssh_crypto_struct *crypto;
crypto = malloc(sizeof(struct ssh_crypto_struct));
if (crypto == NULL) {
@@ -108,6 +112,18 @@ void crypto_free(struct ssh_crypto_struct *crypto){
bignum_free(crypto->y);
bignum_free(crypto->k);
/* lot of other things */
#ifdef WITH_LIBZ
if (crypto->compress_out_ctx &&
(deflateEnd(crypto->compress_out_ctx) != 0)) {
inflateEnd(crypto->compress_out_ctx);
}
if (crypto->compress_in_ctx &&
(deflateEnd(crypto->compress_in_ctx) != 0)) {
inflateEnd(crypto->compress_in_ctx);
}
#endif
/* i'm lost in my own code. good work */
memset(crypto,0,sizeof(*crypto));
@@ -219,11 +235,15 @@ int crypt_set_algorithms_server(ssh_session session){
int i = 0;
struct crypto_struct *ssh_ciphertab=ssh_get_ciphertab();
if (session == NULL) {
return SSH_ERROR;
}
/* we must scan the kex entries to find crypto algorithms and set their appropriate structure */
enter_function();
/* out */
server = session->server_kex.methods[SSH_CRYPT_S_C];
if(session && session->client_kex.methods) {
if(session->client_kex.methods) {
client = session->client_kex.methods[SSH_CRYPT_S_C];
} else {
ssh_log(session,SSH_LOG_PROTOCOL, "Client KEX empty");

View File

@@ -75,12 +75,12 @@ int benchmarks_ping_latency (const char *host, float *average){
}
if(!found)
goto parseerror;
fclose(fd);
pclose(fd);
return 0;
parseerror:
fprintf(stderr,"Parse error : couldn't locate average in %s",line);
fclose(fd);
pclose(fd);
return -1;
}

View File

@@ -21,13 +21,15 @@
* MA 02111-1307, USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <errno.h>
# include <unistd.h>
#endif
@@ -35,6 +37,7 @@
static int verbosity = 0;
#ifndef _WIN32
static int _torture_auth_kbdint(ssh_session session,
const char *password) {
const char *prompt;
@@ -129,6 +132,7 @@ int torture_rmdirs(const char *path) {
rewinddir(d);
}
} else {
closedir(d);
return -1;
}
@@ -146,10 +150,6 @@ int torture_isdir(const char *path) {
return 0;
}
int torture_libssh_verbosity(void){
return verbosity;
}
ssh_session torture_ssh_session(const char *host,
const char *user,
const char *password) {
@@ -216,6 +216,8 @@ failed:
return NULL;
}
#ifdef WITH_SFTP
struct torture_sftp *torture_sftp_session(ssh_session session) {
struct torture_sftp *t;
char template[] = "/tmp/ssh_torture_XXXXXX";
@@ -258,6 +260,7 @@ failed:
}
ssh_disconnect(t->ssh);
ssh_free(t->ssh);
free(t);
return NULL;
}
@@ -281,6 +284,14 @@ void torture_sftp_close(struct torture_sftp *t) {
free(t->testdir);
free(t);
}
#endif /* WITH_SFTP */
#endif /* _WIN32 */
int torture_libssh_verbosity(void){
return verbosity;
}
int main(int argc, char **argv) {
struct argument_s arguments;

View File

@@ -6,6 +6,7 @@ add_cmockery_test(torture_init torture_init.c ${TORTURE_LIBRARY})
add_cmockery_test(torture_list torture_list.c ${TORTURE_LIBRARY})
add_cmockery_test(torture_misc torture_misc.c ${TORTURE_LIBRARY})
add_cmockery_test(torture_options torture_options.c ${TORTURE_LIBRARY})
add_cmockery_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
if (UNIX AND NOT WIN32)
# requires ssh-keygen
add_cmockery_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})

View File

@@ -0,0 +1,55 @@
#define LIBSSH_STATIC
#include "torture.h"
#include "misc.c"
#include "error.c"
/*
* Test the behavior of ssh_is_ipaddr()
*/
static void torture_ssh_is_ipaddr(void **state) {
(void)state;
assert_int_equal(ssh_is_ipaddr("127.0.0.1"),1);
assert_int_equal(ssh_is_ipaddr("0.0.0.0"),1);
assert_int_equal(ssh_is_ipaddr("1.1.1.1"),1);
assert_int_equal(ssh_is_ipaddr("255.255.255.255"),1);
assert_int_equal(ssh_is_ipaddr("128.128.128.128"),1);
assert_int_equal(ssh_is_ipaddr("1.10.100.1"),1);
assert_int_equal(ssh_is_ipaddr("0.1.10.100"),1);
assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),1);
assert_int_equal(ssh_is_ipaddr("fe80:0000:0000:0000:0202:b3ff:fe1e:8329"),1);
assert_int_equal(ssh_is_ipaddr("fe80:0:0:0:202:b3ff:fe1e:8329"),1);
assert_int_equal(ssh_is_ipaddr("fe80::202:b3ff:fe1e:8329"),1);
assert_int_equal(ssh_is_ipaddr("::1"),1);
assert_int_equal(ssh_is_ipaddr("::ffff:192.0.2.128"),1);
assert_int_equal(ssh_is_ipaddr("0.0.0.0.0"),0);
assert_int_equal(ssh_is_ipaddr("0.0.0.0.a"),0);
assert_int_equal(ssh_is_ipaddr("a.0.0.0"),0);
assert_int_equal(ssh_is_ipaddr("0a.0.0.0.0"),0);
assert_int_equal(ssh_is_ipaddr(""),0);
assert_int_equal(ssh_is_ipaddr("0.0.0."),0);
assert_int_equal(ssh_is_ipaddr("0.0"),0);
assert_int_equal(ssh_is_ipaddr("0"),0);
assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334:1002"), 0);
assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0);
assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0);
assert_int_equal(ssh_is_ipaddr(":1"), 0);
}
int torture_run_tests(void) {
int rc;
const UnitTest tests[] = {
unit_test(torture_ssh_is_ipaddr)
};
ssh_init();
rc=run_tests(tests);
ssh_finalize();
return rc;
}

View File

@@ -11,6 +11,8 @@
#include "torture.h"
#include "misc.c"
#include "error.c"
#define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.."
@@ -159,6 +161,30 @@ static void torture_path_expand_known_hosts(void **state) {
free(tmp);
}
static void torture_timeout_elapsed(void **state){
struct ssh_timestamp ts;
(void) state;
ssh_timestamp_init(&ts);
usleep(50000);
assert_true(ssh_timeout_elapsed(&ts,25));
assert_false(ssh_timeout_elapsed(&ts,30000));
assert_false(ssh_timeout_elapsed(&ts,75));
assert_true(ssh_timeout_elapsed(&ts,0));
assert_false(ssh_timeout_elapsed(&ts,-1));
}
static void torture_timeout_update(void **state){
struct ssh_timestamp ts;
(void) state;
ssh_timestamp_init(&ts);
usleep(50000);
assert_int_equal(ssh_timeout_update(&ts,25), 0);
assert_in_range(ssh_timeout_update(&ts,30000),29000,29960);
assert_in_range(ssh_timeout_update(&ts,75),1,40);
assert_int_equal(ssh_timeout_update(&ts,0),0);
assert_int_equal(ssh_timeout_update(&ts,-1),-1);
}
int torture_run_tests(void) {
int rc;
const UnitTest tests[] = {
@@ -173,6 +199,8 @@ int torture_run_tests(void) {
#endif
unit_test_setup_teardown(torture_path_expand_escape, setup, teardown),
unit_test_setup_teardown(torture_path_expand_known_hosts, setup, teardown),
unit_test(torture_timeout_elapsed),
unit_test(torture_timeout_update),
};
ssh_init();