Compare commits

...

176 Commits

Author SHA1 Message Date
Andreas Schneider
f17788adc2 Update ChangeLog. 2013-07-26 08:42:26 +02:00
Andreas Schneider
23e0053a41 BUG 103: Disable proxy command if set to 'none'.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2013-07-26 08:42:26 +02:00
Andreas Schneider
b6788f369e client: Fix possible NULL pointer dereference. 2013-07-26 08:42:26 +02:00
Andreas Schneider
4cc4236182 kex: Fix a double free. 2013-07-26 08:42:26 +02:00
milo
21a1c51eef Check for NULL pointers in channels.c 2013-07-26 08:42:26 +02:00
Andreas Schneider
d796de288e cmake: Set application version as package version. 2013-07-26 08:42:26 +02:00
Andreas Schneider
7ba381116d BUG 103: Fix ProxyCommand parsing. 2013-06-02 19:33:57 +02:00
Andreas Schneider
6f59c0534d config: Rename ssh_config_get_str(). 2013-06-02 19:33:57 +02:00
Andreas Schneider
494fb26b01 opts: Fix segfault in option parser. 2013-06-02 19:33:57 +02:00
Andreas Schneider
d0f9320602 cmake: Fix setting -D_FORTIFY_SOURCE=2. 2013-06-02 19:33:56 +02:00
Aris Adamantiadis
5826cb6ab2 poll: return error on poll() when pollset is empty
(cherry picked from commit 222a0d78ca)
2013-02-27 08:07:44 +01:00
Andreas Schneider
bbdef245a1 Update version number to 0.5.5. 2013-02-12 14:30:22 +01:00
Laurent Bigonville
a0d894dd2a server: Fix typo in dh_handshake_server().
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2013-02-05 21:16:04 +01:00
Andreas Schneider
05d8421290 Update to version 0.5.4. 2013-01-22 11:52:36 +01:00
Andreas Schneider
55b09f4264 CVE-2013-0176: Fix a remote DoS if the client doesn't send a matching kex.
Thanks to Yong Chuan Koh, X-Force Research <kohyc@sg.ibm.com>
2013-01-14 14:38:55 +01:00
Andreas Schneider
f128338132 options: Fix a free crash bug if we parse unknown options.
Thanks to Yong Chuan Koh, X-Force Research <kohyc@sg.ibm.com>
2013-01-11 08:52:27 +01:00
Andreas Schneider
ba231d0844 channels1: Fix severa possible null pointer dereferences.
(cherry picked from commit b811b89f57)
2013-01-10 13:55:12 +01:00
Andreas Schneider
6da817aa47 Update ChangeLog. 2012-11-14 17:56:48 +01:00
Andreas Schneider
05ed61848f cmake: Bump version number. 2012-11-14 17:11:03 +01:00
Andreas Schneider
d63f19c300 CVE-2012-4561: Fix possible free's on invalid pointers. 2012-11-14 17:11:03 +01:00
Andreas Schneider
455da60846 CVE-2012-4561: Fix error handling of try_publickey_from_file(). 2012-11-14 17:11:03 +01:00
Andreas Schneider
46b2eb3c14 CVE-2012-4559: Make sure we don't free name and longname twice on error. 2012-11-14 17:11:03 +01:00
Andreas Schneider
6236001ff4 CVE-2012-4559: Ensure that we don't free req twice. 2012-11-14 17:11:03 +01:00
Andreas Schneider
1471f2c67a CVE-2012-4559: Ensure we don't free blob or request twice. 2012-11-14 17:11:03 +01:00
Andreas Schneider
b485463197 CVE-2012-4560: Fix a write one past the end of 'buf'. 2012-11-14 17:11:03 +01:00
Andreas Schneider
64fca8a7ed CVE-2012-4560: Fix a write one past the end of the 'u' buffer. 2012-11-14 17:11:03 +01:00
Xi Wang
e3d9501b31 CVE-2012-4562: Fix possible string related integer overflows. 2012-11-14 17:11:00 +01:00
Andreas Schneider
1699adfa03 CVE-2012-4562: Fix a possible infinite loop in buffer_reinit().
If needed is bigger than the highest power of two or a which fits in an
integer we will loop forever.
2012-11-14 17:10:57 +01:00
Xi Wang
db81310d71 CVE-2012-4562: Fix multiple integer overflows in buffer-related functions. 2012-11-14 17:10:53 +01:00
Xi Wang
8489521c0d CVE-2012-4562: Fix possible integer overflow in ssh_get_hexa().
No exploit known, but it is better to check the string length.
2012-11-14 17:10:47 +01:00
Andreas Schneider
2ee6282fdd channels: Fix a possible infinite loop if the connection dropped.
This fixes bug #85.
2012-10-22 18:13:53 +02:00
Andreas Schneider
ae218d0d15 channels1: Add missing request_state and set it to accepted.
This fixes bug #88.
2012-10-22 18:06:12 +02:00
Andreas Schneider
26579b2231 auth1: Reset error state to no error.
This fixes bug #89.
2012-10-22 18:06:09 +02:00
Andreas Schneider
04f1d950b9 session: Fix a possible use after free in ssh_free().
We need to cleanup the channels first cause we call ssh_channel_close()
on the channels which still require a working socket and poll context.

Thanks to sh4rm4!
2012-10-22 17:37:50 +02:00
Andreas Schneider
191c0ae2bb doc: Update copyright policy. 2012-10-14 19:58:26 +02:00
Andreas Schneider
5b32f31a31 channel: Fix a possible null pointer dereference.
(cherry picked from commit ceb8072b34)
2012-10-05 11:48:34 +02:00
Andreas Schneider
3eac8e1c18 channels: Fix a possible null pointer dereference.
(cherry picked from commit 656fd60110)
2012-10-05 11:47:35 +02:00
Andreas Schneider
dc8f0cddee getpass: Fix a memory leak in ssh_gets() on error.
(cherry picked from commit 6092596199)
2012-10-05 11:45:47 +02:00
Andreas Schneider
97b263aee9 sftp: Harden sftp_extension_supported() against null pointers.
(cherry picked from commit 22f607649d)
2012-10-05 11:45:28 +02:00
Andreas Schneider
cb53c4f0e1 sftp: Fix a memory on error in sftp_opendir().
(cherry picked from commit b5c4b090da)
2012-10-05 11:45:12 +02:00
Andreas Schneider
0d029e7038 misc: Don't leak memory on ssh_path_expand_escape() on error.
(cherry picked from commit 61d032fc03)
2012-10-05 11:44:50 +02:00
Andreas Schneider
aae725a44c session: Fix a memory leak in ssh_new() on error.
(cherry picked from commit 280ce3fe93)
2012-10-05 11:44:12 +02:00
Werner Koch
0e833d75e6 Fix regression in pre-connected socket setting.
* src/socket.c (ssh_socket_pollcallback): Factor some code out to ...
(ssh_socket_set_connecting): New.
* include/libssh/socket.h (ssh_socket_set_connecting): Add prototype.
* src/client.c (ssh_connect): Use new function for a socket set by
SSH_OPTIONS_FD.

Signed-off-by: Werner Koch <wk@gnupg.org>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2012-09-21 09:41:47 +02:00
Andreas Schneider
ae83f77511 build: Fix missing struct in_addr warning.
(cherry picked from commit 782b2e37c6)
2012-07-17 18:17:05 +02:00
Andreas Schneider
4d8420f328 sftp: Fix bug in sftp_mkdir not returning on error.
resolves: #84
(cherry picked from commit a92c97b2e1)
2012-07-17 18:13:03 +02:00
Andreas Schneider
d8f2a793d3 connect: Fix a build warning.
(cherry picked from commit 8b8d9dc83a)
2012-07-17 17:34:50 +02:00
rofl0r
558b53a856 session: Cleanup timeout functions and fix packets termination.
It is possible that we get unrelated packets while waiting for
termination, thus waiting indefinitely. As a workaround we have to
check the user-supplied timeout.
Also cleaned up ssh_blocking_flush, which was using the timeout in a
bogus manner (resetting the timeout after each check).
2012-01-02 12:42:47 +01:00
Andreas Schneider
0764adc82f message: Fix compiler warning.
(cherry picked from commit 2f861a858b)
2012-01-02 09:31:59 +01:00
rofl0r
87fd7d617e message: Handle all unknown global messages.
Reply to unknown global messages as required by the RFC. Therefore
keepalive@openssh.com style messages should get treated in a sane way.
2012-01-01 20:54:09 +01:00
Andreas Schneider
3e83af5f5e keyfiles: Fix build errors with callbacks.
Introduced with the last commit.
2011-09-17 22:59:13 +02:00
Aris Adamantiadis
0dc57fdcf1 Fixes the ssh_log issue on ssh_bind handles.
(cherry picked from commit da954c2c5e)

Conflicts:

	src/keyfiles.c
2011-09-17 22:01:43 +02:00
Andreas Schneider
3799670d01 doc: Fix threading documentation.
(cherry picked from commit 2cc95e1e08)
2011-09-17 21:32:43 +02:00
Aris Adamantiadis
d6390d50bf Fix documentation bug about threading
(cherry picked from commit c84380bad5)
2011-09-17 21:22:20 +02:00
Andreas Schneider
e27b31c9c4 build: Increase version number. 2011-09-16 21:56:19 +02:00
Andreas Schneider
684b7f6a57 build: Updated changelog. 2011-09-16 21:54:39 +02:00
Aris Adamantiadis
b0b2fd768c SSH1: handle exit-status message (channels would not close) 2011-09-15 11:25:11 +02:00
Aris Adamantiadis
9180bfffcd channels: don't send SSH2 packets on SSH1 ! 2011-09-15 11:25:00 +02:00
Aris Adamantiadis
058bb0f4ea SSH1: fix build
(cherry picked from commit 3eece8ac0b)

Conflicts:

	src/channels.c
	src/channels1.c
2011-09-02 23:02:27 +02:00
Aris Adamantiadis
64b125700e channels: replaced bugged lists with ssh_list
(cherry picked from commit 6d8bb956c5)

Conflicts:

	src/channels.c
	src/session.c
2011-09-02 22:59:44 +02:00
Aris Adamantiadis
6f650a61ca poll: resolve use-after-free + inconsistent callbacks call
This code was weird in the first place. I suspect my change will break something else
(probably the appcode that needed it). ssh_poll_ctx_free is not a good
place to send exception callbacks imho.
(cherry picked from commit b5351f2809)
2011-09-02 22:49:22 +02:00
Aris Adamantiadis
d4e95f4653 Channels: increase window size x10
Provides me a 3x performance boost for async sftp, 5x for sync sftp
(on localhost)
(cherry picked from commit 17ae216340)
2011-09-02 22:45:54 +02:00
Andreas Schneider
26be91fb8e channels: Fix bug #52.
(cherry picked from commit a2c94abb92)

Conflicts:
    src/channels.c
2011-09-02 22:45:50 +02:00
Aris Adamantiadis
43a3becf08 unittests:make sftp_dir pass on my laptop
(cherry picked from commit 7363b29427)
2011-09-02 22:25:26 +02:00
Aris Adamantiadis
d127d68b9f scp: Fixed documentation bug #9
(cherry picked from commit 99e6fde751)
2011-09-02 22:24:47 +02:00
rofl0r
730da3e3c2 channels: Fix possible infinite loop in channel_read().
(cherry picked from commit 66188f1af8)
2011-08-29 21:48:09 +02:00
Jonas Jonsson
661722753b sftp: Handle short reads of sftp_async_read().
sftp_async_read() and sftp_async_read_begin() assume that the whole read
will be successful but when this is not the case, the offset will be
wrong.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d1df255df4)
2011-08-29 10:07:22 +02:00
Andreas Schneider
ac445a1e18 auth: Handle request service timeout in blocking mode.
(cherry picked from commit e5e673bafe)
2011-08-27 00:00:28 +02:00
Andreas Schneider
b7a3d41baf auth: Fix ssh_auth_list() documentation.
The server will not return SSH_AUTH_METHOD_NONE.
(cherry picked from commit 9c376dd913)
2011-08-22 15:04:09 +02:00
Andreas Schneider
096475b356 channels: Fix incorrect return values in ssh_channel_write().
(cherry picked from commit 13227714f2)
2011-08-10 18:37:58 +02:00
rofl0r
d08554dabd session: Fix an infinite loop in the termination callback.
This happened due to the use of the buggy and obsolete timeout
funtions.
(cherry picked from commit 7949f2cdc6)
2011-08-10 18:37:14 +02:00
Andreas Schneider
cbe8f8b760 channels: Handle SSH_AGAIN in channel_open().
(cherry picked from commit 2f87873642)
2011-08-09 23:08:39 +02:00
Mark Riordan
8987bc53e0 Fix "status -5 inflating zlib packet"
Signed-off-by: Mark Riordan <mriordan@ipswitch.com>
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 6c45d6dc01)
2011-08-09 20:13:41 +02:00
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
76 changed files with 2146 additions and 668 deletions

View File

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

View File

@@ -11,9 +11,9 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
### versions ### versions
set(CPACK_PACKAGE_VERSION_MAJOR "0") set(CPACK_PACKAGE_VERSION_MAJOR "${APPLICATION_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "4") set(CPACK_PACKAGE_VERSION_MINOR "${APPLICATION_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "90") set(CPACK_PACKAGE_VERSION_PATCH "${APPLICATION_VERSION_PATCH}")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")

View File

@@ -1,7 +1,64 @@
ChangeLog ChangeLog
========== ==========
version 0.5.0 (released xxxx-xx-xx) version 0.5.5 (released 2013-07-26)
* BUG 103: Fix ProxyCommand parsing.
* Fix setting -D_FORTIFY_SOURCE=2.
* Fix pollset error return if emtpy.
* Fix NULL pointer checks in channel functions.
* Several bugfixes.
version 0.5.4 (released 2013-01-22)
* CVE-2013-0176 - NULL dereference leads to denial of service
* Fixed several NULL pointer dereferences in SSHv1.
* Fixed a free crash bug in options parsing.
version 0.5.3 (released 2012-11-20)
* CVE-2012-4559 Fixed multiple double free() flaws.
* CVE-2012-4560 Fixed multiple buffer overflow flaws.
* CVE-2012-4561 Fixed multiple invalid free() flaws.
* BUG #84 - Fix bug in sftp_mkdir not returning on error.
* BUG #85 - Fixed a possible channel infinite loop if the connection dropped.
* BUG #88 - Added missing channel request_state and set it to accepted.
* BUG #89 - Reset error state to no error on successful SSHv1 authentiction.
* Fixed a possible use after free in ssh_free().
* Fixed multiple possible NULL pointer dereferences.
* Fixed multiple memory leaks in error paths.
* Fixed timeout handling.
* Fixed regression in pre-connected socket setting.
* Handle all unknown global messages.
version 0.5.2 (released 2011-09-17)
* Increased window size x10.
* Fixed SSHv1.
* Fixed bugged lists.
* Fixed use-after-free + inconsistent callbacks call in poll.
* Fixed scp documentation.
* Fixed possible infinite loop in channel_read().
* Fixed handling of short reads of sftp_async_read().
* Fixed handling request service timeout in blocking mode.
* Fixed ssh_auth_list() documentation.
* Fixed incorrect return values in ssh_channel_write().
* Fixed an infinite loop in the termination callback.
* Fixed handling of SSH_AGAIN in channel_open().
* Fixed "status -5 inflating zlib packet"
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 ssh_ prefix to all functions.
* Added complete Windows support. * Added complete Windows support.
* Added improved server support. * Added improved server support.
@@ -10,6 +67,8 @@ version 0.5.0 (released xxxx-xx-xx)
* Added a multiplatform ssh_getpass() function. * Added a multiplatform ssh_getpass() function.
* Added a tutorial. * Added a tutorial.
* Added a lot of documentation. * Added a lot of documentation.
* Fixed a lot of bugs.
* Fixed several memory leaks.
version 0.4.8 (released 2011-01-15) version 0.4.8 (released 2011-01-15)
* Fixed memory leaks in session signing. * 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 # HEADER FILES
check_include_file(argp.h HAVE_ARGP_H) check_include_file(argp.h HAVE_ARGP_H)
check_include_file(pty.h HAVE_PTY_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) if (WIN32)
check_include_file(wspiapi.h HAVE_WSPIAPI_H) check_include_file(wspiapi.h HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H) if (NOT HAVE_WSPIAPI_H)
@@ -91,23 +92,34 @@ if (UNIX)
if (HAVE_LIBSOCKET) if (HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET) endif (HAVE_LIBSOCKET)
# libresolv # libresolv
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV) check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
if (HAVE_LIBRESOLV) if (HAVE_LIBRESOLV)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
endif (HAVE_LIBRESOLV) 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 # librt
if (HAVE_LIBRT) check_library_exists(rt nanosleep "" HAVE_LIBRT)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT)
endif (NOT LINUX) 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(getaddrinfo HAVE_GETADDRINFO)
check_function_exists(poll HAVE_POLL) check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT) check_function_exists(select HAVE_SELECT)
check_function_exists(cfmakeraw HAVE_CFMAKERAW) check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(regcomp HAVE_REGCOMP) check_function_exists(regcomp HAVE_REGCOMP)
check_function_exists(ntohll HAVE_NTOHLL)
endif (UNIX) endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries") set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")

109
README
View File

@@ -55,17 +55,102 @@ ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
5* Copyright policy 5* Copyright policy
-_-_-_-_-_-_-_-_-_-_ -_-_-_-_-_-_-_-_-_-_
The developers of libssh have a policy of asking for contributions to be made libssh is a project with distributed copyright ownership, which means we prefer
under the personal copyright of the contributor, instead of a corporate the copyright on parts of libssh to be held by individuals rather than
copyright. corporations if possible. There are historical legal reasons for this, but one
of the best ways to explain it is that its much easier to work with
individuals who have ownership than corporate legal departments if we ever need
to make reasonable compromises with people using and working with libssh.
There are some reasons for the establishment of this policy: We track the ownership of every part of libssh via git, our source code control
system, so we know the provenance of every piece of code that is committed to
libssh.
* Individual copyrights make copyright registration in the US a simpler So if possible, if youre doing libssh changes on behalf of a company who
process. normally owns all the work you do please get them to assign personal copyright
* If libssh is copyrighted by individuals rather than corporations, ownership of your changes to you as an individual, that makes things very easy
decisions regarding enforcement and protection of copyright will, more for us to work with and avoids bringing corporate legal departments into the
likely, be made in the interests of the project, and not in the interests picture.
of any corporations shareholders.
* If we ever need to relicense a portion of the code contacting individuals If you cant do this we can still accept patches from you owned by your
for permission to do so is much easier than contacting a company. employer under a standard employment contract with corporate copyright
ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux Kernel
community, so it should be very easy to get a sign off from your corporate
legal department. The only changes weve made are to accommodate the license we
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
--------------------------------------------------------------------------
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of
the License, or (at the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------
We will maintain a copy of that email as a record that you have the rights to
contribute code to libssh under the required licenses whilst working for the
company where the email came from.
Then when sending in a patch via the normal mechanisms described above, add a
line that states:
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name and the email address you sent the original email you used
to send the libssh Developers Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
Thats it! Such code can then quite happily contain changes that have copyright
messages such as:
(c) Example Corporation.
and can be merged into the libssh codebase in the same way as patches from any
other individual. You dont need to send in a copy of the libssh Developers
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once weve received the initial email.
Have fun and happy libssh hacking!
The libssh Team

View File

@@ -25,10 +25,15 @@ if (UNIX AND NOT WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
endif (WITH_STACK_PROTECTOR) endif (WITH_STACK_PROTECTOR)
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE) if (CMAKE_BUILD_TYPE)
if (WITH_FORTIFY_SOURCE) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2") if (NOT CMAKE_BUILD_TYPE_LOWER MATCHES debug)
endif (WITH_FORTIFY_SOURCE) check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
endif (WITH_FORTIFY_SOURCE)
endif()
endif()
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU) endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
# #

