Compare commits

..

107 Commits

Author SHA1 Message Date
Andreas Schneider
319129399d Bump version to 0.6.4. 2014-12-17 19:45:23 +01:00
Jon Simons
87ae95eb3c CVE-2014-8132: Fixup error path in ssh_packet_kexinit()
Before this change, dangling pointers can be unintentionally left in the
respective next_crypto kex methods slots.  Ensure to set all slots to
NULL in the error-out path.

Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2ced24ddd67a261dc364ad4d8958c068c1671ae7)
2014-12-17 19:45:23 +01:00
Andreas Schneider
055f102601 libcrypto: Fix Windows build with ssh_reseed().
gettimeofday() is not available on Windows and we need it only in case
of forking.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b7b535816d)
2014-12-17 19:40:57 +01:00
Andreas Schneider
2d6862ddb9 cmake: Fix the build on Windows.
(cherry picked from commit a738507ad2)
2014-12-17 19:31:32 +01:00
Andreas Schneider
22aa60d506 cmake: Fix config variable names.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d8e691b58a)
2014-12-17 10:40:31 +01:00
Andreas Schneider
4b02bbbd32 cmake: Fix libssh cmake-config files.
(cherry picked from commit 142b2e4ede)
2014-12-17 10:40:25 +01:00
William Orr
31ded2070e config: Also tokenize on equal sign.
The ssh config specifies it as a valid separator.

BUG: https://red.libssh.org/issues/166

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 52968b1a11)
2014-12-17 10:35:17 +01:00
Davide \"FunkyAss\" Del Zompo
df3d53e561 doc: clarify tutorial error section
Signed-off-by: Davide "FunkyAss" Del Zompo <davide.delzompo@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit bb197de75d)
2014-12-05 11:09:34 +01:00
Hani Benhabiles
f28c3099da Set the correct error in ssh_options_set().
Signed-off-by: Hani Benhabiles <hani@linux.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 03095f1516)
2014-12-05 11:04:35 +01:00
Andreas Schneider
32a106c70d messages: Fix a possible double free.
Thanks to Ramana Gampa.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2014-12-05 10:59:41 +01:00
Jon Simons
5d75090d9f pki_crypto.c: plug ecdsa_sig->[r,s] bignum leaks
Per ecdsa(3ssl), ECDSA_SIG_new does allocate its 'r' and 's' bignum fields.
Fix a bug where the initial 'r' and 's' bignums were being overwritten with
newly-allocated bignums, resulting in a memory leak.

BUG: https://red.libssh.org/issues/175

Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>

(cherry picked from commit 4745d652b5)
2014-12-05 10:46:31 +01:00
Andreas Schneider
32a3cfe661 connect: Do not fail if the connect is in progress.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a48711ae7e)
2014-10-28 10:33:47 +01:00
Stef Walter
1c59844dfe gssapi: ssh_gssapi_set_creds() is a client side function
It should not be guarded by the WITH_SERVER #ifdef

Signed-off-by: Stef Walter <stefw@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit cd2dc3770a)
2014-10-12 15:47:13 +02:00
William Orr
f071954a76 Check return code of connect(2).
Signed-off-by: William Orr <will@worrbase.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 250f506487)
2014-10-12 15:47:12 +02:00
Artyom V. Poptsov
a033b93c61 pki_gcrypt: Initialize 'type_c' in 'pki_do_sign_sessionid'
Add missing initialization of 'type_c' field of a SSH signature in
'pki_do_sign_sessionid' procedure.

If libssh is compiled with GCrypt, 'dh_handshake_server' fails with
"Could not sign the session id" error.  The change fixes that.

Signed-off-by: Artyom V. Poptsov <poptsov.artyom@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit aaae6cd97d)
2014-10-02 08:30:30 +02:00
Jon Simons
b7856780a9 crypto: check malloc return in ssh_mac_ctx_init
Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit af25c5e668)
2014-10-02 08:26:08 +02:00
Jon Simons
8b3425865a wrapper: fix z_stream leak
Ensure to free the z_stream structures as allocated from
the gzip.c initcompress, initdecompress functions.

Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 092fe0b727)
2014-10-02 08:25:27 +02:00
Andreas Schneider
a30e234c03 string: Correctly burn the string buffer.
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Aris Adamantiadis <aris@0xbadc0de.be>
(cherry picked from commit 1ddb99c46f)
2014-09-15 20:46:06 +02:00
Jon Simons
bbf172a79c session: fix ssh_session->srv.ecdsa_key leak
Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-05-28 10:24:01 +02:00
Andreas Schneider
f28748578d pki: Fix build without ECC support.
Signed-off-by: Andreas Schneider <asn@samba.org>
2014-05-09 08:56:10 +02:00
Andreas Schneider
36f7d1a614 pki: Add missing semi-colon. 2014-05-07 09:36:11 +02:00
Andreas Schneider
71241ca68c pki: Move ssh_pki_key_ecdsa_name() to the correct file. 2014-05-07 09:35:49 +02:00
Andreas Schneider
bfbf9283d0 cmake: Fix doxygen. 2014-05-07 09:35:34 +02:00
Andreas Schneider
d75573e665 cmake: Update doxygen module. 2014-05-07 09:35:34 +02:00
Jon Simons
8fe36e3d07 pki crypto: expose new ssh_pki_key_ecdsa_name API
Enable retrieving the "ecdsa-sha2-nistpNNN" name of ECDSA keys with a
new 'ssh_pki_key_ecdsa_name' API.  This gives more information than the
'ssh_key_type_to_char' API, which yields "ssh-ecdsa" for ECDSA keys.
The motivation is that this info is useful to have in a server context.

The torture_pki unit test is updated to include the new API, and a few
more passes are added to additionally test 384 and 521-bit keys.

Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-05-07 09:35:06 +02:00
Alan Dunn
f2e9ce68e7 messages: Add missing ntohl on X11 request screen number
BUG: https://red.libssh.org/issues/160

Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-05-06 08:56:55 +02:00
Andreas Schneider
cfb4d27c47 pki: Correctly update the ECDSA keytype.
(cherry picked from commit 2884bbf5b1)
2014-05-06 08:54:11 +02:00
Andreas Schneider
d366e289f3 pki: Move ssh_pki_key_ecdsa_name() to the correct file.
(cherry picked from commit f48a99b97c)
2014-05-06 08:54:06 +02:00
Andreas Schneider
2fc8347504 pki: Make pki_key_ecdsa_nid_to_name() a shared function.
(cherry picked from commit 11cfb2903e)
2014-05-06 08:54:00 +02:00
Andreas Schneider
2691ed595e cmake: Install cmake config files to the correct directory.
(cherry picked from commit 291312c5e4)
2014-04-22 09:10:05 +02:00
Andreas Schneider
7b133cf9f5 doc: Improve docs for ssh_channel_get_exit_status().
BUG: https://red.libssh.org/issues/154
(cherry picked from commit adf23533e0)
2014-04-22 09:09:57 +02:00
Andreas Schneider
9b59f1a222 channels: Fix exit-signal request.
BUG: https://red.libssh.org/issues/153
(cherry picked from commit 927cd90dc1)
2014-04-22 09:09:56 +02:00
Andreas Schneider
8f21f879d3 session: Fix a memory leak with custom banner.
BUG: https://red.libssh.org/issues/152
(cherry picked from commit b5efbe75cd)
2014-04-22 09:09:39 +02:00
Andreas Schneider
67752dabfc cmake: Enable creation of the compile command database by default.
(cherry picked from commit 437a39c798)
2014-04-22 09:09:28 +02:00
Jon Simons
34ac4e4248 packet: elide two buffer_prepend calls into one
In packet_send2, rather than issue two separate buffer_prepend_data calls
(each of which may entail realloc + memmove + memcpy), elide the prepend
work into a single buffer_prepend_data: the header information is computed
locally, and a single 5 byte prepend operation is now done instead of
prepending 1, then 4 bytes.

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit aa05248ca8)

Conflicts:
	src/packet.c
2014-03-27 11:25:15 +01:00
Andreas Schneider
1928fb6a85 doc: Fix ssh_userauth_none() function signature.
Thanks to David Tibbe!

BUG: https://red.libssh.org/issues/151
(cherry picked from commit 04543c9dbc)
2014-03-27 11:16:23 +01:00
Alan Dunn
5b1678f197 doc: Improve and consolidate ssh_bind_options_set docs
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 47bd0b6d1f)
2014-03-27 11:15:39 +01:00
Petar Koretic
8aff91dfcb libssh: libhpp: overload read function to support timeout parameter
Signed-off-by: Petar Koretic <petar.koretic@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8e2590b535)
2014-03-27 11:15:39 +01:00
Petar Koretic
c0cc12d582 libssh: libhpp: avoid unnecessary call to ssh_channel_read
ssh_channel_read is a wrapper for ssh_channel_read_timeout with timeout
-1 (infinite) so we call that directly.

Signed-off-by: Petar Koretic <petar.koretic@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c51f42a566)
2014-03-27 11:15:39 +01:00
Petar Koretic
a162071f9a libssh: libhpp: fix multiple definitions for acceptForward function
Defining a non inlined class function in a header will cause multiple
definitions when header is included in more that one file since for each
file function will get defined.

Signed-off-by: Petar Koretic <petar.koretic@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 00d4fbe753)

Conflicts:
	include/libssh/libsshpp.hpp
2014-03-27 11:15:19 +01:00
Jon Simons
2091dab273 channel: check for closed state in waitwindow loops
Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dee8e5688b)
2014-03-27 11:14:25 +01:00
Jon Simons
7f18ec4620 kex: enable more ECDSA hostkey algos
Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 40d81bb7ca)
2014-03-27 11:14:25 +01:00
Jon Simons
8e698382db pki_crypto: guard against NULL pubkey->rsa in signature extraction
Signed-off-by: Jon Simons <jon@jonsimons.org>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 10bc5ac203)
2014-03-27 11:14:25 +01:00
Luka Perkov
ce10d40325 session: fix comment typo
Signed-off-by: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8ba9402282)
2014-03-27 11:14:25 +01:00
Luka Perkov
3fed9a5aff messages: use predefined macro for clearing sensitive data
Signed-off-by: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a2fe341da5)
2014-03-27 11:14:25 +01:00
Luka Perkov
da0c77fdb1 client: fix corner case when sockets are manually created
If the sockets are created manually and passed to libssh the internal session
state is set to SSH_SESSION_STATE_SOCKET_CONNECTED. Result of this fix can be
verified by running torture_connect test (torture_connect_socket) with -vvvv
flags.

Signed-off-by: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit dbb2de272b)
2014-03-27 11:14:25 +01:00
Luka Perkov
818c80baed tests: torture_connect: add test for user provided socket
Signed-off-by: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9423a3a065)
2014-03-27 11:14:25 +01:00
Luka Perkov
bb55bb2daf tests: torture_connect: fix coding style
Signed-off-by: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0c5d4954a7)
2014-03-27 11:14:25 +01:00
Petar Koretic
fdced9d544 pki_crypto: Replace deprecated RSA_generate_key() with RSA_generate_key_ex()
On Mar 16, 09:41, Aris Adamantiadis wrote:
> Hi Petar,
> I agree with the principle, but I don't think this code can work...
> RSA_generate_key takes an RSA* as parameter and in our code we probably
> have key->rsa==NULL. (if we don't then the old code had a memory leak).
>
> Does the test case work ?
>
> Aris
>

Yes, you are right. This works, tested with tests/unittests/torture_pki

Signed-off-by: Petar Koretic <petar.koretic@sartura.hr>
(cherry picked from commit 0b8d24f800)
2014-03-27 11:14:25 +01:00
Luka Perkov
96db44ff17 update gitignore file
The libssh library by default does not allow in-source build (with cmake
MacroEnsureOutOfSourceBuild macro). The INSTALL file (implicitly) suggests
creating a build directory. So lets add build to list of git ignore files to
avoid complaints from git.

Signed-off-by: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 48354f56ec)
2014-03-27 11:14:25 +01:00
Alan Dunn
70dbbfa320 doc: Add ECDSA keys to docs, make key docs consistent
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f6276fe739)
2014-03-27 11:13:15 +01:00
Alan Dunn
1118fc2adf options: Allow use of host ECDSA key
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2a1089d607)
2014-03-27 11:13:15 +01:00
Andreas Schneider
257449a0b6 tests: Check the the ecdsa_nid is the same.
(cherry picked from commit fbf73ede1e)
2014-03-27 11:13:15 +01:00
Alan Dunn
8752460df4 tests: Add test case for bug #147
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 577840d7f7)
2014-03-27 11:13:15 +01:00
Alan Dunn
6f089a098b pki_crypto: Always copy ecdsa_nid into duplicated ECDSA keys
BUG: https://red.libssh.org/issues/147

Signed-off-by: Alan Dunn <amdunn@gmail.com>
2014-03-12 14:16:43 +01:00
Alan Dunn
8b3be050c9 pki: Use SHA-2 for session ID signing with ECDSA keys
Previously, SHA-1 was used always.

BUG: https://red.libssh.org/issues/148

Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-03-12 14:16:35 +01:00
Luka Perkov
ade33474be server: silence build warning
The commit fixes this build warning:

====
src/server.c:223:8: warning: ‘privkey’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey);
        ^
src/server.c:243:11: note: ‘privkey’ was declared here
   ssh_key privkey;
====

Signed-off-by: Luka Perkov <luka.perkov@sartura.hr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-03-12 14:16:33 +01:00
Jon Simons
dbf7749696 packet: log disconnect code in host byte order
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-03-12 14:16:30 +01:00
Jon Simons
2db45dd547 bind: only set bindfd after successful listen
In 'ssh_bind_listen', move setting of 'sshbind->bindfd' to only happen after
the listen call: otherwise 'bindfd' can be set to a bogus descriptor for the
case that listen fails.

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-03-12 14:16:28 +01:00
Andreas Schneider
87145387aa Prepare libssh-0.6.3.
We messed up some thing, so we release 0.6.3.
2014-03-04 13:20:52 +01:00
Aris Adamantiadis
d027460792 bump version to 0.6.2 2014-03-04 11:34:36 +01:00
Aris Adamantiadis
3fdd82f2a8 security: fix for vulnerability CVE-2014-0017
When accepting a new connection, a forking server based on libssh forks
and the child process handles the request. The RAND_bytes() function of
openssl doesn't reset its state after the fork, but simply adds the
current process id (getpid) to the PRNG state, which is not guaranteed
to be unique.
This can cause several children to end up with same PRNG state which is
a security issue.
2014-03-04 09:55:02 +01:00
Andreas Schneider
6cd94a63ff pki: Fix the build on OpenSolaris. 2014-02-12 09:40:09 +01:00
Andreas Schneider
e85b20ba82 pki: Fix memory leak with ecdsa signatures. 2014-02-11 10:31:51 +01:00
Andreas Schneider
78d5d64b38 Update ChangeLog. 2014-02-10 10:17:43 +01:00
Andreas Schneider
f73a44c223 cpack: Ignore obj directory. 2014-02-10 10:17:43 +01:00
Andreas Schneider
1cccfdf8a0 packet: Improve readablity of packet decrypt.
After discussion with Aris and it was not obvious enough to understand
the issue we decided to refactor it.

Reviewd-by: Aris Adamantiadis <aris@0xbadc0de.be>
2014-02-06 20:32:05 +01:00
Alan Dunn
abe4ed0e75 packet_crypt: Make packet_{en,de}crypt fail consistently on len == 0
Right now the behavior of packet_{en,de}crypt on len == 0 depends on
the behavior of malloc.  Instead, make these consistently fail based
on what I assume the desired behavior is due to the first error
message in each.

Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-06 19:40:29 +01:00
Alan Dunn
e7f831f0a3 packet: Do not decrypt zero length rest of buffer
If we receive a packet of length exactly blocksize, then
packet_decrypt gets called on a buffer of size 0.  The check at the
beginning of packet_decrypt indicates that the function should be
called on buffers of at least one blocksize, though the check allows
through zero length.  As is packet_decrypt can return -1 when len is 0
because malloc can return NULL in this case: according to the ISO C
standard, malloc is free to return NULL or a pointer that can be freed
when size == 0, and uclibc by default will return NULL here (in
"non-glibc-compatible" mode).  The net result is that when using
uclibc connections with libssh can anomalously fail.

Alternatively, packet_decrypt (and probably packet_encrypt for
consistency) could be made to always succeed on len == 0 without
depending on the behavior of malloc.

Thanks to Josh Berlin for bringing conneciton failures with uclibc to
my attention.

Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-06 19:40:09 +01:00
Raphael Kubo da Costa
4ea4e12df2 build: Use Threads_FOUND to decide whether to build ssh_threads.
Follow-up to 4e04ec8, which caused a regression on OS X.