View File

@@ -77,6 +77,12 @@
/* Define to 1 if you have the `regcomp' function. */ /* Define to 1 if you have the `regcomp' function. */
#cmakedefine HAVE_REGCOMP 1 #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 ***************************/ /*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */ /* 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), 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. you'll have to jump to the end of this document.
This tutorial describes libssh version 0.5.0. This version is the development This tutorial describes libssh version 0.5.0. This version is a little different
version and is *not* published yet. However, the examples should work with from the 0.4.X series. However, the examples should work with
little changes on versions like 0.4.2 and later. little changes on versions like 0.4.2 and later.

View File

@@ -40,20 +40,105 @@ The libssh library provides:
@section main-copyright Copyright Policy @section main-copyright Copyright Policy
The developers of libssh have a policy of asking for contributions to be made libssh is a project with distributed copyright ownership, which means we prefer
under the personal copyright of the contributor, instead of a corporate the copyright on parts of libssh to be held by individuals rather than
copyright. corporations if possible. There are historical legal reasons for this, but one
of the best ways to explain it is that its much easier to work with
individuals who have ownership than corporate legal departments if we ever need
to make reasonable compromises with people using and working with libssh.
There are some reasons for the establishment of this policy: We track the ownership of every part of libssh via git, our source code control
system, so we know the provenance of every piece of code that is committed to
libssh.
@li Individual copyrights make copyright registration in the US a simpler So if possible, if youre doing libssh changes on behalf of a company who
process. normally owns all the work you do please get them to assign personal copyright
@li If libssh is copyrighted by individuals rather than corporations, ownership of your changes to you as an individual, that makes things very easy
decisions regarding enforcement and protection of copyright will, more for us to work with and avoids bringing corporate legal departments into the
likely, be made in the interests of the project, and not in the interests picture.
of any corporations shareholders.
@li If we ever need to relicense a portion of the code contacting individuals If you cant do this we can still accept patches from you owned by your
for permission to do so is much easier than contacting a company. employer under a standard employment contract with corporate copyright
ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux Kernel
community, so it should be very easy to get a sign off from your corporate
legal department. The only changes weve made are to accommodate the license we
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
@verbatim
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of
the License, or (at the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
@endverbatim
We will maintain a copy of that email as a record that you have the rights to
contribute code to libssh under the required licenses whilst working for the
company where the email came from.
Then when sending in a patch via the normal mechanisms described above, add a
line that states:
@verbatim
Signed-off-by: Random J Developer <random@developer.example.org>
@endverbatim
using your real name and the email address you sent the original email you used
to send the libssh Developers Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
Thats it! Such code can then quite happily contain changes that have copyright
messages such as:
@verbatim
(c) Example Corporation.
@endverbatim
and can be merged into the libssh codebase in the same way as patches from any
other individual. You dont need to send in a copy of the libssh Developers
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once weve received the initial email.
Have fun and happy libssh hacking!
The libssh Team
@section main-rfc Internet standard @section main-rfc Internet standard

View File

@@ -6,16 +6,16 @@ libssh may be used in multithreaded applications, but under several conditions :
- Threading must be initialized during the initialization of libssh. This - Threading must be initialized during the initialization of libssh. This
initialization must be done outside of any threading context. initialization must be done outside of any threading context.
- If pthreads is being used by your application (or your framework's backend), - If pthreads is being used by your application (or your framework's backend),
you must link with libssh_threads_pthread dynamic library and initialize you must link with libssh_threads dynamic library and initialize
threading with the ssh_threads_pthreads threading object. threading with the ssh_threads_pthreads threading object.
- If an other threading library is being used by your application, you must - If an other threading library is being used by your application, you must
implement all the methods of the ssh_threads_callbacks_struct structure implement all the methods of the ssh_threads_callbacks_struct structure
and initialize libssh with it. and initialize libssh with it.
- At all times, you may use different sessions inside threads, make parallel - At all times, you may use different sessions inside threads, make parallel
connections, read/write on different sessions and so on. You can use a connections, read/write on different sessions and so on. You *cannot* use a
single session in several channels at the same time. This will lead to single session (or channels for a single session) in several threads at the same
internal state corruption. This limitation is being worked out and will time. This will most likely lead to internal state corruption. This limitation is
maybe disappear later. being worked out and will maybe disappear later.
@subsection threads_init Initialization of threads @subsection threads_init Initialization of threads
@@ -25,7 +25,7 @@ use, using ssh_threads_set_callbacks(), then call ssh_init().
@code @code
#include <libssh/callbacks.h> #include <libssh/callbacks.h>
... ...
ssh_threads_set_callbacks(ssh_threads_noop); ssh_threads_set_callbacks(ssh_threads_get_noop());
ssh_init(); ssh_init();
@endcode @endcode
@@ -40,14 +40,14 @@ threading backend:
@code @code
#include <libssh/callbacks.h> #include <libssh/callbacks.h>
... ...
ssh_threads_set_callbacks(ssh_threads_pthread); ssh_threads_set_callbacks(ssh_threads_get_pthread());
ssh_init(); ssh_init();
@endcode @endcode
However, you must be sure to link with the library ssh_threads_pthread. If However, you must be sure to link with the library ssh_threads. If
you're using gcc, you must use the commandline you're using gcc, you must use the commandline
@code @code
gcc -o output input.c -lssh -lssh_threads_pthread gcc -o output input.c -lssh -lssh_threads
@endcode @endcode

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,7 @@ program.
#include <libssh/libsshpp.hpp> #include <libssh/libsshpp.hpp>
int main(int argc, const char **argv){ int main(int argc, const char **argv){
ssh::Session session,s2; ssh::Session session;
try { try {
if(argc>1) if(argc>1)
session.setOption(SSH_OPTIONS_HOST,argv[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.setOption(SSH_OPTIONS_HOST,"localhost");
session.connect(); session.connect();
session.userauthAutopubkey(); session.userauthAutopubkey();
session.disconnect();
} catch (ssh::SshException e){ } catch (ssh::SshException e){
std::cout << "Error during connection : "; std::cout << "Error during connection : ";
std::cout << e.getError() << std::endl; std::cout << e.getError() << std::endl;
} }
//s2=session;
return 0; 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 // we already looked for input from stdin. Now, we are looking for input from the channel
if(channel && ssh_channel_is_closed(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); ssh_channel_free(channel);
channel=NULL; channel=NULL;
@@ -261,8 +261,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return; return;
} }
if(lus==0){ if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n"); ssh_log(session,SSH_LOG_RARE,"EOF received");
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); ssh_channel_free(channel);
channel=channels[0]=NULL; channel=channels[0]=NULL;
@@ -280,8 +280,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return; return;
} }
if(lus==0){ if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n"); ssh_log(session,SSH_LOG_RARE,"EOF received");
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); ssh_channel_free(channel);
channel=channels[0]=NULL; channel=channels[0]=NULL;
} else } else
@@ -338,7 +338,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
} }
} }
if(channel && ssh_channel_is_closed(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); ssh_channel_free(channel);
channel=NULL; channel=NULL;
@@ -353,8 +353,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return; return;
} }
if(lus==0){ if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n"); ssh_log(session,SSH_LOG_RARE,"EOF received");
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); ssh_channel_free(channel);
channel=channels[0]=NULL; channel=channels[0]=NULL;
@@ -372,8 +372,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
return; return;
} }
if(lus==0){ if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n"); ssh_log(session,SSH_LOG_RARE,"EOF received");
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); ssh_channel_free(channel);
channel=channels[0]=NULL; channel=channels[0]=NULL;
} else } else
@@ -431,8 +431,11 @@ static void batch_shell(ssh_session session){
ssh_channel channel; ssh_channel channel;
char buffer[1024]; char buffer[1024];
int i,s=0; 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]); s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
free(cmds[i]);
cmds[i] = NULL;
}
channel=ssh_channel_new(session); channel=ssh_channel_new(session);
ssh_channel_open_session(channel); ssh_channel_open_session(channel);
if(ssh_channel_request_exec(channel,buffer)){ 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){ if(ssh_channel_open_session(channel) != SSH_OK){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session)); fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
ssh_channel_free(channel);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){ if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session)); fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_channel_free(channel);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while(!ssh_channel_is_eof(channel)){ while(!ssh_channel_is_eof(channel)){
ssh_channel_read(channel,buffer,1,1); ssh_channel_read(channel,buffer,1,1);
if (write(1,buffer,1) < 0) { if (write(1,buffer,1) < 0) {
fprintf(stderr, "Error writing to buffer\n"); fprintf(stderr, "Error writing to buffer\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return; 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/*"); ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
if(ssh_scp_init(scp) != SSH_OK){ if(ssh_scp_init(scp) != SSH_OK){
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session)); fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
ssh_scp_free(scp);
return -1; return -1;
} }
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n"); 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)); r=ssh_scp_read(scp,buffer,sizeof(buffer));
if(r==SSH_ERROR){ if(r==SSH_ERROR){
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session)); fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1; return -1;
} }
printf("done\n"); printf("done\n");
break; break;
case SSH_ERROR: case SSH_ERROR:
fprintf(stderr,"Error: %s\n",ssh_get_error(session)); fprintf(stderr,"Error: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1; return -1;
case SSH_SCP_REQUEST_WARNING: case SSH_SCP_REQUEST_WARNING:
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp)); fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
@@ -134,6 +144,8 @@ static int fetch_files(ssh_session session){
} }
} while (1); } while (1);
end: end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0; return 0;
} }
@@ -147,6 +159,7 @@ int main(int argc, char **argv){
create_files(session); create_files(session);
fetch_files(session); fetch_files(session);
ssh_disconnect(session); ssh_disconnect(session);
ssh_free(session);
ssh_finalize(); ssh_finalize();
return 0; return 0;
} }

View File

@@ -23,11 +23,10 @@
#define BIND_H_ #define BIND_H_
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/session.h"
struct ssh_bind_struct { struct ssh_bind_struct {
struct error_struct error; struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */
ssh_callbacks callbacks; /* Callbacks to user functions */
struct ssh_bind_callbacks_struct *bind_callbacks; struct ssh_bind_callbacks_struct *bind_callbacks;
void *bind_callbacks_userdata; void *bind_callbacks_userdata;
@@ -40,8 +39,6 @@ struct ssh_bind_struct {
char *bindaddr; char *bindaddr;
socket_t bindfd; socket_t bindfd;
unsigned int bindport; unsigned int bindport;
unsigned int log_verbosity;
int blocking; int blocking;
int toaccept; int toaccept;
}; };

View File

@@ -48,8 +48,6 @@ enum ssh_channel_state_e {
}; };
struct ssh_channel_struct { struct ssh_channel_struct {
struct ssh_channel_struct *prev;
struct ssh_channel_struct *next;
ssh_session session; /* SSH_SESSION pointer */ ssh_session session; /* SSH_SESSION pointer */
uint32_t local_channel; uint32_t local_channel;
uint32_t local_window; uint32_t local_window;
@@ -95,6 +93,7 @@ int channel_write_common(ssh_channel channel, const void *data,
#ifdef WITH_SSH1 #ifdef WITH_SSH1
SSH_PACKET_CALLBACK(ssh_packet_data1); SSH_PACKET_CALLBACK(ssh_packet_data1);
SSH_PACKET_CALLBACK(ssh_packet_close1); SSH_PACKET_CALLBACK(ssh_packet_close1);
SSH_PACKET_CALLBACK(ssh_packet_exist_status1);
/* channels1.c */ /* channels1.c */
int channel_open_session1(ssh_channel channel); int channel_open_session1(ssh_channel channel);
@@ -104,7 +103,7 @@ int channel_change_pty_size1(ssh_channel channel, int cols, int rows);
int channel_request_shell1(ssh_channel channel); int channel_request_shell1(ssh_channel channel);
int channel_request_exec1(ssh_channel channel, const char *cmd); int channel_request_exec1(ssh_channel channel, const char *cmd);
int channel_write1(ssh_channel channel, const void *data, int len); int channel_write1(ssh_channel channel, const void *data, int len);
ssh_channel ssh_get_channel1(ssh_session session);
#endif #endif
#endif /* CHANNELS_H_ */ #endif /* CHANNELS_H_ */

View File

@@ -86,7 +86,7 @@ LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filen
int *type); int *type);
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv); 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_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 void string_burn(ssh_string str);
LIBSSH_API ssh_string string_copy(ssh_string str); LIBSSH_API ssh_string string_copy(ssh_string str);
LIBSSH_API void *string_data(ssh_string str); LIBSSH_API void *string_data(ssh_string str);

View File

@@ -79,7 +79,7 @@
/* libssh version */ /* libssh version */
#define LIBSSH_VERSION_MAJOR 0 #define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 5 #define LIBSSH_VERSION_MINOR 5
#define LIBSSH_VERSION_MICRO 0 #define LIBSSH_VERSION_MICRO 5
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \ #define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \ LIBSSH_VERSION_MINOR, \
@@ -323,6 +323,7 @@ enum ssh_scp_request_types {
SSH_SCP_REQUEST_WARNING 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 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_change_pty_size(ssh_channel channel,int cols,int rows);
LIBSSH_API int ssh_channel_close(ssh_channel channel); 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); timeval * timeout);
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking); 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 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, LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type); 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_tilde(const char *d);
char *ssh_path_expand_escape(ssh_session session, const char *s); 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_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 */ /* macro for byte ordering */
uint64_t ntohll(uint64_t); uint64_t ntohll(uint64_t);
@@ -48,9 +50,15 @@ struct ssh_iterator {
const void *data; const void *data;
}; };
struct ssh_timestamp {
long seconds;
long useconds;
};
struct ssh_list *ssh_list_new(void); struct ssh_list *ssh_list_new(void);
void ssh_list_free(struct ssh_list *list); void ssh_list_free(struct ssh_list *list);
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list); struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
struct ssh_iterator *ssh_list_find(const struct ssh_list *list, void *value);
int ssh_list_append(struct ssh_list *list, const void *data); int ssh_list_append(struct ssh_list *list, const void *data);
int ssh_list_prepend(struct ssh_list *list, const void *data); int ssh_list_prepend(struct ssh_list *list, const void *data);
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator); void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator);
@@ -70,4 +78,9 @@ const void *_ssh_list_pop_head(struct ssh_list *list);
#define ssh_list_pop_head(type, ssh_list)\ #define ssh_list_pop_head(type, ssh_list)\
((type)_ssh_list_pop_head(ssh_list)) ((type)_ssh_list_pop_head(ssh_list))
int ssh_make_milliseconds(long sec, long usec);
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_ */ #endif /* MISC_H_ */

View File

@@ -133,6 +133,7 @@ struct ssh_keys_struct {
}; };
struct ssh_message_struct; struct ssh_message_struct;
struct ssh_common_struct;
/* server data */ /* server data */
@@ -172,8 +173,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_set_default_callbacks(ssh_session session);
void ssh_packet_process(ssh_session session, uint8_t type); void ssh_packet_process(ssh_session session, uint8_t type);
/* connect.c */ /* 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 socket_t ssh_connect_host(ssh_session session, const char *host,const char
*bind_addr, int port, long timeout, long usec); *bind_addr, int port, long timeout, long usec);
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host, socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
@@ -210,6 +209,9 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
int message_handle(ssh_session session, void *user, uint8_t type, ssh_buffer packet); int message_handle(ssh_session session, void *user, uint8_t type, ssh_buffer packet);
/* log.c */ /* log.c */
void ssh_log_common(struct ssh_common_struct *common, int verbosity,
const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
/* misc.c */ /* misc.c */
#ifdef _WIN32 #ifdef _WIN32
int gettimeofday(struct timeval *__p, void *__t); int gettimeofday(struct timeval *__p, void *__t);
@@ -223,16 +225,16 @@ int gettimeofday(struct timeval *__p, void *__t);
#define _enter_function(sess) \ #define _enter_function(sess) \
do {\ do {\
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \ if((sess)->common.log_verbosity >= SSH_LOG_FUNCTIONS){ \
ssh_log((sess),SSH_LOG_FUNCTIONS,"entering function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\ ssh_log((sess),SSH_LOG_FUNCTIONS,"entering function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
(sess)->log_indent++; \ (sess)->common.log_indent++; \
} \ } \
} while(0) } while(0)
#define _leave_function(sess) \ #define _leave_function(sess) \
do { \ do { \
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \ if((sess)->common.log_verbosity >= SSH_LOG_FUNCTIONS){ \
(sess)->log_indent--; \ (sess)->common.log_indent--; \
ssh_log((sess),SSH_LOG_FUNCTIONS,"leaving function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\ ssh_log((sess),SSH_LOG_FUNCTIONS,"leaving function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
}\ }\
} while(0) } while(0)

View File

@@ -87,10 +87,63 @@ LIBSSH_API ssh_bind ssh_bind_new(void);
* *
* @param sshbind The ssh server bind to configure. * @param sshbind The ssh server bind to configure.
* *
* @param type Option to set up. * @param type The option type to set. This could be one of the
* @param value Value to set. * following:
* @returns SSH_OK No error. *
* @returns SSH_ERROR Invalid option or parameter. * - 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, LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
enum ssh_bind_options_e type, const void *value); 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); 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, LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
void *userdata); void *userdata);
@@ -230,6 +303,8 @@ LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
/* deprecated functions */ /* deprecated functions */
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session); 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 #ifdef __cplusplus
} }

View File