Checking the value of CMAKE_THREAD_LIBS_INIT to decide whether any threading
library is present on a system turns out to be wrong -- in OS X, for
example, usage of pthreads does not depend on any additional linker or
compiler flags, so CMAKE_THREAD_LIBS_INIT is empty and our check in
src/CMakeLists.txt failed (it used to work before 4e04ec8 because
CMAKE_HAVE_THREADS_LIBRARY is set).

Instead, just look for Threads_FOUND, which FindThreads sets just like any
other Find module when it has found what it was looking for.

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-06 11:13:23 +01:00
Jon Simons
fb49e194df session: skip timestamp init for non-blocking case
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-06 11:13:22 +01:00
Jon Simons
13f4e31ad1 session: add getters for session cipher names
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-06 11:13:20 +01:00
Aris Adamantiadis
da5fa4ef66 Revert f2c2687ca6
Fix bug #142
The mode does need to be an octal numeric string. Mode 0600 now gets sent on the wire as 0384, triggering a "scp: protocol error: bad mode" response, and an "scp status code 1d not valid" message from libssh.
2014-02-05 22:30:10 +01:00
Aris Adamantiadis
dca415a38e knownhosts: resolve leaks found by coverity 2014-02-05 08:08:31 +01:00
Aris Adamantiadis
56f86cd4a1 knownhosts: detect variations of ecdsa 2014-02-05 08:08:31 +01:00
Aris Adamantiadis
f265afacfb tests: lines lost during last cherry-pick merge 2014-02-04 16:20:20 +01:00
Aris Adamantiadis
99f8b2b803 Kex: fix coverity warning + edge case 2014-02-04 16:04:45 +01:00
Audrius Butkevicius
22edaf43ee server: use custom server banners
Value of session->serverbanner never gets used

Signed-off-by: Audrius Butkevicius <audrius.butkevicius@gmail.com>
2014-02-04 16:04:26 +01:00
Aris Adamantiadis
497bd31364 server: allow custom server banners (bug #83) 2014-02-04 16:04:26 +01:00
Aris Adamantiadis
8ed0c0b3c8 Knownhosts: implement hostkey with knownhosts heuristic 2014-02-04 16:01:37 +01:00
Aris Adamantiadis
ce39d2fa73 knownhosts: add test case for bug #138 2014-02-04 16:01:37 +01:00
Aris Adamantiadis
90d3768f0f known_hosts: add ssh_knownhosts_algorithms()
Goal of that function is to test the preferred key exchange methods
based on what's available in the known_hosts file

Conflicts:
	tests/client/torture_knownhosts.c
2014-02-04 16:01:02 +01:00
Aris Adamantiadis
6f66032209 build: remove OSX deprecated warnings for openssl 2014-02-04 15:55:37 +01:00
Raphael Kubo da Costa
c571cd8402 threads: Be less strict when deciding whether to build libssh_threads.
As mentioned in the previous commit, there are cases where
CMAKE_HAVE_THREADS_LIBRARY is not set and pthreads _is_ being used: one can
pass -DTHREADS_HAVE_PTHREAD_ARG=1 to CMake directly so that it just passes
-pthread to the compiler/linker and does not set CMAKE_HAVE_THREADS_LIBRARY.

Since we are only interested in knowing whether any threading library has
been found, we should use CMAKE_THREAD_LIBS_INIT instead (Threads_FOUND
would also work).

Note that, at the moment, there is only a pthreads backend available in
threads/, so if it is not found configuration will fail because CMake will
try to create a library from an empty set of source files.

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-03 14:39:15 +01:00
Raphael Kubo da Costa
b049e12652 ConfigureChecks: Stop checking for CMAKE_HAVE_THREADS_LIBRARY.
libssh is primarily interested in whether pthreads is present and can be
used. Checking for CMAKE_HAVE_THREADS_LIBRARY is not the same thing, as
there are cases where pthread exists but CMAKE_HAVE_THREADS_LIBRARY is not
set (for example, FreeBSD passes -DTHREADS_HAVE_PTHREAD_ARG=1 to CMake by
default as a way to skip the checks for -lpthread, -lpthreads and others and
tell the build system that -pthread is the one expected to be used).

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-03 14:39:14 +01:00
Jon Simons
785682ac28 socket: fix read of non-connected socket
Ensure to check whether the socket at hand is indeed still connected
throughout POLLIN processing in ssh_socket_pollcallback.

Before this change, the POLLIN block in ssh_socket_pollcallback is
predicated against the condition (s->state == SSH_SOCKET_CONNECTED).
Once entered, data from the socket is consumed through the data
callback in this loop:

  do {
    r = s->callbacks->data(buffer_get_rest(s->in_buffer),
                           buffer_get_rest_len(s->in_buffer),
                           s->callbacks->userdata);
    buffer_pass_bytes(s->in_buffer,r);
  } while (r > 0);

However, it is possible for the socket data callback to change the
state of the socket (closing it, for example).  Fix the loop to only
continue so long as the socket remains connected: this also entails
setting the ssh_socket state to SSH_SOCKET_CLOSED upon close.

The bug can be observed before the change by sending a bogus banner
to the server: 'echo -e "A\r\nB\r\n" | nc localhost 22'.  Each of
'A' and 'B' will be processed by 'callback_receive_banner', even
though the client socket is closed after rejection of 'A'.

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-02 22:21:07 +01:00
Jon Simons
f29f10876a doc: correct ssh_channel_read_timeout units
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-02 22:21:07 +01:00
Audrius Butkevicius
45d28c7682 doc: Document expected return value of channel data callback
Signed-off-by: Audrius Butkevicius <audrius.butkevicius@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-02 22:21:07 +01:00
Audrius Butkevicius
2786565e77 src: Fix argument order in ssh_channel_pty_window_change_callback
So that it would match ssh_channel_pty_request_callback as well as the documentation

Signed-off-by: Audrius Butkevicius <audrius.butkevicius@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-02 22:21:07 +01:00
Joseph Southwell
96ad690c80 src: Define MAX_BUF_SIZE globally and use it.
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-02 22:21:07 +01:00
Joseph Southwell
0d82186503 client: Fix EOF session error reporting.
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-02 22:21:07 +01:00
Oleksandr Shneyder
5157d96958 Make function ssh_channel_accept() nonblocking if timeout is 0.
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-02-02 22:21:07 +01:00
Andreas Schneider
6a0787a366 pki_crypto: Fix memory leak with EC_KEY_set_public_key().
BUG: https://red.libssh.org/issues/146
2014-01-28 12:01:35 +01:00
Andreas Schneider
709e921942 doc: Document the unit for ssh_select() timeout.
BUG: https://red.libssh.org/issues/143
2014-01-23 11:29:58 +01:00
Rod Vagg
43a69b0a65 dh: Fix NULL check for p_group14.
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-23 11:22:22 +01:00
Jon Simons
18506f697c pki_crypto: fix DSA signature extraction
Fix the DSA portion of 'pki_signature_to_blob': before this change, it
is possible to sometimes observe DSA signature validation failure when
testing with OpenSSH clients.  The problem ended up being the following
snippet which did not account for the case when 'ssh_string_len(x)' may
be less than 20:

  r = make_bignum_string(sig->dsa_sig->r);
  ...
  memcpy(buffer,
         ((char *) ssh_string_data(r)) + ssh_string_len(r) - 20,
         20);

Above consider the case that ssh_string_len(r) is 19; in that case the
memcpy unintentionally starts in the wrong place.  The same situation
can happen for value 's' in this code.

To fix, adjust the offsets used for the input and output pointers, taking
into account that the lengths of 'r' and 's' can be less than 20.  With
the fix I am no longer able to reproduce the original failure mode.

BUG: https://red.libssh.org/issues/144

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-23 11:17:45 +01:00
Alan Dunn
15bede0c0e doc: Fix description of error parameter for ssh_get_error*
ssh_get_error can actually work on anything with an ssh_common_struct
as its first member.  It is already used in examples in the
distribution with ssh_sessions and ssh_binds.

Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-22 09:46:00 +01:00
Jon Simons
92dde09a37 pki_crypto: pad RSA signature blobs
Pad RSA signature blobs to the expected RSA signature length
when processing via 'pki_signature_to_blob'.

Some clients, notably PuTTY, may send unpadded RSA signatures
during the public key exchange: before this change, one can
sometimes observe failure in signature validation when using
PuTTY's 'plink' client, along these lines:

   ssh_packet_process: ssh_packet_process: Dispatching handler for packet type 50
   ssh_packet_userauth_request: ssh_packet_userauth_request: Auth request for service ssh-connection, method publickey for user 'foo'
   ssh_pki_signature_verify_blob: ssh_pki_signature_verify_blob: Going to verify a ssh-rsa type signature
   pki_signature_verify: pki_signature_verify: RSA error: error:04091077:rsa routines:INT_RSA_VERIFY:wrong signature length
   ssh_packet_userauth_request: ssh_packet_userauth_request: Received an invalid  signature from peer

For cross-reference this issue once also existed between
PuTTY and OpenSSH:

  http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/rsa-verify-failed.html

  http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ssh-rsa.c?rev=1.19;content-type=text%2Fx-cvsweb-markup

With the fix I am unable to reproduce the above failure mode when
testing with 'plink'.

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-21 16:12:00 +01:00
Alan Dunn
809d76cbf2 Test change to ssh_bind_accept_fd
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-21 16:08:12 +01:00
Alan Dunn
f78a74c160 Import keys during ssh_bind_accept_fd
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-21 16:08:12 +01:00
Alan Dunn
b3b3045a81 Separate out key import functionality from ssh_bind_listen
Signed-off-by: Alan Dunn <amdunn@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-21 16:08:11 +01:00
Andreas Schneider
72fd3a73df doc: Fix channel documentation. 2014-01-17 11:09:07 +01:00
Jon Simons
cf19770ede bind: fix possible double-frees in ssh_bind_free
Make sure to explicitly set key pointers to NULL following the use
of 'ssh_key_free' throughout bind.c.

Before this change, a double free can happen via 'ssh_bind_free'
as in this example callpath:

  // create an ssh_bind
  ssh_bind b = ssh_bind_new();

  // provide a path to a wrong key-type
  ssh_bind_options_set(b, SSH_BIND_OPTIONS_DSAKEY, path_to_rsa_key);

  // initialize set key-type
  ssh_bind_listen(b);

    -> error path "The DSA host key has the wrong type: %d",

       ssh_key_free(sshbind->dsa)

         -> ssh_key_clean(key) // OK

         -> SAFE_FREE(key)     // OK, but, sshbind->dsa is *not* set to NULL

  // ssh_bind_listen failed, so clean up ssh_bind
  ssh_bind_free(b);

    -> ssh_key_free(sshbind->dsa)  // double-free here

To fix, set pointers to NULL that have been free'd with 'ssh_key_free'.

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-16 09:27:55 +01:00
Andreas Schneider
7f42f5a3c9 cmake: Increase version numbers for 0.6.1. 2014-01-16 09:16:11 +01:00
Andreas Schneider
6223e05b23 doc: Use ssh_channel_accept_forward() in documentation. 2014-01-16 09:14:52 +01:00
Oleksandr Shneyder
634671db11 channel: Add ssh_channel_accept_forward().
This works same way as ssh_forward_accept() but can return a destination
port of the channel (useful if SSH connection forwarding several TCP/IP
ports).

Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
2014-01-16 09:13:57 +01:00
Aris Adamantiadis
1f689261ec threads: support libgcrypt 1.6 hack
Not 100% satisfied of this patch, but the way libgcrypt handles
threading in 1.6 is not compatible with custom handlers. The
new code basicaly uses pthreads in every case. This will probably
not work on windows.
2014-01-08 22:06:38 +01:00
62 changed files with 1688 additions and 2070 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@
build
cscope.*
tags
build

View File

@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "6")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION_PATCH "4")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.3.0")
set(LIBRARY_VERSION "4.5.0")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
@@ -97,18 +97,22 @@ install(
)
# cmake config files
configure_file(libssh-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake @ONLY)
configure_file(libssh-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake @ONLY)
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
set(LIBSSH_THREADS_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
configure_file(${PROJECT_NAME}-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake @ONLY)
configure_file(${PROJECT_NAME}-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake @ONLY)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
DESTINATION
${CMAKE_INSTALL_DIR}
${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
COMPONENT
devel
)
# in tree build settings
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)

View File

@@ -19,7 +19,7 @@ set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSIO
### source generator
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if (WIN32)

View File