@@ -61,8 +61,16 @@ enum ssh_pending_call_e {
/* libssh calls may block an undefined amount of time */ /* libssh calls may block an undefined amount of time */
#define SSH_SESSION_FLAG_BLOCKING 1 #define SSH_SESSION_FLAG_BLOCKING 1
struct ssh_session_struct { /* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct {
struct error_struct error; struct error_struct error;
ssh_callbacks callbacks; /* Callbacks to user functions */
int log_verbosity; /* verbosity of the log functions */
int log_indent; /* indentation level in enter_function logs */
};
struct ssh_session_struct {
struct ssh_common_struct common;
struct ssh_socket_struct *socket; struct ssh_socket_struct *socket;
char *serverbanner; char *serverbanner;
char *clientbanner; char *clientbanner;
@@ -110,7 +118,7 @@ struct ssh_session_struct {
struct ssh_crypto_struct *current_crypto; struct ssh_crypto_struct *current_crypto;
struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
ssh_channel channels; /* linked list of channels */ struct ssh_list *channels; /* linked list of channels */
int maxchannel; int maxchannel;
int exec_channel_opened; /* version 1 only. more int exec_channel_opened; /* version 1 only. more
info in channels1.c */ info in channels1.c */
@@ -128,11 +136,8 @@ struct ssh_session_struct {
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */ struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata); int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
void *ssh_message_callback_data; void *ssh_message_callback_data;
int log_verbosity; /*cached copy of the option structure */
int log_indent; /* indentation level in enter_function logs */
void (*ssh_connection_callback)( struct ssh_session_struct *session); void (*ssh_connection_callback)( struct ssh_session_struct *session);
ssh_callbacks callbacks; /* Callbacks to user functions */
struct ssh_packet_callbacks_struct default_packet_callbacks; struct ssh_packet_callbacks_struct default_packet_callbacks;
struct ssh_list *packet_callbacks; struct ssh_list *packet_callbacks;
struct ssh_socket_callbacks_struct socket_callbacks; struct ssh_socket_callbacks_struct socket_callbacks;

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_read_wontblock(ssh_socket s);
void ssh_socket_set_except(ssh_socket s); void ssh_socket_set_except(ssh_socket s);
int ssh_socket_get_status(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_available(ssh_socket s);
int ssh_socket_data_writable(ssh_socket s); int ssh_socket_data_writable(ssh_socket s);
@@ -61,6 +62,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_in(ssh_socket s); struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_in(ssh_socket s);
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_out(ssh_socket s); struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_out(ssh_socket s);
void ssh_socket_set_connecting(ssh_socket s, socket_t fd);
int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr); int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr);
#endif /* SOCKET_H_ */ #endif /* SOCKET_H_ */

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

View File

@@ -44,6 +44,7 @@
#include <unistd.h> #include <unistd.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -438,6 +439,7 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
} }
ssh_string_free(blob); ssh_string_free(blob);
blob = NULL;
reply = ssh_buffer_new(); reply = ssh_buffer_new();
if (reply == NULL) { if (reply == NULL) {
@@ -450,6 +452,7 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
return NULL; return NULL;
} }
ssh_buffer_free(request); ssh_buffer_free(request);
request = NULL;
/* check if reply is valid */ /* check if reply is valid */
if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) { if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) {

View File

@@ -27,6 +27,7 @@
#include <string.h> #include <string.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -62,23 +63,28 @@
* again is necessary * again is necessary
*/ */
static int ask_userauth(ssh_session session) { static int ask_userauth(ssh_session session) {
int rc = 0; int rc = 0;
enter_function(); enter_function();
do { do {
rc=ssh_service_request(session,"ssh-userauth"); rc = ssh_service_request(session,"ssh-userauth");
if(ssh_is_blocking(session)){ if (ssh_is_blocking(session)) {
if(rc==SSH_AGAIN) if (rc == SSH_AGAIN) {
ssh_handle_packets(session,-1); int err = ssh_handle_packets(session, -2);
} else { if (err != SSH_OK) {
/* nonblocking */ /* error or timeout */
ssh_handle_packets(session,0); return SSH_ERROR;
rc=ssh_service_request(session,"ssh-userauth"); }
break; }
} } else {
} while(rc==SSH_AGAIN); /* nonblocking */
leave_function(); ssh_handle_packets(session, 0);
return rc; rc = ssh_service_request(session, "ssh-userauth");
break;
}
} while (rc == SSH_AGAIN);
leave_function();
return rc;
} }
/** /**
@@ -254,7 +260,7 @@ static int wait_auth_status(ssh_session session) {
enter_function(); enter_function();
if(ssh_is_blocking(session)){ 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){ session) == SSH_ERROR){
leave_function(); leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
@@ -308,8 +314,8 @@ int ssh_auth_list(ssh_session session) {
/** /**
* @brief retrieves available authentication methods for this session * @brief retrieves available authentication methods for this session
* @param[in] session the SSH 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, * @returns A bitfield of values SSH_AUTH_METHOD_PASSWORD,
SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED, SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED,
SSH_AUTH_METHOD_INTERACTIVE. SSH_AUTH_METHOD_INTERACTIVE.
@warning Other reserved flags may appear in future versions. @warning Other reserved flags may appear in future versions.
@@ -345,7 +351,7 @@ int ssh_userauth_list(ssh_session session, const char *username) {
* SSH_AUTH_DENIED: Authentication failed: use another method\n * SSH_AUTH_DENIED: Authentication failed: use another method\n
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still * SSH_AUTH_PARTIAL: You've been partially authenticated, you still
* have to use another method\n * 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 * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
* later. * later.
*/ */
@@ -384,6 +390,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
} }
if (user == NULL) { if (user == NULL) {
ssh_set_error_oom(session);
leave_function(); leave_function();
return rc; return rc;
} }
@@ -415,10 +422,12 @@ int ssh_userauth_none(ssh_session session, const char *username) {
method = ssh_string_from_char("none"); method = ssh_string_from_char("none");
if (method == NULL) { if (method == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
service = ssh_string_from_char("ssh-connection"); service = ssh_string_from_char("ssh-connection");
if (service == NULL) { if (service == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -519,6 +528,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
} }
if (user == NULL) { if (user == NULL) {
ssh_set_error_oom(session);
leave_function(); leave_function();
return rc; return rc;
} }
@@ -531,14 +541,17 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection"); service = ssh_string_from_char("ssh-connection");
if (service == NULL) { if (service == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
method = ssh_string_from_char("publickey"); method = ssh_string_from_char("publickey");
if (method == NULL) { if (method == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
algo = ssh_string_from_char(ssh_type_to_char(type)); algo = ssh_string_from_char(ssh_type_to_char(type));
if (algo == NULL) { if (algo == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -549,6 +562,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
buffer_add_u8(session->out_buffer, 0) < 0 || buffer_add_u8(session->out_buffer, 0) < 0 ||
buffer_add_ssh_string(session->out_buffer, algo) < 0 || buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(session->out_buffer, publickey) < 0) { buffer_add_ssh_string(session->out_buffer, publickey) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -640,6 +654,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
} }
if (user == NULL) { if (user == NULL) {
ssh_set_error_oom(session);
leave_function(); leave_function();
return rc; return rc;
} }
@@ -652,24 +667,32 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection"); service = ssh_string_from_char("ssh-connection");
if (service == NULL) { if (service == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
method = ssh_string_from_char("publickey"); method = ssh_string_from_char("publickey");
if (method == NULL) { if (method == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
algo = ssh_string_from_char(ssh_type_to_char(privatekey->type)); algo = ssh_string_from_char(ssh_type_to_char(privatekey->type));
if (algo == NULL) { if (algo == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
if (publickey == NULL) { if (publickey == NULL) {
pk = publickey_from_privatekey(privatekey); pk = publickey_from_privatekey(privatekey);
if (pk == NULL) { if (pk == NULL) {
/* most likely oom, and publickey_from_privatekey does not
* return any more information */
ssh_set_error_oom(session);
goto error; goto error;
} }
pkstr = publickey_to_string(pk); pkstr = publickey_to_string(pk);
publickey_free(pk); publickey_free(pk);
if (pkstr == NULL) { if (pkstr == NULL) {
/* same as above */
ssh_set_error_oom(session);
goto error; goto error;
} }
} }
@@ -682,6 +705,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
buffer_add_u8(session->out_buffer, 1) < 0 || buffer_add_u8(session->out_buffer, 1) < 0 ||
buffer_add_ssh_string(session->out_buffer, algo) < 0 || buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(session->out_buffer, (publickey == NULL ? pkstr : publickey)) < 0) { buffer_add_ssh_string(session->out_buffer, (publickey == NULL ? pkstr : publickey)) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -694,6 +718,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
sign = ssh_do_sign(session,session->out_buffer, privatekey); sign = ssh_do_sign(session,session->out_buffer, privatekey);
if (sign) { if (sign) {
if (buffer_add_ssh_string(session->out_buffer,sign) < 0) { if (buffer_add_ssh_string(session->out_buffer,sign) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
ssh_string_free(sign); ssh_string_free(sign);
@@ -737,7 +762,9 @@ error:
* SSH_AUTH_DENIED: Authentication failed: use another method.\n * SSH_AUTH_DENIED: Authentication failed: use another method.\n
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still * SSH_AUTH_PARTIAL: You've been partially authenticated, you still
* have to use another method.\n * 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 publickey_from_file()
* @see privatekey_from_file() * @see privatekey_from_file()
@@ -756,6 +783,7 @@ int ssh_userauth_privatekey_file(ssh_session session, const char *username,
pubkeyfile = malloc(strlen(filename) + 1 + 4); pubkeyfile = malloc(strlen(filename) + 1 + 4);
if (pubkeyfile == NULL) { if (pubkeyfile == NULL) {
ssh_set_error_oom(session);
leave_function(); leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} }
@@ -837,6 +865,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
} }
if (user == NULL) { if (user == NULL) {
ssh_set_error_oom(session);
leave_function(); leave_function();
return rc; return rc;
} }
@@ -849,18 +878,22 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection"); service = ssh_string_from_char("ssh-connection");
if (service == NULL) { if (service == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
method = ssh_string_from_char("publickey"); method = ssh_string_from_char("publickey");
if (method == NULL) { if (method == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
algo = ssh_string_from_char(ssh_type_to_char(publickey->type)); algo = ssh_string_from_char(ssh_type_to_char(publickey->type));
if (algo == NULL) { if (algo == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
key = publickey_to_string(publickey); key = publickey_to_string(publickey);
if (key == NULL) { if (key == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -872,6 +905,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
buffer_add_u8(session->out_buffer, 1) < 0 || buffer_add_u8(session->out_buffer, 1) < 0 ||
buffer_add_ssh_string(session->out_buffer, algo) < 0 || buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(session->out_buffer, key) < 0) { buffer_add_ssh_string(session->out_buffer, key) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -879,6 +913,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
if (sign) { if (sign) {
if (buffer_add_ssh_string(session->out_buffer, sign) < 0) { if (buffer_add_ssh_string(session->out_buffer, sign) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
ssh_string_free(sign); ssh_string_free(sign);
@@ -929,7 +964,7 @@ error:
* SSH_AUTH_DENIED: Authentication failed: use another method.\n * SSH_AUTH_DENIED: Authentication failed: use another method.\n
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still * SSH_AUTH_PARTIAL: You've been partially authenticated, you still
* have to use another method.\n * 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 * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
* later. * later.
* *
@@ -968,6 +1003,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
} }
if (user == NULL) { if (user == NULL) {
ssh_set_error_oom(session);
leave_function(); leave_function();
return rc; return rc;
} }
@@ -1000,14 +1036,17 @@ int ssh_userauth_password(ssh_session session, const char *username,
service = ssh_string_from_char("ssh-connection"); service = ssh_string_from_char("ssh-connection");
if (service == NULL) { if (service == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
method = ssh_string_from_char("password"); method = ssh_string_from_char("password");
if (method == NULL) { if (method == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
pwd = ssh_string_from_char(password); pwd = ssh_string_from_char(password);
if (pwd == NULL) { if (pwd == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -1017,6 +1056,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
buffer_add_ssh_string(session->out_buffer, method) < 0 || buffer_add_ssh_string(session->out_buffer, method) < 0 ||
buffer_add_u8(session->out_buffer, 0) < 0 || buffer_add_u8(session->out_buffer, 0) < 0 ||
buffer_add_ssh_string(session->out_buffer, pwd) < 0) { buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -1374,18 +1414,22 @@ static int kbdauth_init(ssh_session session, const char *user,
usr = ssh_string_from_char(user); usr = ssh_string_from_char(user);
if (usr == NULL) { if (usr == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
sub = (submethods ? ssh_string_from_char(submethods) : ssh_string_from_char("")); sub = (submethods ? ssh_string_from_char(submethods) : ssh_string_from_char(""));
if (sub == NULL) { if (sub == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
service = ssh_string_from_char("ssh-connection"); service = ssh_string_from_char("ssh-connection");
if (service == NULL) { if (service == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
method = ssh_string_from_char("keyboard-interactive"); method = ssh_string_from_char("keyboard-interactive");
if (method == NULL) { if (method == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -1395,6 +1439,7 @@ static int kbdauth_init(ssh_session session, const char *user,
buffer_add_ssh_string(session->out_buffer, method) < 0 || buffer_add_ssh_string(session->out_buffer, method) < 0 ||
buffer_add_u32(session->out_buffer, 0) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 ||
buffer_add_ssh_string(session->out_buffer, sub) < 0) { buffer_add_ssh_string(session->out_buffer, sub) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -1562,23 +1607,30 @@ static int kbdauth_send(ssh_session session) {
enter_function(); enter_function();
if(session==NULL || session->kbdint == NULL) {
return rc;
}
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE) < 0 || if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE) < 0 ||
buffer_add_u32(session->out_buffer, buffer_add_u32(session->out_buffer,
htonl(session->kbdint->nprompts)) < 0) { htonl(session->kbdint->nprompts)) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
for (i = 0; i < session->kbdint->nprompts; i++) { 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]); answer = ssh_string_from_char(session->kbdint->answers[i]);
} else { } else {
answer = ssh_string_from_char(""); answer = ssh_string_from_char("");
} }
if (answer == NULL) { if (answer == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
if (buffer_add_ssh_string(session->out_buffer, answer) < 0) { if (buffer_add_ssh_string(session->out_buffer, answer) < 0) {
ssh_set_error_oom(session);
goto error; goto error;
} }
@@ -1622,7 +1674,9 @@ error:
* have to use another method\n * have to use another method\n
* SSH_AUTH_SUCCESS: Authentication success\n * SSH_AUTH_SUCCESS: Authentication success\n
* SSH_AUTH_INFO: The server asked some questions. Use * 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_getnprompts()
* @see ssh_userauth_kbdint_getname() * @see ssh_userauth_kbdint_getname()
@@ -1635,7 +1689,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
int rc = SSH_AUTH_ERROR; int rc = SSH_AUTH_ERROR;
if (session->version == 1) { 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; return SSH_AUTH_DENIED;
} }
@@ -1688,8 +1742,12 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
* @returns The number of prompts. * @returns The number of prompts.
*/ */
int ssh_userauth_kbdint_getnprompts(ssh_session session) { int ssh_userauth_kbdint_getnprompts(ssh_session session) {
if(session==NULL || session->kbdint == NULL) if(session==NULL)
return SSH_ERROR; return SSH_ERROR;
if(session->kbdint == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return SSH_ERROR;
}
return session->kbdint->nprompts; return session->kbdint->nprompts;
} }
@@ -1704,8 +1762,12 @@ int ssh_userauth_kbdint_getnprompts(ssh_session session) {
* @returns The name of the message block. Do not free it. * @returns The name of the message block. Do not free it.
*/ */
const char *ssh_userauth_kbdint_getname(ssh_session session) { const char *ssh_userauth_kbdint_getname(ssh_session session) {
if(session==NULL || session->kbdint == NULL) if(session==NULL)
return NULL; return NULL;
if(session->kbdint == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return NULL;
}
return session->kbdint->name; return session->kbdint->name;
} }
@@ -1721,8 +1783,12 @@ const char *ssh_userauth_kbdint_getname(ssh_session session) {
*/ */
const char *ssh_userauth_kbdint_getinstruction(ssh_session session) { const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
if(session==NULL || session->kbdint == NULL) if(session==NULL)
return NULL; return NULL;
if(session->kbdint == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return NULL;
}
return session->kbdint->instruction; return session->kbdint->instruction;
} }
@@ -1744,9 +1810,14 @@ const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
*/ */
const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i, const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
char *echo) { char *echo) {
if(session==NULL || session->kbdint == NULL) if(session==NULL)
return 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; return NULL;
} }
@@ -1773,14 +1844,18 @@ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
*/ */
int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i, int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
const char *answer) { 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) { i > session->kbdint->nprompts) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1; return -1;
} }
if (session->kbdint->answers == NULL) { if (session->kbdint->answers == NULL) {
session->kbdint->answers = malloc(sizeof(char*) * session->kbdint->nprompts); session->kbdint->answers = malloc(sizeof(char*) * session->kbdint->nprompts);
if (session->kbdint->answers == NULL) { if (session->kbdint->answers == NULL) {
ssh_set_error_oom(session);
return -1; return -1;
} }
memset(session->kbdint->answers, 0, sizeof(char *) * session->kbdint->nprompts); memset(session->kbdint->answers, 0, sizeof(char *) * session->kbdint->nprompts);
@@ -1793,6 +1868,7 @@ int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
session->kbdint->answers[i] = strdup(answer); session->kbdint->answers[i] = strdup(answer);
if (session->kbdint->answers[i] == NULL) { if (session->kbdint->answers[i] == NULL) {
ssh_set_error_oom(session);
return -1; return -1;
} }

View File

@@ -38,7 +38,7 @@ static int wait_auth1_status(ssh_session session) {
enter_function(); enter_function();
/* wait for a packet */ /* wait for a packet */
while(session->auth_state == SSH_AUTH_STATE_NONE) 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; break;
ssh_log(session,SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state); ssh_log(session,SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state);
leave_function(); leave_function();
@@ -108,6 +108,7 @@ static int send_username(ssh_session session, const char *username) {
if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){ if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;
session->auth_state=SSH_AUTH_STATE_SUCCESS; session->auth_state=SSH_AUTH_STATE_SUCCESS;
ssh_set_error(session, SSH_NO_ERROR, "Authentication successful");
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} else { } else {
session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT;

View File

@@ -150,7 +150,7 @@ ssh_bind ssh_bind_new(void) {
ZERO_STRUCTP(ptr); ZERO_STRUCTP(ptr);
ptr->bindfd = SSH_INVALID_SOCKET; ptr->bindfd = SSH_INVALID_SOCKET;
ptr->bindport= 22; ptr->bindport= 22;
ptr->log_verbosity = 0; ptr->common.log_verbosity = 0;
return ptr; return ptr;
} }
@@ -160,6 +160,7 @@ int ssh_bind_listen(ssh_bind sshbind) {
socket_t fd; socket_t fd;
if (ssh_init() < 0) { if (ssh_init() < 0) {
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
return -1; return -1;
} }
@@ -185,28 +186,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
return 0; 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, int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
void *userdata){ 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; return SSH_ERROR;
} }
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){ if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
@@ -373,11 +359,13 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
} }
} }
session->log_verbosity = sshbind->log_verbosity; session->common.log_verbosity = sshbind->common.log_verbosity;
ssh_socket_free(session->socket); ssh_socket_free(session->socket);
session->socket = ssh_socket_new(session); session->socket = ssh_socket_new(session);
if (session->socket == NULL) { 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(dsa);
privatekey_free(rsa); privatekey_free(rsa);
return SSH_ERROR; return SSH_ERROR;
@@ -387,7 +375,7 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
session->dsa_key = dsa; session->dsa_key = dsa;
session->rsa_key = rsa; session->rsa_key = rsa;
return SSH_OK; return SSH_OK;
} }

View File

@@ -21,10 +21,12 @@
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -109,13 +111,18 @@ void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
SAFE_FREE(buffer); SAFE_FREE(buffer);
} }
static int realloc_buffer(struct ssh_buffer_struct *buffer, int needed) { static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
int smallest = 1; size_t smallest = 1;
char *new = NULL; char *new;
buffer_verify(buffer); buffer_verify(buffer);
/* Find the smallest power of two which is greater or equal to needed */ /* Find the smallest power of two which is greater or equal to needed */
while(smallest <= needed) { while(smallest <= needed) {
smallest <<= 1; if (smallest == 0) {
return -1;
}
smallest <<= 1;
} }
needed = smallest; needed = smallest;
new = realloc(buffer->data, needed); new = realloc(buffer->data, needed);
@@ -180,6 +187,10 @@ int buffer_reinit(struct ssh_buffer_struct *buffer) {
*/ */
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) { int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
buffer_verify(buffer); buffer_verify(buffer);
if (buffer->used + len < len)
return -1;
if (buffer->allocated < (buffer->used + len)) { if (buffer->allocated < (buffer->used + len)) {
if(buffer->pos > 0) if(buffer->pos > 0)
buffer_shift(buffer); buffer_shift(buffer);
@@ -318,6 +329,8 @@ int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
return 0; return 0;
} }
/* pos isn't high enough */ /* pos isn't high enough */
if (buffer->used - buffer->pos + len < len)
return -1;
if (buffer->allocated < (buffer->used - buffer->pos + len)) { if (buffer->allocated < (buffer->used - buffer->pos + len)) {
if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) { if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) {
return -1; return -1;
@@ -429,7 +442,7 @@ uint32_t buffer_get_rest_len(struct ssh_buffer_struct *buffer){
*/ */
uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){ uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer); buffer_verify(buffer);
if(buffer->used < buffer->pos+len) if (buffer->pos + len < len || buffer->used < buffer->pos + len)
return 0; return 0;
buffer->pos+=len; buffer->pos+=len;
/* if the buffer is empty after having passed the whole bytes into it, we can clean it */ /* if the buffer is empty after having passed the whole bytes into it, we can clean it */
@@ -454,8 +467,11 @@ uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
*/ */
uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){ uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer); buffer_verify(buffer);
if(buffer->used < buffer->pos + len)
return 0; if (buffer->used < len) {
return 0;
}
buffer->used-=len; buffer->used-=len;
buffer_verify(buffer); buffer_verify(buffer);
return len; return len;
@@ -548,7 +564,7 @@ struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer
} }
hostlen = ntohl(stringlen); hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */ /* verify if there is enough space in buffer to get it */
if ((buffer->pos + hostlen) > buffer->used) { if (buffer->pos + hostlen < hostlen || buffer->pos + hostlen > buffer->used) {
return NULL; /* it is indeed */ return NULL; /* it is indeed */
} }
str = ssh_string_new(hostlen); str = ssh_string_new(hostlen);
@@ -585,7 +601,7 @@ struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
} }
bits = ntohs(bits); bits = ntohs(bits);
len = (bits + 7) / 8; len = (bits + 7) / 8;
if ((buffer->pos + len) > buffer->used) { if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return NULL; return NULL;
} }
str = ssh_string_new(len); str = ssh_string_new(len);

View File

@@ -37,7 +37,7 @@ int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
session->callbacks = cb; session->common.callbacks = cb;
leave_function(); leave_function();
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,7 @@
#include "libssh/packet.h" #include "libssh/packet.h"
#include "libssh/channels.h" #include "libssh/channels.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/misc.h"
#ifdef WITH_SSH1 #ifdef WITH_SSH1
@@ -49,11 +50,17 @@
*/ */
int channel_open_session1(ssh_channel chan) { int channel_open_session1(ssh_channel chan) {
ssh_session session;
if (chan == NULL) {
return -1;
}
session = chan->session;
/* /*
* We guess we are requesting an *exec* channel. It can only have one exec * We guess we are requesting an *exec* channel. It can only have one exec
* channel. So we abort with an error if we need more than one. * channel. So we abort with an error if we need more than one.
*/ */
ssh_session session = chan->session;
if (session->exec_channel_opened) { if (session->exec_channel_opened) {
ssh_set_error(session, SSH_REQUEST_DENIED, ssh_set_error(session, SSH_REQUEST_DENIED,
"SSH1 supports only one execution channel. " "SSH1 supports only one execution channel. "
@@ -61,6 +68,7 @@ int channel_open_session1(ssh_channel chan) {
return -1; return -1;
} }
session->exec_channel_opened = 1; session->exec_channel_opened = 1;
chan->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED;
chan->state = SSH_CHANNEL_STATE_OPEN; chan->state = SSH_CHANNEL_STATE_OPEN;
chan->local_maxpacket = 32000; chan->local_maxpacket = 32000;
chan->local_window = 64000; chan->local_window = 64000;
@@ -83,8 +91,14 @@ int channel_open_session1(ssh_channel chan) {
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col, int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col,
int row) { int row) {
ssh_session session = channel->session; ssh_session session;
ssh_string str = NULL; ssh_string str = NULL;
if (channel == NULL) {
return SSH_ERROR;
}
session = channel->session;
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){ if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state"); ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
return SSH_ERROR; return SSH_ERROR;
@@ -137,7 +151,13 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col
} }
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) { int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
ssh_session session = channel->session; ssh_session session;
if (channel == NULL) {
return SSH_ERROR;
}
session = channel->session;
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){ if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state"); ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
return SSH_ERROR; return SSH_ERROR;
@@ -180,7 +200,12 @@ int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
} }
int channel_request_shell1(ssh_channel channel) { int channel_request_shell1(ssh_channel channel) {
ssh_session session = channel->session; ssh_session session;
if (channel == NULL) {
return -1;
}
session = channel->session;
if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) { if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) {
return -1; return -1;
@@ -196,9 +221,14 @@ int channel_request_shell1(ssh_channel channel) {
} }
int channel_request_exec1(ssh_channel channel, const char *cmd) { int channel_request_exec1(ssh_channel channel, const char *cmd) {
ssh_session session = channel->session; ssh_session session;
ssh_string command = NULL; ssh_string command = NULL;
if (channel == NULL) {
return -1;
}
session = channel->session;
command = ssh_string_from_char(cmd); command = ssh_string_from_char(cmd);
if (command == NULL) { if (command == NULL) {
return -1; return -1;
@@ -221,10 +251,15 @@ int channel_request_exec1(ssh_channel channel, const char *cmd) {
} }
SSH_PACKET_CALLBACK(ssh_packet_data1){ SSH_PACKET_CALLBACK(ssh_packet_data1){
ssh_channel channel = session->channels; ssh_channel channel = ssh_get_channel1(session);
ssh_string str = NULL; ssh_string str = NULL;
int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1); int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1);
(void)user; (void)user;
if (channel == NULL) {
return SSH_PACKET_NOT_USED;
}
str = buffer_get_ssh_string(packet); str = buffer_get_ssh_string(packet);
if (str == NULL) { if (str == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n"); ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n");
@@ -232,7 +267,7 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
} }
ssh_log(session, SSH_LOG_PROTOCOL, ssh_log(session, SSH_LOG_PROTOCOL,
"Adding %zu bytes data in %d", "Adding %" PRIdS " bytes data in %d",
ssh_string_len(str), is_stderr); ssh_string_len(str), is_stderr);
if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str), if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str),
@@ -246,10 +281,16 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
} }
SSH_PACKET_CALLBACK(ssh_packet_close1){ SSH_PACKET_CALLBACK(ssh_packet_close1){
ssh_channel channel = session->channels; ssh_channel channel = ssh_get_channel1(session);
uint32_t status; uint32_t status;
(void)type; (void)type;
(void)user; (void)user;
if (channel == NULL) {
return SSH_PACKET_NOT_USED;
}
buffer_get_u32(packet, &status); buffer_get_u32(packet, &status);
/* /*
* It's much more than a channel closing. spec says it's the last * It's much more than a channel closing. spec says it's the last
@@ -266,12 +307,36 @@ SSH_PACKET_CALLBACK(ssh_packet_close1){
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }
SSH_PACKET_CALLBACK(ssh_packet_exist_status1){
ssh_channel channel = ssh_get_channel1(session);
uint32_t status;
(void)type;
(void)user;
if (channel == NULL) {
return SSH_PACKET_NOT_USED;
}
buffer_get_u32(packet, &status);
channel->state = SSH_CHANNEL_STATE_CLOSED;
channel->remote_eof = 1;
channel->exit_status = ntohl(status);
return SSH_PACKET_USED;
}
int channel_write1(ssh_channel channel, const void *data, int len) { int channel_write1(ssh_channel channel, const void *data, int len) {
ssh_session session = channel->session; ssh_session session;
int origlen = len; int origlen = len;
int effectivelen; int effectivelen;
const unsigned char *ptr=data; const unsigned char *ptr=data;
if (channel == NULL) {
return -1;
}
session = channel->session;
while (len > 0) { while (len > 0) {
if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) { if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) {
return -1; return -1;
@@ -295,5 +360,20 @@ int channel_write1(ssh_channel channel, const void *data, int len) {
return origlen; return origlen;
} }
ssh_channel ssh_get_channel1(ssh_session session){
struct ssh_iterator *it;
if (session == NULL) {
return NULL;
}
/* With SSH1, the channel is always the first one */
if(session->channels != NULL){
it = ssh_list_get_iterator(session->channels);
if(it)
return ssh_iterator_value(ssh_channel, it);
}
return NULL;
}
#endif /* WITH_SSH1 */ #endif /* WITH_SSH1 */
/* vim: set ts=2 sw=2 et cindent: */ /* vim: set ts=2 sw=2 et cindent: */

View File

@@ -26,6 +26,7 @@
#include <string.h> #include <string.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -40,8 +41,8 @@
#include "libssh/misc.h" #include "libssh/misc.h"
#define set_status(session, status) do {\ #define set_status(session, status) do {\
if (session->callbacks && session->callbacks->connect_status_function) \ if (session->common.callbacks && session->common.callbacks->connect_status_function) \
session->callbacks->connect_status_function(session->callbacks->userdata, status); \ session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \
} while (0) } while (0)
/** /**
@@ -664,7 +665,7 @@ int ssh_connect(ssh_session session) {
session->socket_callbacks.exception=ssh_socket_exception_callback; session->socket_callbacks.exception=ssh_socket_exception_callback;
session->socket_callbacks.userdata=session; session->socket_callbacks.userdata=session;
if (session->fd != SSH_INVALID_SOCKET) { if (session->fd != SSH_INVALID_SOCKET) {
ssh_socket_set_fd(session->socket, session->fd); ssh_socket_set_connecting(session->socket, session->fd);
ret=SSH_OK; ret=SSH_OK;
#ifndef _WIN32 #ifndef _WIN32
} else if (session->ProxyCommand != NULL){ } else if (session->ProxyCommand != NULL){
@@ -673,8 +674,6 @@ int ssh_connect(ssh_session session) {
} else { } else {
ret=ssh_socket_connect(session->socket, session->host, session->port, ret=ssh_socket_connect(session->socket, session->host, session->port,
session->bindaddr); session->bindaddr);
/*, session->timeout * 1000 + session->timeout_usec); */
} }
if (ret == SSH_ERROR) { if (ret == SSH_ERROR) {
leave_function(); leave_function();
@@ -686,11 +685,21 @@ int ssh_connect(ssh_session session) {
session->alive = 1; session->alive = 1;
ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work"); ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
pending: pending:
session->pending_call_state=SSH_PENDING_CALL_CONNECT; session->pending_call_state=SSH_PENDING_CALL_CONNECT;
if(ssh_is_blocking(session)) if(ssh_is_blocking(session)) {
ssh_handle_packets_termination(session,-1,ssh_connect_termination,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 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); ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){ if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
leave_function(); leave_function();
@@ -747,6 +756,7 @@ int ssh_get_openssh_version(ssh_session session) {
*/ */
void ssh_disconnect(ssh_session session) { void ssh_disconnect(ssh_session session) {
ssh_string str = NULL; ssh_string str = NULL;
struct ssh_iterator *it;
int i; int i;
if (session == NULL) { if (session == NULL) {
@@ -755,7 +765,7 @@ void ssh_disconnect(ssh_session session) {
enter_function(); enter_function();
if (ssh_socket_is_open(session->socket)) { if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) { if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
goto error; goto error;
} }
@@ -780,13 +790,15 @@ void ssh_disconnect(ssh_session session) {
} }
error: error:
session->alive = 0; session->alive = 0;
if(session->socket){ if (session->socket != NULL){
ssh_socket_reset(session->socket); ssh_socket_reset(session->socket);
} }
session->fd = SSH_INVALID_SOCKET; session->fd = SSH_INVALID_SOCKET;
session->session_state=SSH_SESSION_STATE_DISCONNECTED; session->session_state=SSH_SESSION_STATE_DISCONNECTED;
while (session->channels) {
ssh_channel_free(session->channels); while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
ssh_channel_free(ssh_iterator_value(ssh_channel,it));
ssh_list_remove(session->channels, it);
} }
if(session->current_crypto){ if(session->current_crypto){
crypto_free(session->current_crypto); crypto_free(session->current_crypto);

View File

@@ -78,7 +78,7 @@ static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
return SOC_UNSUPPORTED; return SOC_UNSUPPORTED;
} }
static char *ssh_config_get_token(char **str) { static char *ssh_config_get_cmd(char **str) {
register char *c; register char *c;
char *r; char *r;
@@ -98,6 +98,25 @@ static char *ssh_config_get_token(char **str) {
} }
} }
for (r = c; *c; c++) {
if (*c == '\n') {
*c = '\0';
goto out;
}
}
out:
*str = c + 1;
return r;
}
static char *ssh_config_get_token(char **str) {
register char *c;
char *r;
c = ssh_config_get_cmd(str);
for (r = c; *c; c++) { for (r = c; *c; c++) {
if (isblank(*c)) { if (isblank(*c)) {
*c = '\0'; *c = '\0';
@@ -127,7 +146,7 @@ static int ssh_config_get_int(char **str, int notfound) {
return notfound; return notfound;
} }
static const char *ssh_config_get_str(char **str, const char *def) { static const char *ssh_config_get_str_tok(char **str, const char *def) {
char *p; char *p;
p = ssh_config_get_token(str); p = ssh_config_get_token(str);
@@ -141,7 +160,7 @@ static const char *ssh_config_get_str(char **str, const char *def) {
static int ssh_config_get_yesno(char **str, int notfound) { static int ssh_config_get_yesno(char **str, int notfound) {
const char *p; const char *p;
p = ssh_config_get_str(str, NULL); p = ssh_config_get_str_tok(str, NULL);
if (p == NULL) { if (p == NULL) {
return notfound; return notfound;
} }
@@ -192,8 +211,8 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
case SOC_HOST: case SOC_HOST:
*parsing = 0; *parsing = 0;
lowerhost = (session->host) ? ssh_lowercase(session->host) : NULL; lowerhost = (session->host) ? ssh_lowercase(session->host) : NULL;
for (p = ssh_config_get_str(&s, NULL); p && *p; for (p = ssh_config_get_str_tok(&s, NULL); p && *p;
p = ssh_config_get_str(&s, NULL)) { p = ssh_config_get_str_tok(&s, NULL)) {
if (match_hostname(lowerhost, p, strlen(p))) { if (match_hostname(lowerhost, p, strlen(p))) {
*parsing = 1; *parsing = 1;
} }
@@ -201,14 +220,14 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
SAFE_FREE(lowerhost); SAFE_FREE(lowerhost);
break; break;
case SOC_HOSTNAME: case SOC_HOSTNAME:
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_HOST, p); ssh_options_set(session, SSH_OPTIONS_HOST, p);
} }
break; break;
case SOC_PORT: case SOC_PORT:
if (session->port == 22) { if (session->port == 22) {
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p); ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
} }
@@ -216,20 +235,20 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
break; break;
case SOC_USERNAME: case SOC_USERNAME:
if (session->username == NULL) { if (session->username == NULL) {
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_USER, p); ssh_options_set(session, SSH_OPTIONS_USER, p);
} }
} }
break; break;
case SOC_IDENTITY: case SOC_IDENTITY:
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p); ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
} }
break; break;
case SOC_CIPHERS: case SOC_CIPHERS:
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p); ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p);
ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p); ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p);
@@ -246,7 +265,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
} }
break; break;
case SOC_PROTOCOL: case SOC_PROTOCOL:
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
char *a, *b; char *a, *b;
b = strdup(p); b = strdup(p);
@@ -289,13 +308,13 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
} }
break; break;
case SOC_KNOWNHOSTS: case SOC_KNOWNHOSTS:
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, p); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, p);
} }
break; break;
case SOC_PROXYCOMMAND: case SOC_PROXYCOMMAND:
p = ssh_config_get_str(&s, NULL); p = ssh_config_get_cmd(&s);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p); ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
} }
@@ -327,9 +346,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
return 0; return 0;
} }
if (session->log_verbosity) { ssh_log(session, SSH_LOG_RARE, "Reading configuration data from %s", filename);
fprintf(stderr, "Reading configuration data from %s\n", filename);
}
parsing = 1; parsing = 1;
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {

View File

@@ -21,12 +21,17 @@
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include "config.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "libssh/libssh.h"
#include "libssh/misc.h"
#ifdef _WIN32 #ifdef _WIN32
/* /*
* Only use Windows API functions available on Windows 2000 SP4 or later. * Only use Windows API functions available on Windows 2000 SP4 or later.
@@ -78,14 +83,6 @@
#error "Your system must have getaddrinfo()" #error "Your system must have getaddrinfo()"
#endif #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 #ifdef _WIN32
void ssh_sock_set_nonblocking(socket_t sock) { void ssh_sock_set_nonblocking(socket_t sock) {
u_long nonblocking = 1; u_long nonblocking = 1;
@@ -118,53 +115,6 @@ void ssh_sock_set_blocking(socket_t sock) {
#endif /* _WIN32 */ #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){ static int ssh_connect_socket_close(socket_t s){
#ifdef _WIN32 #ifdef _WIN32
return closesocket(s); 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; hints.ai_flags=AI_NUMERICSERV;
#endif #endif
} }
#ifdef HAVE_REGCOMP
if(regexec(ip_regex,host,0,NULL,0) == 0){ if (ssh_is_ipaddr(host)) {
/* this is an IP address */ /* this is an IP address */
ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host); ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
hints.ai_flags |= AI_NUMERICHOST; hints.ai_flags |= AI_NUMERICHOST;
} }
#endif
return getaddrinfo(host, service, &hints, ai); return getaddrinfo(host, service, &hints, ai);
} }
@@ -209,7 +159,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
int timeout_ms; int timeout_ms;
ssh_pollfd_t fds; ssh_pollfd_t fds;
int rc = 0; int rc = 0;
unsigned int len = sizeof(rc); socklen_t len = sizeof(rc);
enter_function(); enter_function();
@@ -472,7 +422,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
* *
* @param[in] timeout A timeout for the select. * @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. * that case, just restart it.
* *
* @warning libssh is not threadsafe here. That means that if a signal is caught * @warning libssh is not threadsafe here. That means that if a signal is caught

View File

@@ -27,6 +27,7 @@
#include <string.h> #include <string.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif

View File

@@ -44,8 +44,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -140,6 +142,7 @@ int ssh_crypto_init(void) {
} }
bignum_bin2bn(p_value, P_LEN, p); bignum_bin2bn(p_value, P_LEN, p);
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
#endif #endif
ssh_crypto_initialized = 1; ssh_crypto_initialized = 1;
@@ -154,8 +157,13 @@ void ssh_crypto_finalize(void) {
g = NULL; g = NULL;
bignum_free(p); bignum_free(p);
p = NULL; 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; ssh_crypto_initialized=0;
} }
} }
@@ -187,6 +195,9 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
char *hexa = NULL; char *hexa = NULL;
size_t i; size_t i;
if (len > (UINT_MAX - 1) / 3)
return NULL;
hexa = malloc(len * 3 + 1); hexa = malloc(len * 3 + 1);
if (hexa == NULL) { if (hexa == NULL) {
return NULL; return NULL;

View File

@@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/session.h"
/** /**
* @defgroup libssh_error The SSH error functions. * @defgroup libssh_error The SSH error functions.
@@ -48,13 +49,13 @@
* @param ... The arguments for the format string. * @param ... The arguments for the format string.
*/ */
void ssh_set_error(void *error, int code, const char *descr, ...) { void ssh_set_error(void *error, int code, const char *descr, ...) {
struct error_struct *err = error; struct ssh_common_struct *err = error;
va_list va; va_list va;
va_start(va, descr); va_start(va, descr);
vsnprintf(err->error_buffer, ERROR_BUFFERLEN, descr, va); vsnprintf(err->error.error_buffer, ERROR_BUFFERLEN, descr, va);
va_end(va); va_end(va);
err->error_code = code; err->error.error_code = code;
ssh_log(error,SSH_LOG_RARE,"Error : %s",err->error_buffer); ssh_log_common(err,SSH_LOG_RARE,"Error : %s",err->error.error_buffer);
} }
/** /**

View File

@@ -61,6 +61,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
} }
fflush(stdout); fflush(stdout);
if (fgets(tmp, len, stdin) == NULL) { if (fgets(tmp, len, stdin) == NULL) {
free(tmp);
return 0; return 0;
} }

View File

@@ -173,7 +173,7 @@ static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t
do { do {
zin->avail_out = BLOCKSIZE; zin->avail_out = BLOCKSIZE;
status = inflate(zin, Z_PARTIAL_FLUSH); status = inflate(zin, Z_PARTIAL_FLUSH);
if (status != Z_OK) { if (status != Z_OK && status != Z_BUF_ERROR) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"status %d inflating zlib packet", status); "status %d inflating zlib packet", status);
ssh_buffer_free(dest); ssh_buffer_free(dest);

View File

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

View File

@@ -432,6 +432,7 @@ int ssh_send_kex(ssh_session session, int server_kex) {
goto error; goto error;
} }
ssh_string_free(str); ssh_string_free(str);
str = NULL;
} }
if (buffer_add_u8(session->out_buffer, 0) < 0) { if (buffer_add_u8(session->out_buffer, 0) < 0) {
@@ -761,7 +762,7 @@ SSH_PACKET_CALLBACK(ssh_packet_publickey1){
} }
bits = ssh_string_len(enc_session) * 8 - 7; 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, ssh_string_len(enc_session));
bits = htons(bits); bits = htons(bits);
/* the encrypted mpint */ /* the encrypted mpint */
@@ -814,14 +815,14 @@ int ssh_get_kex1(ssh_session session) {
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
/* Here the callback is called */ /* Here the callback is called */
while(session->session_state==SSH_SESSION_STATE_INITIAL_KEX){ 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) if(session->session_state==SSH_SESSION_STATE_ERROR)
goto error; goto error;
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS"); ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS");
/* Waiting for SSH_SMSG_SUCCESS */ /* Waiting for SSH_SMSG_SUCCESS */
while(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){ 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) if(session->session_state==SSH_SESSION_STATE_ERROR)
goto error; goto error;

View File

@@ -610,9 +610,9 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
ssh_log(session, SSH_LOG_RARE, ssh_log(session, SSH_LOG_RARE,
"Trying to call external authentication function"); "Trying to call external authentication function");
if (session && session->callbacks && session->callbacks->auth_function) { if (session && session->common.callbacks && session->common.callbacks->auth_function) {
if (session->callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0, if (session->common.callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0,
session->callbacks->userdata) < 0) { session->common.callbacks->userdata) < 0) {
return 0; return 0;
} }
@@ -677,11 +677,15 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
DSA *dsa = NULL; DSA *dsa = NULL;
RSA *rsa = NULL; RSA *rsa = NULL;
BIO *bio = NULL;
#endif #endif
/* TODO Implement to read both DSA and RSA at once. */ /* TODO Implement to read both DSA and RSA at once. */
/* needed for openssl initialization */ /* needed for openssl initialization */
ssh_init(); if (ssh_init() < 0) {
return NULL;
}
ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename); ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
file = fopen(filename,"r"); file = fopen(filename,"r");
if (file == NULL) { if (file == NULL) {
@@ -690,9 +694,18 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
return NULL; 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", ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
filename, passphrase ? "true" : "false", filename, passphrase ? "true" : "false",
session->callbacks && session->callbacks->auth_function ? "true" : "false"); session->common.callbacks && session->common.callbacks->auth_function ? "true" : "false");
if (type == 0) { if (type == 0) {
type = privatekey_type_from_file(file); type = privatekey_type_from_file(file);
@@ -706,9 +719,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:
if (passphrase == NULL) { if (passphrase == NULL) {
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
if (session->callbacks && session->callbacks->auth_function) { if (session->common.callbacks && session->common.callbacks->auth_function) {
auth_cb = session->callbacks->auth_function; auth_cb = session->common.callbacks->auth_function;
auth_ud = session->callbacks->userdata; auth_ud = session->common.callbacks->userdata;
valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud, valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud,
"Passphrase for private key:"); "Passphrase for private key:");
@@ -725,16 +738,17 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
if (!valid) { if (!valid) {
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename); ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
if (session->callbacks && session->callbacks->auth_function) { if (session->common.callbacks && session->common.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 */ } else { /* authcb */
/* openssl uses its own callback to get the passphrase here */ /* 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 */ } /* authcb */
} else { /* passphrase */ } 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); fclose(file);
if (dsa == NULL) { if (dsa == NULL) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
@@ -747,9 +761,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA:
if (passphrase == NULL) { if (passphrase == NULL) {
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
if (session->callbacks && session->callbacks->auth_function) { if (session->common.callbacks && session->common.callbacks->auth_function) {
auth_cb = session->callbacks->auth_function; auth_cb = session->common.callbacks->auth_function;
auth_ud = session->callbacks->userdata; auth_ud = session->common.callbacks->userdata;
valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud, valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud,
"Passphrase for private key:"); "Passphrase for private key:");
} else { /* authcb */ } else { /* authcb */
@@ -765,16 +779,17 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
if (!valid) { if (!valid) {
ssh_set_error(session,SSH_FATAL, "Parsing private key %s", filename); ssh_set_error(session,SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
if (session->callbacks && session->callbacks->auth_function) { if (session->common.callbacks && session->common.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 */ } else { /* authcb */
/* openssl uses its own callback to get the passphrase here */ /* 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 */ } /* authcb */
} else { /* passphrase */ } 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); fclose(file);
if (rsa == NULL) { if (rsa == NULL) {
@@ -786,6 +801,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
} }
break; break;
default: default:
#ifdef HAVE_LIBCRYPTO
BIO_free(bio);
#endif
fclose(file); fclose(file);
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type); ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
return NULL; 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, ssh_private_key _privatekey_from_file(void *session, const char *filename,
int type) { int type) {
ssh_private_key privkey = NULL; ssh_private_key privkey = NULL;
FILE *file = NULL;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
FILE *file = NULL;
gcry_sexp_t dsa = NULL; gcry_sexp_t dsa = NULL;
gcry_sexp_t rsa = NULL; gcry_sexp_t rsa = NULL;
int valid; int valid;
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
DSA *dsa = NULL; DSA *dsa = NULL;
RSA *rsa = NULL; RSA *rsa = NULL;
BIO *bio = NULL;
#endif #endif
#ifdef HAVE_LIBGCRYPT
file = fopen(filename,"r"); file = fopen(filename,"r");
if (file == NULL) { if (file == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED, ssh_set_error(session, SSH_REQUEST_DENIED,
"Error opening %s: %s", filename, strerror(errno)); "Error opening %s: %s", filename, strerror(errno));
return NULL; 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) { switch (type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:
@@ -855,14 +882,16 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
if (!valid) { if (!valid) {
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename); ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO #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) { if (dsa == NULL) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Parsing private key %s: %s", "Parsing private key %s: %s",
filename, ERR_error_string(ERR_get_error(), NULL)); filename, ERR_error_string(ERR_get_error(), NULL));
#else
{
#endif #endif
return NULL; return NULL;
} }
@@ -876,19 +905,26 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
if (!valid) { if (!valid) {
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename); ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
#elif defined HAVE_LIBCRYPTO #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) { if (rsa == NULL) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Parsing private key %s: %s", "Parsing private key %s: %s",
filename, ERR_error_string(ERR_get_error(), NULL)); filename, ERR_error_string(ERR_get_error(), NULL));
#else
{
#endif #endif
return NULL; return NULL;
} }
break; break;
default: 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); ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
return NULL; return NULL;
} }
@@ -1178,7 +1214,7 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
const char *priv; const char *priv;
const char *pub; const char *pub;
char *new; char *new;
ssh_string pubkey=NULL; ssh_string pubkey;
pub = keytab.publickey; pub = keytab.publickey;
if (pub == NULL) { if (pub == NULL) {
@@ -1198,13 +1234,13 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub); ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
if (!ssh_file_readaccess_ok(pub)) { if (!ssh_file_readaccess_ok(pub)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub); ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
goto error; return NULL;
} }
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv); ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
if (!ssh_file_readaccess_ok(priv)) { if (!ssh_file_readaccess_ok(priv)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv); ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
goto error; return NULL;
} }
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key"); ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
@@ -1219,18 +1255,18 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
"Wasn't able to open public key file %s: %s", "Wasn't able to open public key file %s: %s",
pub, pub,
ssh_get_error(session)); ssh_get_error(session));
goto error; return NULL;
} }
new = realloc(*privkeyfile, strlen(priv) + 1); new = realloc(*privkeyfile, strlen(priv) + 1);
if (new == NULL) { if (new == NULL) {
ssh_string_free(pubkey); ssh_string_free(pubkey);
goto error; return NULL;
} }
strcpy(new, priv); strcpy(new, priv);
*privkeyfile = new; *privkeyfile = new;
error:
return pubkey; return pubkey;
} }

View File

@@ -88,6 +88,7 @@ ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
return NULL; return NULL;
} }
ZERO_STRUCTP(key);
key->type = SSH_KEYTYPE_DSS; key->type = SSH_KEYTYPE_DSS;
key->type_c = ssh_type_to_char(key->type); key->type_c = ssh_type_to_char(key->type);
@@ -173,6 +174,7 @@ ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
return NULL; return NULL;
} }
ZERO_STRUCTP(key);
key->type = type; key->type = type;
key->type_c = ssh_type_to_char(key->type); key->type_c = ssh_type_to_char(key->type);
@@ -597,7 +599,9 @@ error:
ssh_string_free(n); ssh_string_free(n);
return rc; return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
} }
#endif
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) { static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
@@ -665,7 +669,9 @@ error:
ssh_string_free(n); ssh_string_free(n);
return rc; return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
} }
#endif
/** /**
* @brief Convert a public_key object into a a SSH string. * @brief Convert a public_key object into a a SSH string.
@@ -893,6 +899,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
ssh_set_error(session, SSH_FATAL, "Not enough space"); ssh_set_error(session, SSH_FATAL, "Not enough space");
return NULL; return NULL;
} }
ZERO_STRUCTP(sign);
tmpbuf = ssh_buffer_new(); tmpbuf = ssh_buffer_new();
if (tmpbuf == NULL) { if (tmpbuf == NULL) {
@@ -1276,6 +1283,7 @@ ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
if (sign == NULL) { if (sign == NULL) {
return NULL; return NULL;
} }
ZERO_STRUCTP(sign);
switch(privatekey->type) { switch(privatekey->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:
@@ -1432,6 +1440,7 @@ ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey)
if (sign == NULL) { if (sign == NULL) {
return NULL; return NULL;
} }
ZERO_STRUCTP(sign);
switch(privatekey->type) { switch(privatekey->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:

View File

@@ -47,6 +47,7 @@
#endif /* HAVE_LIBCRYPTO */ #endif /* HAVE_LIBCRYPTO */
#ifndef _WIN32 #ifndef _WIN32
# include <netinet/in.h>
# include <arpa/inet.h> # include <arpa/inet.h>
#endif #endif