@@ -1,6 +1,39 @@
ChangeLog
==========
version 0.6.4 (released 2014-12-19)
* Fixed CVE-2014-8132.
* Added SHA-2 for session ID signing with ECDSA keys.
* Added support for ECDSA host keys.
* Added support for more ECDSA hostkey algorithms.
* Added ssh_pki_key_ecdsa_name() API.
* Fixed setting the bindfd only after successful listen.
* Fixed issues with user created sockets.
* Fixed several issues in libssh C++ wrapper.
* Fixed several documentation issues.
* Fixed channel exit-signal request.
* Fixed X11 request screen number in messages.
* Fixed several memory leaks.
version 0.6.3 (released 2014-03-04)
* Fixed CVE-2014-0017.
* Fixed memory leak with ecdsa signatures.
version 0.6.2 (released 2014-03-04)
* security: fix for vulnerability CVE-2014-0017
version 0.6.1 (released 2014-02-08)
* Added support for libgcrypt 1.6.
* Added ssh_channel_accept_forward().
* Added known_hosts heuristic during connection (#138).
* Added getters for session cipher names.
* Fixed decrypt of zero length buffer.
* Fixed padding in RSA signature blobs.
* Fixed DSA signature extraction.
* Fixed some memory leaks.
* Fixed read of non-connected socket.
* Fixed thread dectection.
version 0.6.0 (released 2014-01-08)
* Added new publicy key API.
* Added new userauth API.

View File

@@ -51,6 +51,7 @@ check_include_file(pty.h HAVE_PTY_H)
check_include_file(termios.h HAVE_TERMIOS_H)
check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(util.h HAVE_UTIL_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H)
if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
@@ -169,11 +170,9 @@ if (GCRYPT_FOUND)
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
endif (GCRYPT_FOUND)
if (CMAKE_HAVE_THREADS_LIBRARY)
if (CMAKE_USE_PTHREADS_INIT)
set(HAVE_PTHREAD 1)
endif (CMAKE_USE_PTHREADS_INIT)
endif (CMAKE_HAVE_THREADS_LIBRARY)
if (CMAKE_USE_PTHREADS_INIT)
set(HAVE_PTHREAD 1)
endif (CMAKE_USE_PTHREADS_INIT)
# OPTIONS
check_c_source_compiles("

View File

@@ -25,3 +25,6 @@ if (NOT CMAKE_BUILD_TYPE)
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
)
endif (NOT CMAKE_BUILD_TYPE)
# Create the compile command database for clang by default
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

View File

@@ -75,3 +75,10 @@ if (MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
endif (MSVC)
# This removes this annoying warning
# "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]"
if (OSX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
endif (OSX)

View File

@@ -2,10 +2,18 @@
#
# Adds a doxygen target that runs doxygen to generate the html
# and optionally the LaTeX API documentation.
# The doxygen target is added to the doc target as dependency.
# The doxygen target is added to the doc target as a dependency.
# i.e.: the API documentation is built with:
# make doc
#
# USAGE: GLOBAL INSTALL
#
# Install it with:
# cmake ./ && sudo make install
# Add the following to the CMakeLists.txt of your project:
# include(UseDoxygen OPTIONAL)
# Optionally copy Doxyfile.in in the directory of CMakeLists.txt and edit it.
#
# USAGE: INCLUDE IN PROJECT
#
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
@@ -13,88 +21,120 @@
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
#
#
# CONFIGURATION
#
# To configure Doxygen you can edit Doxyfile.in and set some variables in cmake.
# Variables you may define are:
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
#
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
#
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
# DOXYFILE_SOURCE_DIR - Path where the Doxygen input files are.
# Defaults to the current source directory.
# DOXYFILE_EXTRA_SOURCES - Additional source diretories/files for Doxygen to scan.
# The Paths should be in double quotes and separated by space. e.g.:
# "${CMAKE_CURRENT_BINARY_DIR}/foo.c" "${CMAKE_CURRENT_BINARY_DIR}/bar/"
#
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored.
# Defaults to "${CMAKE_CURRENT_BINARY_DIR}/doc".
#
# DOXYFILE_LATEX - ON/OFF; Set to "ON" if you want the LaTeX documentation
# to be built.
# DOXYFILE_LATEX_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
# the Doxygen LaTeX output is stored. Defaults to "latex".
#
# DOXYFILE_HTML_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
# the Doxygen html output is stored. Defaults to "html".
#
#
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
macro(usedoxygen_set_default name value)
if(NOT DEFINED "${name}")
set("${name}" "${value}")
endif()
macro(usedoxygen_set_default name value type docstring)
if(NOT DEFINED "${name}")
set("${name}" "${value}" CACHE "${type}" "${docstring}")
endif()
endmacro()
find_package(Doxygen)
if(DOXYGEN_FOUND)
find_file(DOXYFILE_IN
NAMES
doxy.config.in
PATHS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_ROOT}/Modules/
NO_DEFAULT_PATH)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
find_file(DOXYFILE_IN "Doxyfile.in"
PATHS "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_ROOT}/Modules/"
NO_DEFAULT_PATH
DOC "Path to the doxygen configuration template file")
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
endif()
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc"
PATH "Doxygen output directory")
usedoxygen_set_default(DOXYFILE_HTML_DIR "html"
STRING "Doxygen HTML output directory")
usedoxygen_set_default(DOXYFILE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
PATH "Input files source directory")
usedoxygen_set_default(DOXYFILE_EXTRA_SOURCE_DIRS ""
STRING "Additional source files/directories separated by space")
set(DOXYFILE_SOURCE_DIRS "\"${DOXYFILE_SOURCE_DIR}\" ${DOXYFILE_EXTRA_SOURCES}")
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF)
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory")
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
mark_as_advanced(DOXYFILE_OUTPUT_DIR DOXYFILE_HTML_DIR DOXYFILE_LATEX_DIR
DOXYFILE_SOURCE_DIR DOXYFILE_EXTRA_SOURCE_DIRS DOXYFILE_IN)
set(DOXYFILE_LATEX FALSE)
set(DOXYFILE_PDFLATEX FALSE)
set(DOXYFILE_DOT FALSE)
#find_package(LATEX)
#if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
# set(DOXYFILE_LATEX TRUE)
# usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
#
# set_property(DIRECTORY APPEND PROPERTY
# ADDITIONAL_MAKE_CLEAN_FILES
# "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
#
# if(PDFLATEX_COMPILER)
# set(DOXYFILE_PDFLATEX TRUE)
# endif()
# if(DOXYGEN_DOT_EXECUTABLE)
# set(DOXYFILE_DOT TRUE)
# endif()
#
# add_custom_command(TARGET doxygen
# POST_BUILD
# COMMAND ${CMAKE_MAKE_PROGRAM}
# WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
#endif()
set_property(DIRECTORY
APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
endif()
add_custom_target(doxygen
COMMAND "${DOXYGEN_EXECUTABLE}"
"${DOXYFILE}"
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..."
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
get_target_property(DOC_TARGET doc TYPE)
if(NOT DOC_TARGET)
add_custom_target(doc)
endif()
set(DOXYFILE_DOT "NO")
if(DOXYGEN_DOT_EXECUTABLE)
set(DOXYFILE_DOT "YES")
endif()
add_dependencies(doc doxygen)
## LaTeX
set(DOXYFILE_PDFLATEX "NO")
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
if(DOXYFILE_LATEX STREQUAL "ON")
set(DOXYFILE_GENERATE_LATEX "YES")
find_package(LATEX)
find_program(DOXYFILE_MAKE make)
mark_as_advanced(DOXYFILE_MAKE)
if(LATEX_COMPILER AND MAKEINDEX_COMPILER AND DOXYFILE_MAKE)
if(PDFLATEX_COMPILER)
set(DOXYFILE_PDFLATEX "YES")
endif()
add_custom_command(TARGET doxygen
POST_BUILD
COMMAND "${DOXYFILE_MAKE}"
COMMENT "Running LaTeX for Doxygen documentation in ${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}..."
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
else()
set(DOXYGEN_LATEX "NO")
endif()
else()
set(DOXYFILE_GENERATE_LATEX "NO")
endif()
configure_file("${DOXYFILE_IN}" "${DOXYFILE}" @ONLY)
add_custom_target(doc)
add_dependencies(doc doxygen)
endif()

View File

@@ -23,6 +23,9 @@
/* Define to 1 if you have the <util.h> header file. */
#cmakedefine HAVE_UTIL_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H 1

View File

@@ -285,7 +285,7 @@ int authenticate_kbdint(ssh_session session)
{
int rc;
rc = ssh_userauth_none(session, NULL, NULL);
rc = ssh_userauth_none(session, NULL);
return rc;
}
@endcode
@@ -304,7 +304,7 @@ int test_several_auth_methods(ssh_session session)
{
int method, rc;
rc = ssh_userauth_none(session, NULL, NULL);
rc = ssh_userauth_none(session, NULL);
if (rc != SSH_AUTH_SUCCESS) {
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@@ -145,7 +145,7 @@ or whatever use you have for it.
@subsection libssh_reverse Doing reverse port forwarding with libssh
To do reverse port forwarding, call ssh_forward_listen(),
then ssh_forward_accept().
then ssh_channel_accept_forward().
When you call ssh_forward_listen(), you can let the remote server
chose the non-priviledged port it should listen to. Otherwise, you can chose
@@ -164,6 +164,7 @@ int web_server(ssh_session session)
ssh_channel channel;
char buffer[256];
int nbytes, nwritten;
int port;
char *helloworld = ""
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
@@ -186,7 +187,7 @@ int web_server(ssh_session session)
return rc;
}
channel = ssh_forward_accept(session, 60000);
channel = ssh_channel_accept_forward(session, 60000, &port);
if (channel == NULL)
{
fprintf(stderr, "Error waiting for incoming connection: %s\n",

View File

@@ -443,11 +443,10 @@ Most of time, the error returned are SSH_FATAL, but some functions
(generaly the ssh_request_xxx ones) may fail because of server denying request.
In these cases, SSH_REQUEST_DENIED is returned.
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
That's for thread safety, error messages that can be attached to a session
aren't static anymore. Any error that happens during ssh_options_xxx()
or ssh_connect() (i.e., outside of any session) can be retrieved by
giving NULL as argument.
For thread safety, errors are bound to ssh_session objects.
As long as your ssh_session object is not NULL, you can retrieve the last error
message and error code from the ssh_session using ssh_get_error() and
ssh_get_error_code() respectively.
The SFTP subsystem has its own error codes, in addition to libssh ones.

View File

@@ -61,5 +61,6 @@ implement the following methods :
- mutex_destroy
- thread_id
libgcrypt 1.6 and bigger backend does not support custom callback. Using anything else than pthreads (ssh_threads_get_pthread()) here will fail.
Good luck !
*/

View File

@@ -495,6 +495,8 @@ LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
* @param len the length of the data
* @param is_stderr is 0 for stdout or 1 for stderr
* @param userdata Userdata to be passed to the callback function.
* @returns number of bytes processed by the callee. The remaining bytes will
* be sent in the next callback message, when more data is available.
*/
typedef int (*ssh_channel_data_callback) (ssh_session session,
ssh_channel channel,
@@ -801,6 +803,8 @@ struct ssh_threads_callbacks_struct {
*
* @see ssh_threads_callbacks_struct
* @see SSH_THREADS_PTHREAD
* @bug libgcrypt 1.6 and bigger backend does not support custom callback.
* Using anything else than pthreads here will fail.
*/
LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
*cb);

View File

@@ -49,7 +49,7 @@ int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
int hashbufout_add_cookie(ssh_session session);
int generate_session_keys(ssh_session session);
bignum make_string_bn(ssh_string string);
void make_string_bn_inplace(ssh_string string, bignum bnout);
ssh_string make_bignum_string(bignum num);
#endif /* DH_H_ */

View File

@@ -0,0 +1,27 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 20014 by Aris Adamantiadis <aris@badcode.be>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef KNOWNHOSTS_H_
#define KNOWNHOSTS_H_
char **ssh_knownhosts_algorithms(ssh_session session);
#endif /* KNOWNHOSTS_H_ */

View File

@@ -78,7 +78,7 @@
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 6
#define LIBSSH_VERSION_MICRO 0
#define LIBSSH_VERSION_MICRO 4
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -377,7 +377,7 @@ LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr,
LIBSSH_API int ssh_channel_poll(ssh_channel channel, int is_stderr);
LIBSSH_API int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr);
LIBSSH_API int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
LIBSSH_API int ssh_channel_read_timeout(ssh_channel channel, void *dest, uint32_t count, int is_stderr, int timeout);
LIBSSH_API int ssh_channel_read_timeout(ssh_channel channel, void *dest, uint32_t count, int is_stderr, int timeout_ms);
LIBSSH_API int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
int is_stderr);
LIBSSH_API int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value);
@@ -406,6 +406,7 @@ LIBSSH_API void ssh_disconnect(ssh_session session);
LIBSSH_API char *ssh_dirname (const char *path);
LIBSSH_API int ssh_finalize(void);
LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms);
LIBSSH_API ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int *destination_port);
LIBSSH_API int ssh_forward_cancel(ssh_session session, const char *address, int port);
LIBSSH_API int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
LIBSSH_API void ssh_free(ssh_session session);
@@ -533,6 +534,8 @@ LIBSSH_API int ssh_pki_export_pubkey_base64(const ssh_key key,
LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
const char *filename);
LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key);
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display);
@@ -627,6 +630,8 @@ LIBSSH_API int ssh_event_remove_session(ssh_event event, ssh_session session);
LIBSSH_API void ssh_event_free(ssh_event event);
LIBSSH_API const char* ssh_get_clientbanner(ssh_session session);
LIBSSH_API const char* ssh_get_serverbanner(ssh_session session);
LIBSSH_API const char* ssh_get_cipher_in(ssh_session session);
LIBSSH_API const char* ssh_get_cipher_out(ssh_session session);
#ifndef LIBSSH_LEGACY_0_4
#include "libssh/legacy.h"

View File