View File

@@ -24,7 +24,9 @@
* compatibility * compatibility
*/ */
#include <libssh/libssh.h> #include "config.h"
#include <libssh/priv.h>
#include <libssh/server.h> #include <libssh/server.h>
#include <libssh/buffer.h> #include <libssh/buffer.h>
@@ -240,4 +242,18 @@ char *string_to_char(ssh_string str){
int ssh_accept(ssh_session session) { int ssh_accept(ssh_session session) {
return ssh_handle_key_exchange(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 */ #endif /* WITH_SERVER */

View File

@@ -37,6 +37,33 @@
* @{ * @{
*/ */
/** @internal
* @brief do the actual work of logging an event
*/
static void do_ssh_log(struct ssh_common_struct *common, int verbosity,
const char *buffer){
char indent[256];
int min;
if (common->callbacks && common->callbacks->log_function) {
common->callbacks->log_function((ssh_session)common, verbosity, buffer,
common->callbacks->userdata);
} else if (verbosity == SSH_LOG_FUNCTIONS) {
if (common->log_indent > 255) {
min = 255;
} else {
min = common->log_indent;
}
memset(indent, ' ', min);
indent[min] = '\0';
fprintf(stderr, "[func] %s%s\n", indent, buffer);
} else {
fprintf(stderr, "[%d] %s\n", verbosity, buffer);
}
}
/** /**
* @brief Log a SSH event. * @brief Log a SSH event.
* *
@@ -48,32 +75,31 @@
*/ */
void ssh_log(ssh_session session, int verbosity, const char *format, ...) { void ssh_log(ssh_session session, int verbosity, const char *format, ...) {
char buffer[1024]; char buffer[1024];
char indent[256];
int min;
va_list va; va_list va;
if (verbosity <= session->log_verbosity) { if (verbosity <= session->common.log_verbosity) {
va_start(va, format); va_start(va, format);
vsnprintf(buffer, sizeof(buffer), format, va); vsnprintf(buffer, sizeof(buffer), format, va);
va_end(va); va_end(va);
do_ssh_log(&session->common, verbosity, buffer);
}
}
if (session->callbacks && session->callbacks->log_function) { /** @internal
session->callbacks->log_function(session, verbosity, buffer, * @brief log a SSH event with a common pointer
session->callbacks->userdata); * @param common The SSH/bind session.
} else if (verbosity == SSH_LOG_FUNCTIONS) { * @param verbosity The verbosity of the event.
if (session->log_indent > 255) { * @param format The format string of the log entry.
min = 255; */
} else { void ssh_log_common(struct ssh_common_struct *common, int verbosity, const char *format, ...){
min = session->log_indent; char buffer[1024];
} va_list va;
memset(indent, ' ', min); if (verbosity <= common->log_verbosity) {
indent[min] = '\0'; va_start(va, format);
vsnprintf(buffer, sizeof(buffer), format, va);
fprintf(stderr, "[func] %s%s\n", indent, buffer); va_end(va);
} else { do_ssh_log(common, verbosity, buffer);
fprintf(stderr, "[%d] %s\n", verbosity, buffer);
}
} }
} }

View File

@@ -21,10 +21,13 @@
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include "config.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -67,6 +70,51 @@ static ssh_message ssh_message_new(ssh_session session){
return msg; 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 * @internal
* *
@@ -77,12 +125,16 @@ static ssh_message ssh_message_new(ssh_session session){
* @param[in] message The message to add to the queue. * @param[in] message The message to add to the queue.
*/ */
void ssh_message_queue(ssh_session session, ssh_message message){ void ssh_message_queue(ssh_session session, ssh_message message){
if(message){ if(message) {
if(session->ssh_message_list == NULL){ if(session->ssh_message_list == NULL) {
session->ssh_message_list=ssh_list_new(); 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 +182,7 @@ ssh_message ssh_message_get(ssh_session session) {
session->ssh_message_list = ssh_list_new(); session->ssh_message_list = ssh_list_new();
} }
do { do {
if (ssh_handle_packets(session,-1) == SSH_ERROR) { if (ssh_handle_packets(session, -2) == SSH_ERROR) {
leave_function(); leave_function();
return NULL; return NULL;
} }
@@ -860,6 +912,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
char *bind_addr=NULL; char *bind_addr=NULL;
uint32_t bind_port; uint32_t bind_port;
uint8_t want_reply; uint8_t want_reply;
int rc = SSH_PACKET_USED;
(void)user; (void)user;
(void)type; (void)type;
(void)packet; (void)packet;
@@ -894,9 +947,9 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port); ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
if(ssh_callbacks_exists(session->callbacks, global_request_function)) { if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
ssh_log(session, SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port); ssh_log(session, SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
session->callbacks->global_request_function(session, msg, session->callbacks->userdata); session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
} else { } else {
ssh_message_reply_default(msg); ssh_message_reply_default(msg);
} }
@@ -916,19 +969,21 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port); ssh_log(session, SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, bind_addr, bind_port);
if(ssh_callbacks_exists(session->callbacks, global_request_function)) { if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
session->callbacks->global_request_function(session, msg, session->callbacks->userdata); session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
} else { } else {
ssh_message_reply_default(msg); ssh_message_reply_default(msg);
} }
} else { } else {
ssh_log(session, SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply); ssh_log(session, SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply);
rc = SSH_PACKET_NOT_USED;
} }
SAFE_FREE(msg); SAFE_FREE(msg);
SAFE_FREE(request); SAFE_FREE(request);
SAFE_FREE(bind_addr); SAFE_FREE(bind_addr);
return SSH_PACKET_USED;
return rc;
} }
#endif /* WITH_SERVER */ #endif /* WITH_SERVER */

View File

@@ -22,14 +22,22 @@
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include "config.h"
#ifndef _WIN32 #ifndef _WIN32
/* This is needed for a standard getpwuid_r on opensolaris */ /* This is needed for a standard getpwuid_r on opensolaris */
#define _POSIX_PTHREAD_SEMANTICS #define _POSIX_PTHREAD_SEMANTICS
#include <pwd.h> #include <pwd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.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 <limits.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -37,6 +45,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h> #include <ctype.h>
#include <time.h>
#ifdef _WIN32 #ifdef _WIN32
@@ -136,7 +145,7 @@ char *ssh_get_local_username(ssh_session session) {
/* get the size */ /* get the size */
GetUserName(NULL, &size); GetUserName(NULL, &size);
user = malloc(size); user = (char *) malloc(size);
if (user == NULL) { if (user == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
return NULL; return NULL;
@@ -148,6 +157,49 @@ char *ssh_get_local_username(ssh_session session) {
return NULL; 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 */ #else /* _WIN32 */
#ifndef NSS_BUFLEN_PASSWD #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); rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) { if (rc != 0) {
return NULL; szPath=getenv("HOME");
return szPath ? strdup(szPath) : NULL;
} }
szPath = strdup(pwd.pw_dir); szPath = strdup(pwd.pw_dir);
@@ -203,20 +256,51 @@ char *ssh_get_local_username(ssh_session session) {
return name; 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 */ #endif /* _WIN32 */
#ifndef HAVE_NTOHLL
uint64_t ntohll(uint64_t a) { uint64_t ntohll(uint64_t a) {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
return a; return a;
#else #else /* WORDS_BIGENDIAN */
uint32_t low = (uint32_t)(a & 0xffffffff); uint32_t low = (uint32_t)(a & 0xffffffff);
uint32_t high = (uint32_t)(a >> 32); uint32_t high = (uint32_t)(a >> 32);
low = ntohl(low); low = ntohl(low);
high = ntohl(high); high = ntohl(high);
return ((((uint64_t) low) << 32) | ( high)); return ((((uint64_t) low) << 32) | ( high));
#endif #endif /* WORDS_BIGENDIAN */
} }
#endif /* HAVE_NTOHLL */
char *ssh_lowercase(const char* str) { char *ssh_lowercase(const char* str) {
char *new, *p; char *new, *p;
@@ -293,6 +377,8 @@ struct ssh_list *ssh_list_new(){
void ssh_list_free(struct ssh_list *list){ void ssh_list_free(struct ssh_list *list){
struct ssh_iterator *ptr,*next; struct ssh_iterator *ptr,*next;
if(!list)
return;
ptr=list->root; ptr=list->root;
while(ptr){ while(ptr){
next=ptr->next; next=ptr->next;
@@ -303,9 +389,19 @@ void ssh_list_free(struct ssh_list *list){
} }
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list){ struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list){
if(!list)
return NULL;
return list->root; return list->root;
} }
struct ssh_iterator *ssh_list_find(const struct ssh_list *list, void *value){
struct ssh_iterator *it;
for(it = ssh_list_get_iterator(list); it != NULL ;it=it->next)
if(it->data==value)
return it;
return NULL;
}
static struct ssh_iterator *ssh_iterator_new(const void *data){ static struct ssh_iterator *ssh_iterator_new(const void *data){
struct ssh_iterator *iterator=malloc(sizeof(struct ssh_iterator)); struct ssh_iterator *iterator=malloc(sizeof(struct ssh_iterator));
if(!iterator) if(!iterator)
@@ -559,7 +655,7 @@ char *ssh_path_expand_tilde(const char *d) {
size_t s = p - d; size_t s = p - d;
char u[128]; char u[128];
if (s > sizeof(u)) { if (s >= sizeof(u)) {
return NULL; return NULL;
} }
memcpy(u, d, s); memcpy(u, d, s);
@@ -623,7 +719,8 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
if (*p != '%') { if (*p != '%') {
buf[i] = *p; buf[i] = *p;
i++; i++;
if (i > MAX_BUF_SIZE) { if (i >= MAX_BUF_SIZE) {
free(r);
return NULL; return NULL;
} }
buf[i] = '\0'; buf[i] = '\0';
@@ -664,18 +761,22 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
default: default:
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"Wrong escape sequence detected"); "Wrong escape sequence detected");
free(r);
return NULL; return NULL;
} }
if (x == NULL) { if (x == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
free(r);
return NULL; return NULL;
} }
i += strlen(x); i += strlen(x);
if (i > MAX_BUF_SIZE) { if (i >= MAX_BUF_SIZE) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
"String too long"); "String too long");
free(x);
free(r);
return NULL; return NULL;
} }
l = strlen(buf); l = strlen(buf);
@@ -779,6 +880,120 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
return 0; 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 turn seconds and microseconds pair (as provided by user-set options)
* into millisecond value
* @param[in] sec number of seconds
* @param[in] usec number of microseconds
* @returns milliseconds, or 10000 if user supplied values are equal to zero
*/
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
* @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;
switch(timeout) {
case -2: // -2 means user-defined timeout as available in session->timeout, session->timeout_usec.
fprintf(stderr, "ssh_timeout_elapsed called with -2. this needs to be fixed. "
"please set a breakpoint on %s:%d and fix the caller\n", __FILE__, __LINE__);
case -1: // -1 means infinite timeout
return 0;
case 0: // 0 means no timeout
return 1;
default:
break;
}
ssh_timestamp_init(&now);
return (ssh_timestamp_difference(ts,&now) >= timeout);
}
/**
* @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: */ /* vim: set ts=4 sw=4 et cindent: */

View File

@@ -139,12 +139,12 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
} }
new->fd = src->fd; new->fd = src->fd;
new->port = src->port; new->port = src->port;
new->callbacks = src->callbacks; new->common.callbacks = src->common.callbacks;
new->timeout = src->timeout; new->timeout = src->timeout;
new->timeout_usec = src->timeout_usec; new->timeout_usec = src->timeout_usec;
new->ssh2 = src->ssh2; new->ssh2 = src->ssh2;
new->ssh1 = src->ssh1; new->ssh1 = src->ssh1;
new->log_verbosity = src->log_verbosity; new->common.log_verbosity = src->common.log_verbosity;
new->compressionlevel = src->compressionlevel; new->compressionlevel = src->compressionlevel;
return 0; return 0;
@@ -544,12 +544,12 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
} else { } else {
int *x = (int *) value; int *x = (int *) value;
session->log_verbosity = *x & 0xffff; session->common.log_verbosity = *x & 0xffff;
} }
break; break;
case SSH_OPTIONS_LOG_VERBOSITY_STR: case SSH_OPTIONS_LOG_VERBOSITY_STR:
if (value == NULL) { if (value == NULL) {
session->log_verbosity = 0 & 0xffff; session->common.log_verbosity = 0 & 0xffff;
} else { } else {
q = strdup(value); q = strdup(value);
if (q == NULL) { if (q == NULL) {
@@ -562,7 +562,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
} }
SAFE_FREE(q); SAFE_FREE(q);
session->log_verbosity = i & 0xffff; session->common.log_verbosity = i & 0xffff;
} }
break; break;
case SSH_OPTIONS_CIPHERS_C_S: case SSH_OPTIONS_CIPHERS_C_S:
@@ -655,11 +655,15 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
return -1; return -1;
} else { } else {
SAFE_FREE(session->ProxyCommand); SAFE_FREE(session->ProxyCommand);
q = strdup(value); /* Setting the command to 'none' disables this option. */
if (q == NULL) { rc = strcasecmp(value, "none");
return -1; if (rc != 0) {
q = strdup(value);
if (q == NULL) {
return -1;
}
session->ProxyCommand = q;
} }
session->ProxyCommand = q;
} }
break; break;
default: default:
@@ -698,7 +702,7 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
char *cipher = NULL; char *cipher = NULL;
char *identity = NULL; char *identity = NULL;
char *port = NULL; char *port = NULL;
char **save = NULL; char **save = NULL, **tmp;
int i = 0; int i = 0;
int argc = *argcptr; int argc = *argcptr;
int debuglevel = 0; int debuglevel = 0;
@@ -720,12 +724,6 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
int saveoptind = optind; /* need to save 'em */ int saveoptind = optind; /* need to save 'em */
int saveopterr = opterr; int saveopterr = opterr;
save = malloc(argc * sizeof(char *));
if (save == NULL) {
ssh_set_error_oom(session);
return -1;
}
opterr = 0; /* shut up getopt */ opterr = 0; /* shut up getopt */
while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) { while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) {
switch(i) { switch(i) {
@@ -765,6 +763,13 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
{ {
char opt[3]="- "; char opt[3]="- ";
opt[1] = optopt; opt[1] = optopt;
tmp = realloc(save, (current + 1) * sizeof(char*));
if (tmp == NULL) {
SAFE_FREE(save);
ssh_set_error_oom(session);
return -1;
}
save = tmp;
save[current] = strdup(opt); save[current] = strdup(opt);
if (save[current] == NULL) { if (save[current] == NULL) {
SAFE_FREE(save); SAFE_FREE(save);
@@ -780,7 +785,16 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
} /* while */ } /* while */
opterr = saveopterr; opterr = saveopterr;
while (optind < argc) { while (optind < argc) {
save[current++] = argv[optind++]; tmp = realloc(save, (current + 1) * sizeof(char*));
if (tmp == NULL) {
SAFE_FREE(save);
ssh_set_error_oom(session);
return -1;
}
save = tmp;
save[current] = argv[optind];
current++;
optind++;
} }
if (usersa && usedss) { if (usersa && usedss) {
@@ -1106,12 +1120,12 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
return -1; return -1;
} else { } else {
int *x = (int *) value; int *x = (int *) value;
sshbind->log_verbosity = *x & 0xffff; sshbind->common.log_verbosity = *x & 0xffff;
} }
break; break;
case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR: case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
if (value == NULL) { if (value == NULL) {
sshbind->log_verbosity = 0; sshbind->common.log_verbosity = 0;
} else { } else {
q = strdup(value); q = strdup(value);
if (q == NULL) { if (q == NULL) {
@@ -1124,7 +1138,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
} }
SAFE_FREE(q); SAFE_FREE(q);
sshbind->log_verbosity = i & 0xffff; sshbind->common.log_verbosity = i & 0xffff;
} }
break; break;
case SSH_BIND_OPTIONS_DSAKEY: case SSH_BIND_OPTIONS_DSAKEY:

View File

@@ -29,6 +29,7 @@
#include <errno.h> #include <errno.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -255,7 +256,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
"After padding, %d bytes left in buffer", "After padding, %d bytes left in buffer",
buffer_get_rest_len(session->in_buffer)); buffer_get_rest_len(session->in_buffer));
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ) #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 ..."); ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ...");
if (decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN) < 0) { if (decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN) < 0) {
goto error; goto error;
@@ -457,7 +460,9 @@ static int packet_send2(ssh_session session) {
"Writing on the wire a packet having %u bytes before", currentlen); "Writing on the wire a packet having %u bytes before", currentlen);
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ) #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 ..."); ssh_log(session, SSH_LOG_PACKET, "Compressing out_buffer ...");
if (compress_buffer(session,session->out_buffer) < 0) { if (compress_buffer(session,session->out_buffer) < 0) {
goto error; goto error;

View File

@@ -55,7 +55,7 @@ ssh_packet_callback default_packet_handlers1[]= {
ssh_packet_data1, //SSH_SMSG_STDOUT_DATA 17 ssh_packet_data1, //SSH_SMSG_STDOUT_DATA 17
ssh_packet_data1, //SSH_SMSG_STDERR_DATA 18 ssh_packet_data1, //SSH_SMSG_STDERR_DATA 18
NULL, //SSH_CMSG_EOF 19 NULL, //SSH_CMSG_EOF 19
NULL, //SSH_SMSG_EXITSTATUS 20 ssh_packet_exist_status1, //SSH_SMSG_EXITSTATUS 20
NULL, //SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 NULL, //SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21
NULL, //SSH_MSG_CHANNEL_OPEN_FAILURE 22 NULL, //SSH_MSG_CHANNEL_OPEN_FAILURE 22
NULL, //SSH_MSG_CHANNEL_DATA 23 NULL, //SSH_MSG_CHANNEL_DATA 23

View File

@@ -125,7 +125,7 @@ struct ssh_pcap_file_struct {
ssh_pcap_file ssh_pcap_file_new(){ ssh_pcap_file ssh_pcap_file_new(){
struct ssh_pcap_file_struct *pcap; 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) { if (pcap == NULL) {
return 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 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){ if(ctx==NULL){
ssh_set_error_oom(session); ssh_set_error_oom(session);
return NULL; return NULL;

View File

@@ -105,29 +105,6 @@ static poll_fn ssh_poll_emu;
#include <time.h> #include <time.h>
#include <windows.h> #include <windows.h>
#include <winsock2.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 */ #else /* _WIN32 */
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.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) { void ssh_poll_init(void) {
ssh_poll_emu = bsd_poll; 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) { void ssh_poll_cleanup(void) {
ssh_poll_emu = bsd_poll; 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) { 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 fd Socket that will be polled.
* @param events Poll events that will be monitored for the socket. i.e. * @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 cb Function to be called if any of the events are set.
*
* @param userdata Userdata to be passed to the callback function. NULL if * @param userdata Userdata to be passed to the callback function. NULL if
* not needed. * not needed.
* *
@@ -482,19 +440,9 @@ ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size) {
*/ */
void ssh_poll_ctx_free(ssh_poll_ctx ctx) { void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
if (ctx->polls_allocated > 0) { if (ctx->polls_allocated > 0) {
register size_t i, used; while (ctx->polls_used > 0){
ssh_poll_handle p = ctx->pollptrs[0];
used = ctx->polls_used; ssh_poll_ctx_remove(ctx, p);
for (i = 0; i < used; ) {
ssh_poll_handle p = ctx->pollptrs[i];
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;
} else {
i++;
}
} }
SAFE_FREE(ctx->pollptrs); SAFE_FREE(ctx->pollptrs);
@@ -622,6 +570,7 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) {
* the poll() function. * the poll() function.
* @returns SSH_OK No error. * @returns SSH_OK No error.
* SSH_ERROR Error happened during the poll. * SSH_ERROR Error happened during the poll.
* SSH_AGAIN Timeout occured
*/ */
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) { int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
@@ -632,23 +581,28 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
int revents; int revents;
if (!ctx->polls_used) if (!ctx->polls_used)
return 0; return SSH_ERROR;
rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout); rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
if(rc < 0) if(rc < 0)
rc=SSH_ERROR; return SSH_ERROR;
if(rc <= 0) if (rc == 0)
return rc; return SSH_AGAIN;
used = ctx->polls_used; used = ctx->polls_used;
for (i = 0; i < used && rc > 0; ) { for (i = 0; i < used && rc > 0; ) {
if (!ctx->pollfds[i].revents) { if (!ctx->pollfds[i].revents) {
i++; i++;
} else { } else {
int ret;
p = ctx->pollptrs[i]; p = ctx->pollptrs[i];
fd = ctx->pollfds[i].fd; fd = ctx->pollfds[i].fd;
revents = ctx->pollfds[i].revents; 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 */ /* the poll was removed, reload the used counter and start again */
used = ctx->polls_used; used = ctx->polls_used;
i=0; i=0;

View File

@@ -148,7 +148,7 @@ int ssh_scp_close(ssh_scp scp){
*/ */
while(!ssh_channel_is_eof(scp->channel)){ while(!ssh_channel_is_eof(scp->channel)){
err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0); err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0);
if(err==SSH_ERROR) if(err==SSH_ERROR || err==0)
break; break;
} }
if(ssh_channel_close(scp->channel) == SSH_ERROR){ 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 ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
int w; int w;
//int r; int r;
//uint8_t code; uint8_t code;
if(scp==NULL) if(scp==NULL)
return SSH_ERROR; return SSH_ERROR;
if(scp->state != SSH_SCP_WRITE_WRITING){ 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=channel_get_exit_status(scp->channel);
return SSH_ERROR; 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 */ /* Check if we arrived at end of file */
if(scp->processed == scp->filelen) { if(scp->processed == scp->filelen) {
/* r=channel_read(scp->channel,&code,1,0); code = 0;
if(r==SSH_ERROR){ w = ssh_channel_write(scp->channel, &code, 1);
scp->state=SSH_SCP_ERROR; if(w == SSH_ERROR){
scp->state = SSH_SCP_ERROR;
return SSH_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->processed=scp->filelen=0;
scp->state=SSH_SCP_WRITE_INITED; scp->state=SSH_SCP_WRITE_INITED;
} }
@@ -461,16 +469,20 @@ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
* *
* @returns SSH_SCP_REQUEST_NEWFILE: The other side is sending * @returns SSH_SCP_REQUEST_NEWFILE: The other side is sending
* a file * a file
* SSH_SCP_REQUEST_NEWDIRECTORY: The other side is sending * SSH_SCP_REQUEST_NEWDIR: The other side is sending
* a directory * a directory
* SSH_SCP_REQUEST_END_DIRECTORY: The other side has * SSH_SCP_REQUEST_ENDDIR: The other side has
* finished with the current * finished with the current
* directory * directory
* SSH_SCP_REQUEST_WARNING: The other side sent us a warning
* SSH_SCP_REQUEST_EOF: The other side finished sending us
* files and data.
* SSH_ERROR: Some error happened * SSH_ERROR: Some error happened
* *
* @see ssh_scp_read() * @see ssh_scp_read()
* @see ssh_scp_deny_request() * @see ssh_scp_deny_request()
* @see ssh_scp_accept_request() * @see ssh_scp_accept_request()
* @see ssh_scp_request_get_warning()
*/ */
int ssh_scp_pull_request(ssh_scp scp){ int ssh_scp_pull_request(ssh_scp scp){
char buffer[4096]; char buffer[4096];

View File

@@ -59,8 +59,8 @@
#include "libssh/messages.h" #include "libssh/messages.h"
#define set_status(session, status) do {\ #define set_status(session, status) do {\
if (session->callbacks && session->callbacks->connect_status_function) \ if (session->common.callbacks && session->common.callbacks->connect_status_function) \
session->callbacks->connect_status_function(session->callbacks->userdata, status); \ session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \
} while (0) } while (0)
static int dh_handshake_server(ssh_session session); static int dh_handshake_server(ssh_session session);
@@ -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) { if (server->methods == NULL) {
return -1; return -1;
} }
@@ -184,7 +184,11 @@ static int dh_handshake_server(ssh_session session) {
prv = session->rsa_key; prv = session->rsa_key;
break; break;
default: default:
prv = NULL; ssh_set_error(session,
SSH_FATAL,
"Could not determine the specified hostkey");
ssh_string_free(f);
return -1;
} }
pub = publickey_from_privatekey(prv); pub = publickey_from_privatekey(prv);
@@ -270,6 +274,8 @@ static int dh_handshake_server(ssh_session session) {
*/ */
static void ssh_server_connection_callback(ssh_session session){ static void ssh_server_connection_callback(ssh_session session){
int ssh1,ssh2; int ssh1,ssh2;
int rc;
enter_function(); enter_function();
switch(session->session_state){ switch(session->session_state){
case SSH_SESSION_STATE_NONE: case SSH_SESSION_STATE_NONE:
@@ -338,7 +344,10 @@ static void ssh_server_connection_callback(ssh_session session){
case SSH_SESSION_STATE_KEXINIT_RECEIVED: case SSH_SESSION_STATE_KEXINIT_RECEIVED:
set_status(session,0.6f); set_status(session,0.6f);
ssh_list_kex(session, &session->client_kex); // log client kex ssh_list_kex(session, &session->client_kex); // log client kex
crypt_set_algorithms_server(session); rc = crypt_set_algorithms_server(session);
if (rc == SSH_ERROR) {
goto error;
}
if (set_kex(session) < 0) { if (set_kex(session) < 0) {
goto error; goto error;
} }
@@ -479,8 +488,8 @@ int ssh_handle_key_exchange(ssh_session session) {
* loop until SSH_SESSION_STATE_BANNER_RECEIVED or * loop until SSH_SESSION_STATE_BANNER_RECEIVED or
* SSH_SESSION_STATE_ERROR * SSH_SESSION_STATE_ERROR
*/ */
ssh_handle_packets(session,-1); ssh_handle_packets(session, -2);
ssh_log(session,SSH_LOG_PACKET, "ssh_accept: Actual state : %d", ssh_log(session,SSH_LOG_PACKET, "ssh_handle_key_exchange: Actual state : %d",
session->session_state); session->session_state);
} }
@@ -616,10 +625,13 @@ static int ssh_message_service_request_reply_default(ssh_message msg) {
int ssh_message_service_reply_success(ssh_message msg) { int ssh_message_service_reply_success(ssh_message msg) {
struct ssh_string_struct *service; struct ssh_string_struct *service;
ssh_session session=msg->session; ssh_session session;
if (msg == NULL) { if (msg == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
session = msg->session;
ssh_log(session, SSH_LOG_PACKET, ssh_log(session, SSH_LOG_PACKET,
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service); "Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) { if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {

View File

@@ -86,7 +86,7 @@ ssh_session ssh_new(void) {
session->alive = 0; session->alive = 0;
session->auth_methods = 0; session->auth_methods = 0;
ssh_set_blocking(session, 1); ssh_set_blocking(session, 1);
session->log_indent = 0; session->common.log_indent = 0;
session->maxchannel = FIRST_CHANNEL; session->maxchannel = FIRST_CHANNEL;
/* options */ /* options */
@@ -143,6 +143,7 @@ ssh_session ssh_new(void) {
return session; return session;
err: err:
free(id);
ssh_free(session); ssh_free(session);
return NULL; return NULL;
} }
@@ -157,16 +158,26 @@ err:
*/ */
void ssh_free(ssh_session session) { void ssh_free(ssh_session session) {
int i; int i;
enter_function(); struct ssh_iterator *it;
if (session == NULL) { if (session == NULL) {
return; return;
} }
SAFE_FREE(session->serverbanner); /* delete all channels */
SAFE_FREE(session->clientbanner); while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
SAFE_FREE(session->bindaddr); ssh_channel_free(ssh_iterator_value(ssh_channel,it));
SAFE_FREE(session->banner); ssh_list_remove(session->channels, it);
}
ssh_list_free(session->channels);
session->channels=NULL;
ssh_socket_free(session->socket);
if (session->default_poll_ctx) {
ssh_poll_ctx_free(session->default_poll_ctx);
}
#ifdef WITH_PCAP #ifdef WITH_PCAP
if(session->pcap_ctx){ if(session->pcap_ctx){
ssh_pcap_context_free(session->pcap_ctx); ssh_pcap_context_free(session->pcap_ctx);
@@ -182,14 +193,6 @@ void ssh_free(ssh_session session) {
session->in_buffer=session->out_buffer=NULL; session->in_buffer=session->out_buffer=NULL;
crypto_free(session->current_crypto); crypto_free(session->current_crypto);
crypto_free(session->next_crypto); crypto_free(session->next_crypto);
ssh_socket_free(session->socket);
if(session->default_poll_ctx){
ssh_poll_ctx_free(session->default_poll_ctx);
}
/* delete all channels */
while (session->channels) {
ssh_channel_free(session->channels);
}
#ifndef _WIN32 #ifndef _WIN32
agent_free(session->agent); agent_free(session->agent);
#endif /* _WIN32 */ #endif /* _WIN32 */
@@ -232,6 +235,11 @@ void ssh_free(ssh_session session) {
ssh_list_free(session->identity); ssh_list_free(session->identity);
} }
SAFE_FREE(session->serverbanner);
SAFE_FREE(session->clientbanner);
SAFE_FREE(session->bindaddr);
SAFE_FREE(session->banner);
/* options */ /* options */
SAFE_FREE(session->username); SAFE_FREE(session->username);
SAFE_FREE(session->host); SAFE_FREE(session->host);
@@ -297,6 +305,32 @@ int ssh_is_blocking(ssh_session session){
return (session->flags&SSH_SESSION_FLAG_BLOCKING) ? 1 : 0; 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 -1
* 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;
int rc = SSH_OK;
if(session==NULL)
return SSH_ERROR;
s=session->socket;
while (ssh_socket_buffered_write_bytes(s) > 0 && session->alive) {
rc = ssh_handle_packets(session, timeout);
if(rc == SSH_AGAIN || rc == SSH_ERROR) break;
}
return rc;
}
/** /**
* @brief Check if we are connected. * @brief Check if we are connected.
* *
@@ -381,33 +415,50 @@ void ssh_set_fd_except(ssh_session session) {
* @param[in] session The session handle to use. * @param[in] session The session handle to use.
* *
* @param[in] timeout Set an upper limit on the time for which this function * @param[in] timeout Set an upper limit on the time for which this function
* will block, in milliseconds. Specifying a negative value * will block, in milliseconds. Specifying -1
* means an infinite timeout. This parameter is passed to * means an infinite timeout.
* the poll() function. * 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. * @return SSH_OK on success, SSH_ERROR otherwise.
*/ */
int ssh_handle_packets(ssh_session session, int timeout) { int ssh_handle_packets(ssh_session session, int timeout) {
ssh_poll_handle spoll_in,spoll_out; ssh_poll_handle spoll_in,spoll_out;
ssh_poll_ctx ctx; ssh_poll_ctx ctx;
if(session==NULL || session->socket==NULL) int tm = timeout;
return SSH_ERROR; int rc;
enter_function();
spoll_in=ssh_socket_get_poll_handle_in(session->socket); if (session == NULL || session->socket == NULL) {
spoll_out=ssh_socket_get_poll_handle_out(session->socket); return SSH_ERROR;
ctx=ssh_poll_get_ctx(spoll_in); }
if(ctx==NULL){ enter_function();
ctx=ssh_poll_get_default_ctx(session);
ssh_poll_ctx_add(ctx,spoll_in); spoll_in = ssh_socket_get_poll_handle_in(session->socket);
if(spoll_in != spoll_out) spoll_out = ssh_socket_get_poll_handle_out(session->socket);
ssh_poll_ctx_add(ctx,spoll_out); if (session->server) {
} ssh_poll_add_events(spoll_in, POLLIN);
ssh_poll_ctx_dopoll(ctx,timeout); }
leave_function(); ctx = ssh_poll_get_ctx(spoll_in);
if (session->session_state != SSH_SESSION_STATE_ERROR)
return SSH_OK; if (!ctx) {
else ctx = ssh_poll_get_default_ctx(session);
return SSH_ERROR; 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();
return rc;
} }
/** /**
@@ -430,21 +481,22 @@ int ssh_handle_packets(ssh_session session, int timeout) {
* @return SSH_OK on success, SSH_ERROR otherwise. * @return SSH_OK on success, SSH_ERROR otherwise.
*/ */
int ssh_handle_packets_termination(ssh_session session, int timeout, int ssh_handle_packets_termination(ssh_session session, int timeout,
ssh_termination_function fct, void *user){ ssh_termination_function fct, void *user){
int ret = SSH_ERROR; int ret = SSH_OK;
while(!fct(user)){ struct ssh_timestamp ts;
ret = ssh_handle_packets(session, timeout); ssh_timestamp_init(&ts);
if(ret == SSH_ERROR) while(!fct(user)){
return SSH_ERROR; ret = ssh_handle_packets(session, timeout);
if(timeout == 0){ if(ret == SSH_ERROR || ret == SSH_AGAIN)
if(fct(user)) return ret;
return SSH_OK; if(fct(user))
else return SSH_OK;
return SSH_AGAIN; else if(ssh_timeout_elapsed(&ts, timeout == -2 ? ssh_make_milliseconds(session->timeout, session->timeout_usec) : timeout))
} /* it is possible that we get unrelated packets but still timeout our request,
/* TODO: verify that total timeout has not expired and then return SSH_AGAIN */ * so simply relying on the poll timeout is not enough */
} return SSH_AGAIN;
return ret; }
return ret;
} }
/** /**
@@ -552,6 +604,7 @@ SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){
ssh_socket_close(session->socket); ssh_socket_close(session->socket);
session->alive = 0; session->alive = 0;
session->session_state= SSH_SESSION_STATE_ERROR;
/* TODO: handle a graceful disconnect */ /* TODO: handle a graceful disconnect */
return SSH_PACKET_USED; return SSH_PACKET_USED;
} }

View File

@@ -35,6 +35,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#else #else
#define S_IFSOCK 0140000 #define S_IFSOCK 0140000
@@ -668,10 +669,18 @@ int sftp_extension_supported(sftp_session sftp, const char *name,
const char *data) { const char *data) {
int i, n; int i, n;
if (sftp == NULL || name == NULL || data == NULL) {
return 0;
}
n = sftp_extensions_get_count(sftp); n = sftp_extensions_get_count(sftp);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (strcmp(sftp_extensions_get_name(sftp, i), name) == 0 && const char *ext_name = sftp_extensions_get_name(sftp, i);
strcmp(sftp_extensions_get_data(sftp, i), data) == 0) { const char *ext_data = sftp_extensions_get_data(sftp, i);
if (ext_name != NULL && ext_data != NULL &&
strcmp(ext_name, name) == 0 &&
strcmp(ext_data, data) == 0) {
return 1; return 1;
} }
} }
@@ -939,6 +948,7 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path){
dir = malloc(sizeof(struct sftp_dir_struct)); dir = malloc(sizeof(struct sftp_dir_struct));
if (dir == NULL) { if (dir == NULL) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
free(file);
return NULL; return NULL;
} }
ZERO_STRUCTP(dir); ZERO_STRUCTP(dir);
@@ -1193,8 +1203,8 @@ static char *sftp_parse_longname(const char *longname,
so that number of pairs equals extended_count */ so that number of pairs equals extended_count */
static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf, static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
int expectname) { int expectname) {
ssh_string longname = NULL; ssh_string longname;
ssh_string name = NULL; ssh_string name;
sftp_attributes attr; sftp_attributes attr;
uint32_t flags = 0; uint32_t flags = 0;
int ok = 0; int ok = 0;
@@ -1209,19 +1219,27 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
/* This isn't really a loop, but it is like a try..catch.. */ /* This isn't really a loop, but it is like a try..catch.. */
do { do {
if (expectname) { if (expectname) {
if ((name = buffer_get_ssh_string(buf)) == NULL || name = buffer_get_ssh_string(buf);
(attr->name = ssh_string_to_char(name)) == NULL) { if (name == NULL) {
break; break;
} }
attr->name = ssh_string_to_char(name);
ssh_string_free(name); ssh_string_free(name);
if (attr->name == NULL) {
break;
}
ssh_log(sftp->session, SSH_LOG_RARE, "Name: %s", attr->name); ssh_log(sftp->session, SSH_LOG_RARE, "Name: %s", attr->name);
if ((longname=buffer_get_ssh_string(buf)) == NULL || longname = buffer_get_ssh_string(buf);
(attr->longname=ssh_string_to_char(longname)) == NULL) { if (longname == NULL) {
break;
}
attr->longname = ssh_string_to_char(longname);
ssh_string_free(longname);
if (attr->longname == NULL) {
break; break;
} }
ssh_string_free(longname);
/* Set owner and group if we talk to openssh and have the longname */ /* Set owner and group if we talk to openssh and have the longname */
if (ssh_get_openssh_version(sftp->session)) { if (ssh_get_openssh_version(sftp->session)) {
@@ -1326,8 +1344,6 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
if (!ok) { if (!ok) {
/* break issued somewhere */ /* break issued somewhere */
ssh_string_free(name);
ssh_string_free(longname);
ssh_string_free(attr->extended_type); ssh_string_free(attr->extended_type);
ssh_string_free(attr->extended_data); ssh_string_free(attr->extended_data);
SAFE_FREE(attr->name); SAFE_FREE(attr->name);
@@ -1817,7 +1833,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
if (ssh_string_len(datastring) > count) { if (ssh_string_len(datastring) > count) {
ssh_set_error(sftp->session, SSH_FATAL, ssh_set_error(sftp->session, SSH_FATAL,
"Received a too big DATA packet from sftp server: " "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_len(datastring), count);
ssh_string_free(datastring); ssh_string_free(datastring);
return -1; return -1;
@@ -1938,16 +1954,15 @@ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){
if (ssh_string_len(datastring) > size) { if (ssh_string_len(datastring) > size) {
ssh_set_error(sftp->session, SSH_FATAL, ssh_set_error(sftp->session, SSH_FATAL,
"Received a too big DATA packet from sftp server: " "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_len(datastring), size);
ssh_string_free(datastring); ssh_string_free(datastring);
sftp_leave_function(); sftp_leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
len = ssh_string_len(datastring); len = ssh_string_len(datastring);
//handle->offset+=len; /* Update the offset with the correct value */
/* We already have set the offset previously. All we can do is warn that the expected len file->offset = file->offset - (size - len);
* and effective lengths are different */
memcpy(data, ssh_string_data(datastring), len); memcpy(data, ssh_string_data(datastring), len);
ssh_string_free(datastring); ssh_string_free(datastring);
sftp_leave_function(); sftp_leave_function();
@@ -2054,6 +2069,7 @@ int sftp_seek(sftp_file file, uint32_t new_offset) {
} }
file->offset = new_offset; file->offset = new_offset;
file->eof = 0;
return 0; return 0;
} }
@@ -2064,6 +2080,7 @@ int sftp_seek64(sftp_file file, uint64_t new_offset) {
} }
file->offset = new_offset; file->offset = new_offset;
file->eof = 0;
return 0; return 0;
} }
@@ -2080,6 +2097,7 @@ uint64_t sftp_tell64(sftp_file file) {
/* Rewinds the position of the file pointer to the beginning of the file.*/ /* Rewinds the position of the file pointer to the beginning of the file.*/
void sftp_rewind(sftp_file file) { void sftp_rewind(sftp_file file) {
file->offset = 0; file->offset = 0;
file->eof = 0;
} }
/* code written by Nick */ /* code written by Nick */
@@ -2109,10 +2127,12 @@ int sftp_unlink(sftp_session sftp, const char *file) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(filename); ssh_string_free(filename);
return -1;
} }
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) { if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) {
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(filename); ssh_string_free(filename);
return -1;
} }
ssh_string_free(filename); ssh_string_free(filename);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
@@ -2265,6 +2285,7 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode) {
sftp_packet_write(sftp, SSH_FXP_MKDIR, buffer) < 0) { sftp_packet_write(sftp, SSH_FXP_MKDIR, buffer) < 0) {
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(path); ssh_string_free(path);
return -1;
} }
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(path); ssh_string_free(path);
@@ -2846,7 +2867,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); ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support sftp_statvfs",sftp->version);
return NULL; return NULL;
} }
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);

View File

@@ -26,6 +26,7 @@
#include <stdio.h> #include <stdio.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -37,6 +38,7 @@
#include "libssh/misc.h" #include "libssh/misc.h"
sftp_client_message sftp_get_client_message(sftp_session sftp) { sftp_client_message sftp_get_client_message(sftp_session sftp) {
ssh_session session = sftp->session;
sftp_packet packet; sftp_packet packet;
sftp_client_message msg; sftp_client_message msg;
ssh_buffer payload; ssh_buffer payload;
@@ -44,12 +46,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
msg = malloc(sizeof (struct sftp_client_message_struct)); msg = malloc(sizeof (struct sftp_client_message_struct));
if (msg == NULL) { if (msg == NULL) {
ssh_set_error_oom(session);
return NULL; return NULL;
} }
ZERO_STRUCTP(msg); ZERO_STRUCTP(msg);
packet = sftp_packet_read(sftp); packet = sftp_packet_read(sftp);
if (packet == NULL) { if (packet == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -65,6 +69,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_READDIR: case SSH_FXP_READDIR:
msg->handle = buffer_get_ssh_string(payload); msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) { if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -72,6 +77,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_READ: case SSH_FXP_READ:
msg->handle = buffer_get_ssh_string(payload); msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) { if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -81,12 +87,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_WRITE: case SSH_FXP_WRITE:
msg->handle = buffer_get_ssh_string(payload); msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) { if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
buffer_get_u64(payload, &msg->offset); buffer_get_u64(payload, &msg->offset);
msg->data = buffer_get_ssh_string(payload); msg->data = buffer_get_ssh_string(payload);
if (msg->data == NULL) { if (msg->data == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -98,12 +106,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_REALPATH: case SSH_FXP_REALPATH:
tmp = buffer_get_ssh_string(payload); tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) { if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->filename = ssh_string_to_char(tmp); msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp); ssh_string_free(tmp);
if (msg->filename == NULL) { if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -112,17 +122,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_SYMLINK: case SSH_FXP_SYMLINK:
tmp = buffer_get_ssh_string(payload); tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) { if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->filename = ssh_string_to_char(tmp); msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp); ssh_string_free(tmp);
if (msg->filename == NULL) { if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->data = buffer_get_ssh_string(payload); msg->data = buffer_get_ssh_string(payload);
if (msg->data == NULL) { if (msg->data == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -131,17 +144,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_SETSTAT: case SSH_FXP_SETSTAT:
tmp = buffer_get_ssh_string(payload); tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) { if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->filename=ssh_string_to_char(tmp); msg->filename=ssh_string_to_char(tmp);
ssh_string_free(tmp); ssh_string_free(tmp);
if (msg->filename == NULL) { if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->attr = sftp_parse_attr(sftp, payload, 0); msg->attr = sftp_parse_attr(sftp, payload, 0);
if (msg->attr == NULL) { if (msg->attr == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -149,11 +165,13 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_FSETSTAT: case SSH_FXP_FSETSTAT:
msg->handle = buffer_get_ssh_string(payload); msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) { if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->attr = sftp_parse_attr(sftp, payload, 0); msg->attr = sftp_parse_attr(sftp, payload, 0);
if (msg->attr == NULL) { if (msg->attr == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -162,12 +180,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_STAT: case SSH_FXP_STAT:
tmp = buffer_get_ssh_string(payload); tmp = buffer_get_ssh_string(payload);
if (tmp == NULL) { if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->filename = ssh_string_to_char(tmp); msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp); ssh_string_free(tmp);
if (msg->filename == NULL) { if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
@@ -178,31 +198,38 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
case SSH_FXP_OPEN: case SSH_FXP_OPEN:
tmp=buffer_get_ssh_string(payload); tmp=buffer_get_ssh_string(payload);
if (tmp == NULL) { if (tmp == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
msg->filename = ssh_string_to_char(tmp); msg->filename = ssh_string_to_char(tmp);
ssh_string_free(tmp); ssh_string_free(tmp);
if (msg->filename == NULL) { if (msg->filename == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
buffer_get_u32(payload,&msg->flags); buffer_get_u32(payload,&msg->flags);
msg->attr = sftp_parse_attr(sftp, payload, 0); msg->attr = sftp_parse_attr(sftp, payload, 0);
if (msg->attr == NULL) { if (msg->attr == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
case SSH_FXP_FSTAT: case SSH_FXP_FSTAT:
msg->handle = buffer_get_ssh_string(payload); msg->handle = buffer_get_ssh_string(payload);
if (msg->handle == NULL) { if (msg->handle == NULL) {
ssh_set_error_oom(session);
sftp_client_message_free(msg); sftp_client_message_free(msg);
return NULL; return NULL;
} }
buffer_get_u32(payload, &msg->flags); buffer_get_u32(payload, &msg->flags);
break; break;
default: 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); msg->flags = ntohl(msg->flags);

View File

@@ -91,6 +91,8 @@ struct ssh_socket_struct {
ssh_poll_handle poll_out; 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_read(ssh_socket s, void *buffer, uint32_t len);
static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer, static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
uint32_t len); 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) * \brief inits the socket system (windows specific)
*/ */
int ssh_socket_init(void) { int ssh_socket_init(void) {
if (sockets_initialized == 0) {
#ifdef _WIN32 #ifdef _WIN32
struct WSAData wsaData; struct WSAData wsaData;
/* Initiates use of the Winsock DLL by a process. */ /* Initiates use of the Winsock DLL by a process. */
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1; return -1;
} }
#endif #endif
ssh_poll_init(); ssh_poll_init();
sockets_initialized = 1;
}
return 0; return 0;
} }
@@ -118,7 +124,13 @@ int ssh_socket_init(void) {
* @brief Cleanup the socket system. * @brief Cleanup the socket system.
*/ */
void ssh_socket_cleanup(void) { void ssh_socket_cleanup(void) {
if (sockets_initialized == 1) {
ssh_poll_cleanup(); 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)); s = malloc(sizeof(struct ssh_socket_struct));
if (s == NULL) { if (s == NULL) {
ssh_set_error_oom(session);
return NULL; return NULL;
} }
s->fd_in = SSH_INVALID_SOCKET; s->fd_in = SSH_INVALID_SOCKET;
@@ -140,11 +153,13 @@ ssh_socket ssh_socket_new(ssh_session session) {
s->session = session; s->session = session;
s->in_buffer = ssh_buffer_new(); s->in_buffer = ssh_buffer_new();
if (s->in_buffer == NULL) { if (s->in_buffer == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(s); SAFE_FREE(s);
return NULL; return NULL;
} }
s->out_buffer=ssh_buffer_new(); s->out_buffer=ssh_buffer_new();
if (s->out_buffer == NULL) { if (s->out_buffer == NULL) {
ssh_set_error_oom(session);
ssh_buffer_free(s->in_buffer); ssh_buffer_free(s->in_buffer);
SAFE_FREE(s); SAFE_FREE(s);
return NULL; 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 */ /* Check if we are in a connecting state */
if(s->state==SSH_SOCKET_CONNECTING){ if(s->state==SSH_SOCKET_CONNECTING){
s->state=SSH_SOCKET_ERROR; 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; s->last_errno=err;
ssh_socket_close(s); ssh_socket_close(s);
if(s->callbacks && s->callbacks->connected) 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; s->read_wontblock=1;
r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer)); r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer));
if(r<0){ if(r<0){
if(p != NULL) if(p != NULL) {
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); ssh_poll_remove_events(p, POLLIN);
}
if(s->callbacks && s->callbacks->exception){ if(s->callbacks && s->callbacks->exception){
s->callbacks->exception( s->callbacks->exception(
SSH_SOCKET_EXCEPTION_ERROR, SSH_SOCKET_EXCEPTION_ERROR,
s->last_errno,s->callbacks->userdata); 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){ 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){ if(s->callbacks && s->callbacks->exception){
s->callbacks->exception( s->callbacks->exception(
SSH_SOCKET_EXCEPTION_EOF, SSH_SOCKET_EXCEPTION_EOF,
0,s->callbacks->userdata); 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){ 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), buffer_get_rest_len(s->in_buffer),
s->callbacks->userdata); s->callbacks->userdata);
buffer_pass_bytes(s->in_buffer,r); 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){ if(s->state == SSH_SOCKET_CONNECTING){
ssh_log(s->session,SSH_LOG_PACKET,"Received POLLOUT in connecting state"); ssh_log(s->session,SSH_LOG_PACKET,"Received POLLOUT in connecting state");
s->state = SSH_SOCKET_CONNECTED; 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)); ssh_sock_set_blocking(ssh_socket_get_fd_in(s));
if(s->callbacks && s->callbacks->connected) if(s->callbacks && s->callbacks->connected)
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata); 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 */ /* So, we can write data */
s->write_wontblock=1; 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 buffered data is pending, write it */
if(buffer_get_rest_len(s->out_buffer) > 0){ 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); fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == SSH_INVALID_SOCKET) { 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; return -1;
} }
if (fcntl(fd, F_SETFD, 1) == -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); close(fd);
return -1; return -1;
} }
if (connect(fd, (struct sockaddr *) &sunaddr, if (connect(fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) { sizeof(sunaddr)) < 0) {
ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s",
strerror(errno));
close(fd); close(fd);
return -1; return -1;
} }
@@ -544,6 +586,7 @@ int ssh_socket_write(ssh_socket s, const void *buffer, int len) {
enter_function(); enter_function();
if(len > 0) { if(len > 0) {
if (buffer_add_data(s->out_buffer, buffer, len) < 0) { if (buffer_add_data(s->out_buffer, buffer, len) < 0) {
ssh_set_error_oom(s->session);
return SSH_ERROR; return SSH_ERROR;
} }
ssh_socket_nonblocking_flush(s); ssh_socket_nonblocking_flush(s);
@@ -632,6 +675,18 @@ int ssh_socket_data_writable(ssh_socket s) {
return s->write_wontblock; 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 ssh_socket_get_status(ssh_socket s) {
int r = 0; int r = 0;
@@ -646,6 +701,25 @@ int ssh_socket_get_status(ssh_socket s) {
return r; return r;
} }
/**
* @internal
* @brief Set a socket into the connecting state
* @param s socket handle
* @param fd file descriptor
*/
void ssh_socket_set_connecting(ssh_socket s, int fd){
ssh_socket_set_fd(s,fd);
s->state=SSH_SOCKET_CONNECTING;
/* POLLOUT is the event to wait for in a nonblocking connect */
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLOUT);
#ifdef _WIN32
ssh_poll_add_events(ssh_socket_get_poll_handle_in(s),POLLWRNORM);
#endif
}
/** /**
* @internal * @internal
* @brief Launches a socket connection * @brief Launches a socket connection
@@ -665,19 +739,16 @@ int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bin
socket_t fd; socket_t fd;
ssh_session session=s->session; ssh_session session=s->session;
enter_function(); 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; return SSH_ERROR;
}
fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port); fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port);
ssh_log(session,SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd); ssh_log(session,SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd);
if(fd == SSH_INVALID_SOCKET) if(fd == SSH_INVALID_SOCKET)
return SSH_ERROR; return SSH_ERROR;
ssh_socket_set_fd(s,fd); ssh_socket_set_connecting(s,fd);
s->state=SSH_SOCKET_CONNECTING;
/* POLLOUT is the event to wait for in a nonblocking connect */
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLOUT);
#ifdef _WIN32
ssh_poll_add_events(ssh_socket_get_poll_handle_in(s),POLLWRNORM);
#endif
leave_function(); leave_function();
return SSH_OK; return SSH_OK;
} }
@@ -744,7 +815,7 @@ int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
s->state=SSH_SOCKET_CONNECTED; s->state=SSH_SOCKET_CONNECTED;
s->fd_is_socket=0; s->fd_is_socket=0;
/* POLLOUT is the event to wait for in a nonblocking connect */ /* 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); ssh_poll_set_events(ssh_socket_get_poll_handle_out(s),POLLOUT);
if(s->callbacks && s->callbacks->connected) if(s->callbacks && s->callbacks->connected)
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata); s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);

View File

@@ -21,10 +21,13 @@
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include <errno.h>
#include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifndef _WIN32 #ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@@ -50,7 +53,11 @@
struct ssh_string_struct *ssh_string_new(size_t size) { struct ssh_string_struct *ssh_string_new(size_t size) {
struct ssh_string_struct *str = NULL; struct ssh_string_struct *str = NULL;
str = malloc(size + 4); if (size > UINT_MAX - sizeof(struct ssh_string_struct)) {
return NULL;
}
str = malloc(sizeof(struct ssh_string_struct) + size);
if (str == NULL) { if (str == NULL) {
return NULL; return NULL;
} }
@@ -91,8 +98,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. * @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 *ssh_string_from_char(const char *what) {
struct ssh_string_struct *ptr = NULL; struct ssh_string_struct *ptr;
size_t len = strlen(what); size_t len;
if(what == NULL) {
errno = EINVAL;
return NULL;
}
len = strlen(what);
ptr = malloc(4 + len); ptr = malloc(4 + len);
if (ptr == NULL) { if (ptr == NULL) {
@@ -133,16 +147,22 @@ size_t ssh_string_len(struct ssh_string_struct *s) {
char *ssh_string_to_char(struct ssh_string_struct *s) { char *ssh_string_to_char(struct ssh_string_struct *s) {
size_t len; size_t len;
char *new; char *new;
if(s==NULL) if (s == NULL || s->string == NULL) {
return NULL; return NULL;
len = ntohl(s->size) + 1; }
new = malloc(len);
len = ssh_string_len(s);
if (len + 1 < len) {
return NULL;
}
new = malloc(len + 1);
if (new == NULL) { if (new == NULL) {
return NULL; return NULL;
} }
memcpy(new, s->string, len - 1); memcpy(new, s->string, len);
new[len - 1] = '\0'; new[len] = '\0';
return new; return new;
} }
@@ -164,7 +184,12 @@ void ssh_string_free_char(char *s) {
* @return Newly allocated copy of the string, NULL on error. * @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 *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) { if (new == NULL) {
return 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 n=CRYPTO_num_locks();
int i; int i;
if(user_callbacks == &ssh_threads_noop) if(user_callbacks == &ssh_threads_noop)
@@ -109,7 +109,7 @@ static int libcrypto_thread_init(){
return SSH_OK; return SSH_OK;
} }
static void libcrypto_thread_finalize(){ static void libcrypto_thread_finalize(void){
int n=CRYPTO_num_locks(); int n=CRYPTO_num_locks();
int i; int i;
if (libcrypto_mutexes==NULL) if (libcrypto_mutexes==NULL)

View File

@@ -86,6 +86,12 @@ install(
if (WITH_STATIC_LIB) if (WITH_STATIC_LIB)
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS}) 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( set_target_properties(
${LIBSSH_THREADS_STATIC_LIBRARY} ${LIBSSH_THREADS_STATIC_LIBRARY}
PROPERTIES PROPERTIES
@@ -93,15 +99,26 @@ if (WITH_STATIC_LIB)
${LIBRARY_VERSION} ${LIBRARY_VERSION}
SOVERSION SOVERSION
${LIBRARY_SOVERSION} ${LIBRARY_SOVERSION}
COMPILE_FLAGS OUTPUT_NAME
"-DLIBSSH_STATIC" 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( install(
TARGETS TARGETS
${LIBSSH_THREADS_STATIC_LIBRARY} ${LIBSSH_THREADS_STATIC_LIBRARY}
DESTINATION DESTINATION
${LIB_INSTALL_DIR} ${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
COMPONENT COMPONENT
libraries libraries
) )

View File

@@ -38,6 +38,10 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#ifdef WITH_LIBZ
#include <zlib.h>
#endif
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/crypto.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_new(void) {
struct ssh_crypto_struct *crypto; struct ssh_crypto_struct *crypto;
crypto = malloc(sizeof(struct ssh_crypto_struct)); crypto = malloc(sizeof(struct ssh_crypto_struct));
if (crypto == NULL) { if (crypto == NULL) {
@@ -108,6 +112,18 @@ void crypto_free(struct ssh_crypto_struct *crypto){
bignum_free(crypto->y); bignum_free(crypto->y);
bignum_free(crypto->k); bignum_free(crypto->k);
/* lot of other things */ /* 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 */ /* i'm lost in my own code. good work */
memset(crypto,0,sizeof(*crypto)); memset(crypto,0,sizeof(*crypto));
@@ -219,11 +235,15 @@ int crypt_set_algorithms_server(ssh_session session){
int i = 0; int i = 0;
struct crypto_struct *ssh_ciphertab=ssh_get_ciphertab(); 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 */ /* we must scan the kex entries to find crypto algorithms and set their appropriate structure */
enter_function(); enter_function();
/* out */ /* out */
server = session->server_kex.methods[SSH_CRYPT_S_C]; 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]; client = session->client_kex.methods[SSH_CRYPT_S_C];
} else { } else {
ssh_log(session,SSH_LOG_PROTOCOL, "Client KEX empty"); 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) if(!found)
goto parseerror; goto parseerror;
fclose(fd); pclose(fd);
return 0; return 0;
parseerror: parseerror:
fprintf(stderr,"Parse error : couldn't locate average in %s",line); fprintf(stderr,"Parse error : couldn't locate average in %s",line);
fclose(fd); pclose(fd);
return -1; return -1;
} }

View File

@@ -41,6 +41,8 @@ static void torture_sftp_mkdir(void **state) {
snprintf(tmpdir, sizeof(tmpdir), "%s/mkdir_test", t->testdir); snprintf(tmpdir, sizeof(tmpdir), "%s/mkdir_test", t->testdir);
rc = sftp_mkdir(t->sftp, tmpdir, 0755); rc = sftp_mkdir(t->sftp, tmpdir, 0755);
if(rc != SSH_OK)
fprintf(stderr,"error:%s\n",ssh_get_error(t->sftp->session));
assert_true(rc == 0); assert_true(rc == 0);
/* check if it really has been created */ /* check if it really has been created */

View File

@@ -21,13 +21,15 @@
* MA 02111-1307, USA. * MA 02111-1307, USA.
*/ */
#include <sys/types.h> #include "config.h"
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <errno.h>
# include <unistd.h> # include <unistd.h>
#endif #endif
@@ -35,6 +37,7 @@
static int verbosity = 0; static int verbosity = 0;
#ifndef _WIN32
static int _torture_auth_kbdint(ssh_session session, static int _torture_auth_kbdint(ssh_session session,
const char *password) { const char *password) {
const char *prompt; const char *prompt;
@@ -129,6 +132,7 @@ int torture_rmdirs(const char *path) {
rewinddir(d); rewinddir(d);
} }
} else { } else {
closedir(d);
return -1; return -1;
} }
@@ -146,10 +150,6 @@ int torture_isdir(const char *path) {
return 0; return 0;
} }
int torture_libssh_verbosity(void){
return verbosity;
}
ssh_session torture_ssh_session(const char *host, ssh_session torture_ssh_session(const char *host,
const char *user, const char *user,
const char *password) { const char *password) {
@@ -216,6 +216,8 @@ failed:
return NULL; return NULL;
} }
#ifdef WITH_SFTP
struct torture_sftp *torture_sftp_session(ssh_session session) { struct torture_sftp *torture_sftp_session(ssh_session session) {
struct torture_sftp *t; struct torture_sftp *t;
char template[] = "/tmp/ssh_torture_XXXXXX"; char template[] = "/tmp/ssh_torture_XXXXXX";
@@ -246,6 +248,8 @@ struct torture_sftp *torture_sftp_session(ssh_session session) {
if (p == NULL) { if (p == NULL) {
goto failed; goto failed;
} }
/* useful if TESTUSER is not the local user */
chmod(template,0777);
t->testdir = strdup(p); t->testdir = strdup(p);
if (t->testdir == NULL) { if (t->testdir == NULL) {
goto failed; goto failed;
@@ -258,6 +262,7 @@ failed:
} }
ssh_disconnect(t->ssh); ssh_disconnect(t->ssh);
ssh_free(t->ssh); ssh_free(t->ssh);
free(t);
return NULL; return NULL;
} }
@@ -281,6 +286,14 @@ void torture_sftp_close(struct torture_sftp *t) {
free(t->testdir); free(t->testdir);
free(t); free(t);
} }
#endif /* WITH_SFTP */
#endif /* _WIN32 */
int torture_libssh_verbosity(void){
return verbosity;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct argument_s arguments; 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_list torture_list.c ${TORTURE_LIBRARY})
add_cmockery_test(torture_misc torture_misc.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_options torture_options.c ${TORTURE_LIBRARY})
add_cmockery_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
if (UNIX AND NOT WIN32) if (UNIX AND NOT WIN32)
# requires ssh-keygen # requires ssh-keygen
add_cmockery_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY}) 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 "torture.h"
#include "misc.c" #include "misc.c"
#include "error.c"
#define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.." #define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.."
@@ -159,6 +161,30 @@ static void torture_path_expand_known_hosts(void **state) {
free(tmp); 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 torture_run_tests(void) {
int rc; int rc;
const UnitTest tests[] = { const UnitTest tests[] = {
@@ -173,6 +199,8 @@ int torture_run_tests(void) {
#endif #endif
unit_test_setup_teardown(torture_path_expand_escape, setup, teardown), unit_test_setup_teardown(torture_path_expand_escape, setup, teardown),
unit_test_setup_teardown(torture_path_expand_known_hosts, 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(); ssh_init();

View File

@@ -119,6 +119,23 @@ static void torture_options_set_identity(void **state) {
assert_string_equal(session->identity->root->next->data, "identity1"); assert_string_equal(session->identity->root->next->data, "identity1");
} }
static void torture_options_proxycommand(void **state) {
ssh_session session = *state;
int rc;
/* Enable ProxyCommand */
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "ssh -q -A -X -W %h:%p JUMPHOST");
assert_int_equal(rc, 0);
assert_string_equal(session->ProxyCommand, "ssh -q -A -X -W %h:%p JUMPHOST");
/* Disable ProxyCommand */
rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "none");
assert_int_equal(rc, 0);
assert_true(session->ProxyCommand == NULL);
}
int torture_run_tests(void) { int torture_run_tests(void) {
int rc; int rc;
const UnitTest tests[] = { const UnitTest tests[] = {
@@ -127,6 +144,7 @@ int torture_run_tests(void) {
unit_test_setup_teardown(torture_options_set_fd, setup, teardown), unit_test_setup_teardown(torture_options_set_fd, setup, teardown),
unit_test_setup_teardown(torture_options_set_user, setup, teardown), unit_test_setup_teardown(torture_options_set_user, setup, teardown),
unit_test_setup_teardown(torture_options_set_identity, setup, teardown), unit_test_setup_teardown(torture_options_set_identity, setup, teardown),
unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
}; };
ssh_init(); ssh_init();