@@ -361,8 +361,8 @@ public:
* @see ssh_channel_forward_accept
* @see Session::listenForward
*/
Channel *acceptForward(int timeout_ms);
/* acceptForward is implemented later in this file */
inline Channel *acceptForward(int timeout_ms);
/* implemented outside the class due Channel references */
void_throwable cancelForward(const char *address, int port){
int err=ssh_forward_cancel(c_session, address, port);
@@ -480,12 +480,30 @@ public:
ssh_throw(err);
return err;
}
int read(void *dest, size_t count, bool is_stderr=false){
int read(void *dest, size_t count, bool is_stderr){
int err;
/* handle int overflow */
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read(channel,dest,count,is_stderr);
err=ssh_channel_read_timeout(channel,dest,count,is_stderr,-1);
ssh_throw(err);
return err;
}
int read(void *dest, size_t count, int timeout){
int err;
/* handle int overflow */
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read_timeout(channel,dest,count,false,timeout);
ssh_throw(err);
return err;
}
int read(void *dest, size_t count, bool is_stderr=false, int timeout=-1){
int err;
/* handle int overflow */
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read_timeout(channel,dest,count,is_stderr,timeout);
ssh_throw(err);
return err;
}

View File

@@ -34,6 +34,7 @@ void _ssh_pki_log(const char *function,
const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
int pki_key_ecdsa_nid_from_name(const char *name);
const char *pki_key_ecdsa_nid_to_name(int nid);
/* SSH Key Functions */
ssh_key pki_key_dup(const ssh_key key, int demote);

View File

@@ -120,11 +120,24 @@ int gettimeofday(struct timeval *__p, void *__t);
#include "libssh/callbacks.h"
/* some constants */
#ifndef MAX_PACKAT_LEN
#define MAX_PACKET_LEN 262144
#endif
#ifndef ERROR_BUFFERLEN
#define ERROR_BUFFERLEN 1024
#endif
#ifndef CLIENTBANNER1
#define CLIENTBANNER1 "SSH-1.5-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
#endif
#ifndef CLIENTBANNER2
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
#endif
#ifndef KBDINT_MAX_PROMPT
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
#endif
#ifndef MAX_BUF_SIZE
#define MAX_BUF_SIZE 4096
#endif
#ifndef __FUNCTION__
#if defined(__SUNPRO_C)
@@ -155,16 +168,6 @@ int gettimeofday(struct timeval *__p, void *__t);
#include <sys/time.h>
#endif
/*
* get rid of deprecacy warnings on OSX when using OpenSSL
*/
#if defined(__APPLE__)
#ifdef MAC_OS_X_VERSION_MIN_REQUIRED
#undef MAC_OS_X_VERSION_MIN_REQUIRED
#endif
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
#endif
/* forward declarations */
struct ssh_common_struct;
struct ssh_kex_struct;

View File

@@ -44,7 +44,8 @@ enum ssh_bind_options_e {
SSH_BIND_OPTIONS_RSAKEY,
SSH_BIND_OPTIONS_BANNER,
SSH_BIND_OPTIONS_LOG_VERBOSITY,
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
SSH_BIND_OPTIONS_ECDSAKEY
};
typedef struct ssh_bind_struct* ssh_bind;
@@ -80,69 +81,6 @@ typedef struct ssh_bind_callbacks_struct *ssh_bind_callbacks;
*/
LIBSSH_API ssh_bind ssh_bind_new(void);
/**
* @brief Set the options for the current SSH server bind.
*
* @param sshbind The ssh server bind to configure.
*
* @param type The option type to set. This could be one of the
* following:
*
* - SSH_BIND_OPTIONS_BINDADDR
* The ip address to bind (const char *).
*
* - SSH_BIND_OPTIONS_BINDPORT
* The port to bind (unsigned int).
*
* - SSH_BIND_OPTIONS_BINDPORT_STR
* The port to bind (const char *).
*
* - SSH_BIND_OPTIONS_HOSTKEY
* This specifies the file containing the private host key used
* by SSHv1. (const char *).
*
* - SSH_BIND_OPTIONS_DSAKEY
* This specifies the file containing the private host dsa key
* used by SSHv2. (const char *).
*
* - SSH_BIND_OPTIONS_RSAKEY
* This specifies the file containing the private host dsa key
* used by SSHv2. (const char *).
*
* - SSH_BIND_OPTIONS_BANNER
* That the server banner (version string) for SSH.
* (const char *).
*
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
* Set the session logging verbosity (int).\n
* \n
* The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown.
* - SSH_LOG_NOLOG: No logging
* - SSH_LOG_RARE: Rare conditions or warnings
* - SSH_LOG_ENTRY: API-accessible entrypoints
* - SSH_LOG_PACKET: Packet id and size
* - SSH_LOG_FUNCTIONS: Function entering and leaving
*
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
* Set the session logging verbosity (const char *).\n
* \n
* The verbosity of the messages. Every log smaller or
* equal to verbosity will be shown.
* - SSH_LOG_NOLOG: No logging
* - SSH_LOG_RARE: Rare conditions or warnings
* - SSH_LOG_ENTRY: API-accessible entrypoints
* - SSH_LOG_PACKET: Packet id and size
* - SSH_LOG_FUNCTIONS: Function entering and leaving
* \n
* See the corresponding numbers in libssh.h.
*
* @param value The value to set. This is a generic pointer and the
* datatype which is used should be set according to the
* type set.
*
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
*/
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
enum ssh_bind_options_e type, const void *value);

View File

@@ -175,6 +175,7 @@ struct ssh_session_struct {
char *knownhosts;
char *wanted_methods[10];
char *ProxyCommand;
char *custombanner;
unsigned long timeout; /* seconds */
unsigned long timeout_usec;
unsigned int port;

View File

@@ -70,5 +70,6 @@ int crypt_set_algorithms_server(ssh_session session);
struct ssh_crypto_struct *crypto_new(void);
void crypto_free(struct ssh_crypto_struct *crypto);
void ssh_reseed(void);
#endif /* WRAPPER_H_ */

View File

@@ -7,5 +7,7 @@ else()
set(LIBSSH_INCLUDE_DIR @INCLUDE_INSTALL_DIR@)
endif()
set(LIBSSH_LIRBARY @LIB_INSTALL_DIR@/libssh.so)
set(LIBSSH_LIRBARIES @LIB_INSTALL_DIR@/libssh.so)
set(LIBSSH_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
set(LIBSSH_LIBRARIES @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
set(LIBSSH_THREADS_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_THREADS_LIBRARY_NAME@)

View File

@@ -288,6 +288,6 @@ if (WITH_STATIC_LIB)
)
endif (WITH_STATIC_LIB)
if (CMAKE_HAVE_THREADS_LIBRARY)
if (Threads_FOUND)
add_subdirectory(threads)
endif (CMAKE_HAVE_THREADS_LIBRARY)
endif (Threads_FOUND)

View File

@@ -144,26 +144,19 @@ ssh_bind ssh_bind_new(void) {
return ptr;
}
int ssh_bind_listen(ssh_bind sshbind) {
const char *host;
socket_t fd;
static int ssh_bind_import_keys(ssh_bind sshbind) {
int rc;
if (ssh_init() < 0) {
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
return -1;
}
if (sshbind->ecdsakey == NULL &&
sshbind->dsakey == NULL &&
sshbind->rsakey == NULL) {
ssh_set_error(sshbind, SSH_FATAL,
"DSA or RSA host key file must be set before listen()");
"ECDSA, DSA, or RSA host key file must be set");
return SSH_ERROR;
}
#ifdef HAVE_ECC
if (sshbind->ecdsakey) {
if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) {
rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
NULL,
NULL,
@@ -179,12 +172,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
ssh_set_error(sshbind, SSH_FATAL,
"The ECDSA host key has the wrong type");
ssh_key_free(sshbind->ecdsa);
sshbind->ecdsa = NULL;
return SSH_ERROR;
}
}
#endif
if (sshbind->dsakey) {
if (sshbind->dsa == NULL && sshbind->dsakey != NULL) {
rc = ssh_pki_import_privkey_file(sshbind->dsakey,
NULL,
NULL,
@@ -201,11 +195,12 @@ int ssh_bind_listen(ssh_bind sshbind) {
"The DSA host key has the wrong type: %d",
ssh_key_type(sshbind->dsa));
ssh_key_free(sshbind->dsa);
sshbind->dsa = NULL;
return SSH_ERROR;
}
}
if (sshbind->rsakey) {
if (sshbind->rsa == NULL && sshbind->rsakey != NULL) {
rc = ssh_pki_import_privkey_file(sshbind->rsakey,
NULL,
NULL,
@@ -222,10 +217,29 @@ int ssh_bind_listen(ssh_bind sshbind) {
ssh_set_error(sshbind, SSH_FATAL,
"The RSA host key has the wrong type");
ssh_key_free(sshbind->rsa);
sshbind->rsa = NULL;
return SSH_ERROR;
}
}
return SSH_OK;
}
int ssh_bind_listen(ssh_bind sshbind) {
const char *host;
socket_t fd;
int rc;
if (ssh_init() < 0) {
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
return -1;
}
rc = ssh_bind_import_keys(sshbind);
if (rc != SSH_OK) {
return SSH_ERROR;
}
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
host = sshbind->bindaddr;
if (host == NULL) {
@@ -235,10 +249,11 @@ int ssh_bind_listen(ssh_bind sshbind) {
fd = bind_socket(sshbind, host, sshbind->bindport);
if (fd == SSH_INVALID_SOCKET) {
ssh_key_free(sshbind->dsa);
sshbind->dsa = NULL;
ssh_key_free(sshbind->rsa);
sshbind->rsa = NULL;
return -1;
}
sshbind->bindfd = fd;
if (listen(fd, 10) < 0) {
ssh_set_error(sshbind, SSH_FATAL,
@@ -246,9 +261,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
fd, strerror(errno));
close(fd);
ssh_key_free(sshbind->dsa);
sshbind->dsa = NULL;
ssh_key_free(sshbind->rsa);
sshbind->rsa = NULL;
return -1;
}
sshbind->bindfd = fd;
} else {
SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket");
}
@@ -348,8 +367,11 @@ void ssh_bind_free(ssh_bind sshbind){
SAFE_FREE(sshbind->ecdsakey);
ssh_key_free(sshbind->dsa);
sshbind->dsa = NULL;
ssh_key_free(sshbind->rsa);
sshbind->rsa = NULL;
ssh_key_free(sshbind->ecdsa);
sshbind->ecdsa = NULL;
for (i = 0; i < 10; i++) {
if (sshbind->wanted_methods[i]) {
@@ -361,7 +383,7 @@ void ssh_bind_free(ssh_bind sshbind){
}
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
int i;
int i, rc;
if (session == NULL){
ssh_set_error(sshbind, SSH_FATAL,"session is null");
@@ -392,7 +414,8 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
}
session->common.log_verbosity = sshbind->common.log_verbosity;
if(sshbind->banner != NULL)
session->opts.custombanner = strdup(sshbind->banner);
ssh_socket_free(session->socket);
session->socket = ssh_socket_new(session);
if (session->socket == NULL) {
@@ -403,6 +426,16 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
ssh_socket_set_fd(session->socket, fd);
ssh_socket_get_poll_handle_out(session->socket);
/* We must try to import any keys that could be imported in case
* we are not using ssh_bind_listen (which is the other place
* where keys can be imported) on this ssh_bind and are instead
* only using ssh_bind_accept_fd to manage sockets ourselves.
*/
rc = ssh_bind_import_keys(sshbind);
if (rc != SSH_OK) {
return SSH_ERROR;
}
#ifdef HAVE_ECC
if (sshbind->ecdsa) {
session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa);
@@ -426,6 +459,8 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
return SSH_ERROR;
}
}
/* force PRNG to change state in case we fork after ssh_bind_accept */
ssh_reseed();
return SSH_OK;
}

View File

@@ -916,10 +916,10 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
* SSH_AGAIN if in nonblocking mode and call has
* to be done again.
*
* @see channel_open_forward()
* @see channel_request_env()
* @see channel_request_shell()
* @see channel_request_exec()
* @see ssh_channel_open_forward()
* @see ssh_channel_request_env()
* @see ssh_channel_request_shell()
* @see ssh_channel_request_exec()
*/
int ssh_channel_open_session(ssh_channel channel) {
if(channel == NULL) {
@@ -952,7 +952,7 @@ int ssh_channel_open_session(ssh_channel channel) {
* SSH_AGAIN if in nonblocking mode and call has
* to be done again.
*
* @see channel_open_forward()
* @see ssh_channel_open_forward()
*/
int ssh_channel_open_auth_agent(ssh_channel channel){
if(channel == NULL) {
@@ -1120,8 +1120,24 @@ void ssh_channel_do_free(ssh_channel channel){
*
* @return SSH_OK on success, SSH_ERROR if an error occurred.
*
* @see channel_close()
* @see channel_free()
* Example:
@code
rc = ssh_channel_send_eof(channel);
if (rc == SSH_ERROR) {
return -1;
}
while(!ssh_channel_is_eof(channel)) {
rc = ssh_channel_read(channel, buf, sizeof(buf), 0);
if (rc == SSH_ERROR) {
return -1;
}
}
ssh_channel_close(channel);
@endcode
*
* @see ssh_channel_close()
* @see ssh_channel_free()
* @see ssh_channel_is_eof()
*/
int ssh_channel_send_eof(ssh_channel channel){
ssh_session session;
@@ -1170,8 +1186,8 @@ error:
*
* @return SSH_OK on success, SSH_ERROR if an error occurred.
*
* @see channel_free()
* @see channel_eof()
* @see ssh_channel_free()
* @see ssh_channel_is_eof()
*/
int ssh_channel_close(ssh_channel channel){
ssh_session session;
@@ -1222,7 +1238,8 @@ error:
static int ssh_channel_waitwindow_termination(void *c){
ssh_channel channel = (ssh_channel) c;
if (channel->remote_window > 0 ||
channel->session->session_state == SSH_SESSION_STATE_ERROR)
channel->session->session_state == SSH_SESSION_STATE_ERROR ||
channel->state == SSH_CHANNEL_STATE_CLOSED)
return 1;
else
return 0;
@@ -1329,7 +1346,8 @@ int channel_write_common(ssh_channel channel, const void *data,
ssh_channel_waitwindow_termination,channel);
if (rc == SSH_ERROR ||
!ssh_channel_waitwindow_termination(channel) ||
channel->session->session_state == SSH_SESSION_STATE_ERROR)
channel->session->session_state == SSH_SESSION_STATE_ERROR ||
channel->state == SSH_CHANNEL_STATE_CLOSED)
goto out;
continue;
}
@@ -1397,7 +1415,7 @@ uint32_t ssh_channel_window_size(ssh_channel channel) {
*
* @return The number of bytes written, SSH_ERROR on error.
*
* @see channel_read()
* @see ssh_channel_read()
*/
int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len) {
return channel_write_common(channel, data, len, 0);
@@ -1410,7 +1428,7 @@ int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len) {
*
* @return 0 if channel is closed, nonzero otherwise.
*
* @see channel_is_closed()
* @see ssh_channel_is_closed()
*/
int ssh_channel_is_open(ssh_channel channel) {
if(channel == NULL) {
@@ -1426,7 +1444,7 @@ int ssh_channel_is_open(ssh_channel channel) {
*
* @return 0 if channel is opened, nonzero otherwise.
*
* @see channel_is_open()
* @see ssh_channel_is_open()
*/
int ssh_channel_is_closed(ssh_channel channel) {
if(channel == NULL) {
@@ -1725,7 +1743,7 @@ error:
* SSH_AGAIN if in nonblocking mode and call has
* to be done again.
*
* @see channel_request_pty_size()
* @see ssh_channel_request_pty_size()
*/
int ssh_channel_request_pty(ssh_channel channel) {
return ssh_channel_request_pty_size(channel, "xterm", 80, 24);
@@ -1964,7 +1982,7 @@ error:
}
static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
int timeout_ms) {
int timeout_ms, int *destination_port) {
#ifndef _WIN32
static const struct timespec ts = {
.tv_sec = 0,
@@ -1981,7 +1999,11 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
* 50 ms. So we need to decrement by 100 ms.
*/
for (t = timeout_ms; t >= 0; t -= 100) {
ssh_handle_packets(session, 50);
if (timeout_ms == 0) {
ssh_handle_packets(session, 0);
} else {
ssh_handle_packets(session, 50);
}
if (session->ssh_message_list) {
iterator = ssh_list_get_iterator(session->ssh_message_list);
@@ -1991,6 +2013,10 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
ssh_message_subtype(msg) == channeltype) {
ssh_list_remove(session->ssh_message_list, iterator);
channel = ssh_message_channel_request_open_reply_accept(msg);
if(destination_port) {
*destination_port=msg->channel_request_open.destination_port;
}
ssh_message_free(msg);
return channel;
}
@@ -2021,7 +2047,7 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
* the server.
*/
ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms) {
return ssh_channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms);
return ssh_channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms, NULL);
}
/**
@@ -2275,7 +2301,23 @@ error:
* the server
*/
ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms) {
return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms);
return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, NULL);
}
/**
* @brief Accept an incoming TCP/IP forwarding channel and get information
* about incomming connection
* @param[in] session The ssh session to use.
*
* @param[in] timeout_ms A timeout in milliseconds.
*
* @param[in] destination_port A pointer to destination port or NULL.
*
* @return Newly created channel, or NULL if no incoming channel request from
* the server
*/
ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int* destination_port) {
return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, destination_port);
}
/**
@@ -2411,20 +2453,22 @@ error:
* SSH_ERROR if an error occurred,
* SSH_AGAIN if in nonblocking mode and call has
* to be done again.
* @code
* rc = channel_request_exec(channel, "ps aux");
* if (rc > 0) {
* return -1;
* }
*
* while ((rc = channel_read(channel, buffer, sizeof(buffer), 0)) > 0) {
* if (fwrite(buffer, 1, rc, stdout) != (unsigned int) rc) {
* return -1;
* }
* }
* @endcode
* Example:
@code
rc = channel_request_exec(channel, "ps aux");
if (rc > 0) {
return -1;
}
while ((rc = channel_read(channel, buffer, sizeof(buffer), 0)) > 0) {
if (fwrite(buffer, 1, rc, stdout) != (unsigned int) rc) {
return -1;
}
}
@endcode
*
* @see channel_request_shell()
* @see ssh_channel_request_shell()
*/
int ssh_channel_request_exec(ssh_channel channel, const char *cmd) {
ssh_buffer buffer = NULL;
@@ -2678,16 +2722,16 @@ int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_std
/**
* @brief Reads data from a channel.
*
* @param[in] channel The channel to read from.
* @param[in] channel The channel to read from.
*
* @param[in] dest The destination buffer which will get the data.
* @param[in] dest The destination buffer which will get the data.
*
* @param[in] count The count of bytes to be read.
* @param[in] count The count of bytes to be read.
*
* @param[in] is_stderr A boolean value to mark reading from the stderr flow.
* @param[in] is_stderr A boolean value to mark reading from the stderr flow.
*
* @param[in] timeout A timeout in seconds. A value of -1 means infinite
* timeout.
* @param[in] timeout_ms A timeout in milliseconds. A value of -1 means
* infinite timeout.
*
* @return The number of bytes read, 0 on end of file or SSH_ERROR
* on error. In nonblocking mode it Can return 0 if no data
@@ -2803,7 +2847,7 @@ int ssh_channel_read_timeout(ssh_channel channel,
*
* @warning Don't forget to check for EOF as it would return 0 here.
*
* @see channel_is_eof()
* @see ssh_channel_is_eof()
*/
int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
int is_stderr) {
@@ -2855,7 +2899,7 @@ int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count
*
* @warning When the channel is in EOF state, the function returns SSH_EOF.
*
* @see channel_is_eof()
* @see ssh_channel_is_eof()
*/
int ssh_channel_poll(ssh_channel channel, int is_stderr){
ssh_buffer stdbuf;
@@ -2907,7 +2951,7 @@ int ssh_channel_poll(ssh_channel channel, int is_stderr){
*
* @warning When the channel is in EOF state, the function returns SSH_EOF.
*
* @see channel_is_eof()
* @see ssh_channel_is_eof()
*/
int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr){
ssh_session session;
@@ -2980,6 +3024,11 @@ static int ssh_channel_exit_status_termination(void *c){
* (yet).
* @warning This function may block until a timeout (or never)
* if the other side is not willing to close the channel.
*
* If you're looking for an async handling of this register a callback for the
* exit status.
*
* @see ssh_channel_exit_status_callback
*/
int ssh_channel_get_exit_status(ssh_channel channel) {
int rc;
@@ -3212,7 +3261,7 @@ int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans,
*
* @return The number of bytes written, SSH_ERROR on error.
*
* @see channel_read()
* @see ssh_channel_read()
*/
int ssh_channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) {
return channel_write_common(channel, data, len, 1);
@@ -3418,9 +3467,9 @@ error:
}
/**
* @brief Send an exit signal to remote process (as described in RFC 4254, section 6.10).
* @brief Send an exit signal to remote process (RFC 4254, section 6.10).
*
* Sends a signal 'sig' to the remote process.
* This sends the exit status of the remote process.
* Note, that remote system may not support signals concept.
* In such a case this request will be silently ignored.
* Only SSH-v2 is supported (I'm not sure about SSH-v1).
@@ -3498,7 +3547,7 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig,
goto error;
}
rc = channel_request(channel, "signal", buffer, 0);
rc = channel_request(channel, "exit-signal", buffer, 0);
error:
ssh_buffer_free(buffer);
if(tmp)

View File

@@ -60,12 +60,15 @@
static void socket_callback_connected(int code, int errno_code, void *user){
ssh_session session=(ssh_session)user;
if(session->session_state != SSH_SESSION_STATE_CONNECTING){
if (session->session_state != SSH_SESSION_STATE_CONNECTING &&
session->session_state != SSH_SESSION_STATE_SOCKET_CONNECTED)
{
ssh_set_error(session,SSH_FATAL, "Wrong state in socket_callback_connected : %d",
session->session_state);
return;
}
SSH_LOG(SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno_code);
if(code == SSH_SOCKET_CONNECTED_OK)
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
@@ -152,19 +155,27 @@ int ssh_send_banner(ssh_session session, int server) {
banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2;
if (server) {
session->serverbanner = strdup(banner);
if(session->opts.custombanner == NULL){
session->serverbanner = strdup(banner);
} else {
session->serverbanner = malloc(strlen(session->opts.custombanner) + 9);
if(!session->serverbanner)
goto end;
strcpy(session->serverbanner, "SSH-2.0-");
strcat(session->serverbanner, session->opts.custombanner);
}
if (session->serverbanner == NULL) {
goto end;
}
snprintf(buffer, 128, "%s\n", session->serverbanner);
} else {
session->clientbanner = strdup(banner);
if (session->clientbanner == NULL) {
goto end;
}
snprintf(buffer, 128, "%s\n", session->clientbanner);
}
snprintf(buffer, 128, "%s\n", banner);
if (ssh_socket_write(session->socket, buffer, strlen(buffer)) == SSH_ERROR) {
goto end;
}
@@ -536,7 +547,8 @@ pending:
}
SSH_LOG(SSH_LOG_PACKET,"ssh_connect: Actual timeout : %d", timeout);
ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
if (ret == SSH_ERROR || !ssh_connect_termination(session)) {
if (session->session_state != SSH_SESSION_STATE_ERROR &&
(ret == SSH_ERROR || !ssh_connect_termination(session))) {
ssh_set_error(session, SSH_FATAL,
"Timeout connecting to %s", session->opts.host);
session->session_state = SSH_SESSION_STATE_ERROR;

View File

@@ -128,7 +128,7 @@ static char *ssh_config_get_token(char **str) {
c = ssh_config_get_cmd(str);
for (r = c; *c; c++) {
if (isblank(*c)) {
if (isblank(*c) || *c == '=') {
*c = '\0';
goto out;
}

View File

@@ -382,7 +382,15 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
continue;
}
connect(s, itr->ai_addr, itr->ai_addrlen);
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
if (rc == -1 && (errno != EINPROGRESS)) {
ssh_set_error(session, SSH_FATAL,
"Failed to connect: %s", strerror(errno));
ssh_connect_socket_close(s);
s = -1;
continue;
}
break;
}
@@ -421,7 +429,7 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
* @param[in] readfds A fd_set of file descriptors to be select'ed for
* reading.
*
* @param[in] timeout A timeout for the select.
* @param[in] timeout The timeout in milliseconds.
*
* @return SSH_OK on success,
* SSH_ERROR on error,

View File

@@ -170,7 +170,7 @@ int ssh_crypto_init(void) {
return -1;
}
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, &p_group14);
if (p_group1 == NULL) {
if (p_group14 == NULL) {
bignum_free(g);
bignum_free(p_group1);
g = NULL;
@@ -407,6 +407,15 @@ bignum make_string_bn(ssh_string string){
return bn;
}
void make_string_bn_inplace(ssh_string string, bignum bnout) {
unsigned int len = ssh_string_len(string);
#ifdef HAVE_LIBGCRYPT
#error "unsupported"
#elif defined HAVE_LIBCRYPTO
bignum_bin2bn(string->data, len, bnout);
#endif
}
ssh_string dh_get_e(ssh_session session) {
return make_bignum_string(session->next_crypto->e);
}

View File

@@ -104,7 +104,7 @@ void _ssh_set_error_invalid(void *error, const char *function)
/**
* @brief Retrieve the error text message from the last error.
*
* @param error The SSH session pointer.
* @param error An ssh_session or ssh_bind.
*
* @return A static string describing the error.
*/
@@ -117,7 +117,7 @@ const char *ssh_get_error(void *error) {
/**
* @brief Retrieve the error code from the last error.
*
* @param error The SSH session pointer.
* @param error An ssh_session or ssh_bind.
*
* \return SSH_NO_ERROR No error occurred\n
* SSH_REQUEST_DENIED The last request was denied but situation is

View File

@@ -539,8 +539,12 @@ ssh_gssapi_creds ssh_gssapi_get_creds(ssh_session session){
return (ssh_gssapi_creds)session->gssapi->client_creds;
}
#endif /* SERVER */
/**
* @brief Set the forwadable ticket to be given to the server for authentication.
* Unlike ssh_gssapi_get_creds() this is called on the client side of an ssh
* connection.
*
* @param[in] creds gssapi credentials handle.
*/
@@ -559,8 +563,6 @@ void ssh_gssapi_set_creds(ssh_session session, const ssh_gssapi_creds creds)
session->gssapi->client.client_deleg_creds = (gss_cred_id_t)creds;
}
#endif /* SERVER */
static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid){
ssh_string str;
int rc;

View File

@@ -35,6 +35,7 @@
#include "libssh/ssh2.h"
#include "libssh/string.h"
#include "libssh/curve25519.h"
#include "libssh/knownhosts.h"
#ifdef HAVE_LIBGCRYPT
# define BLOWFISH "blowfish-cbc,"
@@ -72,7 +73,7 @@
#ifdef HAVE_ECDH
#define ECDH "ecdh-sha2-nistp256,"
#define HOSTKEYS "ecdsa-sha2-nistp256,ssh-rsa,ssh-dss"
#define HOSTKEYS "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-dss"
#else
#define HOSTKEYS "ssh-rsa,ssh-dss"
#define ECDH ""
@@ -314,7 +315,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
for (i = 0; i < KEX_METHODS_SIZE; i++) {
str = buffer_get_ssh_string(packet);
if (str == NULL) {
break;
goto error;
}
if (buffer_add_ssh_string(session->in_hashbuf, str) < 0) {
@@ -349,6 +350,11 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
error:
ssh_string_free(str);
for (i = 0; i < SSH_KEX_METHODS; i++) {
if (server_kex) {
session->next_crypto->client_kex.methods[i] = NULL;
} else { /* client */
session->next_crypto->server_kex.methods[i] = NULL;
}
SAFE_FREE(strings[i]);
}
@@ -373,6 +379,53 @@ void ssh_list_kex(struct ssh_kex_struct *kex) {
}
}
/**
* @internal
* @brief selects the hostkey mechanisms to be chosen for the key exchange,
* as some hostkey mechanisms may be present in known_hosts file and preferred
* @returns a cstring containing a comma-separated list of hostkey methods.
* NULL if no method matches
*/
static char *ssh_client_select_hostkeys(ssh_session session){
char methods_buffer[128]={0};
static const char *preferred_hostkeys[]={"ecdsa-sha2-nistp521","ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp256", "ssh-rsa", "ssh-dss", "ssh-rsa1", NULL};
char **methods;
int i,j;
int needcoma=0;
methods = ssh_knownhosts_algorithms(session);
if (methods == NULL || methods[0] == NULL){
SAFE_FREE(methods);
return NULL;
}
for (i=0;preferred_hostkeys[i] != NULL; ++i){
for (j=0; methods[j] != NULL; ++j){
if(strcmp(preferred_hostkeys[i], methods[j]) == 0){
if (verify_existing_algo(SSH_HOSTKEYS, methods[j])){
if(needcoma)
strncat(methods_buffer,",",sizeof(methods_buffer)-strlen(methods_buffer)-1);
strncat(methods_buffer, methods[j], sizeof(methods_buffer)-strlen(methods_buffer)-1);
needcoma = 1;
}
}
}
}
for(i=0;methods[i]!= NULL; ++i){
SAFE_FREE(methods[i]);
}
SAFE_FREE(methods);
if(strlen(methods_buffer) > 0){
SSH_LOG(SSH_LOG_DEBUG, "Changing host key method to \"%s\"", methods_buffer);
return strdup(methods_buffer);
} else {
SSH_LOG(SSH_LOG_DEBUG, "No supported kex method for existing key in known_hosts file");
return NULL;
}
}
/**
* @brief sets the key exchange parameters to be sent to the server,
* in function of the options and available methods.
@@ -385,6 +438,13 @@ int set_client_kex(ssh_session session){
ssh_get_random(client->cookie, 16, 0);
memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **));
/* first check if we have specific host key methods */
if(session->opts.wanted_methods[SSH_HOSTKEYS] == NULL){
/* Only if no override */
session->opts.wanted_methods[SSH_HOSTKEYS] =
ssh_client_select_hostkeys(session);
}
for (i = 0; i < KEX_METHODS_SIZE; i++) {
wanted = session->opts.wanted_methods[i];
if (wanted == NULL)

View File

@@ -34,7 +34,7 @@
#include "libssh/misc.h"
#include "libssh/pki.h"
#include "libssh/options.h"
#include "libssh/knownhosts.h"
/*todo: remove this include */
#include "libssh/string.h"
@@ -647,6 +647,102 @@ int ssh_write_knownhost(ssh_session session) {
return 0;
}
#define KNOWNHOSTS_MAXTYPES 10
/**
* @internal
* @brief Check which kind of host keys should be preferred for connection
* by reading the known_hosts file.
*
* @param[in] session The SSH session to use.
*
* @returns array of supported key types
* NULL on error
*/
char **ssh_knownhosts_algorithms(ssh_session session) {
FILE *file = NULL;
char **tokens;
char *host;
char *hostport;
const char *type;
int match;
char **array;
int i=0, j;
if (session->opts.knownhosts == NULL) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file");
return NULL;
}
}
if (session->opts.host == NULL) {
return NULL;
}
host = ssh_lowercase(session->opts.host);
hostport = ssh_hostport(host, session->opts.port);
array = malloc(sizeof(char *) * KNOWNHOSTS_MAXTYPES);
if (host == NULL || hostport == NULL || array == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(host);
SAFE_FREE(hostport);
SAFE_FREE(array);
return NULL;
}
do {
tokens = ssh_get_knownhost_line(&file,
session->opts.knownhosts, &type);
/* End of file, return the current state */
if (tokens == NULL) {
break;
}
match = match_hashed_host(host, tokens[0]);
if (match == 0){
match = match_hostname(hostport, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hostname(host, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hashed_host(hostport, tokens[0]);
}
if (match) {
/* We got a match. Now check the key type */
SSH_LOG(SSH_LOG_DEBUG, "server %s:%d has %s in known_hosts",
host, session->opts.port, type);
/* don't copy more than once */
for(j=0;j<i && match;++j){
if(strcmp(array[j], type)==0)
match=0;
}
if (match){
array[i] = strdup(type);
i++;
if(i>= KNOWNHOSTS_MAXTYPES-1){
tokens_free(tokens);
break;
}
}
}
tokens_free(tokens);
} while (1);
array[i]=NULL;
SAFE_FREE(host);
SAFE_FREE(hostport);
if (file != NULL) {
fclose(file);
}
/* Return the current state at end of file */
return array;
}
/** @} */
/* vim: set ts=4 sw=4 et cindent: */

View File

@@ -19,10 +19,14 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "libssh/priv.h"
#include "libssh/session.h"
@@ -38,6 +42,8 @@
#include <openssl/rsa.h>
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
#include <openssl/rand.h>
#ifdef HAVE_OPENSSL_AES_H
#define HAS_AES
#include <openssl/aes.h>
@@ -74,6 +80,14 @@ static int alloc_key(struct ssh_cipher_struct *cipher) {
return 0;
}
void ssh_reseed(void){
#ifndef _WIN32
struct timeval tv;
gettimeofday(&tv, NULL);
RAND_add(&tv, sizeof(tv), 0.0);
#endif
}
SHACTX sha1_init(void) {
SHACTX c = malloc(sizeof(*c));
if (c == NULL) {
@@ -193,7 +207,11 @@ void md5_final(unsigned char *md, MD5CTX c) {
}
ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct));
if (ctx == NULL) {
return NULL;
}
ctx->mac_type=type;
switch(type){
case SSH_MAC_SHA1:

View File

@@ -45,6 +45,9 @@ static int alloc_key(struct ssh_cipher_struct *cipher) {
return 0;
}
void ssh_reseed(void){
}
SHACTX sha1_init(void) {
SHACTX ctx = NULL;
gcry_md_open(&ctx, GCRY_MD_SHA1, 0);
@@ -88,7 +91,11 @@ void md5_final(unsigned char *md, MD5CTX c) {
}
ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct));
if (ctx == NULL) {
return NULL;
}
ctx->mac_type=type;
switch(type){
case SSH_MAC_SHA1:

View File

@@ -208,8 +208,8 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
ssh_callbacks_exists(channel->callbacks, channel_pty_window_change_function)) {
rc = channel->callbacks->channel_pty_window_change_function(session,
channel,
msg->channel_request.height, msg->channel_request.width,
msg->channel_request.pxheight, msg->channel_request.pxwidth,
msg->channel_request.width, msg->channel_request.height,
msg->channel_request.pxwidth, msg->channel_request.pxheight,
channel->callbacks->userdata);
} else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_EXEC &&
ssh_callbacks_exists(channel->callbacks, channel_exec_request_function)) {
@@ -508,8 +508,7 @@ void ssh_message_free(ssh_message msg){
case SSH_REQUEST_AUTH:
SAFE_FREE(msg->auth_request.username);
if (msg->auth_request.password) {
memset(msg->auth_request.password, 0,
strlen(msg->auth_request.password));
BURN_STRING(msg->auth_request.password);
SAFE_FREE(msg->auth_request.password);
}
ssh_key_free(msg->auth_request.pubkey);
@@ -1372,6 +1371,7 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel,
msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight);
msg->channel_request.modes = buffer_get_ssh_string(packet);
if (msg->channel_request.modes == NULL) {
msg->channel_request.TERM = NULL;
SAFE_FREE(term_c);
goto error;
}
@@ -1470,6 +1470,7 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel,
if (strcmp(request, "x11-req") == 0) {
ssh_string auth_protocol = NULL;
ssh_string auth_cookie = NULL;
uint32_t screen_number;
buffer_get_u8(packet, &msg->channel_request.x11_single_connection);
@@ -1497,7 +1498,8 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel,
ssh_string_free(auth_protocol);
ssh_string_free(auth_cookie);
buffer_get_u32(packet, &msg->channel_request.x11_screen_number);
buffer_get_u32(packet, &screen_number);
msg->channel_request.x11_screen_number = ntohl(screen_number);
goto end;
}

View File

@@ -697,7 +697,6 @@ char *ssh_path_expand_tilde(const char *d) {
}
char *ssh_path_expand_escape(ssh_session session, const char *s) {
#define MAX_BUF_SIZE 4096
char host[NI_MAXHOST];
char buf[MAX_BUF_SIZE];
char *r, *x = NULL;

View File

@@ -512,7 +512,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
}
session->opts.username = q;
} else if (v[0] == '\0') {
ssh_set_error_oom(session);
ssh_set_error_invalid(session);
return -1;
} else { /* username provided */
session->opts.username = strdup(value);
@@ -531,7 +531,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
return -1;
}
} else if (v[0] == '\0') {
ssh_set_error_oom(session);
ssh_set_error_invalid(session);
return -1;
} else {
session->opts.sshdir = ssh_path_expand_tilde(v);
@@ -1303,65 +1303,89 @@ static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo,
return 0;
}
static int ssh_bind_set_key(ssh_bind sshbind, char **key_loc,
const void *value) {
if (value == NULL) {
ssh_set_error_invalid(sshbind);
return -1;
} else {
SAFE_FREE(*key_loc);
*key_loc = strdup(value);
if (*key_loc == NULL) {
ssh_set_error_oom(sshbind);
return -1;
}
}
return 0;
}
/**
* @brief This function can set all possible ssh bind options.
* @brief Set options for an SSH server bind.
*
* @param sshbind An allocated ssh bind structure.
* @param sshbind The ssh server bind to configure.
*
* @param type The option type to set. This could be one of the
* @param type The option type to set. This should be one of the
* following:
*
* SSH_BIND_OPTIONS_LOG_VERBOSITY:
* Set the session logging verbosity (integer).
*
* 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 (integer).
*
* 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_BINDADDR:
* Set the bind address.
*
* SSH_BIND_OPTIONS_BINDPORT:
* Set the bind port, default is 22.
*
* SSH_BIND_OPTIONS_HOSTKEY:
* - SSH_BIND_OPTIONS_HOSTKEY:
* Set the server public key type: ssh-rsa or ssh-dss
* (string).
* (const char *).
*
* SSH_BIND_OPTIONS_DSAKEY:
* Set the path to the dsa ssh host key (string).
* - SSH_BIND_OPTIONS_BINDADDR:
* Set the IP address to bind (const char *).
*
* SSH_BIND_OPTIONS_RSAKEY:
* Set the path to the ssh host rsa key (string).
* - SSH_BIND_OPTIONS_BINDPORT:
* Set the port to bind (unsigned int *).
*
* SSH_BIND_OPTIONS_BANNER:
* Set the server banner sent to clients (string).
* - SSH_BIND_OPTIONS_BINDPORT_STR:
* Set the port to bind (const char *).
*
* - SSH_BIND_OPTIONS_LOG_VERBOSITY:
* Set the session logging verbosity (int *).
* The logging verbosity should have one of the
* following values, which are listed in order
* of increasing verbosity. Every log message
* with verbosity less than or equal to the
* logging 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 via a
* string that will be converted to a numerical
* value (e.g. "3") and interpreted according
* to the values of
* SSH_BIND_OPTIONS_LOG_VERBOSITY above (const
* char *).
*
* - SSH_BIND_OPTIONS_DSAKEY:
* Set the path to the ssh host dsa key, SSHv2
* only (const char *).
*
* - SSH_BIND_OPTIONS_RSAKEY:
* Set the path to the ssh host rsa key, SSHv2
* only (const char *).
*
* - SSH_BIND_OPTIONS_ECDSAKEY:
* Set the path to the ssh host ecdsa key,
* SSHv2 only (const char *).
*
* - SSH_BIND_OPTIONS_BANNER:
* Set the server banner sent to clients (const char *).
*
* @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.
* datatype which should be used is described at the
* corresponding value of type above.
*
* @return 0 on success, < 0 on error.
* @return 0 on success, < 0 on error, invalid option, or parameter.
*/
int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
const void *value) {
char *p, *q;
int i;
int i, rc;
if (sshbind == NULL) {
return -1;
@@ -1445,31 +1469,23 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
}
break;
case SSH_BIND_OPTIONS_DSAKEY:
if (value == NULL) {
ssh_set_error_invalid(sshbind);
return -1;
} else {
SAFE_FREE(sshbind->dsakey);
sshbind->dsakey = strdup(value);
if (sshbind->dsakey == NULL) {
ssh_set_error_oom(sshbind);
return -1;
rc = ssh_bind_set_key(sshbind, &sshbind->dsakey, value);
if (rc < 0) {
return -1;
}
}
break;
break;
case SSH_BIND_OPTIONS_RSAKEY:
if (value == NULL) {
ssh_set_error_invalid(sshbind);
return -1;
} else {
SAFE_FREE(sshbind->rsakey);
sshbind->rsakey = strdup(value);
if (sshbind->rsakey == NULL) {
ssh_set_error_oom(sshbind);
return -1;
rc = ssh_bind_set_key(sshbind, &sshbind->rsakey, value);
if (rc < 0) {
return -1;
}
}
break;
break;
case SSH_BIND_OPTIONS_ECDSAKEY:
rc = ssh_bind_set_key(sshbind, &sshbind->ecdsakey, value);
if (rc < 0) {
return -1;
}
break;
case SSH_BIND_OPTIONS_BANNER:
if (value == NULL) {
ssh_set_error_invalid(sshbind);

View File

@@ -251,12 +251,18 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
* Decrypt the rest of the packet (blocksize bytes already
* have been decrypted)
*/
rc = packet_decrypt(session,
((uint8_t*)buffer_get_rest(session->in_buffer) + blocksize),
buffer_get_rest_len(session->in_buffer) - blocksize);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "Decrypt error");
goto error;
uint32_t buffer_len = buffer_get_rest_len(session->in_buffer);
/* The following check avoids decrypting zero bytes */
if (buffer_len > blocksize) {
uint8_t *payload = ((uint8_t*)buffer_get_rest(session->in_buffer) + blocksize);
uint32_t plen = buffer_len - blocksize;
rc = packet_decrypt(session, payload, plen);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "Decrypt error");
goto error;
}
}
/* copy the last part from the incoming buffer */
@@ -498,11 +504,13 @@ static int packet_send2(ssh_session session) {
session->current_crypto->out_cipher->blocksize : 8);
uint32_t currentlen = buffer_get_rest_len(session->out_buffer);
unsigned char *hmac = NULL;
char padstring[32] = {0};
char padstring[32] = { 0 };
int rc = SSH_ERROR;
uint32_t finallen,payloadsize,compsize;
uint8_t padding;
uint8_t header[sizeof(padding) + sizeof(finallen)] = { 0 };
payloadsize = currentlen;
#ifdef WITH_ZLIB
if (session->current_crypto
@@ -522,19 +530,18 @@ static int packet_send2(ssh_session session) {
if (session->current_crypto) {
ssh_get_random(padstring, padding, 0);
} else {
memset(padstring,0,padding);
}
finallen = htonl(currentlen + padding + 1);
if (buffer_prepend_data(session->out_buffer, &padding, sizeof(uint8_t)) < 0) {
memcpy(&header[0], &finallen, sizeof(finallen));
header[sizeof(finallen)] = padding;
rc = buffer_prepend_data(session->out_buffer, &header, sizeof(header));
if (rc < 0) {
goto error;
}
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
goto error;
}
if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
rc = buffer_add_data(session->out_buffer, padstring, padding);
if (rc < 0) {
goto error;
}
#ifdef WITH_PCAP

View File

@@ -106,7 +106,7 @@ int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user
size_t processed=0;
uint32_t padding;
uint32_t crc;
uint32_t len;
uint32_t len, buffer_len;
ssh_session session=(ssh_session)user;
switch (session->packet_state){
@@ -168,11 +168,16 @@ int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user
* We decrypt everything, missing the lenght part (which was
* previously read, unencrypted, and is not part of the buffer
*/
if (packet_decrypt(session,
ssh_buffer_get_begin(session->in_buffer),
ssh_buffer_get_len(session->in_buffer)) < 0) {
ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
goto error;
buffer_len = ssh_buffer_get_len(session->in_buffer);
if (buffer_len > 0) {
int rc;
rc = packet_decrypt(session,
ssh_buffer_get_begin(session->in_buffer),
buffer_len);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
goto error;
}
}
}
#ifdef DEBUG_CRYPTO
@@ -300,6 +305,8 @@ int packet_send1(ssh_session session) {
ssh_buffer_get_len(session->out_buffer));
#endif
/* session->out_buffer should have more than sizeof(uint32_t) bytes
in it as required for packet_encrypt */
packet_encrypt(session, (unsigned char *)ssh_buffer_get_begin(session->out_buffer) + sizeof(uint32_t),
ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t));

View File

@@ -43,29 +43,35 @@
* @brief Handle a SSH_DISCONNECT packet.
*/
SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){
uint32_t code;
char *error=NULL;
ssh_string error_s;
(void)user;
(void)type;
buffer_get_u32(packet, &code);
int rc;
uint32_t code = 0;
char *error = NULL;
ssh_string error_s;
(void)user;
(void)type;
rc = buffer_get_u32(packet, &code);
if (rc != 0) {
code = ntohl(code);
}
error_s = buffer_get_ssh_string(packet);
if (error_s != NULL) {
error = ssh_string_to_char(error_s);
ssh_string_free(error_s);
}
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT %d:%s",code,
error != NULL ? error : "no error");
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT %d:%s",
code, error != NULL ? error : "no error");
ssh_set_error(session, SSH_FATAL,
"Received SSH_MSG_DISCONNECT: %d:%s",code,
error != NULL ? error : "no error");
"Received SSH_MSG_DISCONNECT: %d:%s",
code, error != NULL ? error : "no error");
SAFE_FREE(error);
ssh_socket_close(session->socket);
session->alive = 0;
session->session_state= SSH_SESSION_STATE_ERROR;
/* TODO: handle a graceful disconnect */
return SSH_PACKET_USED;
session->session_state = SSH_SESSION_STATE_ERROR;
/* TODO: handle a graceful disconnect */
return SSH_PACKET_USED;
}
/**

View File

@@ -22,6 +22,7 @@
*/
#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -59,6 +60,9 @@ uint32_t packet_decrypt_len(ssh_session session, char *crypted){
int packet_decrypt(ssh_session session, void *data,uint32_t len) {
struct ssh_cipher_struct *crypto = session->current_crypto->in_cipher;
char *out = NULL;
assert(len);
if(len % session->current_crypto->in_cipher->blocksize != 0){
ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
return SSH_ERROR;
@@ -89,6 +93,8 @@ unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) {
unsigned int finallen;
uint32_t seq;
assert(len);
if (!session->current_crypto) {
return NULL; /* nothing to do here */
}

View File

@@ -98,6 +98,25 @@ enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey) {
return SSH_KEYTYPE_UNKNOWN;
}
/**
* @brief returns the ECDSA key name ("ecdsa-sha2-nistp256" for example)
*
* @param[in] key the ssh_key whose ECDSA name to get
*
* @returns the ECDSA key name ("ecdsa-sha2-nistp256" for example)
*
* @returns "unknown" if the ECDSA key name is not known
*/
const char *ssh_pki_key_ecdsa_name(const ssh_key key)
{
#ifdef HAVE_OPENSSL_ECC /* FIXME Better ECC check needed */
return pki_key_ecdsa_nid_to_name(key->ecdsa_nid);
#else
(void) key; /* unused */
return NULL;
#endif
}
/**
* @brief creates a new empty SSH key
* @returns an empty ssh_key handle, or NULL on error.
@@ -331,6 +350,10 @@ void ssh_signature_free(ssh_signature sig)
#endif
break;
case SSH_KEYTYPE_ECDSA:
#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ECC)
ECDSA_SIG_free(sig->ecdsa_sig);
#endif
break;
case SSH_KEYTYPE_UNKNOWN:
break;
}
@@ -720,6 +743,9 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
if (rc < 0) {
goto fail;
}
/* Update key type */
key->type_c = ssh_pki_key_ecdsa_name(key);
}
break;
#endif
@@ -976,8 +1002,12 @@ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
rc = pki_key_generate_ecdsa(key, parameter);
if(rc == SSH_ERROR)
if (rc == SSH_ERROR) {
goto error;
}
/* Update key type */
key->type_c = ssh_pki_key_ecdsa_name(key);
break;
#endif
case SSH_KEYTYPE_UNKNOWN:
@@ -1295,6 +1325,11 @@ int ssh_pki_signature_verify_blob(ssh_session session,
evp(key->ecdsa_nid, digest, dlen, ehash, &elen);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash to be verified with ecdsa",
ehash, elen);
#endif
rc = pki_signature_verify(session,
sig,
key,
@@ -1361,6 +1396,10 @@ ssh_string ssh_pki_do_sign(ssh_session session,
evp_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
evp_final(ctx, ehash, &elen);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash being signed", ehash, elen);
#endif
sig = pki_do_sign(privkey, ehash, elen);
#endif
} else {
@@ -1454,10 +1493,8 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
const ssh_key privkey)
{
struct ssh_crypto_struct *crypto;
unsigned char hash[SHA_DIGEST_LEN] = {0};
ssh_signature sig;
ssh_string sig_blob;
SHACTX ctx;
int rc;
if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) {
@@ -1466,24 +1503,47 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
crypto = session->next_crypto ? session->next_crypto :
session->current_crypto;
ctx = sha1_init();
if (ctx == NULL) {
return NULL;
}
if (crypto->secret_hash == NULL){
ssh_set_error(session,SSH_FATAL,"Missing secret_hash");
return NULL;
}
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
sha1_final(hash, ctx);
if (privkey->type == SSH_KEYTYPE_ECDSA) {
#ifdef HAVE_ECC
unsigned char ehash[EVP_DIGEST_LEN] = {0};
uint32_t elen;
evp(privkey->ecdsa_nid, crypto->secret_hash, crypto->digest_len,
ehash, &elen);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
ssh_print_hexa("Hash being signed", ehash, elen);
#endif
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
if (sig == NULL) {
return NULL;
sig = pki_do_sign_sessionid(privkey, ehash, elen);
if (sig == NULL) {
return NULL;
}
#endif
} else {
unsigned char hash[SHA_DIGEST_LEN] = {0};
SHACTX ctx;
ctx = sha1_init();
if (ctx == NULL) {
return NULL;
}
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
sha1_final(hash, ctx);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
#endif
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
if (sig == NULL) {
return NULL;
}
}
rc = ssh_pki_export_signature_blob(sig, &sig_blob);

View File

@@ -89,7 +89,7 @@ static int pki_key_ecdsa_to_nid(EC_KEY *k)
return -1;
}
static const char *pki_key_ecdsa_nid_to_name(int nid)
const char *pki_key_ecdsa_nid_to_name(int nid)
{
switch (nid) {
case NID_X9_62_prime256v1:
@@ -200,9 +200,11 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
return -1;
}
/* EC_KEY_set_public_key duplicates p */
ok = EC_KEY_set_public_key(key->ecdsa, p);
EC_POINT_free(p);
if (!ok) {
EC_POINT_free(p);
return -1;
}
return 0;
@@ -343,13 +345,13 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
break;
case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC
new->ecdsa_nid = key->ecdsa_nid;
/* privkey -> pubkey */
if (demote && ssh_key_is_private(key)) {
const EC_POINT *p;
int ok;
new->ecdsa_nid = key->ecdsa_nid;
new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
if (new->ecdsa == NULL) {
goto fail;
@@ -381,10 +383,20 @@ fail:
}
int pki_key_generate_rsa(ssh_key key, int parameter){
key->rsa = RSA_generate_key(parameter, 65537, NULL, NULL);
if(key->rsa == NULL)
return SSH_ERROR;
return SSH_OK;
BIGNUM *e;
int rc;
e = BN_new();
key->rsa = RSA_new();
BN_set_word(e, 65537);
rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL);
BN_free(e);
if (rc == -1 || key->rsa == NULL)
return SSH_ERROR;
return SSH_OK;
}
int pki_key_generate_dss(ssh_key key, int parameter){
@@ -1094,41 +1106,65 @@ static ssh_string _RSA_do_sign(const unsigned char *digest,
return sig_blob;
}
static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
{
char buffer[40] = { 0 };
ssh_string sig_blob = NULL;
ssh_string r;
int r_len, r_offset_in, r_offset_out;
ssh_string s;
int s_len, s_offset_in, s_offset_out;
r = make_bignum_string(sig->dsa_sig->r);
if (r == NULL) {
return NULL;
}
s = make_bignum_string(sig->dsa_sig->s);
if (s == NULL) {
ssh_string_free(r);
return NULL;
}
r_len = ssh_string_len(r);
r_offset_in = (r_len > 20) ? (r_len - 20) : 0;
r_offset_out = (r_len < 20) ? (20 - r_len) : 0;
s_len = ssh_string_len(s);
s_offset_in = (s_len > 20) ? (s_len - 20) : 0;
s_offset_out = (s_len < 20) ? (20 - s_len) : 0;
memcpy(buffer + r_offset_out,
((char *)ssh_string_data(r)) + r_offset_in,
r_len - r_offset_in);
memcpy(buffer + 20 + s_offset_out,
((char *)ssh_string_data(s)) + s_offset_in,
s_len - s_offset_in);
ssh_string_free(r);
ssh_string_free(s);
sig_blob = ssh_string_new(40);
if (sig_blob == NULL) {
return NULL;
}
ssh_string_fill(sig_blob, buffer, 40);
return sig_blob;
}
ssh_string pki_signature_to_blob(const ssh_signature sig)
{
char buffer[40] = {0};
ssh_string sig_blob = NULL;
ssh_string r;
ssh_string s;
ssh_string sig_blob = NULL;
switch(sig->type) {
case SSH_KEYTYPE_DSS:
r = make_bignum_string(sig->dsa_sig->r);
if (r == NULL) {
return NULL;
}
s = make_bignum_string(sig->dsa_sig->s);
if (s == NULL) {
ssh_string_free(r);
return NULL;
}
memcpy(buffer,
((char *)ssh_string_data(r)) + ssh_string_len(r) - 20,
20);
memcpy(buffer + 20,
((char *)ssh_string_data(s)) + ssh_string_len(s) - 20,
20);
ssh_string_free(r);
ssh_string_free(s);
sig_blob = ssh_string_new(40);
if (sig_blob == NULL) {
return NULL;
}
ssh_string_fill(sig_blob, buffer, 40);
sig_blob = pki_dsa_signature_to_blob(sig);
break;
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
@@ -1188,6 +1224,67 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
return sig_blob;
}
static ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey,
const ssh_string sig_blob,
ssh_signature sig)
{
uint32_t pad_len = 0;
char *blob_orig;
char *blob_padded_data;
ssh_string sig_blob_padded;
size_t rsalen = 0;
size_t len = ssh_string_len(sig_blob);
if (pubkey->rsa == NULL) {
ssh_pki_log("Pubkey RSA field NULL");
goto errout;
}
rsalen = RSA_size(pubkey->rsa);
if (len > rsalen) {
ssh_pki_log("Signature is too big: %lu > %lu",
(unsigned long)len, (unsigned long)rsalen);
goto errout;
}
#ifdef DEBUG_CRYPTO
ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
#endif
if (len == rsalen) {
sig->rsa_sig = ssh_string_copy(sig_blob);
} else {
/* pad the blob to the expected rsalen size */
ssh_pki_log("RSA signature len %lu < %lu",
(unsigned long)len, (unsigned long)rsalen);
pad_len = rsalen - len;
sig_blob_padded = ssh_string_new(rsalen);
if (sig_blob_padded == NULL) {
goto errout;
}
blob_padded_data = (char *) ssh_string_data(sig_blob_padded);
blob_orig = (char *) ssh_string_data(sig_blob);
/* front-pad the buffer with zeroes */
BURN_BUFFER(blob_padded_data, pad_len);
/* fill the rest with the actual signature blob */
memcpy(blob_padded_data + pad_len, blob_orig, len);
sig->rsa_sig = sig_blob_padded;
}
return sig;
errout:
ssh_signature_free(sig);
return NULL;
}
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
const ssh_string sig_blob,
enum ssh_keytypes_e type)
@@ -1196,7 +1293,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_string r;
ssh_string s;
size_t len;
size_t rsalen;
sig = ssh_signature_new();
if (sig == NULL) {
@@ -1260,29 +1356,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
break;
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
rsalen = RSA_size(pubkey->rsa);
if (len > rsalen) {
ssh_pki_log("Signature is to big size: %lu",
(unsigned long)len);
ssh_signature_free(sig);
return NULL;
}
if (len < rsalen) {
ssh_pki_log("RSA signature len %lu < %lu",
(unsigned long)len, (unsigned long)rsalen);
}
#ifdef DEBUG_CRYPTO
ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
#endif
sig->rsa_sig = ssh_string_copy(sig_blob);
if (sig->rsa_sig == NULL) {
ssh_signature_free(sig);
return NULL;
}
sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
break;
case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC
@@ -1323,7 +1397,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
#endif
sig->ecdsa_sig->r = make_string_bn(r);
make_string_bn_inplace(r, sig->ecdsa_sig->r);
ssh_string_burn(r);
ssh_string_free(r);
if (sig->ecdsa_sig->r == NULL) {
@@ -1344,7 +1418,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
#endif
sig->ecdsa_sig->s = make_string_bn(s);
make_string_bn_inplace(s, sig->ecdsa_sig->s);
ssh_string_burn(s);
ssh_string_free(s);
if (sig->ecdsa_sig->s == NULL) {

View File

@@ -1657,6 +1657,7 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
return NULL;
}
sig->type = key->type;
sig->type_c = key->type_c;
switch(key->type) {
case SSH_KEYTYPE_DSS:

View File

@@ -545,7 +545,7 @@ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
* @see ssh_scp_request_get_warning()
*/
int ssh_scp_pull_request(ssh_scp scp){
char buffer[4096] = {0};
char buffer[MAX_BUF_SIZE] = {0};
char *mode=NULL;
char *p,*tmp;
uint64_t size;
@@ -642,7 +642,7 @@ int ssh_scp_pull_request(ssh_scp scp){
* the message failed, or sending it in a bad state.
*/
int ssh_scp_deny_request(ssh_scp scp, const char *reason){
char buffer[4096];
char buffer[MAX_BUF_SIZE];
int err;
if(scp==NULL)
return SSH_ERROR;
@@ -814,7 +814,7 @@ int ssh_scp_integer_mode(const char *mode){
*/
char *ssh_scp_string_mode(int mode){
char buffer[16];
snprintf(buffer,sizeof(buffer),"%.4d",mode);
snprintf(buffer,sizeof(buffer),"%.4o",mode);
return strdup(buffer);
}

View File

@@ -217,6 +217,7 @@ int ssh_get_key_params(ssh_session session, ssh_key *privkey){
*privkey = session->srv.ecdsa_key;
break;
case SSH_KEYTYPE_UNKNOWN:
default:
*privkey = NULL;
}

View File

@@ -226,7 +226,11 @@ void ssh_free(ssh_session session) {
#endif /* _WIN32 */
ssh_key_free(session->srv.dsa_key);
session->srv.dsa_key = NULL;
ssh_key_free(session->srv.rsa_key);
session->srv.rsa_key = NULL;
ssh_key_free(session->srv.ecdsa_key);
session->srv.ecdsa_key = NULL;
if (session->ssh_message_list) {
ssh_message msg;
@@ -261,6 +265,7 @@ void ssh_free(ssh_session session) {
SAFE_FREE(session->banner);
SAFE_FREE(session->opts.bindaddr);
SAFE_FREE(session->opts.custombanner);
SAFE_FREE(session->opts.username);
SAFE_FREE(session->opts.host);
SAFE_FREE(session->opts.sshdir);
@@ -275,7 +280,7 @@ void ssh_free(ssh_session session) {
}
}
/* burn connection, it could hang sensitive datas */
/* burn connection, it could contain sensitive data */
BURN_BUFFER(session, sizeof(struct ssh_session_struct));
SAFE_FREE(session);
}
@@ -309,6 +314,38 @@ const char* ssh_get_serverbanner(ssh_session session) {
return session->serverbanner;
}
/**
* @brief get the name of the input for the given session.
*
* @param[in] session The SSH session.
*
* @return Returns cipher name or NULL.
*/
const char* ssh_get_cipher_in(ssh_session session) {
if ((session != NULL) &&
(session->current_crypto != NULL) &&
(session->current_crypto->in_cipher != NULL)) {
return session->current_crypto->in_cipher->name;
}
return NULL;
}
/**
* @brief get the name of the output cipher for the given session.
*
* @param[in] session The SSH session.
*
* @return Returns cipher name or NULL.
*/
const char* ssh_get_cipher_out(ssh_session session) {
if ((session != NULL) &&
(session->current_crypto != NULL) &&
(session->current_crypto->out_cipher != NULL)) {
return session->current_crypto->out_cipher->name;
}
return NULL;
}
/**
* @brief Disconnect impolitely from a remote host by closing the socket.
*
@@ -567,7 +604,11 @@ int ssh_handle_packets_termination(ssh_session session,
}
}
ssh_timestamp_init(&ts);
/* avoid unnecessary syscall for the SSH_TIMEOUT_NONBLOCKING case */
if (timeout != SSH_TIMEOUT_NONBLOCKING) {
ssh_timestamp_init(&ts);
}
tm = timeout;
while(!fct(user)) {
ret = ssh_handle_packets(session, tm);
@@ -695,8 +736,13 @@ void ssh_socket_exception_callback(int code, int errno_code, void *user){
ssh_session session=(ssh_session)user;
SSH_LOG(SSH_LOG_RARE,"Socket exception callback: %d (%d)",code, errno_code);
session->session_state=SSH_SESSION_STATE_ERROR;
ssh_set_error(session,SSH_FATAL,"Socket error: %s",strerror(errno_code));
session->session_state = SSH_SESSION_STATE_ERROR;
if (errno_code == 0 && code == SSH_SOCKET_EXCEPTION_EOF) {
ssh_set_error(session, SSH_FATAL, "Socket error: disconnected");
} else {
ssh_set_error(session, SSH_FATAL, "Socket error: %s", strerror(errno_code));
}
session->ssh_connection_callback(session);
}

View File

@@ -308,7 +308,7 @@ int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload){
}
sftp_packet sftp_packet_read(sftp_session sftp) {
unsigned char buffer[4096];
unsigned char buffer[MAX_BUF_SIZE];
sftp_packet packet = NULL;
uint32_t size;
int r;

View File

@@ -218,7 +218,7 @@ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks){
*/
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s){
ssh_socket s=(ssh_socket )v_s;
char buffer[4096];
char buffer[MAX_BUF_SIZE];
int r;
int err=0;
socklen_t errlen=sizeof(err);
@@ -291,7 +291,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
buffer_get_rest_len(s->in_buffer),
s->callbacks->userdata);
buffer_pass_bytes(s->in_buffer,r);
} while (r > 0);
} while ((r > 0) && (s->state == SSH_SOCKET_CONNECTED));
/* p may have been freed, so don't use it
* anymore in this function */
p = NULL;
@@ -440,6 +440,8 @@ void ssh_socket_close(ssh_socket s){
ssh_poll_free(s->poll_out);
s->poll_out=NULL;
}
s->state = SSH_SOCKET_CLOSED;
}
/**

View File

@@ -235,10 +235,11 @@ struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) {
* @param[in] s The string to burn.
*/
void ssh_string_burn(struct ssh_string_struct *s) {
if (s == NULL) {
return;
}
memset(s->data, 'X', ssh_string_len(s));
if (s == NULL || s->size == 0) {
return;
}
BURN_BUFFER(s->data, ssh_string_len(s));
}
/**

View File

@@ -59,8 +59,28 @@ struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void) {
static struct ssh_threads_callbacks_struct *user_callbacks =&ssh_threads_noop;
#ifdef HAVE_LIBGCRYPT
#if (GCRYPT_VERSION_NUMBER >= 0x010600)
/* libgcrypt >= 1.6 does not support custom callbacks */
GCRY_THREAD_OPTION_PTHREAD_IMPL;
/* Libgcrypt specific way of handling thread callbacks */
static int libgcrypt_thread_init(void){
if(user_callbacks == NULL)
return SSH_ERROR;
if(user_callbacks == &ssh_threads_noop)
return SSH_OK;
if (strcmp(user_callbacks->type, "threads_pthread") == 0){
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
return SSH_OK;
} else {
/* not supported */
SSH_LOG(SSH_LOG_WARN, "Custom thread handlers not supported with libgcrypt >=1.6, using pthreads");
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
return SSH_OK;
}
}
#else
/* Libgcrypt < 1.6 specific way of handling thread callbacks */
static struct gcry_thread_cbs gcrypt_threads_callbacks;
@@ -79,7 +99,8 @@ static int libgcrypt_thread_init(void){
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcrypt_threads_callbacks);
return SSH_OK;
}
#else
#endif /* GCRYPT_VERSION_NUMBER */
#else /* HAVE_LIBGCRYPT */
/* Libcrypto specific stuff */

View File

@@ -53,73 +53,75 @@ include_directories(
${LIBSSH_THREADS_PRIVATE_INCLUDE_DIRS}
)
add_library(${LIBSSH_THREADS_SHARED_LIBRARY} SHARED ${libssh_threads_SRCS})
if (libssh_threads_SRCS)
add_library(${LIBSSH_THREADS_SHARED_LIBRARY} SHARED ${libssh_threads_SRCS})
target_link_libraries(${LIBSSH_THREADS_SHARED_LIBRARY} ${LIBSSH_THREADS_LINK_LIBRARIES})
target_link_libraries(${LIBSSH_THREADS_SHARED_LIBRARY} ${LIBSSH_THREADS_LINK_LIBRARIES})
set_target_properties(
${LIBSSH_THREADS_SHARED_LIBRARY}
PROPERTIES
VERSION
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
OUTPUT_NAME
ssh_threads
DEFINE_SYMBOL
LIBSSH_EXPORTS
)
if (WITH_VISIBILITY_HIDDEN)
set_target_properties(${LIBSSH_THREADS_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
endif (WITH_VISIBILITY_HIDDEN)
install(
TARGETS
${LIBSSH_THREADS_SHARED_LIBRARY}
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
COMPONENT libraries
)
if (WITH_STATIC_LIB)
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS})
if (MSVC)
set(OUTPUT_SUFFIX static)
else (MSVC)
set(OUTPUT_SUFFIX )
endif (MSVC)
set_target_properties(
${LIBSSH_THREADS_STATIC_LIBRARY}
PROPERTIES
VERSION
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
OUTPUT_NAME
ssh_threads
ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
)
if (WIN32)
set_target_properties(
${LIBSSH_THREADS_STATIC_LIBRARY}
PROPERTIES
COMPILE_FLAGS
"-DLIBSSH_STATIC"
)
endif (WIN32)
${LIBSSH_THREADS_SHARED_LIBRARY}
PROPERTIES
VERSION
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
OUTPUT_NAME
ssh_threads
DEFINE_SYMBOL
LIBSSH_EXPORTS
)
install(
TARGETS
${LIBSSH_THREADS_STATIC_LIBRARY}
DESTINATION
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
COMPONENT
libraries
)
endif (WITH_STATIC_LIB)
if (WITH_VISIBILITY_HIDDEN)
set_target_properties(${LIBSSH_THREADS_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
endif (WITH_VISIBILITY_HIDDEN)
install(
TARGETS
${LIBSSH_THREADS_SHARED_LIBRARY}
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
COMPONENT libraries
)
if (WITH_STATIC_LIB)
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS})
if (MSVC)
set(OUTPUT_SUFFIX static)
else (MSVC)
set(OUTPUT_SUFFIX )
endif (MSVC)
set_target_properties(
${LIBSSH_THREADS_STATIC_LIBRARY}
PROPERTIES
VERSION
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
OUTPUT_NAME
ssh_threads
ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
)
if (WIN32)
set_target_properties(
${LIBSSH_THREADS_STATIC_LIBRARY}
PROPERTIES
COMPILE_FLAGS
"-DLIBSSH_STATIC"
)
endif (WIN32)
install(
TARGETS
${LIBSSH_THREADS_STATIC_LIBRARY}
DESTINATION
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
COMPONENT
libraries
)
endif (WITH_STATIC_LIB)
endif (libssh_threads_SRCS)

View File

@@ -130,10 +130,13 @@ void crypto_free(struct ssh_crypto_struct *crypto){
(deflateEnd(crypto->compress_out_ctx) != 0)) {
inflateEnd(crypto->compress_out_ctx);
}
SAFE_FREE(crypto->compress_out_ctx);
if (crypto->compress_in_ctx &&
(deflateEnd(crypto->compress_in_ctx) != 0)) {
inflateEnd(crypto->compress_in_ctx);
}
SAFE_FREE(crypto->compress_in_ctx);
#endif /* WITH_ZLIB */
if(crypto->encryptIV)
SAFE_FREE(crypto->encryptIV);

View File

@@ -24,6 +24,7 @@
#include "torture.h"
#include <libssh/libssh.h>
#include <sys/time.h>
#include <arpa/inet.h>
#define HOST "localhost"
/* Should work until Apnic decides to assign it :) */
@@ -54,12 +55,11 @@ static void torture_connect_nonblocking(void **state) {
ssh_set_blocking(session,0);
do {
rc = ssh_connect(session);
assert_true(rc != SSH_ERROR);
rc = ssh_connect(session);
assert_true(rc != SSH_ERROR);
} while(rc == SSH_AGAIN);
assert_true(rc==SSH_OK);
assert_true(rc == SSH_OK);
}
static void torture_connect_timeout(void **state) {
@@ -84,9 +84,9 @@ static void torture_connect_timeout(void **state) {
sec = after.tv_sec - before.tv_sec;
usec = after.tv_usec - before.tv_usec;
/* Borrow a second for the missing usecs, but don't bother calculating */
if(usec < 0)
if (usec < 0)
sec--;
assert_in_range(sec,1,3);
assert_in_range(sec, 1, 3);
}
static void torture_connect_double(void **state) {
@@ -102,10 +102,9 @@ static void torture_connect_double(void **state) {
rc = ssh_connect(session);
assert_true(rc == SSH_OK);
}
static void torture_connect_failure(void **state){
static void torture_connect_failure(void **state) {
/*
* The intent of this test is to check that a fresh
* ssh_new/ssh_disconnect/ssh_free sequence doesn't crash/leak
@@ -114,6 +113,30 @@ static void torture_connect_failure(void **state){
ssh_session session = *state;
ssh_disconnect(session);
}
static void torture_connect_socket(void **state) {
ssh_session session = *state;
int rc;
int sock_fd = 0;
struct sockaddr_in server_addr;
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
assert_true(sock_fd > 0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(22);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
rc = connect(sock_fd, &server_addr, sizeof(server_addr));
assert_true(rc == 0);
ssh_options_set(session, SSH_OPTIONS_FD, &sock_fd);
rc = ssh_connect(session);
assert_true(rc == SSH_OK);
}
int torture_run_tests(void) {
int rc;
const UnitTest tests[] = {
@@ -121,6 +144,7 @@ int torture_run_tests(void) {
unit_test_setup_teardown(torture_connect_double, setup, teardown),
unit_test_setup_teardown(torture_connect_failure, setup, teardown),
unit_test_setup_teardown(torture_connect_timeout, setup, teardown),
unit_test_setup_teardown(torture_connect_socket, setup, teardown),
};
ssh_init();

View File

@@ -23,8 +23,26 @@
#include "torture.h"
#include "session.c"
#include "known_hosts.c"
#define KNOWNHOSTFILES "libssh_torture_knownhosts"
#define BADRSA "AAAAB3NzaC1yc2EAAAADAQABAAABAQChm5" \
"a6Av65O8cKtx5YXOnui3wJnYE6A6J/I4kZSAibbn14Jcl+34VJQwv96f25AxNmo" \
"NwoiZV93IzdypQmiuieh6s6wB9WhYjU9K/6CkIpNhpCxswA90b3ePjS7LnR9B9J" \
"slPSbG1H0KC1c5lb7G3utXteXtM+4YvCvpN5VdC4CpghT+p0cwN2Na8Md5vRItz" \
"YgIytryNn7LLiwYfoSxvWigFrTTZsrVtCOYyNgklmffpGdzuC43wdANvTewfI9G" \
"o71r8EXmEc228CrYPmb8Scv3mpXFK/BosohSGkPlEHu9lf3YjnknBicDaVtJOYp" \
"wnXJPjZo2EhG79HxDRpjJHH"
#define BADDSA "AAAAB3NzaC1kc3MAAACBAITDKqGQ5aC5wHySG6ZdL1+BVBY2nLP5vzw3i3pvZfP" \
"yNUS0UCwrt5pajsMvDRGXXebTJhWVonDnv8tpSgiuIBXMZrma8CU1KCFGRzwb/n8" \
"cc5tJmIphlOUTrObjBmsRz7u1eZmoaddXC9ask6BNnt0DmhzYi2esL3mbardy8IN" \
"zAAAAFQDlPFCm410pgQQPb3X5FWjyVEIl+QAAAIAp0vqfir8K8p+zP4dzFG7ppnt" \
"DjaXf3ge6URF7f5xPDo6CClGo2JQ2REF8NxM7K9cLgR9Ifx2ahO48UMgrXEl/BOp" \
"IQHpeBqUz26a49O5J0WEW16YSUHxWwMxWVe/SRmyKdTUZJ6fcepH88JNqm3XudNn" \
"s78grM+yx9mcXnK2AsAAAAIBxpF8ZQIlGrSgwCmCfwjP156bC3Ya6LYf9ZpLJ0dX" \
"EcxqLVllrNEvd2EGD9p16BYO2yaalYon8im59PtOcul2ay5XQ6rVDQ2T0pgNUpsI" \
"h0dSi8VJXI1wes5HTyLsv9VBmU1uCXUUvufoQKfF/OcSH0ufcCpnd62g1/adZcy2" \
"WJg=="
static void setup(void **state) {
int verbosity=torture_libssh_verbosity();
@@ -93,10 +111,184 @@ static void torture_knownhosts_port(void **state) {
assert_true(rc == SSH_SERVER_KNOWN_OK);
}
static void torture_knownhosts_fail(void **state) {
ssh_session session = *state;
FILE *file;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa");
assert_true(rc == SSH_OK);
file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
fclose(file);
rc = ssh_connect(session);
assert_true(rc==SSH_OK);
rc = ssh_is_server_known(session);
assert_true(rc == SSH_SERVER_KNOWN_CHANGED);
}
static void torture_knownhosts_other(void **state) {
ssh_session session = *state;
FILE *file;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-dss");
assert_true(rc == SSH_OK);
file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
fclose(file);
rc = ssh_connect(session);
assert_true(rc==SSH_OK);
rc = ssh_is_server_known(session);
assert_true(rc == SSH_SERVER_FOUND_OTHER);
}
static void torture_knownhosts_other_auto(void **state) {
ssh_session session = *state;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-dss");
assert_true(rc == SSH_OK);
rc = ssh_connect(session);
assert_true(rc==SSH_OK);
rc = ssh_is_server_known(session);
assert_true(rc == SSH_SERVER_NOT_KNOWN);
rc = ssh_write_knownhost(session);
assert_true(rc == SSH_OK);
ssh_disconnect(session);
ssh_free(session);
/* connect again and check host key */
*state = session = ssh_new();
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK);
rc = ssh_connect(session);
assert_true(rc==SSH_OK);
/* ssh-rsa is the default but libssh should try ssh-dss instead */
rc = ssh_is_server_known(session);
assert_true(rc == SSH_SERVER_KNOWN_OK);
}
static void torture_knownhosts_conflict(void **state) {
ssh_session session = *state;
FILE *file;
int rc;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa");
assert_true(rc == SSH_OK);
file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
fprintf(file, "localhost ssh-dss %s\n", BADDSA);
fclose(file);
rc = ssh_connect(session);
assert_true(rc==SSH_OK);
rc = ssh_is_server_known(session);
assert_true(rc == SSH_SERVER_KNOWN_CHANGED);
rc = ssh_write_knownhost(session);
assert_true(rc==SSH_OK);
ssh_disconnect(session);
ssh_free(session);
/* connect again and check host key */
*state = session = ssh_new();
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa");
assert_true(rc == SSH_OK);
rc = ssh_connect(session);
assert_true(rc == SSH_OK);
rc = ssh_is_server_known(session);
assert_true(rc == SSH_SERVER_KNOWN_OK);
}
static void torture_knownhosts_precheck(void **state) {
ssh_session session = *state;
FILE *file;
int rc;
char **kex;
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
assert_true(rc == SSH_OK);
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
assert_true(rc == SSH_OK);
file = fopen(KNOWNHOSTFILES, "w");
assert_true(file != NULL);
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
fprintf(file, "localhost ssh-dss %s\n", BADDSA);
fclose(file);
kex = ssh_knownhosts_algorithms(session);
assert_true(kex != NULL);
assert_string_equal(kex[0],"ssh-rsa");
assert_string_equal(kex[1],"ssh-dss");
assert_true(kex[2]==NULL);
free(kex[1]);
free(kex[0]);
free(kex);
}
int torture_run_tests(void) {
int rc;
const UnitTest tests[] = {
unit_test_setup_teardown(torture_knownhosts_port, setup, teardown),
unit_test_setup_teardown(torture_knownhosts_fail, setup, teardown),
unit_test_setup_teardown(torture_knownhosts_other, setup, teardown),
unit_test_setup_teardown(torture_knownhosts_other_auto, setup, teardown),
unit_test_setup_teardown(torture_knownhosts_conflict, setup, teardown),
unit_test_setup_teardown(torture_knownhosts_precheck, setup, teardown)
};
ssh_init();

View File

@@ -0,0 +1,139 @@
/* Test the ability to use ssh_bind_accept_fd.
*
* Expected behavior: Prints "SUCCESS!"
*
* Faulty behavior observed before change: Connection timeout
*/
#include <arpa/inet.h>
#include <err.h>
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
struct options {
const char *server_keyfile;
} options;
const char HOST[] = "127.0.0.1";
const int PORT = 3333;
int get_connection() {
int rc, server_socket, client_conn = -1;
struct sockaddr_in server_socket_addr;
struct sockaddr_storage client_conn_addr;
socklen_t client_conn_addr_size = sizeof(client_conn_addr);
server_socket = socket(PF_INET, SOCK_STREAM, 0);
if (server_socket < 0) {
goto out;
}
server_socket_addr.sin_family = AF_INET;
server_socket_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, HOST, &server_socket_addr.sin_addr) != 1) {
goto out;
}
rc = bind(server_socket, (struct sockaddr *)&server_socket_addr,
sizeof(server_socket_addr));
if (rc < 0) {
goto out;
}
if (listen(server_socket, 0) < 0) {
goto out;
}
client_conn = accept(server_socket,
(struct sockaddr *)&client_conn_addr,
&client_conn_addr_size);
out:
return client_conn;
}
void ssh_server() {
ssh_bind bind;
ssh_session session;
int client_conn = get_connection();
if (client_conn < 0) {
err(1, "get_connection");
}
bind = ssh_bind_new();
if (!bind) {
errx(1, "ssh_bind_new");
}
if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY,
options.server_keyfile) != SSH_OK) {
errx(1, "ssh_bind_options_set(SSH_BIND_OPTIONS_DSAKEY");
}
session = ssh_new();
if (!session) {
errx(1, "ssh_new");
}
if (ssh_bind_accept_fd(bind, session, client_conn) != SSH_OK) {
errx(1, "ssh_bind_accept: %s", ssh_get_error(bind));
}
if (ssh_handle_key_exchange(session) != SSH_OK) {
errx(1, "ssh_handle_key_exchange: %s", ssh_get_error(session));
}
printf("SUCCESS!\n");
}
void ssh_client() {
ssh_session session;
session = ssh_new();
if (!session) {
errx(1, "ssh_new");
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, HOST) < 0) {
errx(1, "ssh_options_set(SSH_OPTIONS_HOST)");
}
if (ssh_options_set(session, SSH_OPTIONS_PORT, &PORT) < 0) {
errx(1, "ssh_options_set(SSH_OPTIONS_PORT)");
}
if (ssh_connect(session) != SSH_OK) {
errx(1, "ssh_connect: %s", ssh_get_error(session));
}
}
int main(int argc, const char *argv[]) {
if (argc != 2) {
printf("Usage: %s <private key file>\n", argv[0]);
exit(1);
}
options.server_keyfile = argv[1];
pid_t pid = fork();
if (pid < 0) {
errx(1, "fork");
}
if (pid == 0) {
/* Allow the server to get set up */
sleep(3);
ssh_client();
} else {
ssh_server();
}
return 0;
}

View File

@@ -36,17 +36,36 @@ static void setup_dsa_key(void **state) {
}
#ifdef HAVE_OPENSSL_ECC
static void setup_ecdsa_key(void **state) {
int rc;
static void setup_ecdsa_key(void **state, int ecdsa_bits) {
int rc = -1;
(void) state; /* unused */
unlink(LIBSSH_ECDSA_TESTKEY);
unlink(LIBSSH_ECDSA_TESTKEY ".pub");
rc = system("ssh-keygen -t ecdsa -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
if (ecdsa_bits == 256) {
rc = system("ssh-keygen -t ecdsa -b 256 -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
} else if (ecdsa_bits == 384) {
rc = system("ssh-keygen -t ecdsa -b 384 -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
} else if (ecdsa_bits == 521) {
rc = system("ssh-keygen -t ecdsa -b 521 -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
}
assert_true(rc == 0);
}
static void setup_ecdsa_key_521(void **state) {
setup_ecdsa_key(state, 521);
}
static void setup_ecdsa_key_384(void **state) {
setup_ecdsa_key(state, 384);
}
static void setup_ecdsa_key_256(void **state) {
setup_ecdsa_key(state, 256);
}
#endif
static void setup_both_keys(void **state) {
@@ -766,6 +785,39 @@ static void torture_pki_duplicate_key_ecdsa(void **state)
ssh_string_free_char(b64_key);
ssh_string_free_char(b64_key_gen);
}
/* Test case for bug #147: Private ECDSA key duplication did not carry
* over parts of the key that then caused subsequent key demotion to
* fail.
*/
static void torture_pki_ecdsa_duplicate_then_demote(void **state)
{
ssh_key pubkey;
ssh_key privkey;
ssh_key privkey_dup;
int rc;
(void) state;
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY,
NULL,
NULL,
NULL,
&privkey);
assert_true(rc == 0);
privkey_dup = ssh_key_dup(privkey);
assert_true(privkey_dup != NULL);
assert_int_equal(privkey->ecdsa_nid, privkey_dup->ecdsa_nid);
rc = ssh_pki_export_privkey_to_pubkey(privkey_dup, &pubkey);
assert_true(rc == 0);
assert_int_equal(pubkey->ecdsa_nid, privkey->ecdsa_nid);
ssh_key_free(pubkey);
ssh_key_free(privkey);
ssh_key_free(privkey_dup);
}
#endif
static void torture_pki_generate_key_rsa(void **state)
@@ -906,6 +958,9 @@ static void torture_pki_generate_key_ecdsa(void **state)
int rc;
ssh_key key;
ssh_signature sign;
enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN;
const char *type_char = NULL;
const char *etype_char = NULL;
ssh_session session=ssh_new();
(void) state;
@@ -916,6 +971,13 @@ static void torture_pki_generate_key_ecdsa(void **state)
assert_true(sign != NULL);
rc = pki_signature_verify(session,sign,key,HASH,20);
assert_true(rc == SSH_OK);
type = ssh_key_type(key);
assert_true(type == SSH_KEYTYPE_ECDSA);
type_char = ssh_key_type_to_char(type);
assert_true(strcmp(type_char, "ssh-ecdsa") == 0);
etype_char = ssh_pki_key_ecdsa_name(key);
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp256") == 0);
ssh_signature_free(sign);
ssh_key_free(key);
key=NULL;
@@ -927,6 +989,13 @@ static void torture_pki_generate_key_ecdsa(void **state)
assert_true(sign != NULL);
rc = pki_signature_verify(session,sign,key,HASH,20);
assert_true(rc == SSH_OK);
type = ssh_key_type(key);
assert_true(type == SSH_KEYTYPE_ECDSA);
type_char = ssh_key_type_to_char(type);
assert_true(strcmp(type_char, "ssh-ecdsa") == 0);
etype_char =ssh_pki_key_ecdsa_name(key);
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp384") == 0);
ssh_signature_free(sign);
ssh_key_free(key);
key=NULL;
@@ -938,6 +1007,13 @@ static void torture_pki_generate_key_ecdsa(void **state)
assert_true(sign != NULL);
rc = pki_signature_verify(session,sign,key,HASH,20);
assert_true(rc == SSH_OK);
type = ssh_key_type(key);
assert_true(type == SSH_KEYTYPE_ECDSA);
type_char = ssh_key_type_to_char(type);
assert_true(strcmp(type_char, "ssh-ecdsa") == 0);
etype_char =ssh_pki_key_ecdsa_name(key);
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp521") == 0);
ssh_signature_free(sign);
ssh_key_free(key);
key=NULL;
@@ -1070,6 +1146,42 @@ static void torture_pki_write_privkey_ecdsa(void **state)
#endif
#endif /* HAVE_LIBCRYPTO */
#ifdef HAVE_ECC
static void torture_pki_ecdsa_name(void **state, const char *expected_name)
{
int rc;
ssh_key key;
const char *etype_char = NULL;
(void) state; /* unused */
ssh_set_log_level(5);
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &key);
assert_true(rc == 0);
etype_char =ssh_pki_key_ecdsa_name(key);
assert_true(strcmp(etype_char, expected_name) == 0);
ssh_key_free(key);
}
static void torture_pki_ecdsa_name256(void **state)
{
torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp256");
}
static void torture_pki_ecdsa_name384(void **state)
{
torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp384");
}
static void torture_pki_ecdsa_name521(void **state)
{
torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp521");
}
#endif
int torture_run_tests(void) {
int rc;
const UnitTest tests[] = {
@@ -1092,7 +1204,13 @@ int torture_run_tests(void) {
teardown),
#ifdef HAVE_ECC
unit_test_setup_teardown(torture_pki_import_privkey_base64_ECDSA,
setup_ecdsa_key,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_pki_import_privkey_base64_ECDSA,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_pki_import_privkey_base64_ECDSA,
setup_ecdsa_key_521,
teardown),
#endif
unit_test_setup_teardown(torture_pki_import_privkey_base64_passphrase,
@@ -1107,7 +1225,22 @@ int torture_run_tests(void) {
teardown),
#ifdef HAVE_ECC
unit_test_setup_teardown(torture_pki_publickey_from_privatekey_ECDSA,
setup_ecdsa_key,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_pki_publickey_from_privatekey_ECDSA,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_pki_publickey_from_privatekey_ECDSA,
setup_ecdsa_key_521,
teardown),
unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote,
setup_ecdsa_key_521,
teardown),
#endif
/* public key */
@@ -1119,7 +1252,13 @@ int torture_run_tests(void) {
teardown),
#ifdef HAVE_ECC
unit_test_setup_teardown(torture_pki_publickey_ecdsa_base64,
setup_ecdsa_key,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_pki_publickey_ecdsa_base64,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_pki_publickey_ecdsa_base64,
setup_ecdsa_key_521,
teardown),
#endif
@@ -1131,7 +1270,13 @@ int torture_run_tests(void) {
teardown),
#ifdef HAVE_ECC
unit_test_setup_teardown(torture_generate_pubkey_from_privkey_ecdsa,
setup_ecdsa_key,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_generate_pubkey_from_privkey_ecdsa,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_generate_pubkey_from_privkey_ecdsa,
setup_ecdsa_key_521,
teardown),
#endif
@@ -1143,7 +1288,13 @@ int torture_run_tests(void) {
teardown),
#ifdef HAVE_ECC
unit_test_setup_teardown(torture_pki_duplicate_key_ecdsa,
setup_ecdsa_key,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_pki_duplicate_key_ecdsa,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_pki_duplicate_key_ecdsa,
setup_ecdsa_key_521,
teardown),
#endif
unit_test(torture_pki_generate_key_rsa),
@@ -1161,10 +1312,27 @@ int torture_run_tests(void) {
teardown),
#ifdef HAVE_ECC
unit_test_setup_teardown(torture_pki_write_privkey_ecdsa,
setup_ecdsa_key,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_pki_write_privkey_ecdsa,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_pki_write_privkey_ecdsa,
setup_ecdsa_key_521,
teardown),
#endif
#endif /* HAVE_LIBCRYPTO */
#ifdef HAVE_ECC
unit_test_setup_teardown(torture_pki_ecdsa_name256,
setup_ecdsa_key_256,
teardown),
unit_test_setup_teardown(torture_pki_ecdsa_name384,
setup_ecdsa_key_384,
teardown),
unit_test_setup_teardown(torture_pki_ecdsa_name521,
setup_ecdsa_key_521,
teardown),
#endif
};
(void)setup_both_keys;