Compare commits

...

165 Commits

Author SHA1 Message Date
Daniel Stenberg
c889058cb3 updated info for 1.2.4 2010-02-13 17:10:30 +01:00
Dan Fandrich
69c876e210 Allow compiling with OpenSSL when AES isn't available. 2010-02-10 14:49:17 -08:00
Dave McCaldon
10f5c70ac0 Fix Tru64 socklen_t compile issue with example/direct_tcpip.c
Building libssh2-1.2.3 on Tru64 fails at line 48 and 166 because socklen_t
isn't defined on Tru64 unless _POSIX_PII_SOCKET is defined.

This patch updates configure.ac to add -D_POSIX_PII_SOCKET when building
on Tru64 platform(s).
2010-02-09 11:45:40 +01:00
Dave McCaldon
ea914c8b72 Resolve compile issues on Solaris x64 and UltraSPARC
Solaris builds of libssh2-1.2.3 failed on both x64 and UltraSPARC
platforms because of two problems:

1) src/agent.c:145 sun is a reserved word when using the SUNWspro compiler
2) example/direct_tcpip.c:84 INADDR_NONE is not defined
2010-02-09 11:19:52 +01:00
Daniel Stenberg
64a6c255ec towards 1.2.4 now 2010-02-03 19:36:19 +01:00
Daniel Stenberg
e09d6ac653 Version 1.2.3 (February 3, 2010) 2010-02-03 19:23:28 +01:00
Daniel Stenberg
91841731af fix building out of source tree by proving better include path
when building out of source tree, we provide -I$(top_builddir)/example
since the libssh2_config.h gets generated in that dir
2010-02-03 19:21:12 +01:00
Sofian Brabez
a190437c4a Replace : in hexdump with " " (two spaces) 2010-02-01 16:30:47 +01:00
Peter Stuge
68a900d27a Detect when the forwarded connection is closed in example/direct_tcpip.c 2010-01-30 00:45:56 +01:00
Peter Stuge
e4b7baa885 Fix example/direct_tcpip.c to work also on WIN32
read() and write() are no good for WIN32 sockets, use recv() and send().
2010-01-30 00:35:05 +01:00
Peter Stuge
2622bbaf33 Ignore libssh2_config.h.in and stamp-h2 in example/ and remove .cvsignore 2010-01-30 00:25:46 +01:00
Peter Stuge
d3dbe4c81e Simplify WIN32 ifdefs in example/direct_tcpip.c to allow standalone compile 2010-01-30 00:01:51 +01:00
Peter Stuge
095ccbf825 Always #define INVALID_SOCKET -1 in libssh2_priv.h when not on win32
Fix broken builds since commit abd9bd0bbe
for all non-win32 platforms.
2010-01-29 23:51:38 +01:00
Peter Stuge
8eafded280 Include hmac-md5 and hmac-md5-96 only if crypto backend supports MD5 2010-01-29 23:22:56 +01:00
Peter Stuge
6df87e64b7 Use LIBSSH2_HOSTKEY_HASH_SHA1 instead of _MD5 in examples and tests
MD5 support is optional and may not always be available, while SHA1 is both
required and recommended.
2010-01-29 23:06:31 +01:00
Peter Stuge
3ddac8ac66 Update mailing list address in configure.ac to @cool.haxx.se 2010-01-29 22:31:40 +01:00
Peter Stuge
6c543545fe Make example/direct_tcpip.c compile for win32
One warning from FD_SET() remains, it is also in some other examples.
2010-01-29 20:35:24 +01:00
Peter Stuge
abd9bd0bbe Correctly check for an invalid socket in session_startup() 2010-01-29 20:29:01 +01:00
Peter Stuge
5dd4005ace Small documentation fix after Dave's _USERAUTH_FAILURE improvement 2010-01-29 09:16:39 +01:00
Dave McCaldon
8f102b8f56 Handle SSH_MSG_USERAUTH_FAILURE for password and kbd-int authentication
Neither libssh2_userauth_password_ex() nor
libssh2_userauth_keyboard_interactive_ex() would return a login failure
error if the server responded with a SSH_MSG_USERAUTH_FAILURE, instead
you would see whatever previous error had occurred, typically
LIBSSH2_ERROR_EAGAIN.

This patch changes error code -18 to LIBSSH2_ERROR_AUTHENTICATION_FAILED
and makes LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED an alias for
LIBSSH2_ERROR_AUTHENTICATION_FAILED.  In addition, new logic in
userauth_password() properly handles SSH_MSG_USERAUTH_FAILURE and both
this function and userauth_keyboard_interactive() now properly return
LIBSSH2_ERROR_AUTHENTICATION_FAILED.
2010-01-29 09:14:11 +01:00
Simon Josefsson
7d71f92a9c Fix. 2010-01-28 15:06:40 +01:00
Simon Josefsson
f6fab0d9ea Also deal with GLOBAL_REQUEST keep-alives. 2010-01-28 15:03:24 +01:00
Simon Josefsson
cc7f90f1d4 Make OpenSSH-style keepalive work against libssh2 clients. 2010-01-28 14:30:25 +01:00
Daniel Stenberg
6d55714ab5 clarified 2010-01-27 14:57:12 +01:00
Dave McCaldon
6b23f640f8 Fix trace context lookup in libssh2_debug()
The trace context is actually a bitmask so that tracing output can be
controlled by setting a bitmask using libssh2_trace().  However, the logic
in libssh2_debug() that converted the context to a string was using the
context value as an array index.  Because the code used a bounds check on
the array, there was never a danger of a crash, but you would certainly
either get the wrong string, or "unknown".

This patch adds a lookup that iterates over the context strings and uses
it's index to check for the corresponding bit in the context.
2010-01-26 17:33:25 +01:00
Peter Stuge
2cb8866f0a Fix typo in RELEASE-NOTES 2010-01-21 20:55:53 +01:00
Daniel Stenberg
3b3e13366e updated for 1.2.3 with all the stuff I found in the log 2010-01-20 19:57:42 +01:00
Daniel Stenberg
9f4292433a ignore more generated files 2010-01-20 19:46:36 +01:00
Dave McCaldon
f077984394 Pass user context through libssh2_trace_sethandler() to callback
The libssh2_trace_sethandler() call allows the user to handle the output of libssh2 rather than having it written to stderr.  This patch updates libssh2_trace_sethandler() to allow a user-defined void* context value to be passed back to the output handler.
2010-01-20 19:42:09 +01:00
Dave McCaldon
44eba0c993 Add libssh2_trace_sethandler() to the API (even more) 2010-01-15 22:58:44 +01:00
Dave McCaldon
474e38119b Add libssh2_trace_sethandler() to the API 2010-01-15 22:57:20 +01:00
Daniel Stenberg
7f27b0822d cleanup includes
We now produce a local libssh2_config.h file in this dir for the
examples to use so I cleaned up the include path at the same time.
2010-01-13 22:21:09 +01:00
Daniel Stenberg
e3d8c1cfed generate a libssh2_config.h in the example dir
buildconf copies the template to example/ and configure makes sure
to generate a proper file from it and the direct_tcpip.c example
is the first one to use it - to make sure it builds fine on more
paltforms
2010-01-13 13:46:56 +01:00
Simon Josefsson
11a114ee7c Remove redundant #includes and reorder sys/types.h include. 2010-01-13 11:03:26 +01:00
Daniel Stenberg
e48907ee05 avoid a free(NULL) 2010-01-10 00:00:31 +01:00
Simon Josefsson
3f6bc287f9 Make it simpler to get more debug info. 2010-01-07 19:43:40 +01:00
Daiki Ueno
e84fe88526 Simplify the commit 63457dfa using type cast from size_t * to ulong *. 2010-01-01 17:51:42 +09:00
Alexander Lamaison
73e37b3b49 Fixed memory leak in userauth_publickey().
userauth_publickey_fromfile() reads the key from a
file using file_read_publickey() which returns two
allocated strings, the decoded key and the key
method (such as "ssh-dss").  The latter can be
derived from the former but returning both avoids a
later allocation while doing so.

Older versions of userauth_publickey_fromfile() used
this method string directly but when
userauth_publickey() was factored out of
userauth_publickey_fromfile() it derived the method
from the key itself.  This resulted in the method
being allocated twice.

This fix, which maintains the optimisation that
avoids an extra allocation, changes
userauth_publickey() so it doesn't allocate and
derive the method when userauth_pblc_method already
has a value.

Signed-off-by: Alexander Lamaison <awl03@doc.ic.ac.uk>
2009-12-30 04:18:36 +00:00
Daiki Ueno
7926c9cfaa Fix the return value description of libssh2_knownhost_free(). 2009-12-25 10:26:51 +09:00
Daiki Ueno
63457dfa6c Fix compiler warnings for size_t pointers on 32-bit Windows. 2009-12-25 10:21:15 +09:00
Daiki Ueno
d00e97a7f1 Define INVALID_SOCKET and use it instead of SOCKET_BAD.
Revert the part of previous commit that defines SOCKET_BAD library wide.
2009-12-25 10:04:34 +09:00
Daiki Ueno
8436e45ea6 Use libssh2_socket_t in the ssh-agent stuff.
Define a portability macro SOCKET_BAD which means "invalid socket".
2009-12-24 19:45:57 +09:00
Daiki Ueno
0b6e37872d Mark/unmark connection to Pageant is open/close. 2009-12-24 17:57:15 +09:00
Daiki Ueno
1b3b7b2214 Add test to check if the socket is connected. 2009-12-24 16:49:28 +09:00
Peter Stuge
6a249d7b6c Add libssh2.pc to top-level .gitignore 2009-12-24 02:18:40 +01:00
Peter Stuge
87e32272f9 Fix publickey authentication regression
Commit 70b199f476 introduced a parsing
bug in file_read_publickey() which made the algorithm name contain an
extra trailing space character, breaking all publickey authentication.
2009-12-24 02:18:40 +01:00
Peter Stuge
bd0505d6b9 Add a direct-tcpip example which shows local port forwarding 2009-12-24 02:18:39 +01:00
Peter Stuge
f70dbfa3e6 Add session parameter and LIBSSH2_TRACE_SOCKET to libssh2_trace(3) man page 2009-12-24 02:18:39 +01:00
Peter Stuge
a2452d7eee Add TODO: Expose error messages sent by the server 2009-12-24 02:18:39 +01:00
Daiki Ueno
bbb2f29037 Fix doc comments. 2009-12-23 09:12:31 +09:00
Daiki Ueno
3138b5891f Add man pages for ssh-agent API. 2009-12-23 09:12:02 +09:00
Daiki Ueno
c573af83de Don't request userauthlist after authentication. 2009-12-23 07:59:37 +09:00
Simon Josefsson
ea8babf6d1 Add. 2009-12-21 12:30:17 +01:00
Daiki Ueno
db26c4eace Add an example to use ssh-agent API.
Signed-off-by: Simon Josefsson <simon@josefsson.org>
2009-12-21 12:19:33 +01:00
Daiki Ueno
7b351eed36 Add ssh-agent API.
Signed-off-by: Simon Josefsson <simon@josefsson.org>
2009-12-21 12:19:20 +01:00
Daiki Ueno
58abc7e30b Add callback-based API for publickey auth.
Signed-off-by: Simon Josefsson <simon@josefsson.org>
2009-12-21 12:15:33 +01:00
Simon Josefsson
0a3b350012 Move examples from example/simple to example/. 2009-12-19 10:56:03 +01:00
Simon Josefsson
b5e358618b Move examples from example/simple to example/. 2009-12-19 10:54:45 +01:00
Daniel Stenberg
dd81bda112 _libssh2_list_insert() fixed to work
While this is code not currently in use, it is part of the generic linked
list code and since I found the error I thought I'd better fix it since we
might bring in this function into the code one day.
2009-12-17 11:35:54 +01:00
Simon Josefsson
12433b4511 Silence compiler warnings.
Based on patch by Kamil Dudka <kdudka@redhat.com> in
<http://www.mail-archive.com/libssh2-devel@cool.haxx.se/msg00796.html>.
2009-12-16 16:14:55 +01:00
Kamil Dudka
39cbd17e19 libgcrypt: simplify code of _libssh2_dsa_sha1_sign
Signed-off-by: Simon Josefsson <simon@josefsson.org>
2009-12-16 16:08:25 +01:00
Kamil Dudka
1f91ab049f libgcrypt: follow-up for ssh-dss padding fix
Signed-off-by: Simon Josefsson <simon@josefsson.org>
2009-12-16 16:08:21 +01:00
Dan Fandrich
f2e5b49904 Check for the right environment variable in the test app 2009-12-15 15:21:06 -08:00
Simon Josefsson
b4c0821332 Silence warning about unused function parameter.
Reported by Steven Van Ingelgem <steven@vaningelgem.be>.
2009-12-14 15:50:41 +01:00
Daniel Stenberg
70b199f476 avoid returning data to memory already freed
In case of failure we must make sure that the data we return
doesn't point to a memory area already freed. Reported anonymously
in the bug report #2910103.
2009-12-10 23:40:44 +01:00
Peter Stuge
d142f385da Use LIBSSH2_TRACE_* internally and remove redundant LIBSSH2_DBG_* 2009-12-08 08:52:03 +01:00
Peter Stuge
1a491c6f00 Add LIBSSH2_TRACE_SOCKET context for tracing send() and recv()
Helpful in debugging the -39 errors.
2009-12-08 08:40:30 +01:00
Peter Stuge
1256c61815 Another transport layer fix for bogus -39 (LIBSSH2_ERROR_BAD_USE) errors
Commit 683aa0f6b5 made send_existing() send
more than just the second part of a packet when the kernel did not accept
the full packet, but the function still overlooked the SSH protocol
overhead in each packet, often 48 bytes.

If only the last few bytes of a packet remained, then the packet would
erroneously be considered completely sent, and the next call to write
more data in the session would return a -39 error.
2009-12-08 07:33:05 +01:00
Daniel Stenberg
95f559a926 move local variable to be more localized 2009-12-06 19:14:36 +01:00
Daniel Stenberg
052a68db30 fixed some indent mistakes 2009-12-06 19:14:36 +01:00
Peter Stuge
1aba38cd7d Fix padding in ssh-dss signature blob encoding
DSA signatures consist of two 160-bit integers called r and s. In ssh-dss
signature blobs r and s are stored directly after each other in binary
representation, making up a 320-bit (40 byte) string. (See RFC4253 p14.)

The crypto wrappers in libssh2 would either pack r and s incorrectly, or
fail, when at least one integer was small enough to be stored in 19 bytes
or less.

The patch ensures that r and s are always stored as two 160 bit numbers.
2009-12-06 08:07:40 +01:00
Peter Stuge
7317edab61 Don't always clear write direction blocking flag
When libssh2_transport_write() is called to continue sending a
partially sent packet the write direction flag must not be cleared
until the previous packet has been completely sent, or the app would
hang if the packet still isn't sent completely, since select() gets
called by the internal blocking emulation layer in libssh2 but would
then not be watching the socket for writability.

Clear the flag only once processing of previous packet data is
complete and a new packet is about to be prepared.
2009-11-27 07:52:26 +01:00
Alexander Lamaison
e642e2c202 Detabify. 2009-11-24 14:54:10 +00:00
Daniel Stenberg
f07cf3afd3 Fixed memory leak in sftp_fstat(). 2009-11-24 14:45:46 +00:00
Simon Josefsson
1e350754f6 Mark date of 1.2.2 release. 2009-11-17 09:51:12 +01:00
Simon Josefsson
55031fa320 Merge branch 'master' of ssh://git.stuge.se/var/lib/git/libssh2 2009-11-17 09:50:12 +01:00
Daniel Stenberg
355fbf4d5b prepared for 1.2.2 2009-11-16 22:43:55 +01:00
Simon Josefsson
74c63852d7 Improve NEWS items. 2009-11-16 16:24:36 +01:00
Simon Josefsson
ebbd7c879b Support AES-Counter ciphers. 2009-11-16 16:04:00 +01:00
Simon Josefsson
b78f854d8b Silence compiler warning.
Reported by Steven Van Ingelgem <steven@vaningelgem.be>
in <http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2566>.
2009-11-04 14:47:00 +01:00
Simon Josefsson
1f0d47fa92 Mention libssh2-style.el. 2009-10-29 10:39:15 +01:00
Simon Josefsson
463e09e55f Use memmove instead of memcpy on overlapping memory areas.
Reported by Bob Alexander <balexander@expressor-software.com> in
<http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
2009-10-28 15:31:00 +01:00
Simon Josefsson
82bf39dbfa Add. 2009-10-28 15:29:36 +01:00
Simon Josefsson
e5f170bae2 Protect against crash on too small SSH_MSG_IGNORE packets.
Reported by Bob Alexander <balexander@expressor-software.com>
in <http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
2009-10-28 15:27:11 +01:00
Simon Josefsson
fc60563840 add copyright line 2009-10-27 20:32:24 +01:00
Simon Josefsson
b38b4fb859 support arcfour128 cipher per RFC 4345 2009-10-27 20:03:30 +01:00
Cristian Rodríguez
3182045c2d add support for GCC visibility features 2009-10-21 17:02:12 +02:00
Simon Josefsson
60d73d5663 less hard coding of cipher mode in libgcrypt backend 2009-10-19 17:36:50 +02:00
Juzna
1e80194b97 libssh2_channel_forward_accept() and listening fixes
The forward accepting was not done right before, and the
packet_queue_listener function didn't assign a necessary
variable. All fixed by Juzna. I (Daniel) modified the
forward_accept() change somewhat.
2009-10-18 03:41:25 +02:00
Daniel Stenberg
0c13f7beda added man page for libssh2_knownhost_free 2009-10-18 03:03:55 +02:00
Daniel Stenberg
b859f4d9d2 more CVS => DEV conversions 2009-10-17 21:36:57 +02:00
Daniel Stenberg
13092c5a5e remove references to "CVS" 2009-10-17 21:36:05 +02:00
Daniel Stenberg
22b73235d3 we are on the 1.2.2 track nowadays 2009-10-17 21:34:49 +02:00
Peter Stuge
55034294e8 Ensure that win32/libssh2.dsp will be generated with CRLF line endings
First, win32/msvcproj.{head,foot} are now committed with CRLF line endings,
and .gitattributes specifies that these should not be changed on checkout or
commit. These are win32 files so it makes sense to store them with native
line endings.

Second, the rules for generating libssh2.dsp and libssh2.vcproj are changed
so that the full file contents passes through awk, which strips all CR and
then prints each line with one CRLF line ending. Stripping CR is important
to avoid CRCRLF in case the input already comes with CRLF.
2009-10-17 02:58:53 +02:00
Dan Fandrich
5e80055d22 Make sure permissions on the private host key file is tight enough that
sshd doesn't complain. Quote $srcdir to try to cope with embedded spaces.
2009-09-29 15:27:17 -07:00
Peter Stuge
11ca8d5583 Clarify the scp_write examples slightly and use an octal mask for the mode 2009-09-30 00:12:23 +02:00
Daniel Stenberg
9162fd7e61 1.2.1 preparations 2009-09-29 13:20:32 +02:00
Daniel Stenberg
7208e8d0d9 remove ChangeLog and win32/libssh2.dsp only at make distclean 2009-09-28 14:21:56 +02:00
Simon Josefsson
e1bb074287 Fix shell usage. 2009-09-23 09:39:47 +02:00
Daniel Stenberg
e887ffca4c clarify that the paths are the remote ones 2009-09-22 23:54:10 +02:00
Daniel Stenberg
65d1cb8107 let hpux systems build with _REENTRANT defined as well 2009-09-22 23:46:45 +02:00
Daniel Stenberg
4ed82f0e78 updated to match reality
I went over the commit log and added what I believe is all notable
changes and bugfixes since the 1.2 release
2009-09-20 20:14:23 +02:00
Peter Stuge
3cc2f143c1 Fix scp examples to loop correctly over libssh2_channel_write() 2009-09-20 01:35:19 +02:00
Peter Stuge
683aa0f6b5 Fix transport layer bug causing invalid -39 (LIBSSH2_ERROR_BAD_USE) errors
The channel layer sends packets using the transport layer, possibly
calling _libssh2_transport_write() many times for each packet.

The transport layer uses the send_existing() helper to send out any
remaining parts of previous packets before a new packet is started.

The bug made send_existing() consider the entire packet sent as soon as it
successfully sent the second part of a packet, even if the packet was not
completely done yet.
2009-09-20 00:30:42 +02:00
Neil Gierman
7a9d36903a Added gettimeofday() function for win32
Neil Gierman's patch adds a gettimeofday() function for win32
for the libssh2_trace() functionality. The code originates from
cygwin and was put in the public domain by the author
Danny Smith <dannysmith@users.sourceforge.net>
2009-09-19 22:39:50 +02:00
Daniel Stenberg
c2375dbfa4 libssh2_channel_read_ex() must return 0 when closed
If the channel is already at EOF or even closed at the end of the
libssh2_channel_read_ex() function and there's no data to return,
we need to signal that back. We may have gotten that info while
draining the incoming transport layer until EAGAIN so we must not
be fooled by that return code.
2009-09-16 23:46:30 +02:00
Dan Fandrich
906a7d8866 Ignore tags file 2009-09-16 07:49:32 -07:00
Dan Fandrich
1418993a0f Some platforms need sys/socket.h included before netinet/in.h.
Fixed an unused variable compiler warning.
2009-09-16 07:49:32 -07:00
Daniel Stenberg
c4b7f0394b libssh2_channel_wait_closed() could hang
libssh2_channel_wait_closed() had a bad loop waiting for the
channel to close, as it could easily miss the info and then if
the socket would be silent from that moment the funtion would
hang if in blocking-mode or just return EAGAIN wrongly to the
app. The drain-transport loop now correctly checks if the close
has arrived.
2009-09-16 13:49:04 +02:00
Daniel Stenberg
9e84b999a5 make libssh2_scp_send/recv do blocking mode correctly
Somehow I had completely missed to make the libssh2_scp_send/recv
functions support the blocking mode the correct way so when I
cleaned up things the other day blocking mode broke for them...
Fixed now.
2009-09-15 23:29:46 +02:00
Guenter Knauf
3fda91d725 changed NetWare test makefile static link order 2009-09-08 01:32:45 +02:00
Guenter Knauf
7c32c84d0e removed conditional sources from Makefile.inc
added ifdef blocks to libgcrypt.c, pem.c, openssl.c
2009-09-07 18:10:49 +02:00
Simon Josefsson
766127ad57 Fix compilation errors. 2009-09-07 14:14:10 +02:00
Guenter Knauf
a9e7f87e31 some more NetWare build fixes. 2009-09-06 06:57:55 +02:00
Guenter Knauf
a04a0b6c69 some more NetWare makefile fixes. 2009-09-06 06:31:59 +02:00
Guenter Knauf
1f8d58a4ce added sys/select.h include to samples for fd_set on NetWare. 2009-09-06 06:15:29 +02:00
Guenter Knauf
4b482eddbe accept CFLAGS from environment. 2009-09-06 04:36:51 +02:00
Guenter Knauf
05eb612f8e some more .cvsignore / .gitignore fixes. 2009-09-04 02:23:28 +02:00
Guenter Knauf
d48ee98ecf renamed .cvsignore to .gitignore. 2009-09-04 02:12:50 +02:00
Guenter Knauf
536443246e changed conditional into make language. 2009-09-04 01:24:38 +02:00
Guenter Knauf
b728b1018f changed NetWare and MingW32 makefile to use Makefile.inc. 2009-09-03 22:06:59 +02:00
Daniel Stenberg
3f5a6662d0 CVS leftovers removed 2009-09-02 22:41:47 +02:00
Daniel Stenberg
33f4e0f250 libssh2_version() exists since 1.1 2009-09-02 22:39:48 +02:00
Hacki
8dabb1c5eb added knownhost.c to makefiles. 2009-09-02 20:03:27 +02:00
Alexander Lamaison
0d6aaa1f56 Pass private-key to OpenSSL as a filename with BIO_new_file().
This keeps all FILE* handling on the OpenSSL side of the DLL boundary avoiding crashes on Windows while removing the need for libssh2 to read the private key file into memory.  This is now done by OpenSSL which is likely to do a better job of it.
2009-09-02 14:59:40 +01:00
Daniel Stenberg
00fac145ba generate and install libssh2.pc
oh these are necessary libssh2.pc changes too
2009-09-01 10:04:13 +02:00
Daniel Stenberg
f65f71a156 first take at producing and installing a pkg-config file 2009-09-01 09:55:25 +02:00
Daniel Stenberg
3142e8df7e renamed to .ac 2009-09-01 09:51:14 +02:00
Daniel Stenberg
bffefb12ea renamed to the modern name "configure.ac" 2009-09-01 09:48:14 +02:00
Daniel Stenberg
feadd5f321 always braces and else and brace on the same line removed
I don't follow those particular guidelines myself so I think I'd
rather remove them here and keep my style than the opposite. As
I am the most frequent writer of code for the moment.
2009-09-01 09:42:33 +02:00
Daniel Stenberg
7c139633a1 _libssh2_channel_write() only sends the 32K first bytes
In theory we could split larger buffers into several smaller
packets to pass to transport_write(), but for now we instead only
deal with the first 32K in this call and assume the app will call
this function again with the rest!  The 32K size is a
conservative limit based on the text in RFC4253 section 6.1.
2009-08-30 23:52:11 +02:00
Daniel Stenberg
692401633a document _libssh2_channel_write's return code 2009-08-30 19:46:42 +02:00
Daniel Stenberg
5bb1fb5cbc s/libssh2_channel_write_ex/_libssh2_channel_write internally 2009-08-30 19:31:07 +02:00
Daniel Stenberg
5e5ead00b4 call libssh2_error() when transport_write() returns EAGAIN
_libssh2_channel_write() should never return error without
libssh2_error() getting called
2009-08-30 19:28:43 +02:00
Daniel Stenberg
06278728e2 clarify that zero can be returned without meaning error 2009-08-30 17:07:50 +02:00
Daniel Stenberg
0357befa42 remove debug leftovers 2009-08-30 17:06:57 +02:00
Daniel Stenberg
85198c1cdb channel_read() was changed to _libssh2_channel_read() as lots of
internal code was changed to use that instead of wrongly using
libssh2_channel_read_ex(). Some files now need to include
channel.h to get this proto.

channel_read() calls libssh2_error() properly on transport_read()
failures

channel_read() was adjusted to not "invent" EAGAIN return code in
case the transport_read() didn't return it

channel_close() now returns 0 or error code, as
documented. Previously it would return number of bytes read in
the last read, which was confusing (and useless).
2009-08-30 17:00:49 +02:00
Daniel Stenberg
face4750ca changed all return EAGAIN to return the variable instead
I made this change just to easier grep for "return .*EAGAIN" cases
as they should be very rare or done wrongly. Already worked to find
a flaw, marked with "TODO FIXME THIS IS WRONG" in channel.c. I also
fixed a few cases to become more general returns now when we have
more unified return codes internally.
2009-08-25 00:54:47 +02:00
Daniel Stenberg
a1365916c7 _libssh2_channel_write() must not invent EAGAIN situations
it is important that only the transport layer can generate EAGAIN
error codes so that we limit where we need to set direction bits
and more. When the local window is too small to send data we simply
stop trying to send and (risk) returning zero in
_libssh2_channel_write()
2009-08-25 00:25:08 +02:00
Daniel Stenberg
f64a84a909 error code cleanup 2009-08-25 00:23:34 +02:00
Daniel Stenberg
fba3877ed8 remove all libssh2pack_t leftovers 2009-08-24 23:57:15 +02:00
Daniel Stenberg
f1e010f5d4 removed the libssh2pack_t type
and a minor _libssh2_transport_read() simplification
2009-08-24 23:50:53 +02:00
Daniel Stenberg
9e96acf86e fix return codes, shortened a very long function name 2009-08-24 23:49:58 +02:00
Daniel Stenberg
1a157d27cc remove use of libssh2_channel_receive_window_adjust
_libssh2_channel_receive_window_adjust is the new replacement that
is both the correct internal version instead of the external API one,
and it has the return code flaw fixed. I also fixed more return
codes to pass long the correct error found.
2009-08-24 23:24:35 +02:00
Daniel Stenberg
b3418bb1eb more proper return codes, added a missing libssh2_error() call 2009-08-24 23:23:46 +02:00
Daniel Stenberg
08be841b4d clear socket_block_directions bits before send/recv
These two places are the only places where send and recv are called
outside of transport.c so make sure they clear/set the bits correctly.
2009-08-24 23:22:39 +02:00
Daniel Stenberg
e39128df52 simplified fullpacket, clarified _libssh2_transport_write() comment 2009-08-24 23:13:14 +02:00
Daniel Stenberg
5c6b8166c7 cleaned up _libssh2_packet_add()
removed some code duplication, changed a few return -1 to return
error codes instead and added a missing libssh2_error() invoke
2009-08-24 23:03:08 +02:00
Daniel Stenberg
dcb9625473 convert return -1 instances to return [proper error code] 2009-08-24 22:50:46 +02:00
Daniel Stenberg
c1b687c9e4 simplify code by removing code duplication 2009-08-24 22:44:22 +02:00
Daniel Stenberg
13e920d4ef fix several return -1 to return a proper error code
On many places in the code there have been laziness return -1
statements lying around that should be fixed to return sensible
error codes. Here's a take at fixing a few offenders.
2009-08-24 22:28:27 +02:00
Daniel Stenberg
314e61e545 change transport to use unified error codes
I added three new public error codes, and then modified the return
codes we use in the transport layer to use the generic error codes
so that there won't be any risk of internal confusions due to
different error code sets.
2009-08-24 22:27:11 +02:00
Daniel Stenberg
13c16db3bc changes from int to libssh2_socket_t for sokcets
modified two functions to use libssh2_socket_t instead of int
when referring to a socket descriptor
2009-08-24 14:13:00 +02:00
Daniel Stenberg
82c3f0ba72 introducing libssh2_socket_t type and fixed iovec for windows
Steven Van Ingelgem introduces libssh2_socket_t as a generic socket
type to use internally to avoid compiler warnings and mistakes. Also,
the private struct iovec declaration for windows is now made to look
like the POSIX struct does.
2009-08-24 14:07:05 +02:00
Daniel Stenberg
9e099fb88a linked list changes and minor bug fixes 2009-08-20 01:03:40 +02:00
Daniel Stenberg
415efe10ac linked list code is now converted to new functions 2009-08-20 01:00:54 +02:00
Daniel Stenberg
4b1cb4e95e remove superfluous braces and re-indent somewhat 2009-08-20 00:59:23 +02:00
Daniel Stenberg
d8b6f3c7b8 move over lots of code to the _libssh2_list_* functions
and I fixed a few minor bugs at the same time
2009-08-20 00:56:54 +02:00
Daniel Stenberg
a871f0b214 converted listeners to the linked list functions 2009-08-20 00:56:54 +02:00
Daniel Stenberg
08cad8e14c moved the handling of SFTP handles to new linked list code
Each SFTP file handle is now handled by the "mother-struct"
using the generic linked list functions. The goal is to move
all custom linked list code to use this set of functions.

I also moved the list declarations to the misc.h where they
belong and made misc.h no longer include libssh2_priv.h itself
since now libssh2_priv.h needs misc.h...

In misc.c I added a #if 0'ed _libssh2_list_insert() function
because I ended up writing one, and I believe we may need it here
too once we move over more stuff to use the _libssh2_list* family.
2009-08-20 00:56:54 +02:00
Daniel Stenberg
46178378f2 correct the comment for _libssh2_list_add()
it adds the new node to the _end_ of the list
2009-08-20 00:56:54 +02:00
Steven Van Ingelgem
28b179ecf2 Suppress signed/unsigned comparison warning. 2009-08-16 23:14:20 +01:00
Daniel Stenberg
7b4d6b2868 added contributors from the 1.2 release notes 2009-08-11 10:11:11 +02:00
Simon Josefsson
fbe4737719 Need to use $(EXEEXT) on programs in TESTS to fix mingw cross-compiles. 2009-08-11 02:46:45 +02:00
Daniel Stenberg
ce4ad0d086 start working on 1.2.1 2009-08-10 22:58:15 +02:00
98 changed files with 3936 additions and 1868 deletions

View File

@@ -1,28 +0,0 @@
.deps
.libs
*.lib
*.pdb
*.dll
*.exe
*.obj
.*.swp
Debug
Release
*.exp
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.guess
config.log
config.status
config.sub
configure
depcomp
libtool
ltmain.sh
missing
ssh2_sample
libssh2-*.tar.gz
INSTALL
install-sh

View File

@@ -1,11 +0,0 @@
jas4711:Simon Josefsson <simon@josefsson.org>
bagder:Daniel Stenberg
sarag:Sara Golemon <pollita@libssh2.org>
gusarov:Mikhail Gusarov <dottedmag@dottedmag.net>
wez:Wez Furlong
edink:Edink Kadribasic
jehousley: James Housley
gknauf: Guenter Knauf
dfandrich: Dan Fandrich
yangtse: Yang Tse
thomaspu: Paul Thomas

2
.gitattribute Normal file
View File

@@ -0,0 +1,2 @@
win32/msvcproj.head -crlf
win32/msvcproj.foot -crlf

2
.gitignore vendored
View File

@@ -30,3 +30,5 @@ install-sh
*.lo
*.la
mkinstalldirs
tags
libssh2.pc

View File

@@ -6,6 +6,7 @@
Adam Gobiowski
Alexander Holyapin
Alexander Lamaison
Ben Kibbey
Bjorn Stenborg
Carlo Bramini
Dan Casey
@@ -15,15 +16,19 @@ David J Sullivan
David Robins
Edink Kadribasic
Erik Brossler
Francois Dupoux
Guenter Knauf
Heiner Steven
James Housleys
Jean-Louis Charton
Jussi Mononen
Mark McPherson
Markus Moeller
Mike Protts
Mikhail Gusarov
Neil Gierman
Olivier Hervieu
Paul Veldkamp
Peter O'Gorman
Peter Stuge
Romain Bondue
@@ -34,6 +39,8 @@ Selcuk Gueney
Simon Hart
Simon Josefsson
Steven Ayre
Steven Van Ingelgem
Tor Arntsen
Vincent Jaulin
Vlad Grachov
Wez Furlong

View File

@@ -1,6 +1,7 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2006-2007 The Written Word, Inc.
* Copyright (c) 2009 Daniel Stenberg
* Copyright (C) 2008, 2009 Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,

11
HACKING
View File

@@ -9,14 +9,5 @@ libssh2 source code style guide:
go_nuts();
}
- write both braces on the else line:
if (banana) {
go_nuts();
} else {
stay_calm();
}
- use braces even for single-statement blocks
- keep source lines shorter than 80 columns
- See libssh2-style.el for how to achieve this within Emacs

View File

@@ -2,6 +2,9 @@ AUTOMAKE_OPTIONS = foreign nostdinc
SUBDIRS = src example tests docs
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libssh2.pc
include_HEADERS = \
include/libssh2.h \
include/libssh2_publickey.h \
@@ -16,8 +19,7 @@ NETWAREFILES = nw/keepscreen.c \
DSP = win32/libssh2.dsp
VCPROJ = win32/libssh2.vcproj
#Need to include $(VCPROJ) to CLEANFILES and WIN32FILES when I get a proper vc8proj.head|foot
CLEANFILES = $(DSP)
DISTCLEANFILES = $(DSP)
WIN32FILES = win32/Makefile.win32 win32/libssh2.dsw \
win32/config.mk win32/Makefile win32/test/Makefile.win32 \
@@ -25,14 +27,14 @@ win32/libssh2_config.h win32/tests.dsp win32/rules.mk $(DSP) \
win32/msvcproj.head win32/msvcproj.foot
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \
maketgz NMakefile TODO RELEASE-NOTES
maketgz NMakefile TODO RELEASE-NOTES libssh2.pc.in
ACLOCAL_AMFLAGS = -I m4
.PHONY: ChangeLog
ChangeLog:
echo "see NEWS" > ./ChangeLog
CLEANFILES += ChangeLog
DISTCLEANFILES += ChangeLog
dist-hook:
rm -rf $(top_builddir)/tests/log
@@ -73,55 +75,54 @@ include Makefile.inc
WIN32SOURCES = $(CSOURCES)
WIN32HEADERS = $(HHEADERS) libssh2_config.h
DSPOUT = | awk '{printf("%s\r\n", $$0)}' >> $(DSP)
VCPROJOUT = | awk '{printf("%s\r\n", $$0)}' >> $(VCPROJ)
$(DSP): win32/msvcproj.head win32/msvcproj.foot Makefile.am
echo "creating $(DSP)"
@(cp $(srcdir)/win32/msvcproj.head $(DSP); \
echo "# Begin Group \"Source Files\"" $(DSPOUT); \
echo "" $(DSPOUT); \
echo "# PROP Default_Filter \"cpp;c;cxx\"" $(DSPOUT); \
win32_srcs='$(WIN32SOURCES)'; \
sorted_srcs=`for file in $$win32_srcs; do echo $$file; done | sort`; \
for file in $$sorted_srcs; do \
echo "# Begin Source File" $(DSPOUT); \
echo "" $(DSPOUT); \
echo "SOURCE=..\\src\\"$$file $(DSPOUT); \
echo "# End Source File" $(DSPOUT); \
@( (cat $(srcdir)/win32/msvcproj.head; \
echo "# Begin Group \"Source Files\""; \
echo ""; \
echo "# PROP Default_Filter \"cpp;c;cxx\""; \
win32_srcs='$(WIN32SOURCES)'; \
sorted_srcs=`for file in $$win32_srcs; do echo $$file; done | sort`; \
for file in $$sorted_srcs; do \
echo "# Begin Source File"; \
echo ""; \
echo "SOURCE=..\\src\\"$$file; \
echo "# End Source File"; \
done; \
echo "# End Group" $(DSPOUT); \
echo "# Begin Group \"Header Files\"" $(DSPOUT); \
echo "" $(DSPOUT); \
echo "# PROP Default_Filter \"h;hpp;hxx\"" $(DSPOUT); \
win32_hdrs='$(WIN32HEADERS)'; \
sorted_hdrs=`for file in $$win32_hdrs; do echo $$file; done | sort`; \
for file in $$sorted_hdrs; do \
echo "# Begin Source File" $(DSPOUT); \
echo "" $(DSPOUT); \
if [ "$$file" == "libssh2_config.h" ]; \
then \
echo "SOURCE=.\\"$$file $(DSPOUT); \
else \
echo "SOURCE=..\\src\\"$$file $(DSPOUT); \
fi; \
echo "# End Source File" $(DSPOUT); \
echo "# End Group"; \
echo "# Begin Group \"Header Files\""; \
echo ""; \
echo "# PROP Default_Filter \"h;hpp;hxx\""; \
win32_hdrs='$(WIN32HEADERS)'; \
sorted_hdrs=`for file in $$win32_hdrs; do echo $$file; done | sort`; \
for file in $$sorted_hdrs; do \
echo "# Begin Source File"; \
echo ""; \
if [ "$$file" == "libssh2_config.h" ]; \
then \
echo "SOURCE=.\\"$$file; \
else \
echo "SOURCE=..\\src\\"$$file; \
fi; \
echo "# End Source File"; \
done; \
echo "# End Group" $(DSPOUT); \
cat $(srcdir)/win32/msvcproj.foot $(DSPOUT) )
echo "# End Group"; \
cat $(srcdir)/win32/msvcproj.foot) | \
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )
$(VCPROJ): win32/vc8proj.head win32/vc8proj.foot Makefile.am
echo "creating $(VCPROJ)"
@(cp $(srcdir)/vc8proj.head $(VCPROJ); \
win32_srcs='$(WIN32SOURCES)'; \
sorted_srcs=`for file in $$win32_srcs; do echo $$file; done | sort`; \
for file in $$sorted_srcs; do \
echo "<File RelativePath=\""..\src\$$file"\"></File>" $(VCPROJOUT); \
@( (cat $(srcdir)/vc8proj.head; \
win32_srcs='$(WIN32SOURCES)'; \
sorted_srcs=`for file in $$win32_srcs; do echo $$file; done | sort`; \
for file in $$sorted_srcs; do \
echo "<File RelativePath=\""..\src\$$file"\"></File>"; \
done; \
echo "</Filter><Filter Name=\"Header Files\">" $(VCPROJOUT); \
win32_hdrs='$(WIN32HEADERS)'; \
sorted_hdrs=`for file in $$win32_hdrs; do echo $$file; done | sort`; \
for file in $$sorted_hdrs; do \
echo "<File RelativePath=\""..\src\$$file"\"></File>" $(VCPROJOUT); \
echo "</Filter><Filter Name=\"Header Files\">"; \
win32_hdrs='$(WIN32HEADERS)'; \
sorted_hdrs=`for file in $$win32_hdrs; do echo $$file; done | sort`; \
for file in $$sorted_hdrs; do \
echo "<File RelativePath=\""..\src\$$file"\"></File>"; \
done; \
cat $(srcdir)/vc8proj.foot $(VCPROJOUT) )
cat $(srcdir)/vc8proj.foot) | \
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )

View File

@@ -1,11 +1,5 @@
CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
packet.c publickey.c scp.c session.c sftp.c userauth.c transport.c \
version.c knownhost.c
if LIBGCRYPT
CSOURCES += libgcrypt.c pem.c
else
CSOURCES += openssl.c
endif
version.c knownhost.c agent.c openssl.c libgcrypt.c pem.c
HHEADERS = libssh2_priv.h openssl.h libgcrypt.h transport.h channel.h comp.h mac.h misc.h

80
NEWS
View File

@@ -1,3 +1,83 @@
Version 1.2.4 (February 13, 2010)
o Resolve compile issues on Solaris x64 and UltraSPARC
o Allow compiling with OpenSSL when AES isn't available
o Fix Tru64 socklen_t compile issue with example/direct_tcpip.c
Version 1.2.3 (February 3, 2010)
o Added libssh2_trace_sethandler()
o Added the direct_tcpip.c example
o Fixed memory leak in userauth_publickey
o Added support for authentication via SSH-Agent. By Daiki Ueno.
o Respond to unknown SSH_MSG_GLOBAL_REQUEST/SSH_MSG_CHANNEL_REQUEST
with SSH_MSG_REQUEST_FAILURE/SSH_MSG_CHANNEL_FAILURE in order to
make (at least) OpenSSH server keepalive work. Before OpenSSH
servers (configured with a positive ClientAliveInterval) would
terminate connections against libssh2 clients because libssh2 did
not respond properly to the request. By Simon Josefsson.
Version 1.2.2 (November 16, 2009)
* This release includes the following changes:
o Fix crash when server sends an invalid SSH_MSG_IGNORE message.
Reported by Bob Alexander <balexander@expressor-software.com> in
<http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
By Simon Josefsson.
o Support for the "aes128-ctr", "aes192-ctr", "aes256-ctr" ciphers
as per RFC 4344 for libgcrypt and OpenSSL. They are now the
preferred ciphers. By Simon Josefsson.
o Support for the "arcfour128" cipher as per RFC 4345 for libgcrypt
and OpenSSL. It is preferred over the normal "arcfour" cipher
which is somewhat broken. By Simon Josefsson.
o Add support for GCC visibility features. By Cristian Rodr<64>guez.
o Fix libssh2_channel_forward_accept. By Juzna.
o Generate Win32 files correctly. By Peter Stuge.
o Fix permission issue in ssh2 self test. By Dan Fandrich.
o Use memmove instead of memcpy in one place which copies
overlapping memory areas.
o Cleanup hard coding of cipher modes in libgcrypt backend. By Simon.
o Added man page for libssh2_knownhost_free. By Daniel.
Version 1.2.1 (September 28, 2009)
* This release includes the following changes:
o generate and install libssh2.pc
... and the following bugfixes:
o proper return codes returned from several functions
o return EAGAIN internal cleanup
o added knownhost.c to windows makefiles
o pass private-key to OpenSSL as a filename with BIO_new_file().
o make libssh2_scp_send/recv do blocking mode correctly
o libssh2_channel_wait_closed() could hang
o libssh2_channel_read_ex() must return 0 when closed
o added gettimeofday() function for win32 for the debug trace outputs
o transport layer bug causing invalid -39 (LIBSSH2_ERROR_BAD_USE) errors
o scp examples now loop correctly over libssh2_channel_write()
* (August 29 2009) Daniel Stenberg:
- I fixed all code to use the recently added dedicated linked list functions
instead of doing the same stuff spread out all over.
- I also fixed a few cases where local variables where used to keep memory
but was used to keep state for re-invokes due to non-blocking situations
which would lead to segfaults.
Version 1.2 (August 10, 2009)
-----------------------------

View File

@@ -1,6 +1,6 @@
!include "win32/config.mk"
# SUBDIRS=src example\simple
# SUBDIRS=src example
SUBDIRS=src
all-sub:

View File

@@ -1,40 +1,18 @@
libssh2 1.2
libssh2 1.2.4
This release includes the following changes:
o we've switched to using git for source code control
o we're offering an alternative web site at http://libssh2.haxx.se/
o the libssh2-devel mailing list moved to http://cool.haxx.se/
o libssh2_poll() and libssh2_poll_channel_read() are now deprecated
o a range of libssh2_knownhost_*() functions were added to the API to work
with OpenSSH style known_hosts files etc
o added libssh2_session_hostkey()
o added an X11 forwarding example
o the makefile now generate MSVS project files
o
This release includes the following bugfixes:
o bad 0-return from libssh2_channel_read
o failure to "drain" the transport data caused badness
o memory leak in libssh2_sftp_shutdown()
o fixed stroll() #if condition
o build thread-safe on Solaris
o error when including libssh2.h in two files on Windows fixed
o custom memory function extra argument was wrong
o transport now checks for and bail out on packets claing to be zero sized
o fixed a number of compiler warnings
o buildconf runs on Mac OS X
o public headers includable on their own
o bad debugdump() caused SIGSEGV at times (when libssh2_trace() was used)
o possible data loss when send_existing() failed to send its buffer
o passing FILE*s across DLL boundaries (OpenSSL) caused crashes on Windows
o Resolve compile issues on Solaris x64 and UltraSPARC
o Allow compiling with OpenSSL when AES isn't available
o Fix Tru64 socklen_t compile issue with example/direct_tcpip.c
This release would not have looked like this without help, code, reports and
advice from friends like these:
Simon Josefsson, Neil Gierman, Alexander Lamaison, Peter Stuge,
Steven Van Ingelgem, Ben Kibbey, Francois Dupoux, Mark McPherson,
Guenter Knauf, Yang Tse, Tor Arntsen, Jussi Mononen, Olivier Hervieu,
Paul Veldkamp
Dan Fandrich, Dave McCaldon, Peter Stuge
Thanks! (and sorry if I forgot to mention someone)

5
TODO
View File

@@ -8,9 +8,6 @@ Things TODO
* Provide a libssh2_scp_send() API for files larger than 4GB (32bit size)
* Convert the linked list code used all over to use the (new) generic linked
list code. See the _libssh2_list_*() functions in src/misc.c
* Add more info to the man pages.
* Decrease the number of mallocs. Everywhere.
@@ -21,6 +18,8 @@ Things TODO
* Fix all compiler warnings (some can't be done without API changes)
* Expose error messages sent by the server
At next SONAME bump
===================

View File

@@ -297,7 +297,7 @@ dnl Internal macro for CURL_CONFIGURE_REENTRANT.
AC_DEFUN([CURL_CHECK_NEED_REENTRANT_SYSTEM], [
case $host in
*-*-solaris*)
*-*-solaris* | *-*-hpux*)
tmp_need_reentrant="yes"
;;
*)

View File

@@ -22,6 +22,6 @@ ${AUTOHEADER:-autoheader}
# copy the private libssh2_config.h.in to the examples dir so that
# it can be included without pointing the include path to the private
# source dir
cp src/libssh2_config.h.in example/simple/config.h.in
cp src/libssh2_config.h.in example/libssh2_config.h.in
${AUTOCONF:-autoconf}
${AUTOMAKE:-automake} --add-missing --copy

View File

@@ -1,8 +1,8 @@
# AC_PREREQ(2.57)
AC_INIT(libssh2, [-], libssh2-devel@lists.sourceforge.net)
AC_INIT(libssh2, [-], libssh2-devel@cool.haxx.se)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADER([src/libssh2_config.h])
AM_CONFIG_HEADER([src/libssh2_config.h example/libssh2_config.h])
AM_MAINTAINER_MODE
dnl SED is needed by some of the tools
@@ -41,6 +41,9 @@ case "$host" in
;;
*hpux*)
;;
*osf*)
CFLAGS="$CFLAGS -D_POSIX_PII_SOCKET"
;;
*)
;;
esac
@@ -162,11 +165,51 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
AC_MSG_RESULT(no)
)
dnl ************************************************************
dnl Enable hiding of internal symbols in library to reduce its size and
dnl speed dynamic linking of applications. This currently is only supported
dnl on gcc >= 4.0 and SunPro C.
dnl
AC_MSG_CHECKING([whether to enable hidden symbols in the library])
AC_ARG_ENABLE(hidden-symbols,
AC_HELP_STRING([--enable-hidden-symbols],[Hide internal symbols in library])
AC_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibility in library]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_CHECKING([whether $CC supports it])
if test "$GCC" = yes ; then
if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then
AC_MSG_RESULT(yes)
AC_DEFINE(LIBSSH2_API, [__attribute__ ((visibility ("default")))], [to make a symbol visible])
CFLAGS="$CFLAGS -fvisibility=hidden"
else
AC_MSG_RESULT(no)
fi
else
dnl Test for SunPro cc
if $CC 2>&1 | grep flags >/dev/null && $CC -flags | grep xldscope= >/dev/null ; then
AC_MSG_RESULT(yes)
AC_DEFINE(LIBSSH2_API, [__global], [to make a symbol visible])
CFLAGS="$CFLAGS -xldscope=hidden"
else
AC_MSG_RESULT(no)
fi
fi
;;
esac ],
AC_MSG_RESULT(no)
)
# Checks for header files.
# AC_HEADER_STDC
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/ioctl.h sys/time.h])
AC_CHECK_HEADERS([arpa/inet.h netinet/in.h])
AC_CHECK_HEADERS([sys/un.h])
case $host in
*-*-cygwin* | *-*-cegcc*)
@@ -213,6 +256,6 @@ AC_CONFIG_FILES([Makefile
src/Makefile
tests/Makefile
example/Makefile
example/simple/Makefile
docs/Makefile])
docs/Makefile
libssh2.pc])
AC_OUTPUT

View File

View File

@@ -3,6 +3,13 @@
EXTRA_DIST = template.3
dist_man_MANS = \
libssh2_agent_connect.3 \
libssh2_agent_disconnect.3 \
libssh2_agent_free.3 \
libssh2_agent_get_identity.3 \
libssh2_agent_init.3 \
libssh2_agent_list_identities.3 \
libssh2_agent_userauth.3 \
libssh2_banner_set.3 \
libssh2_base64_decode.3 \
libssh2_channel_close.3 \
@@ -40,6 +47,7 @@ dist_man_MANS = \
libssh2_knownhost_del.3 \
libssh2_knownhost_get.3 \
libssh2_knownhost_init.3 \
libssh2_knownhost_free.3 \
libssh2_knownhost_readfile.3 \
libssh2_knownhost_readline.3 \
libssh2_knownhost_writefile.3 \
@@ -89,6 +97,7 @@ dist_man_MANS = \
libssh2_sftp_unlink_ex.3 \
libssh2_sftp_write.3 \
libssh2_trace.3 \
libssh2_trace_sethandler.3 \
libssh2_userauth_authenticated.3 \
libssh2_userauth_hostbased_fromfile_ex.3 \
libssh2_userauth_keyboard_interactive_ex.3 \

View File

@@ -0,0 +1,23 @@
.\"
.\" Copyright (c) 2009 by Daiki Ueno
.\"
.TH libssh2_agent_connect 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_agent_connect - connect to an ssh-agent
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_agent_connect(LIBSSH2_AGENT *agent);
.SH DESCRIPTION
Connect to an ssh-agent running on the system.
Call \fBlibssh2_agent_disconnect(3)\fP to close the connection after
you're doing using it.
.SH RETURN VALUE
Returns 0 if succeeded, or a negative value for error.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_agent_init(3)
.BR libssh2_agent_disconnect(3)

View File

@@ -0,0 +1,20 @@
.\"
.\" Copyright (c) 2009 by Daiki Ueno
.\"
.TH libssh2_agent_disconnect 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_agent_disconnect - close a connection to an ssh-agent
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_agent_disconnect(LIBSSH2_AGENT *agent);
.SH DESCRIPTION
Close a connection to an ssh-agent.
.SH RETURN VALUE
Returns 0 if succeeded, or a negative value for error.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_agent_connect(3)
.BR libssh2_agent_free(3)

20
docs/libssh2_agent_free.3 Normal file
View File

@@ -0,0 +1,20 @@
.\"
.\" Copyright (c) 2009 by Daiki Ueno
.\"
.TH libssh2_agent_free 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_agent_free - free an ssh-agent handle
.SH SYNOPSIS
#include <libssh2.h>
void libssh2_agent_free(LIBSSH2_AGENT *agent);
.SH DESCRIPTION
Free an ssh-agent handle. This function also frees the internal
collection of public keys.
.SH RETURN VALUE
None.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_agent_init(3)
.BR libssh2_agent_disconnect(3)

View File

@@ -0,0 +1,34 @@
.\"
.\" Copyright (c) 2009 by Daiki Ueno
.\"
.TH libssh2_agent_get_identity 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_agent_get_identity - get a public key off the collection of public keys managed by ssh-agent
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
struct libssh2_agent_publickey **store,
struct libssh2_agent_publickey *prev);
.SH DESCRIPTION
\fIlibssh2_agent_get_identity(3)\fP allows an application to iterate
over all public keys in the collection managed by ssh-agent.
\fIstore\fP should point to a pointer that gets filled in to point to the
public key data.
\fIprev\fP is a pointer to a previous 'struct libssh2_agent_publickey'
as returned by a previous invoke of this function, or NULL to get the
first entry in the internal collection.
.SH RETURN VALUE
Returns 0 if everything is fine and information about a host was stored in
the \fIstore\fP struct.
Returns 1 if it reached the end of public keys.
Returns negative values for error
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_agent_list_identities(3)
.BR libssh2_agent_userauth(3)

26
docs/libssh2_agent_init.3 Normal file
View File

@@ -0,0 +1,26 @@
.\"
.\" Copyright (c) 2009 by Daiki Ueno
.\"
.TH libssh2_agent_init 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_agent_init - init an ssh-agent handle
.SH SYNOPSIS
#include <libssh2.h>
LIBSSH2_AGENT *libssh2_agent_init(LIBSSH2_SESSION *session);
.SH DESCRIPTION
Init an ssh-agent handle. Returns the handle to an internal
representation of an ssh-agent connection. After the successful
initialization, an application can call \fBlibssh2_agent_connect(3)\fP
to connect to a running ssh-agent.
Call \fBlibssh2_agent_free(3)\fP to free the handle again after you're
doing using it.
.SH RETURN VALUE
Returns a handle pointer or NULL if something went wrong. The returned handle
is used as input to all other ssh-agent related functions libssh2 provides.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_agent_connect(3)
.BR libssh2_agent_free(3)

View File

@@ -0,0 +1,24 @@
.\"
.\" Copyright (c) 2009 by Daiki Ueno
.\"
.TH libssh2_agent_list_identities 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_agent_list_identities - request an ssh-agent to list of public keys.
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_agent_list_identities(LIBSSH2_AGENT *agent);
.SH DESCRIPTION
Request an ssh-agent to list of public keys, and stores them in the
internal collection of the handle. Call
\fIlibssh2_agent_get_identity(3)\fP to get a public key off the
collection.
.SH RETURN VALUE
Returns 0 if succeeded, or a negative value for error.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_agent_connect(3)
.BR libssh2_agent_get_identity(3)

View File

@@ -0,0 +1,29 @@
.\"
.\" Copyright (c) 2009 by Daiki Ueno
.\"
.TH libssh2_agent_userauth 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_agent_userauth - authenticate a session with a public key, with the help of ssh-agent
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_agent_userauth(LIBSSH2_AGENT *agent,
const char *username,
struct libssh2_agent_publickey *identity);
.SH DESCRIPTION
\fIagent\fP - ssh-agent handle as returned by
.BR libssh2_agent_init(3)
\fIusername\fP - Remote user name to authenticate as.
\fIidentity\fP - Public key to authenticate with, as returned by
.BR libssh2_agent_get_identity(3)
Attempt public key authentication with the help of ssh-agent.
.SH RETURN VALUE
Returns 0 if succeeded, or a negative value for error.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_agent_init(3)
.BR libssh2_agent_get_identity(3)

View File

@@ -35,6 +35,9 @@ macros.
Actual number of bytes read or negative on failure. It returns
LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
Note that a return value of zero (0) can in fact be a legitimate value and
only signals that no payload data was read. It is not an error.
.SH ERRORS
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.

View File

@@ -0,0 +1,20 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_free 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_free - free a collection of known hosts
.SH SYNOPSIS
#include <libssh2.h>
void libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
.SH DESCRIPTION
Free a collection of known hosts.
.SH RETURN VALUE
None.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_init(3)
.BR libssh2_knownhost_add(3)
.BR libssh2_knownhost_check(3)

View File

@@ -11,6 +11,9 @@ LIBSSH2_KNOWNHOSTS *libssh2_knownhost_init(LIBSSH2_SESSION *session);
.SH DESCRIPTION
Init a collection of known hosts for this session. Returns the handle to an
internal representation of a known host collection.
Call \fBlibssh2_knownhost_free(3)\fP to free the collection again after you're
doing using it.
.SH RETURN VALUE
Returns a handle pointer or NULL if something went wrong. The returned handle
is used as input to all other known host related functions libssh2 provides.

View File

@@ -13,7 +13,8 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb);
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
\fIpath\fP - Full path and filename of file to transfer
\fIpath\fP - Full path and filename of file to transfer. That is the remote
file name.
\fIsb\fP - Populated with remote file's size, mode, mtime, and atime

View File

@@ -12,7 +12,8 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
\fIpath\fP - Full path and filename of file to transfer
\fIpath\fP - Full path and filename of file to transfer to. That is the remote
file name.
\fImode\fP - File access mode to create file with

View File

@@ -11,21 +11,26 @@ ssize_t
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count);
.SH DESCRIPTION
\fIhandle\fP - SFTP File Handle as returned by
.BR libssh2_sftp_open_ex(3)
\fIhandle\fP - SFTP file handle as returned by \fIlibssh2_sftp_open_ex(3)\fP.
\fIbuffer\fP - Pre-initialized data buffer to write to the LIBSSH2_SFTP_HANDLE.
\fIbuffer\fP - points to the data to send off
\fIcount\fP - Number of bytes from buffer to write. Note that it may not
be possible to write all bytes as requested.
Write a block of data to a LIBSSH2_SFTP_HANDLE. This method is modeled after the POSIX write() function and uses the same calling semantics.
\fIcount\fP - Number of bytes from 'buffer' to write. Note that it may not be
possible to write all bytes as requested.
\fBlibssh2_sftp_write(3)\fP writes a block of data to the SFTP server. This
method is modeled after the POSIX write() function and uses the same calling
semantics.
.SH RETURN VALUE
Actual number of bytes written or negative on failure. It returns
LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
Actual number of bytes written or negative on failure.
If used in non-blocking mode, it returns LIBSSH2_ERROR_EAGAIN when it would
otherwise block. While LIBSSH2_ERROR_EAGAIN is a negative number, it isn't
really a failure per se.
If this function returns 0 (zero) it should not be considered an error, but
simply that there was no error but yet no payload data got sent to the other
end.
.SH ERRORS
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
@@ -36,6 +41,5 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response was
received on the socket, or an SFTP operation caused an errorcode to
be returned by the server.
.SH SEE ALSO
.BR libssh2_sftp_open_ex(3)

View File

@@ -6,16 +6,18 @@ libssh2_trace - enable debug info from inside libssh2
.SH SYNOPSIS
#include <libssh2.h>
void libssh2_trace(int bitmask);
void libssh2_trace(LIBSSH2_SESSION *session, int bitmask);
.SH DESCRIPTION
This is a function present in the library that can be used to get debug info
from within libssh2 when it is running. Helpful when trying to trace or debug
behaviors. This function has no effect unless libssh2 was built to support
this option, and a typical "release build" might not.
behaviors. Note that this function has no effect unless libssh2 was built to
support tracing! It is usually disabled in release builds.
\fBbitmask\fP can be set to none, one or more of these bits:
\fBbitmask\fP can be set to the logical OR of none, one or more of these:
.RS
.IP LIBSSH2_TRACE_SOCKET
Socket low-level debugging
.IP LIBSSH2_TRACE_TRANS
Transport layer debugging
.IP LIBSSH2_TRACE_KEX

View File

@@ -0,0 +1,30 @@
.\" $Id: libssh2_trace_sethandler.3,v 1.1 2008/12/26 07:46:45 bagder Exp $
.\"
.TH libssh2_trace_sethandler 3 "15 Jan 2010" "libssh2 1.2.3" "libssh2 manual"
.SH NAME
libssh2_trace_sethandler - set a trace output handler
.SH SYNOPSIS
.nf
#include <libssh2.h>
typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION *session,
void* context,
const char *data,
size_t length);
int libssh2_trace_sethandler(LIBSSH2_SESSION *session,
void* context,
libssh2_trace_handler_func callback);
.SH DESCRIPTION
libssh2_trace_sethandler installs a trace output handler for your application.
By default, when tracing has been switched on via a call to libssh2_trace(),
all output is written to stderr. By calling this method and passing a
function pointer that matches the libssh2_trace_handler_func prototype,
libssh2 will call back as it generates trace output. This can be used to
capture the trace output and put it into a log file or diagnostic window.
This function has no effect unless libssh2 was built to support this option,
and a typical "release build" might not.
\fBcontext\fP can be used to pass arbitrary user defined data back into the callback when invoked.
.SH AVAILABILITY
Added in libssh2 version 1.2.3

View File

@@ -39,5 +39,7 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.
\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password or public/private key.
.SH SEE ALSO
.BR libssh2_session_init_ex(3)

View File

@@ -46,5 +46,7 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
\fILIBSSH2_ERROR_PASSWORD_EXPIRED\fP -
\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password or public/private key.
.SH SEE ALSO
.BR libssh2_session_init_ex(3)

View File

@@ -40,12 +40,11 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
\fILIBSSH2_ERROR_SOCKET_TIMEOUT\fP -
\fILIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED\fP - >The username/public key
\fILIBSSH2_ERROR_PUBLICKEY_UNVERIFIED\fP - The username/public key
combination was invalid.
\fILIBSSH2_ERROR_PUBLICKEY_UNVERIFIED\fP - The username/public key
combination was invalid, or the signature for the supplied public
key was invalid.
\fILIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - Authentication using the supplied
public key was not accepted.
.SH SEE ALSO
.BR libssh2_session_init_ex(3)

View File

@@ -1,2 +0,0 @@
Makefile
Makefile.in

View File

@@ -1,5 +1,8 @@
Makefile
Makefile.in
*.gcno
*.gcda
direct_tcpip
scp
scp_nonblock
scp_write
@@ -16,3 +19,7 @@ sftp_write
sftp_write_nonblock
config.h.in
ssh2_exec
ssh2_agent
libssh2_config.h
libssh2_config.h.in
stamp-h2

View File

@@ -1,2 +1,16 @@
AUTOMAKE_OPTIONS = foreign nostdinc
SUBDIRS = simple
EXTRA_DIST = libssh2_config.h.in
# samples
noinst_PROGRAMS = direct_tcpip ssh2 \
scp scp_nonblock \
scp_write scp_write_nonblock \
sftp sftp_nonblock \
sftp_write sftp_write_nonblock \
sftp_mkdir sftp_mkdir_nonblock \
sftp_RW_nonblock \
sftpdir sftpdir_nonblock ssh2_exec ssh2_agent
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/example
LDADD = $(top_builddir)/src/libssh2.la

275
example/direct_tcpip.c Normal file
View File

@@ -0,0 +1,275 @@
#include <libssh2.h>
#ifdef WIN32
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#ifndef INADDR_NONE
#define INADDR_NONE (in_addr_t)-1
#endif
const char *keyfile1 = "/home/username/.ssh/id_rsa.pub";
const char *keyfile2 = "/home/username/.ssh/id_rsa";
const char *username = "username";
const char *password = "";
const char *server_ip = "127.0.0.1";
const char *local_listenip = "127.0.0.1";
unsigned int local_listenport = 2222;
const char *remote_desthost = "localhost"; /* resolved by the server */
unsigned int remote_destport = 22;
enum {
AUTH_NONE = 0,
AUTH_PASSWORD,
AUTH_PUBLICKEY
};
int main(int argc, char *argv[])
{
int rc, sock = -1, listensock = -1, forwardsock = -1, i, auth = AUTH_NONE;
struct sockaddr_in sin;
socklen_t sinlen;
const char *fingerprint;
char *userauthlist;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel = NULL;
const char *shost;
unsigned int sport;
fd_set fds;
struct timeval tv;
ssize_t len, wr;
char buf[16384];
#ifdef WIN32
char sockopt;
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
#else
int sockopt;
#endif
if (argc > 1)
server_ip = argv[1];
if (argc > 2)
username = argv[2];
if (argc > 3)
password = argv[3];
if (argc > 4)
local_listenip = argv[4];
if (argc > 5)
local_listenport = atoi(argv[5]);
if (argc > 6)
remote_desthost = argv[6];
if (argc > 7)
remote_destport = atoi(argv[7]);
/* Connect to SSH server */
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sin.sin_family = AF_INET;
if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(server_ip))) {
perror("inet_addr");
return -1;
}
sin.sin_port = htons(22);
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
return -1;
}
/* Create a session instance */
session = libssh2_session_init();
if(!session) {
fprintf(stderr, "Could not initialize SSH session!\n");
return -1;
}
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
rc = libssh2_session_startup(session, sock);
if(rc) {
fprintf(stderr, "Error when starting up SSH session: %d\n", rc);
return -1;
}
/* At this point we havn't yet authenticated. The first thing to do
* is check the hostkey's fingerprint against our known hosts Your app
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
fprintf(stderr, "Fingerprint: ");
for(i = 0; i < 20; i++)
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
fprintf(stderr, "\n");
/* check what authentication methods are available */
userauthlist = libssh2_userauth_list(session, username, strlen(username));
printf("Authentication methods: %s\n", userauthlist);
if (strstr(userauthlist, "password"))
auth |= AUTH_PASSWORD;
if (strstr(userauthlist, "publickey"))
auth |= AUTH_PUBLICKEY;
/* check for options */
if(argc > 8) {
if ((auth & AUTH_PASSWORD) && !strcasecmp(argv[8], "-p"))
auth = AUTH_PASSWORD;
if ((auth & AUTH_PUBLICKEY) && !strcasecmp(argv[8], "-k"))
auth = AUTH_PUBLICKEY;
}
if (auth & AUTH_PASSWORD) {
if (libssh2_userauth_password(session, username, password)) {
fprintf(stderr, "Authentication by password failed.\n");
goto shutdown;
}
} else if (auth & AUTH_PUBLICKEY) {
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) {
printf("\tAuthentication by public key failed!\n");
goto shutdown;
}
printf("\tAuthentication by public key succeeded.\n");
} else {
printf("No supported authentication methods found!\n");
goto shutdown;
}
listensock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sin.sin_family = AF_INET;
sin.sin_port = htons(local_listenport);
if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(local_listenip))) {
perror("inet_addr");
goto shutdown;
}
sockopt = 1;
setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
sinlen=sizeof(sin);
if (-1 == bind(listensock, (struct sockaddr *)&sin, sinlen)) {
perror("bind");
goto shutdown;
}
if (-1 == listen(listensock, 2)) {
perror("listen");
goto shutdown;
}
printf("Waiting for TCP connection on %s:%d...\n",
inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
forwardsock = accept(listensock, (struct sockaddr *)&sin, &sinlen);
if (-1 == forwardsock) {
perror("accept");
goto shutdown;
}
shost = inet_ntoa(sin.sin_addr);
sport = ntohs(sin.sin_port);
printf("Forwarding connection from %s:%d here to remote %s:%d\n", shost,
sport, remote_desthost, remote_destport);
channel = libssh2_channel_direct_tcpip_ex(session, remote_desthost,
remote_destport, shost, sport);
if (!channel) {
fprintf(stderr, "Could not open the direct-tcpip channel!\n");
fprintf(stderr, "(Note that this can be a problem at the server! Please review the server logs.)\n");
goto shutdown;
}
/* Must use non-blocking IO hereafter due to the current libssh2 API */
libssh2_session_set_blocking(session, 0);
while (1) {
FD_ZERO(&fds);
FD_SET(forwardsock, &fds);
tv.tv_sec = 0;
tv.tv_usec = 100000;
rc = select(forwardsock + 1, &fds, NULL, NULL, &tv);
if (-1 == rc) {
perror("select");
goto shutdown;
}
if (rc && FD_ISSET(forwardsock, &fds)) {
len = recv(forwardsock, buf, sizeof(buf), 0);
if (len < 0) {
perror("read");
goto shutdown;
} else if (0 == len) {
printf("The client at %s:%d disconnected!\n", shost, sport);
goto shutdown;
}
wr = 0;
do {
i = libssh2_channel_write(channel, buf, len);
if (i < 0) {
fprintf(stderr, "libssh2_channel_write: %d\n", i);
goto shutdown;
}
wr += i;
} while(i > 0 && wr < len);
}
while (1) {
len = libssh2_channel_read(channel, buf, sizeof(buf));
if (LIBSSH2_ERROR_EAGAIN == len)
break;
else if (len < 0) {
fprintf(stderr, "libssh2_channel_read: %d", (int)len);
goto shutdown;
}
wr = 0;
while (wr < len) {
i = send(forwardsock, buf + wr, len - wr, 0);
if (i <= 0) {
perror("write");
goto shutdown;
}
wr += i;
}
if (libssh2_channel_eof(channel)) {
printf("The server at %s:%d disconnected!\n",
remote_desthost, remote_destport);
goto shutdown;
}
}
}
shutdown:
#ifdef WIN32
closesocket(forwardsock);
closesocket(listensock);
#else
close(forwardsock);
close(listensock);
#endif
if (channel)
libssh2_channel_free(channel);
libssh2_session_disconnect(session, "Client disconnecting normally");
libssh2_session_free(session);
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
return 0;
}

View File

@@ -10,12 +10,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -103,9 +103,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
fprintf(stderr, "Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
}
fprintf(stderr, "\n");

View File

@@ -15,11 +15,14 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -157,9 +160,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
fprintf(stderr, "Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
}
fprintf(stderr, "\n");

View File

@@ -10,12 +10,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -47,7 +47,7 @@ int main(int argc, char *argv[])
FILE *local;
int rc;
char mem[1024];
size_t nread;
size_t nread, sent;
char *ptr;
struct stat fileinfo;
@@ -118,9 +118,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
fprintf(stderr, "Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
}
fprintf(stderr, "\n");
@@ -142,8 +142,8 @@ int main(int argc, char *argv[])
}
}
/* Request a file via SCP */
channel = libssh2_scp_send(session, scppath, 0x1FF & fileinfo.st_mode,
/* Send a file via scp. The mode parameter must only have permissions! */
channel = libssh2_scp_send(session, scppath, fileinfo.st_mode & 0777,
(unsigned long)fileinfo.st_size);
if (!channel) {
@@ -159,13 +159,20 @@ int main(int argc, char *argv[])
break;
}
ptr = mem;
sent = 0;
do {
/* write data in a loop until we block */
/* write the same data over and over, until error or completion */
rc = libssh2_channel_write(channel, ptr, nread);
ptr += rc;
nread -= nread;
} while (rc > 0);
if (rc < 0) {
fprintf(stderr, "ERROR %d\n", rc);
} else {
/* rc indicates how many bytes were written this time */
sent += rc;
}
} while (rc > 0 && sent < nread);
ptr += sent;
nread -= sent;
} while (1);
fprintf(stderr, "Sending EOF\n");

View File

@@ -11,12 +11,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -51,7 +51,7 @@ int main(int argc, char *argv[])
long flag = 1;
#endif
char mem[1024];
size_t nread;
size_t nread, sent;
char *ptr;
struct stat fileinfo;
@@ -126,9 +126,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
fprintf(stderr, "Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
}
fprintf(stderr, "\n");
@@ -153,9 +153,9 @@ int main(int argc, char *argv[])
}
}
/* Request a file via SCP */
/* Send a file via scp. The mode parameter must only have permissions! */
do {
channel = libssh2_scp_send(session, scppath, 0x1FF & fileinfo.st_mode,
channel = libssh2_scp_send(session, scppath, fileinfo.st_mode & 0777,
(unsigned long)fileinfo.st_size);
if ((!channel) && (libssh2_session_last_errno(session) !=
@@ -176,17 +176,22 @@ int main(int argc, char *argv[])
break;
}
ptr = mem;
sent = 0;
do {
/* write data in a loop until we block */
while ((rc = libssh2_channel_write(channel, ptr, nread)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc < 0) {
/* write the same data over and over, until error or completion */
rc = libssh2_channel_write(channel, ptr, nread);
if (LIBSSH2_ERROR_EAGAIN == rc) { /* must loop around */
continue;
} else if (rc < 0) {
fprintf(stderr, "ERROR %d\n", rc);
} else {
/* rc indicates how many bytes were written this time */
sent += rc;
}
ptr += rc;
nread -= rc;
} while (nread > 0);
} while (rc > 0 && sent < nread);
ptr += sent;
nread -= sent;
} while (1);
fprintf(stderr, "Sending EOF\n");

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -136,9 +136,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
fprintf(stderr, "Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
}
fprintf(stderr, "\n");

View File

@@ -16,11 +16,14 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -106,9 +109,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -105,9 +105,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -108,9 +108,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -16,11 +16,14 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -158,9 +161,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
fprintf(stderr, "Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
}
fprintf(stderr, "\n");

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -123,9 +123,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -127,9 +127,9 @@ int main(int argc, char *argv[])
* have it hard coded, may go to a file, may present it to the user,
* that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -105,9 +105,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -111,9 +111,9 @@ int main(int argc, char *argv[])
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -1,21 +0,0 @@
Makefile
Makefile.in
.deps
.libs
*.gcno
*.gcda
scp
scp_nonblock
scp_write
scp_write_nonblock
sftp
sftp_nonblock
sftpdir
sftpdir_nonblock
ssh2
sftp_RW_nonblock
sftp_mkdir
sftp_mkdir_nonblock
sftp_write
sftp_write_nonblock

View File

@@ -1,16 +0,0 @@
AUTOMAKE_OPTIONS = foreign nostdinc
# samples
noinst_PROGRAMS = ssh2 \
scp scp_nonblock \
scp_write scp_write_nonblock \
sftp sftp_nonblock \
sftp_write sftp_write_nonblock \
sftp_mkdir sftp_mkdir_nonblock \
sftp_RW_nonblock \
sftpdir sftpdir_nonblock ssh2_exec
# the examples need the $(top_builddir)/src since when building outside of the
# source dir they still need to reach the libssh2_config.h header
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_builddir)/src
LDADD = $(top_builddir)/src/libssh2.la

View File

@@ -19,12 +19,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -121,9 +121,9 @@ int main(int argc, char *argv[])
* hard coded, may go to a file, may present it to the user, that's your
* call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

229
example/ssh2_agent.c Normal file
View File

@@ -0,0 +1,229 @@
/*
* Sample showing how to do SSH2 connect using ssh-agent.
*
* The sample code has default values for host name, user name:
*
* "ssh2_agent host user"
*/
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
# ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
const char *username="username";
int main(int argc, char *argv[])
{
unsigned long hostaddr;
int sock = -1, i, j, rc;
struct sockaddr_in sin;
const char *fingerprint;
char *userauthlist;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
LIBSSH2_AGENT *agent = NULL;
struct libssh2_agent_publickey *identity, *prev_identity = NULL;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
hostaddr = inet_addr(argv[1]);
} else {
hostaddr = htonl(0x7F000001);
}
if(argc > 2) {
username = argv[2];
}
/* Ultra basic "connect to port 22 on localhost". Your code is
* responsible for creating the socket establishing the connection
*/
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
fprintf(stderr, "failed to create socket!\n");
rc = 1;
goto shutdown;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
goto shutdown;
}
/* Create a session instance and start it up. This will trade welcome
* banners, exchange keys, and setup crypto, compression, and MAC layers
*/
session = libssh2_session_init();
if (libssh2_session_startup(session, sock)) {
fprintf(stderr, "Failure establishing SSH session\n");
return 1;
}
/* check what authentication methods are available */
userauthlist = libssh2_userauth_list(session, username, strlen(username));
printf("Authentication methods: %s\n", userauthlist);
if (strstr(userauthlist, "publickey") == NULL) {
fprintf(stderr, "\"publickey\" authentication is not supported\n");
goto shutdown;
}
/* Connect to the ssh-agent */
agent = libssh2_agent_init(session);
if (!agent) {
fprintf(stderr, "Failure initializing ssh-agent support\n");
rc = 1;
goto shutdown;
}
if (libssh2_agent_connect(agent)) {
fprintf(stderr, "Failure connecting to ssh-agent\n");
rc = 1;
goto shutdown;
}
if (libssh2_agent_list_identities(agent)) {
fprintf(stderr, "Failure requesting identities to ssh-agent\n");
rc = 1;
goto shutdown;
}
while (1) {
rc = libssh2_agent_get_identity(agent, &identity, prev_identity);
if (rc == 1)
break;
if (rc < 0) {
fprintf(stderr,
"Failure obtaining identity from ssh-agent support\n");
rc = 1;
goto shutdown;
}
if (libssh2_agent_userauth(agent, username, identity)) {
printf("\tAuthentication with username %s and "
"public key %s failed!\n",
username, identity->comment);
} else {
printf("\tAuthentication with username %s and "
"public key %s succeeded!\n",
username, identity->comment);
break;
}
prev_identity = identity;
}
if (rc) {
fprintf(stderr, "Couldn't continue authentication\n");
goto shutdown;
}
/* At this point we havn't authenticated. The first thing to do is check
* the hostkey's fingerprint against our known hosts Your app may have it
* hard coded, may go to a file, may present it to the user, that's your
* call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");
/* Request a shell */
if (!(channel = libssh2_channel_open_session(session))) {
fprintf(stderr, "Unable to open a session\n");
goto shutdown;
}
/* Some environment variables may be set,
* It's up to the server which ones it'll allow though
*/
libssh2_channel_setenv(channel, "FOO", "bar");
/* Request a terminal with 'vanilla' terminal emulation
* See /etc/termcap for more options
*/
if (libssh2_channel_request_pty(channel, "vanilla")) {
fprintf(stderr, "Failed requesting pty\n");
goto skip_shell;
}
/* Open a SHELL on that pty */
if (libssh2_channel_shell(channel)) {
fprintf(stderr, "Unable to request shell on allocated pty\n");
goto shutdown;
}
/* At this point the shell can be interacted with using
* libssh2_channel_read()
* libssh2_channel_read_stderr()
* libssh2_channel_write()
* libssh2_channel_write_stderr()
*
* Blocking mode may be (en|dis)abled with: libssh2_channel_set_blocking()
* If the server send EOF, libssh2_channel_eof() will return non-0
* To send EOF to the server use: libssh2_channel_send_eof()
* A channel can be closed with: libssh2_channel_close()
* A channel can be freed with: libssh2_channel_free()
*/
skip_shell:
if (channel) {
libssh2_channel_free(channel);
channel = NULL;
}
/* Other channel types are supported via:
* libssh2_scp_send()
* libssh2_scp_recv()
* libssh2_channel_direct_tcpip()
*/
shutdown:
libssh2_agent_disconnect(agent);
libssh2_agent_free(agent);
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
if (sock != -1) {
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
}
printf("all done!\n");
return rc;
}

View File

@@ -18,11 +18,14 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>

View File

@@ -84,17 +84,17 @@ typedef unsigned long long libssh2_uint64_t;
typedef long long libssh2_int64_t;
#endif
/* We use underscore instead of dash when appending CVS in dev versions just
/* We use underscore instead of dash when appending DEV in dev versions just
to make the BANNER define (used by src/session.c) be a valid SSH
banner. Release versions have no appended strings and may of course not
have dashes either. */
#define LIBSSH2_VERSION "1.1.1_CVS"
#define LIBSSH2_VERSION "1.2.4_DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBSSH2_VERSION_MAJOR 1
#define LIBSSH2_VERSION_MINOR 1
#define LIBSSH2_VERSION_PATCH 1
#define LIBSSH2_VERSION_MINOR 2
#define LIBSSH2_VERSION_PATCH 4
/* This is the numeric version of the libssh2 version number, meant for easier
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
@@ -111,18 +111,18 @@ typedef long long libssh2_int64_t;
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
*/
#define LIBSSH2_VERSION_NUM 0x010101
#define LIBSSH2_VERSION_NUM 0x010204
/*
* This is the date and time when the full source package was created. The
* timestamp is not stored in CVS, as the timestamp is properly set in the
* tarballs by the maketgz script.
* timestamp is not stored in the source code repo, as the timestamp is
* properly set in the tarballs by the maketgz script.
*
* The format of the date should follow this template:
*
* "Mon Feb 12 11:35:33 UTC 2007"
*/
#define LIBSSH2_TIMESTAMP "CVS"
#define LIBSSH2_TIMESTAMP "DEV"
/* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
@@ -178,6 +178,11 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
unsigned int length;
} LIBSSH2_USERAUTH_KBDINT_RESPONSE;
/* 'publickey' authentication callback */
#define LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC(name) \
int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, \
const unsigned char *data, size_t data_len, void **abstract)
/* 'keyboard-interactive' authentication callback */
#define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) \
void name_(const char* name, int name_len, const char* instruction, \
@@ -242,6 +247,7 @@ typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
typedef struct _LIBSSH2_KNOWNHOSTS LIBSSH2_KNOWNHOSTS;
typedef struct _LIBSSH2_AGENT LIBSSH2_AGENT;
typedef struct _LIBSSH2_POLLFD {
unsigned char type; /* LIBSSH2_POLLFD_* below */
@@ -335,7 +341,8 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_PASSWORD_EXPIRED -15
#define LIBSSH2_ERROR_FILE -16
#define LIBSSH2_ERROR_METHOD_NONE -17
#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED -18
#define LIBSSH2_ERROR_AUTHENTICATION_FAILED -18
#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED LIBSSH2_ERROR_AUTHENTICATION_FAILED
#define LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED -19
#define LIBSSH2_ERROR_CHANNEL_OUTOFORDER -20
#define LIBSSH2_ERROR_CHANNEL_FAILURE -21
@@ -356,6 +363,10 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_PUBLICKEY_PROTOCOL -36
#define LIBSSH2_ERROR_EAGAIN -37
#define LIBSSH2_ERROR_BUFFER_TOO_SMALL -38
#define LIBSSH2_ERROR_BAD_USE -39
#define LIBSSH2_ERROR_COMPRESS -40
#define LIBSSH2_ERROR_OUT_OF_BOUNDARY -41
#define LIBSSH2_ERROR_AGENT_PROTOCOL -42
/* Session API */
LIBSSH2_API LIBSSH2_SESSION *
@@ -433,6 +444,14 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
strlen(username), (publickey), \
(privatekey), (passphrase))
LIBSSH2_API int
libssh2_userauth_publickey(LIBSSH2_SESSION *session,
const char *username,
const unsigned char *pubkeydata,
size_t pubkeydata_len,
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
void **abstract);
LIBSSH2_API int
libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
const char *username,
@@ -675,6 +694,7 @@ LIBSSH2_API
const char *libssh2_version(int req_version_num);
#define HAVE_LIBSSH2_KNOWNHOST_API 0x010101 /* since 1.1.1 */
#define HAVE_LIBSSH2_VERSION_API 0x010100 /* libssh2_version since 1.1 */
struct libssh2_knownhost {
unsigned int magic; /* magic stored by the library */
@@ -866,6 +886,93 @@ libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost **store,
struct libssh2_knownhost *prev);
#define HAVE_LIBSSH2_AGENT_API 0x010202 /* since 1.2.2 */
struct libssh2_agent_publickey {
unsigned int magic; /* magic stored by the library */
void *node; /* handle to the internal representation of key */
unsigned char *blob; /* public key blob */
size_t blob_len; /* length of the public key blob */
char *comment; /* comment in printable format */
};
/*
* libssh2_agent_init
*
* Init an ssh-agent handle. Returns the pointer to the handle.
*
*/
LIBSSH2_API LIBSSH2_AGENT *
libssh2_agent_init(LIBSSH2_SESSION *session);
/*
* libssh2_agent_connect()
*
* Connect to an ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_connect(LIBSSH2_AGENT *agent);
/*
* libssh2_agent_list_identities()
*
* Request an ssh-agent to list identities.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_list_identities(LIBSSH2_AGENT *agent);
/*
* libssh2_agent_get_identity()
*
* Traverse the internal list of public keys. Pass NULL to 'prev' to get
* the first one. Or pass a poiner to the previously returned one to get the
* next.
*
* Returns:
* 0 if a fine public key was stored in 'store'
* 1 if end of public keys
* [negative] on errors
*/
LIBSSH2_API int
libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
struct libssh2_agent_publickey **store,
struct libssh2_agent_publickey *prev);
/*
* libssh2_agent_userauth()
*
* Do publickey user authentication with the help of ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_userauth(LIBSSH2_AGENT *agent,
const char *username,
struct libssh2_agent_publickey *identity);
/*
* libssh2_agent_disconnect()
*
* Close a connection to an ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_disconnect(LIBSSH2_AGENT *agent);
/*
* libssh2_agent_free()
*
* Free an ssh-agent handle. This function also frees the internal
* collection of public keys.
*/
LIBSSH2_API void
libssh2_agent_free(LIBSSH2_AGENT *agent);
/* NOTE NOTE NOTE
libssh2_trace() has no function in builds that aren't built with debug
enabled
@@ -879,6 +986,15 @@ LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask);
#define LIBSSH2_TRACE_SFTP (1<<6)
#define LIBSSH2_TRACE_ERROR (1<<7)
#define LIBSSH2_TRACE_PUBLICKEY (1<<8)
#define LIBSSH2_TRACE_SOCKET (1<<9)
typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*,
void*,
const char *,
size_t);
LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session,
void* context,
libssh2_trace_handler_func callback);
#ifdef __cplusplus
} /* extern "C" */

16
libssh2.pc.in Normal file
View File

@@ -0,0 +1,16 @@
###########################################################################
# libssh2 installation details
###########################################################################
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libssh2
URL: http://www.libssh2.org/
Description: Library for SSH based connunication
Version: @VERSION@
Libs: -L${libdir} -lssh2 @LDFLAGS@ @LIBS@
Libs.private: @LIBS@
Cflags: -I${includedir}

View File

@@ -1,5 +0,0 @@
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4

View File

@@ -96,7 +96,7 @@ LIBARCH_L = $(shell $(AWK) 'BEGIN {print tolower(ARGV[1])}' $(LIBARCH))
-include $(OBJDIR)/version.inc
# Global flags for all compilers
CFLAGS = $(OPT) -D$(DB) -DNETWARE -nostdinc
CFLAGS += $(OPT) -D$(DB) -DNETWARE -nostdinc
#CFLAGS += -DHAVE_CONFIG_H
ifeq ($(CC),mwccnlm)
@@ -184,8 +184,7 @@ ifdef XDCOPT
XDCDATA = $(OBJDIR)/$(TARGET).xdc
endif
ifeq ($(findstring linux,$(OSTYPE)),linux)
#-include $(NDKBASE)/nlmconv/ncpfs.inc
ifeq ($(findstring /sh,$(SHELL)),/sh)
DL = '
DS = /
else
@@ -194,24 +193,10 @@ endif
vpath %.c . ../src
OBJECTS = \
channel.o \
comp.o \
crypt.o \
hostkey.o \
kex.o \
mac.o \
misc.o \
openssl.o \
packet.o \
pem.o \
publickey.o \
scp.o \
session.o \
sftp.o \
transport.o \
userauth.o
# include Makefile.inc to get CSOURCES define
include ../Makefile.inc
OBJECTS := $(patsubst %.c,%.o,$(CSOURCES))
ifeq ($(LIBARCH),CLIB)
# CLIB lacks of snprint() function - here's a replacement:
# http://www.ijs.si/software/snprintf/
@@ -220,7 +205,6 @@ vpath %.c $(SNPRINTF)
endif
OBJS := $(addprefix $(OBJDIR)/,$(OBJECTS))
OBJL = $(OBJS) $(OBJDIR)/nwlib.o $(LDLIBS)
all: lib nlm
@@ -382,6 +366,8 @@ ifeq ($(LIBARCH),CLIB)
@echo $(DL)#define HAVE_STRICMP 1$(DL) >> $@
@echo $(DL)#define socklen_t int$(DL) >> $@
@echo $(DL)#define sleep(s) delay(1000 * s)$(DL) >> $@
@echo $(DL)#define strcasecmp stricmp$(DL) >> $@
@echo $(DL)#define strncasecmp strnicmp$(DL) >> $@
else
@echo $(DL)#define OS "i586-pc-libc-NetWare"$(DL) >> $@
@echo $(DL)#define HAVE_DLFCN_H 1$(DL) >> $@
@@ -508,6 +494,7 @@ endif
@echo $(DL) libssh2_channel_eof,$(DL) >> $@
@echo $(DL) libssh2_channel_flush_ex,$(DL) >> $@
@echo $(DL) libssh2_channel_free,$(DL) >> $@
@echo $(DL) libssh2_channel_get_exit_status,$(DL) >> $@
@echo $(DL) libssh2_channel_open_ex,$(DL) >> $@
@echo $(DL) libssh2_channel_process_startup,$(DL) >> $@
@echo $(DL) libssh2_channel_read_ex,$(DL) >> $@
@@ -521,11 +508,18 @@ endif
@echo $(DL) libssh2_hostkey_hash,$(DL) >> $@
@echo $(DL) libssh2_scp_recv,$(DL) >> $@
@echo $(DL) libssh2_scp_send_ex,$(DL) >> $@
@echo $(DL) libssh2_knownhost_add,$(DL) >> $@
@echo $(DL) libssh2_knownhost_check,$(DL) >> $@
@echo $(DL) libssh2_knownhost_free,$(DL) >> $@
@echo $(DL) libssh2_knownhost_init,$(DL) >> $@
@echo $(DL) libssh2_knownhost_readfile,$(DL) >> $@
@echo $(DL) libssh2_knownhost_writefile,$(DL) >> $@
@echo $(DL) libssh2_session_abstract,$(DL) >> $@
@echo $(DL) libssh2_session_block_directions,$(DL) >> $@
@echo $(DL) libssh2_session_callback_set,$(DL) >> $@
@echo $(DL) libssh2_session_disconnect_ex,$(DL) >> $@
@echo $(DL) libssh2_session_free,$(DL) >> $@
@echo $(DL) libssh2_session_hostkey,$(DL) >> $@
@echo $(DL) libssh2_session_init_ex,$(DL) >> $@
@echo $(DL) libssh2_session_last_errno,$(DL) >> $@
@echo $(DL) libssh2_session_last_error,$(DL) >> $@

View File

@@ -28,8 +28,8 @@ endif
LINK_STATIC = 1
# Edit the vars below to change NLM target settings.
SAMPLES = ../../example/simple
TARGETS := $(patsubst $(SAMPLES)/%.c,%.nlm,$(strip $(wildcard $(SAMPLES)/*.c)))
SAMPLES = ../../example
TARGETS := $(filter-out x11.nlm,$(patsubst $(SAMPLES)/%.c,%.nlm,$(strip $(wildcard $(SAMPLES)/*.c))))
VERSION = $(LIBSSH2_VERSION)
COPYR = Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
WWWURL = http://www.libssh2.org/
@@ -89,7 +89,7 @@ LIBARCH_L = $(shell $(AWK) 'BEGIN {print tolower(ARGV[1])}' $(LIBARCH))
-include $(OBJDIR)/version.inc
# Global flags for all compilers
CFLAGS = $(OPT) -D$(DB) -DNETWARE -nostdinc
CFLAGS += $(OPT) -D$(DB) -DNETWARE -nostdinc
ifeq ($(CC),mwccnlm)
LD = mwldnlm
@@ -116,12 +116,15 @@ LDFLAGS = -T
AR = ar
ARFLAGS = -cq
LIBEXT = a
CFLAGS += -fno-builtin -fpack-struct -fpcc-struct-return -fno-strict-aliasing
CFLAGS += -Wall,no-unused # -pedantic
CFLAGS += -fno-builtin -fpcc-struct-return -fno-strict-aliasing
CFLAGS += -Wall # -pedantic
ifeq ($(LIBARCH),LIBC)
PRELUDE = $(SDK_LIBC)/imports/libcpre.gcc.o
else
PRELUDE = $(SDK_CLIB)/imports/clibpre.gcc.o
# PRELUDE = $(SDK_CLIB)/imports/clibpre.gcc.o
# to avoid the __init_* / __deinit_* whoes dont use prelude from NDK
# http://www.gknw.net/development/mk_nlm/gcc_pre.zip
PRELUDE = $(NDK_ROOT)/pre/prelude.o
CFLAGS += -include $(NDKBASE)/nlmconv/genlm.h
endif
endif
@@ -135,6 +138,13 @@ INCLUDES = -I.. -I../../include
LDLIBS =
ifdef LINK_STATIC
LDLIBS += ../libssh2.$(LIBEXT)
else
IMPORTS += @../libssh2.imp
MODULES += libssh2.nlm
endif
INCLUDES += -I$(OPENSSL_PATH)/outinc_nw_$(LIBARCH_L) -I$(OPENSSL_PATH)/outinc_nw_$(LIBARCH_L)/openssl
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/ssl.$(LIBEXT)
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/crypto.$(LIBEXT)
@@ -150,13 +160,6 @@ else
endif
endif
ifdef LINK_STATIC
LDLIBS += ../libssh2.$(LIBEXT)
else
IMPORTS += @../libssh2.imp
MODULES += libssh2.nlm
endif
ifeq ($(LIBARCH),LIBC)
INCLUDES += -I$(SDK_LIBC)/include
# INCLUDES += -I$(SDK_LIBC)/include/nks
@@ -177,8 +180,11 @@ ifeq ($(MTSAFE),NO)
XDCOPT = -u
endif
ifeq ($(findstring linux,$(OSTYPE)),linux)
DL = '
ifeq ($(findstring /sh,$(SHELL)),/sh)
DL = '
DS = /
else
DS = \\
endif
vpath %.c $(SAMPLES)
@@ -188,7 +194,7 @@ vpath %.c $(SAMPLES)
all: prebuild $(TARGETS)
prebuild: $(OBJDIR) $(OBJDIR)/version.inc config.h
prebuild: $(OBJDIR) $(OBJDIR)/version.inc
$(OBJDIR)/%.o: %.c
# @echo Compiling $<
@@ -276,7 +282,7 @@ ifdef IMPORTS
@echo $(DL)import $(IMPORTS)$(DL) >> $@
endif
ifeq ($(LD),nlmconv)
@echo $(DL)input $(<:.def=.o)$(DL) >> $@
@echo $(DL)input $(@:.def=.o)$(DL) >> $@
@echo $(DL)input $(PRELUDE)$(DL) >> $@
ifdef LDLIBS
@echo $(DL)input $(LDLIBS)$(DL) >> $@
@@ -284,7 +290,7 @@ endif
@echo $(DL)output $(notdir $(@:.def=.nlm))$(DL) >> $@
endif
config.h: Makefile.netware
ssh2_config.h: Makefile.netware
@echo Creating $@
@echo $(DL)/* $@ for NetWare target.$(DL) > $@
@echo $(DL)** Do not edit this file - it is created by make!$(DL) >> $@

View File

@@ -1,20 +0,0 @@
.deps
.libs
*.lib
*.pdb
*.dll
*.exe
*.obj
*.gcno
*.gcda
.*.swp
Debug
Release
*.exp
Makefile
Makefile.in
*.lo
libssh2.la
libssh2_config.h
libssh2_config.h.in
stamp-h1

759
src/agent.c Normal file
View File

@@ -0,0 +1,759 @@
/*
* Copyright (c) 2009 by Daiki Ueno
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#include "misc.h"
#include <errno.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#else
/* Use the existence of sys/un.h as a test if Unix domain socket is
supported. winsock*.h define PF_UNIX/AF_UNIX but do not actually
support them. */
#undef PF_UNIX
#endif
/* Requests from client to agent for protocol 1 key operations */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENTC_RSA_CHALLENGE 3
#define SSH_AGENTC_ADD_RSA_IDENTITY 7
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
/* Requests from client to agent for protocol 2 key operations */
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
/* Key-type independent requests from client to agent */
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
#define SSH_AGENTC_LOCK 22
#define SSH_AGENTC_UNLOCK 23
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
/* Generic replies from agent to client */
#define SSH_AGENT_FAILURE 5
#define SSH_AGENT_SUCCESS 6
/* Replies from agent to client for protocol 1 key operations */
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
#define SSH_AGENT_RSA_RESPONSE 4
/* Replies from agent to client for protocol 2 key operations */
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENT_SIGN_RESPONSE 14
/* Key constraint identifiers */
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
/* non-blocking mode on agent connection is not yet implemented, but
for future use. */
typedef enum {
agent_NB_state_init = 0,
agent_NB_state_request_created,
agent_NB_state_request_length_sent,
agent_NB_state_request_sent,
agent_NB_state_response_length_received,
agent_NB_state_response_received
} agent_nonblocking_states;
typedef struct agent_transaction_ctx {
unsigned char *request;
size_t request_len;
unsigned char *response;
size_t response_len;
agent_nonblocking_states state;
} *agent_transaction_ctx_t;
typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
agent_transaction_ctx_t transctx);
typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
struct agent_publickey {
struct list_node node;
/* this is the struct we expose externally */
struct libssh2_agent_publickey external;
};
struct agent_ops {
agent_connect_func connect;
agent_transact_func transact;
agent_disconnect_func disconnect;
};
struct _LIBSSH2_AGENT
{
LIBSSH2_SESSION *session; /* the session this "belongs to" */
libssh2_socket_t fd;
struct agent_ops *ops;
struct agent_transaction_ctx transctx;
struct agent_publickey *identity;
struct list_head head; /* list of public keys */
};
#ifdef PF_UNIX
static int
agent_connect_unix(LIBSSH2_AGENT *agent)
{
const char *path;
struct sockaddr_un s_un;
path = getenv("SSH_AUTH_SOCK");
if (!path) {
return -1;
}
agent->fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (agent->fd < 0) {
return -1;
}
s_un.sun_family = AF_UNIX;
strncpy (s_un.sun_path, path, sizeof s_un.sun_path);
if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) {
close (agent->fd);
return -1;
}
return 0;
}
static int
agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
{
unsigned char buf[4], *s;
int rc;
/* Send the length of the request */
if (transctx->state == agent_NB_state_request_created) {
_libssh2_htonu32(buf, transctx->request_len);
rc = send(agent->fd, buf, sizeof buf, 0);
if (rc < 0) {
if (errno == EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return -1;
}
transctx->state = agent_NB_state_request_length_sent;
}
/* Send the request body */
if (transctx->state == agent_NB_state_request_length_sent) {
rc = send(agent->fd, transctx->request,
transctx->request_len, 0);
if (rc < 0) {
if (errno == EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return -1;
}
transctx->state = agent_NB_state_request_sent;
}
/* Receive the length of a response */
if (transctx->state == agent_NB_state_request_sent) {
rc = recv(agent->fd, buf, sizeof buf, 0);
if (rc < 0) {
if (errno == EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return -1;
}
transctx->response_len = _libssh2_ntohu32(buf);
s = transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
if (!transctx->response) {
return LIBSSH2_ERROR_ALLOC;
}
transctx->state = agent_NB_state_response_length_received;
}
/* Receive the response body */
if (transctx->state == agent_NB_state_response_length_received) {
rc = recv(agent->fd, transctx->response, transctx->response_len, 0);
if (rc < 0) {
if (errno == EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return -1;
}
transctx->state = agent_NB_state_response_received;
}
return 0;
}
static int
agent_disconnect_unix(LIBSSH2_AGENT *agent)
{
return close(agent->fd);
}
struct agent_ops agent_ops_unix = {
agent_connect_unix,
agent_transact_unix,
agent_disconnect_unix
};
#endif /* PF_UNIX */
#ifdef WIN32
/* Code to talk to Pageant was taken from PuTTY.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas
* Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,
* Markus Kuhn, Colin Watson, and CORE SDI S.A.
*/
#define PAGEANT_COPYDATA_ID 0x804e50ba /* random goop */
#define PAGEANT_MAX_MSGLEN 8192
static int
agent_connect_pageant(LIBSSH2_AGENT *agent)
{
HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd)
return -1;
agent->fd = 0; /* Mark as the connection has been established */
return 0;
}
static int
agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
{
HWND hwnd;
char mapname[23];
HANDLE filemap;
unsigned char *p;
int id;
COPYDATASTRUCT cds;
if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) {
return LIBSSH2_ERROR_INVAL;
}
hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd) {
return -1;
}
sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, PAGEANT_MAX_MSGLEN, mapname);
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
return -1;
}
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
_libssh2_htonu32(p, transctx->request_len);
memcpy(p + 4, transctx->request, transctx->request_len);
cds.dwData = PAGEANT_COPYDATA_ID;
cds.cbData = 1 + strlen(mapname);
cds.lpData = mapname;
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
if (id > 0) {
transctx->response_len = _libssh2_ntohu32(p);
if (transctx->response_len > PAGEANT_MAX_MSGLEN) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return LIBSSH2_ERROR_AGENT_PROTOCOL;
}
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
if (!transctx->response) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return LIBSSH2_ERROR_ALLOC;
}
memcpy(transctx->response, p + 4, transctx->response_len);
}
UnmapViewOfFile(p);
CloseHandle(filemap);
return 0;
}
static int
agent_disconnect_pageant(LIBSSH2_AGENT *agent)
{
agent->fd = INVALID_SOCKET;
return 0;
}
struct agent_ops agent_ops_pageant = {
agent_connect_pageant,
agent_transact_pageant,
agent_disconnect_pageant
};
#endif /* WIN32 */
static struct {
const char *name;
struct agent_ops *ops;
} supported_backends[] = {
#ifdef WIN32
{"Pageant", &agent_ops_pageant},
#endif /* WIN32 */
#ifdef PF_UNIX
{"Unix", &agent_ops_unix},
#endif /* PF_UNIX */
{NULL}
};
static int
agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
const unsigned char *data, size_t data_len, void **abstract)
{
LIBSSH2_AGENT *agent = (LIBSSH2_AGENT *) (*abstract);
agent_transaction_ctx_t transctx = &agent->transctx;
struct agent_publickey *identity = agent->identity;
ssize_t len = 1 + 4 + identity->external.blob_len + 4 + data_len + 4;
ssize_t method_len;
unsigned char *s;
int rc;
/* Create a request to sign the data */
if (transctx->state == agent_NB_state_init) {
s = transctx->request = LIBSSH2_ALLOC(session, len);
if (!transctx->request) {
return LIBSSH2_ERROR_ALLOC;
}
*s++ = SSH2_AGENTC_SIGN_REQUEST;
/* key blob */
_libssh2_htonu32(s, identity->external.blob_len);
s += 4;
memcpy(s, identity->external.blob, identity->external.blob_len);
s += identity->external.blob_len;
/* data */
_libssh2_htonu32(s, data_len);
s += 4;
memcpy(s, data, data_len);
s += data_len;
/* flags */
_libssh2_htonu32(s, 0);
s += 4;
transctx->request_len = s - transctx->request;
transctx->state = agent_NB_state_request_created;
}
/* Make sure to be re-called as a result of EAGAIN. */
if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST) {
return LIBSSH2_ERROR_BAD_USE;
}
rc = agent->ops->transact(agent, transctx);
if (rc) {
goto error;
}
LIBSSH2_FREE(session, transctx->request);
transctx->request = NULL;
len = transctx->response_len;
s = transctx->response;
len--;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
if (*s != SSH2_AGENT_SIGN_RESPONSE) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s++;
/* Skip the entire length of the signature */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s += 4;
/* Skip signing method */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
method_len = _libssh2_ntohu32(s);
s += 4;
len -= method_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s += method_len;
/* Read the signature */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
*sig_len = _libssh2_ntohu32(s);
s += 4;
len -= *sig_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
*sig = LIBSSH2_ALLOC(session, *sig_len);
if (!*sig) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
memcpy(*sig, s, *sig_len);
error:
LIBSSH2_FREE(session, transctx->request);
transctx->request = NULL;
LIBSSH2_FREE(session, transctx->response);
transctx->response = NULL;
return rc;
}
static int
agent_list_identities(LIBSSH2_AGENT *agent)
{
agent_transaction_ctx_t transctx = &agent->transctx;
ssize_t len, num_identities;
unsigned char *s;
int rc;
/* Create a request to list identities */
if (transctx->state == agent_NB_state_init) {
unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES;
transctx->request = &c;
transctx->request_len = 1;
transctx->state = agent_NB_state_request_created;
}
/* Make sure to be re-called as a result of EAGAIN. */
if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) {
return LIBSSH2_ERROR_BAD_USE;
}
rc = agent->ops->transact(agent, transctx);
if (rc) {
goto error;
}
transctx->request = NULL;
len = transctx->response_len;
s = transctx->response;
len--;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
if (*s != SSH2_AGENT_IDENTITIES_ANSWER) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
s++;
/* Read the length of identities */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
num_identities = _libssh2_ntohu32(s);
s += 4;
while (num_identities--) {
struct agent_publickey *identity;
ssize_t comment_len;
identity = LIBSSH2_ALLOC(agent->session, sizeof *identity);
if (!identity) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
/* Read the length of the blob */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
identity->external.blob_len = _libssh2_ntohu32(s);
s += 4;
/* Read the blob */
len -= identity->external.blob_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
identity->external.blob = LIBSSH2_ALLOC(agent->session,
identity->external.blob_len);
if (!identity->external.blob) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
memcpy(identity->external.blob, s, identity->external.blob_len);
s += identity->external.blob_len;
/* Read the length of the comment */
len -= 4;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
comment_len = _libssh2_ntohu32(s);
s += 4;
/* Read the comment */
len -= comment_len;
if (len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
identity->external.comment = LIBSSH2_ALLOC(agent->session,
comment_len + 1);
if (!identity->external.comment) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
identity->external.comment[comment_len] = '\0';
memcpy(identity->external.comment, s, comment_len);
s += comment_len;
_libssh2_list_add(&agent->head, &identity->node);
}
error:
LIBSSH2_FREE(agent->session, transctx->response);
transctx->response = NULL;
return rc;
}
static void
agent_free_identities(LIBSSH2_AGENT *agent) {
struct agent_publickey *node;
struct agent_publickey *next;
for (node = _libssh2_list_first(&agent->head); node; node = next) {
next = _libssh2_list_next(&node->node);
LIBSSH2_FREE(agent->session, node->external.blob);
LIBSSH2_FREE(agent->session, node->external.comment);
LIBSSH2_FREE(agent->session, node);
}
_libssh2_list_init(&agent->head);
}
#define AGENT_PUBLICKEY_MAGIC 0x3bdefed2
/*
* agent_publickey_to_external()
*
* Copies data from the internal to the external representation struct.
*
*/
static struct libssh2_agent_publickey *
agent_publickey_to_external(struct agent_publickey *node)
{
struct libssh2_agent_publickey *ext = &node->external;
ext->magic = AGENT_PUBLICKEY_MAGIC;
ext->node = node;
return ext;
}
/*
* libssh2_agent_init
*
* Init an ssh-agent handle. Returns the pointer to the handle.
*
*/
LIBSSH2_API LIBSSH2_AGENT *
libssh2_agent_init(LIBSSH2_SESSION *session)
{
LIBSSH2_AGENT *agent;
agent = LIBSSH2_ALLOC(session, sizeof *agent);
if (!agent) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate space for agent connection", 0);
return NULL;
}
memset(agent, 0, sizeof *agent);
agent->session = session;
_libssh2_list_init(&agent->head);
return agent;
}
/*
* libssh2_agent_connect()
*
* Connect to an ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_connect(LIBSSH2_AGENT *agent)
{
int i, rc = -1;
for (i = 0; supported_backends[i].name; i++) {
agent->ops = supported_backends[i].ops;
rc = agent->ops->connect(agent);
if (!rc)
return 0;
}
return rc;
}
/*
* libssh2_agent_list_identities()
*
* Request ssh-agent to list identities.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_list_identities(LIBSSH2_AGENT *agent)
{
memset(&agent->transctx, 0, sizeof agent->transctx);
/* Abondon the last fetched identities */
agent_free_identities(agent);
return agent_list_identities(agent);
}
/*
* libssh2_agent_get_identity()
*
* Traverse the internal list of public keys. Pass NULL to 'prev' to get
* the first one. Or pass a poiner to the previously returned one to get the
* next.
*
* Returns:
* 0 if a fine public key was stored in 'store'
* 1 if end of public keys
* [negative] on errors
*/
LIBSSH2_API int
libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
struct libssh2_agent_publickey **ext,
struct libssh2_agent_publickey *oprev)
{
struct agent_publickey *node;
if (oprev && oprev->node) {
/* we have a starting point */
struct agent_publickey *prev = oprev->node;
/* get the next node in the list */
node = _libssh2_list_next(&prev->node);
}
else
node = _libssh2_list_first(&agent->head);
if (!node)
/* no (more) node */
return 1;
*ext = agent_publickey_to_external(node);
return 0;
}
/*
* libssh2_agent_userauth()
*
* Do publickey user authentication with the help of ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_userauth(LIBSSH2_AGENT *agent,
const char *username,
struct libssh2_agent_publickey *identity)
{
void *abstract = agent;
if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
memset(&agent->transctx, 0, sizeof agent->transctx);
agent->identity = identity->node;
}
return libssh2_userauth_publickey(agent->session, username,
identity->blob,
identity->blob_len,
agent_sign,
&abstract);
}
/*
* libssh2_agent_disconnect()
*
* Close a connection to an ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
{
if (agent->ops && agent->fd != INVALID_SOCKET)
return agent->ops->disconnect(agent);
return 0;
}
/*
* libssh2_agent_free()
*
* Free an ssh-agent handle. This function also frees the internal
* collection of public keys.
*/
LIBSSH2_API void
libssh2_agent_free(LIBSSH2_AGENT *agent) {
/* Allow connection freeing when the socket has lost its connection */
if (agent->fd != INVALID_SOCKET) {
libssh2_agent_disconnect(agent);
}
agent_free_identities(agent);
LIBSSH2_FREE(agent->session, agent);
}

File diff suppressed because it is too large Load Diff

View File

@@ -104,5 +104,17 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
const char *request, unsigned int request_len,
const char *message, unsigned int message_len);
/*
* _libssh2_channel_read
*
* Read data from a channel
*
* It is important to not return 0 until the currently read channel is
* complete. If we read stuff from the wire but it was no payload data to fill
* in the buffer with, we MUST make sure to return PACKET_EAGAIN.
*/
ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
char *buf, size_t buflen);
#endif /* __LIBSSH2_CHANNEL_H */

View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2009 Simon Josefsson <simon@josefsson.org>
* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -114,6 +115,44 @@ crypt_dtor(LIBSSH2_SESSION * session, void **abstract)
return 0;
}
#if LIBSSH2_AES_CTR
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = {
"aes128-ctr",
16, /* blocksize */
16, /* initial value length */
16, /* secret length -- 16*8 == 128bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes128ctr
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = {
"aes192-ctr",
16, /* blocksize */
16, /* initial value length */
24, /* secret length -- 24*8 == 192bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes192ctr
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = {
"aes256-ctr",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes256ctr
};
#endif
#if LIBSSH2_AES
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
"aes128-cbc",
@@ -192,6 +231,40 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
&crypt_dtor,
_libssh2_cipher_arcfour
};
static int
crypt_init_arcfour128(LIBSSH2_SESSION * session,
const LIBSSH2_CRYPT_METHOD * method,
unsigned char *iv, int *free_iv,
unsigned char *secret, int *free_secret,
int encrypt, void **abstract)
{
int rc;
rc = crypt_init (session, method, iv, free_iv, secret, free_secret,
encrypt, abstract);
if (rc == 0) {
struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
unsigned char block[8];
size_t discard = 1536;
for (; discard; discard -= 8)
_libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block);
}
return rc;
}
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = {
"arcfour128",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
0, /* flags */
&crypt_init_arcfour128,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_arcfour
};
#endif /* LIBSSH2_RC4 */
#if LIBSSH2_CAST
@@ -223,6 +296,11 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
#endif
static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
#if LIBSSH2_AES_CTR
&libssh2_crypt_method_aes128_ctr,
&libssh2_crypt_method_aes192_ctr,
&libssh2_crypt_method_aes256_ctr,
#endif /* LIBSSH2_AES */
#if LIBSSH2_AES
&libssh2_crypt_method_aes256_cbc,
&libssh2_crypt_method_rijndael_cbc_lysator_liu_se, /* == aes256-cbc */
@@ -233,6 +311,7 @@ static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
&libssh2_crypt_method_blowfish_cbc,
#endif /* LIBSSH2_BLOWFISH */
#if LIBSSH2_RC4
&libssh2_crypt_method_arcfour128,
&libssh2_crypt_method_arcfour,
#endif /* LIBSSH2_RC4 */
#if LIBSSH2_CAST

View File

@@ -114,7 +114,6 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
void **abstract)
{
libssh2_rsa_ctx *rsactx;
FILE *fp;
int ret;
if (*abstract) {
@@ -122,13 +121,7 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
*abstract = NULL;
}
fp = fopen(privkeyfile, "r");
if (!fp) {
return -1;
}
ret = _libssh2_rsa_new_private(&rsactx, session, fp, passphrase);
fclose(fp);
ret = _libssh2_rsa_new_private(&rsactx, session, privkeyfile, passphrase);
if (ret) {
return -1;
}
@@ -296,7 +289,6 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
void **abstract)
{
libssh2_dsa_ctx *dsactx;
FILE *fp;
int ret;
if (*abstract) {
@@ -304,13 +296,7 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
*abstract = NULL;
}
fp = fopen(privkeyfile, "r");
if (!fp) {
return -1;
}
ret = _libssh2_dsa_new_private(&dsactx, session, fp, passphrase);
fclose(fp);
ret = _libssh2_dsa_new_private(&dsactx, session, privkeyfile, passphrase);
if (ret) {
return -1;
}

242
src/kex.c
View File

@@ -69,22 +69,20 @@
} \
}
/* kex_method_diffie_hellman_groupGP_sha1_key_exchange
/*
* diffie_hellman_sha1
*
* Diffie Hellman Key Exchange, Group Agnostic
*/
static int
kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
_libssh2_bn * g,
_libssh2_bn * p,
int group_order,
unsigned char
packet_type_init,
unsigned char
packet_type_reply,
unsigned char *midhash,
unsigned long midhash_len,
kmdhgGPsha1kex_state_t
* exchange_state)
static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
_libssh2_bn *g,
_libssh2_bn *p,
int group_order,
unsigned char packet_type_init,
unsigned char packet_type_reply,
unsigned char *midhash,
unsigned long midhash_len,
kmdhgGPsha1kex_state_t *exchange_state)
{
int ret = 0;
int rc;
@@ -122,7 +120,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (!exchange_state->e_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Out of memory error",
0);
ret = -1;
ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit;
}
exchange_state->e_packet[0] = packet_type_init;
@@ -137,7 +135,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
exchange_state->e_packet + 6);
}
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending KEX packet %d",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending KEX packet %d",
(int) packet_type_init);
exchange_state->state = libssh2_NB_state_created;
}
@@ -146,11 +144,11 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
rc = _libssh2_transport_write(session, exchange_state->e_packet,
exchange_state->e_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, rc,
"Unable to send KEX init message", 0);
ret = -1;
ret = rc;
goto clean_exit;
}
exchange_state->state = libssh2_NB_state_sent;
@@ -163,20 +161,20 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
* need to silently ignore it */
int burn_type;
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Waiting for badly guessed KEX packet (to be ignored)");
burn_type =
_libssh2_packet_burn(session, &exchange_state->burn_state);
if (burn_type == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return burn_type;
} else if (burn_type <= 0) {
/* Failed to receive a packet */
ret = -1;
ret = burn_type;
goto clean_exit;
}
session->burn_optimistic_kexinit = 0;
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Burnt packet of type: %02x",
(unsigned int) burn_type);
}
@@ -191,12 +189,12 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&exchange_state->s_packet_len, 0, NULL,
0, &exchange_state->req_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
if (rc) {
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply", 0);
ret = -1;
ret = rc;
goto clean_exit;
}
@@ -211,7 +209,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for a copy of the host key",
0);
ret = -1;
ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit;
}
memcpy(session->server_hostkey, exchange_state->s,
@@ -235,7 +233,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
}
*(--fprint) = '\0';
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server's MD5 Fingerprint: %s", fingerprint);
}
#endif /* LIBSSH2DEBUG */
@@ -258,17 +256,17 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
}
*(--fprint) = '\0';
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server's SHA1 Fingerprint: %s", fingerprint);
}
#endif /* LIBSSH2DEBUG */
if (session->hostkey->
init(session, session->server_hostkey, session->server_hostkey_len,
&session->server_hostkey_abstract)) {
if (session->hostkey->init(session, session->server_hostkey,
session->server_hostkey_len,
&session->server_hostkey_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
"Unable to initialize hostkey importer", 0);
ret = -1;
ret = LIBSSH2_ERROR_HOSTKEY_INIT;
goto clean_exit;
}
@@ -296,7 +294,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (!exchange_state->k_value) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K", 0);
ret = -1;
ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit;
}
_libssh2_htonu32(exchange_state->k_value,
@@ -412,7 +410,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
goto clean_exit;
}
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending NEWKEYS message");
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending NEWKEYS message");
exchange_state->c = SSH_MSG_NEWKEYS;
exchange_state->state = libssh2_NB_state_sent2;
@@ -421,11 +419,10 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (exchange_state->state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_write(session, &exchange_state->c, 1);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send NEWKEYS message", 0);
ret = -1;
libssh2_error(session, rc, "Unable to send NEWKEYS message", 0);
ret = rc;
goto clean_exit;
}
@@ -438,17 +435,16 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&exchange_state->tmp_len, 0, NULL, 0,
&exchange_state->req_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for NEWKEYS", 0);
ret = -1;
libssh2_error(session, rc, "Timed out waiting for NEWKEYS", 0);
ret = rc;
goto clean_exit;
}
/* The first key exchange has been performed,
switch to active crypt/comp/mac mode */
session->state |= LIBSSH2_STATE_NEWKEYS;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Received NEWKEYS message");
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
/* This will actually end up being just packet_type(1)
for this packet type anyway */
@@ -457,13 +453,15 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (!session->session_id) {
session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
if (!session->session_id) {
ret = -1;
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for SHA digest", 0);
ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit;
}
memcpy(session->session_id, exchange_state->h_sig_comp,
SHA_DIGEST_LENGTH);
session->session_id_len = SHA_DIGEST_LENGTH;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "session_id calculated");
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated");
}
/* Cleanup any existing cipher */
@@ -489,7 +487,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
secret_len, "C");
if (!secret) {
LIBSSH2_FREE(session, iv);
ret = -1;
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
if (session->local.crypt->
@@ -497,7 +495,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&free_secret, 1, &session->local.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret);
ret = -1;
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
@@ -511,7 +509,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server IV and Key calculated");
if (session->remote.crypt->dtor) {
@@ -528,7 +526,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
session->remote.crypt->
iv_len, "B");
if (!iv) {
ret = -1;
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
@@ -536,7 +534,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
secret_len, "D");
if (!secret) {
LIBSSH2_FREE(session, iv);
ret = -1;
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
if (session->remote.crypt->
@@ -544,7 +542,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&free_secret, 0, &session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret);
ret = -1;
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
@@ -558,7 +556,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client IV and Key calculated");
if (session->local.mac->dtor) {
@@ -573,7 +571,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
session->local.mac->
key_len, "E");
if (!key) {
ret = -1;
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->local.mac->init(session, key, &free_key,
@@ -584,7 +582,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, key);
}
}
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server HMAC Key calculated");
if (session->remote.mac->dtor) {
@@ -599,7 +597,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
session->remote.mac->
key_len, "F");
if (!key) {
ret = -1;
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->remote.mac->init(session, key, &free_key,
@@ -610,7 +608,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, key);
}
}
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client HMAC Key calculated");
}
@@ -686,23 +684,16 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
_libssh2_bn_set_word(key_state->g, 2);
_libssh2_bn_from_bin(key_state->p, 128, p_value);
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group1 Key Exchange");
key_state->state = libssh2_NB_state_created;
}
ret =
kex_method_diffie_hellman_groupGP_sha1_key_exchange(session,
key_state->g,
key_state->p, 128,
SSH_MSG_KEXDH_INIT,
SSH_MSG_KEXDH_REPLY,
NULL, 0,
&key_state->
exchange_state);
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128,
SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
}
_libssh2_bn_free(key_state->p);
@@ -769,23 +760,16 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
_libssh2_bn_set_word(key_state->g, 2);
_libssh2_bn_from_bin(key_state->p, 256, p_value);
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group14 Key Exchange");
key_state->state = libssh2_NB_state_created;
}
ret =
kex_method_diffie_hellman_groupGP_sha1_key_exchange(session,
key_state->g,
key_state->p,
256,
SSH_MSG_KEXDH_INIT,
SSH_MSG_KEXDH_REPLY,
NULL, 0,
&key_state->
exchange_state);
ret = diffie_hellman_sha1(session, key_state->g, key_state->p,
256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
}
key_state->state = libssh2_NB_state_idle;
@@ -822,13 +806,13 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
_libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
_libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
key_state->request_len = 13;
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group-Exchange (New Method)");
#else
key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
_libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
key_state->request_len = 5;
_libssh2_debug(session, LIBSSH2_DBG_KEX,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Initiating Diffie-Hellman Group-Exchange (Old Method)");
#endif
@@ -839,11 +823,11 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
rc = _libssh2_transport_write(session, key_state->request,
key_state->request_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, rc,
"Unable to send Group Exchange Request", 0);
ret = -1;
ret = rc;
goto dh_gex_clean_exit;
}
@@ -855,11 +839,11 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
&key_state->data, &key_state->data_len,
0, NULL, 0, &key_state->req_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply", 0);
ret = -1;
ret = rc;
goto dh_gex_clean_exit;
}
@@ -878,14 +862,14 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
_libssh2_bn_from_bin(key_state->g, g_len, s);
s += g_len;
ret =
kex_method_diffie_hellman_groupGP_sha1_key_exchange
(session, key_state->g, key_state->p, p_len,
SSH_MSG_KEX_DH_GEX_INIT, SSH_MSG_KEX_DH_GEX_REPLY,
key_state->data + 1, key_state->data_len - 1,
&key_state->exchange_state);
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len,
SSH_MSG_KEX_DH_GEX_INIT,
SSH_MSG_KEX_DH_GEX_REPLY,
key_state->data + 1,
key_state->data_len - 1,
&key_state->exchange_state);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
}
LIBSSH2_FREE(session, key_state->data);
@@ -1056,7 +1040,7 @@ static int kexinit(LIBSSH2_SESSION * session)
if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory", 0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
*(s++) = SSH_MSG_KEXINIT;
@@ -1106,25 +1090,25 @@ static int kexinit(LIBSSH2_SESSION * session)
/* Funnily enough, they'll all "appear" to be '\0' terminated */
unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent KEX: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent KEX: %s", p);
p += kex_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent HOSTKEY: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent HOSTKEY: %s", p);
p += hostkey_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_CS: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_CS: %s", p);
p += crypt_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_SC: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_SC: %s", p);
p += crypt_sc_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_CS: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_CS: %s", p);
p += mac_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_SC: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_SC: %s", p);
p += mac_sc_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_CS: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_CS: %s", p);
p += comp_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_SC: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_SC: %s", p);
p += comp_sc_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_CS: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_CS: %s", p);
p += lang_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_SC: %s", p);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_SC: %s", p);
p += lang_sc_len + 4;
}
#endif /* LIBSSH2DEBUG */
@@ -1139,14 +1123,14 @@ static int kexinit(LIBSSH2_SESSION * session)
if (rc == PACKET_EAGAIN) {
session->kexinit_data = data;
session->kexinit_data_len = data_len;
return PACKET_EAGAIN;
return rc;
}
else if (rc) {
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, rc,
"Unable to send KEXINIT packet to remote host", 0);
session->kexinit_state = libssh2_NB_state_idle;
return -1;
return rc;
}
if (session->local.kexinit) {
@@ -1623,24 +1607,24 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
return -1;
}
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on KEX method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on KEX method: %s",
session->kex->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on HOSTKEY method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on HOSTKEY method: %s",
session->hostkey->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_CS method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_CS method: %s",
session->local.crypt->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_SC method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_SC method: %s",
session->remote.crypt->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_CS method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_CS method: %s",
session->local.mac->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_SC method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_SC method: %s",
session->remote.mac->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_CS method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_CS method: %s",
session->local.comp->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_SC method: %s",
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_SC method: %s",
session->remote.comp->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_CS method:"); /* None yet */
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_SC method:"); /* None yet */
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on LANG_CS method:"); /* None yet */
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on LANG_SC method:"); /* None yet */
/* Initialize compression layer */
if (session->local.comp && session->local.comp->init &&
@@ -1662,6 +1646,8 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
/* libssh2_kex_exchange
* Exchange keys
* Returns 0 on success, non-zero on failure
*
* Returns some errors without libssh2_error()
*/
int
libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
@@ -1704,7 +1690,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
retcode = kexinit(session);
if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN;
return retcode;
} else if (retcode) {
session->local.kexinit = key_state->oldlocal;
session->local.kexinit_len = key_state->oldlocal_len;
@@ -1725,7 +1711,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
&key_state->req_state);
if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN;
return retcode;
}
else if (retcode) {
if (session->local.kexinit) {
@@ -1746,9 +1732,8 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
session->remote.kexinit_len = key_state->data_len;
if (kex_agree_methods(session, key_state->data,
key_state->data_len)) {
rc = -1;
}
key_state->data_len))
rc = LIBSSH2_ERROR_KEX_FAILURE;
key_state->state = libssh2_NB_state_sent2;
}
@@ -1758,16 +1743,15 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
if (rc == 0) {
if (key_state->state == libssh2_NB_state_sent2) {
retcode =
session->kex->exchange_keys(session,
&key_state->key_state_low);
retcode = session->kex->exchange_keys(session,
&key_state->key_state_low);
if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN;
return retcode;
} else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
"Unrecoverable error exchanging keys", 0);
rc = -1;
rc = retcode;
}
}
}

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2006, 2007, The Written Word, Inc.
* Copyright (C) 2008, Simon Josefsson
/* Copyright (C) 2008, 2009, Simon Josefsson
* Copyright (C) 2006, 2007, The Written Word, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -37,6 +37,9 @@
*/
#include "libssh2_priv.h"
#ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */
#include <string.h>
int
@@ -149,8 +152,9 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase)
const char *filename, unsigned const char *passphrase)
{
FILE *fp;
unsigned char *data, *save_data;
unsigned int datalen;
int ret;
@@ -159,10 +163,16 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
(void) passphrase;
fp = fopen(filename, "r");
if (!fp) {
return -1;
}
ret = _libssh2_pem_parse(session,
"-----BEGIN RSA PRIVATE KEY-----",
"-----END RSA PRIVATE KEY-----",
fp, &data, &datalen);
fclose(fp);
if (ret) {
return -1;
}
@@ -244,8 +254,9 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
int
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase)
const char *filename, unsigned const char *passphrase)
{
FILE *fp;
unsigned char *data, *save_data;
unsigned int datalen;
int ret;
@@ -254,10 +265,16 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
(void) passphrase;
fp = fopen(filename, "r");
if (!fp) {
return -1;
}
ret = _libssh2_pem_parse(session,
"-----BEGIN DSA PRIVATE KEY-----",
"-----END DSA PRIVATE KEY-----",
fp, &data, &datalen);
fclose(fp);
if (ret) {
return -1;
}
@@ -407,61 +424,54 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
return -1;
}
memset(sig, 0, 40);
/* Extract R. */
data = gcry_sexp_find_token(sig_sexp, "r", 0);
if (!data) {
ret = -1;
goto out;
}
if (!data)
goto err;
tmp = gcry_sexp_nth_data(data, 1, &size);
if (!tmp) {
ret = -1;
goto out;
}
if (!tmp)
goto err;
if (tmp[0] == '\0') {
tmp++;
size--;
}
if (size != 20) {
ret = -1;
goto out;
}
if (size < 1 || size > 20)
goto err;
memcpy(sig, tmp, 20);
memcpy(sig + (20 - size), tmp, size);
gcry_sexp_release(data);
/* Extract S. */
data = gcry_sexp_find_token(sig_sexp, "s", 0);
if (!data) {
ret = -1;
goto out;
}
if (!data)
goto err;
tmp = gcry_sexp_nth_data(data, 1, &size);
if (!tmp) {
ret = -1;
goto out;
}
if (!tmp)
goto err;
if (tmp[0] == '\0') {
tmp++;
size--;
}
if (size != 20) {
ret = -1;
goto out;
}
if (size < 1 || size > 20)
goto err;
memcpy(sig + 20, tmp, 20);
memcpy(sig + 20 + (20 - size), tmp, size);
goto out;
err:
ret = -1;
ret = 0;
out:
if (sig_sexp) {
gcry_sexp_release(sig_sexp);
@@ -507,16 +517,14 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),
unsigned char *iv, unsigned char *secret, int encrypt)
{
int mode = 0, ret;
int keylen = gcry_cipher_get_algo_keylen(algo);
int ret;
int cipher = _libssh2_gcry_cipher (algo);
int mode = _libssh2_gcry_mode (algo);
int keylen = gcry_cipher_get_algo_keylen(cipher);
(void) encrypt;
if (algo != GCRY_CIPHER_ARCFOUR) {
mode = GCRY_CIPHER_MODE_CBC;
}
ret = gcry_cipher_open(h, algo, mode, 0);
ret = gcry_cipher_open(h, cipher, mode, 0);
if (ret) {
return -1;
}
@@ -527,10 +535,13 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
return -1;
}
if (algo != GCRY_CIPHER_ARCFOUR) {
int blklen = gcry_cipher_get_algo_blklen(algo);
ret = gcry_cipher_setiv(*h, iv, blklen);
if (ret) {
if (mode != GCRY_CIPHER_MODE_STREAM) {
int blklen = gcry_cipher_get_algo_blklen(cipher);
if (mode == GCRY_CIPHER_MODE_CTR)
ret = gcry_cipher_setctr(*h, iv, blklen);
else
ret = gcry_cipher_setiv(*h, iv, blklen);
if (ret) {
gcry_cipher_close(*h);
return -1;
}
@@ -544,8 +555,10 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo),
int encrypt, unsigned char *block)
{
size_t blklen = gcry_cipher_get_algo_blklen(algo);
int cipher = _libssh2_gcry_cipher (algo);
size_t blklen = gcry_cipher_get_algo_blklen(cipher);
int ret;
if (blklen == 1) {
/* Hack for arcfour. */
blklen = 8;
@@ -558,3 +571,5 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
}
return ret;
}
#endif /* LIBSSH2_LIBGCRYPT */

View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2006, 2007, The Written Word, Inc.
* Copyright (C) 2008, Simon Josefsson
/*
* Copyright (C) 2008, 2009 Simon Josefsson
* Copyright (C) 2006, 2007, The Written Word, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -43,6 +44,7 @@
#define LIBSSH2_HMAC_RIPEMD 1
#define LIBSSH2_AES 1
#define LIBSSH2_AES_CTR 1
#define LIBSSH2_BLOWFISH 1
#define LIBSSH2_RC4 1
#define LIBSSH2_CAST 1
@@ -112,7 +114,8 @@ int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *coeffdata, unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase);
const char *filename,
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig,
unsigned long sig_len,
@@ -140,7 +143,8 @@ int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
const unsigned char *x, unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase);
const char *filename,
unsigned const char *passphrase);
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsa,
const unsigned char *sig,
const unsigned char *m, unsigned long m_len);
@@ -153,13 +157,30 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
#define _libssh2_cipher_type(name) int name
#define _libssh2_cipher_ctx gcry_cipher_hd_t
#define _libssh2_cipher_aes256 GCRY_CIPHER_AES256
#define _libssh2_cipher_aes192 GCRY_CIPHER_AES192
#define _libssh2_cipher_aes128 GCRY_CIPHER_AES128
#define _libssh2_cipher_blowfish GCRY_CIPHER_BLOWFISH
#define _libssh2_cipher_arcfour GCRY_CIPHER_ARCFOUR
#define _libssh2_cipher_cast5 GCRY_CIPHER_CAST5
#define _libssh2_cipher_3des GCRY_CIPHER_3DES
#define _libssh2_gcry_ciphermode(c,m) ((c << 8) | m)
#define _libssh2_gcry_cipher(c) (c >> 8)
#define _libssh2_gcry_mode(m) (m & 0xFF)
#define _libssh2_cipher_aes256ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes192ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes128ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes256 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_aes192 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_aes128 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_blowfish \
_libssh2_gcry_ciphermode(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_arcfour \
_libssh2_gcry_ciphermode(GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM)
#define _libssh2_cipher_cast5 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_3des \
_libssh2_gcry_ciphermode(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC)
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -85,6 +86,7 @@
#include "libssh2.h"
#include "libssh2_publickey.h"
#include "libssh2_sftp.h"
#include "misc.h" /* for the linked list stuff */
#ifndef FALSE
#define FALSE 0
@@ -96,10 +98,9 @@
/* Provide iovec / writev on WIN32 platform. */
#ifdef WIN32
/* same as WSABUF */
struct iovec {
u_long iov_len;
char *iov_base;
size_t iov_len;
void * iov_base;
};
#define inline __inline
@@ -149,6 +150,13 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
#endif
#ifdef WIN32
typedef SOCKET libssh2_socket_t;
#else /* !WIN32 */
typedef int libssh2_socket_t;
#define INVALID_SOCKET -1
#endif /* WIN32 */
/* RFC4253 section 6.1 Maximum Packet Length says:
*
* "All implementations MUST be able to process packets with
@@ -187,10 +195,6 @@ typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD;
typedef struct _LIBSSH2_PACKET LIBSSH2_PACKET;
typedef struct _LIBSSH2_PACKET_BRIGADE LIBSSH2_PACKET_BRIGADE;
typedef struct _LIBSSH2_CHANNEL_BRIGADE LIBSSH2_CHANNEL_BRIGADE;
typedef int libssh2pack_t;
typedef enum
{
@@ -207,7 +211,9 @@ typedef enum
libssh2_NB_state_sent7,
libssh2_NB_state_jump1,
libssh2_NB_state_jump2,
libssh2_NB_state_jump3
libssh2_NB_state_jump3,
libssh2_NB_state_jump4,
libssh2_NB_state_jump5
} libssh2_nonblocking_states;
typedef struct packet_require_state_t
@@ -288,6 +294,7 @@ typedef struct packet_queue_listener_state_t
uint32_t sport;
uint32_t host_len;
uint32_t shost_len;
LIBSSH2_CHANNEL *channel;
} packet_queue_listener_state_t;
#define X11FwdUnAvil "X11 Forward Unavailable"
@@ -302,10 +309,13 @@ typedef struct packet_x11_open_state_t
uint32_t packet_size;
uint32_t sport;
uint32_t shost_len;
LIBSSH2_CHANNEL *channel;
} packet_x11_open_state_t;
struct _LIBSSH2_PACKET
{
struct list_node node; /* linked list header */
unsigned char type;
/* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */
@@ -318,15 +328,6 @@ struct _LIBSSH2_PACKET
/* Can the message be confirmed? */
int mac;
LIBSSH2_PACKET_BRIGADE *brigade;
LIBSSH2_PACKET *next, *prev;
};
struct _LIBSSH2_PACKET_BRIGADE
{
LIBSSH2_PACKET *head, *tail;
};
typedef struct _libssh2_channel_data
@@ -343,6 +344,8 @@ typedef struct _libssh2_channel_data
struct _LIBSSH2_CHANNEL
{
struct list_node node;
unsigned char *channel_type;
unsigned channel_type_len;
@@ -355,8 +358,6 @@ struct _LIBSSH2_CHANNEL
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *next, *prev;
void *abstract;
LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb));
@@ -399,8 +400,6 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_read_ex() */
libssh2_nonblocking_states read_state;
LIBSSH2_PACKET *read_packet;
LIBSSH2_PACKET *read_next;
uint32_t read_local_id;
@@ -429,24 +428,21 @@ struct _LIBSSH2_CHANNEL
libssh2_nonblocking_states extData2_state;
};
struct _LIBSSH2_CHANNEL_BRIGADE
{
LIBSSH2_CHANNEL *head, *tail;
};
struct _LIBSSH2_LISTENER
{
struct list_node node; /* linked list header */
LIBSSH2_SESSION *session;
char *host;
int port;
LIBSSH2_CHANNEL *queue;
/* a list of CHANNELs for this listener */
struct list_head queue;
int queue_size;
int queue_maxsize;
LIBSSH2_LISTENER *prev, *next;
/* State variables used in libssh2_channel_forward_cancel() */
libssh2_nonblocking_states chanFwdCncl_state;
unsigned char *chanFwdCncl_data;
@@ -547,8 +543,9 @@ struct _LIBSSH2_PUBLICKEY
struct _LIBSSH2_SFTP_HANDLE
{
struct list_node node;
LIBSSH2_SFTP *sftp;
LIBSSH2_SFTP_HANDLE *prev, *next;
/* This is a pre-allocated buffer used for sending SFTP requests as the
whole thing might not get sent in one go. This buffer is used for read,
@@ -586,9 +583,10 @@ struct _LIBSSH2_SFTP
unsigned long request_id, version;
LIBSSH2_PACKET_BRIGADE packets;
struct list_head packets;
LIBSSH2_SFTP_HANDLE *handles;
/* a list of _LIBSSH2_SFTP_HANDLE structs */
struct list_head sftp_handles;
unsigned long last_errno;
@@ -713,18 +711,19 @@ struct _LIBSSH2_SESSION
/* (local as source of data -- packet_write ) */
libssh2_endpoint_data local;
/* Inbound Data buffer -- Sometimes the packet that comes in isn't the
/* Inbound Data linked list -- Sometimes the packet that comes in isn't the
packet we're ready for */
LIBSSH2_PACKET_BRIGADE packets;
struct list_head packets;
/* Active connection channels */
LIBSSH2_CHANNEL_BRIGADE channels;
struct list_head channels;
unsigned long next_channel;
LIBSSH2_LISTENER *listeners;
struct list_head listeners; /* list of LIBSSH2_LISTENER structs */
/* Actual I/O socket */
int socket_fd;
libssh2_socket_t socket_fd;
int socket_state;
int socket_block_directions;
int socket_prev_blockstate; /* stores the state of the socket blockiness
@@ -740,6 +739,8 @@ struct _LIBSSH2_SESSION
struct transportpacket packet;
#ifdef LIBSSH2DEBUG
int showmask; /* what debug/trace messages to display */
libssh2_trace_handler_func tracehandler; /* callback to display trace messages */
void* tracehandler_context; /* context for the trace handler */
#endif
/* State variables used in libssh2_banner_send() */
@@ -811,7 +812,7 @@ struct _LIBSSH2_SESSION
unsigned char *userauth_pblc_b;
packet_requirev_state_t userauth_pblc_packet_requirev_state;
/* State variables used in llibssh2_userauth_keyboard_interactive_ex() */
/* State variables used in libssh2_userauth_keyboard_interactive_ex() */
libssh2_nonblocking_states userauth_kybd_state;
unsigned char *userauth_kybd_data;
unsigned long userauth_kybd_data_len;
@@ -860,7 +861,6 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_packet_add() */
libssh2_nonblocking_states packAdd_state;
LIBSSH2_PACKET *packAdd_packet;
LIBSSH2_CHANNEL *packAdd_channel;
unsigned long packAdd_data_head;
key_exchange_state_t packAdd_key_state;
@@ -871,7 +871,7 @@ struct _LIBSSH2_SESSION
libssh2_nonblocking_states fullpacket_state;
int fullpacket_macstate;
int fullpacket_payload_len;
libssh2pack_t fullpacket_packet_type;
int fullpacket_packet_type;
/* State variables used in libssh2_sftp_init() */
libssh2_nonblocking_states sftpInit_state;
@@ -928,22 +928,6 @@ struct _LIBSSH2_SESSION
#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
#endif
/* -------- */
/* First take towards a generic linked list handling code for libssh2
internals */
struct list_head {
struct list_node *last;
struct list_node *first;
};
struct list_node {
struct list_node *next;
struct list_node *prev;
struct list_head *head;
};
/* --------- */
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional
@@ -1036,14 +1020,6 @@ struct _LIBSSH2_MAC_METHOD
int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
};
#define LIBSSH2_DBG_TRANS 1
#define LIBSSH2_DBG_KEX 2
#define LIBSSH2_DBG_AUTH 3
#define LIBSSH2_DBG_CONN 4
#define LIBSSH2_DBG_SCP 5
#define LIBSSH2_DBG_SFTP 6
#define LIBSSH2_DBG_ERROR 7
#define LIBSSH2_DBG_PUBLICKEY 8
#ifdef LIBSSH2DEBUG
void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
...);
@@ -1070,7 +1046,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
session->err_msglen = strlen(errmsg); \
session->err_should_free = should_free; \
session->err_code = errcode; \
_libssh2_debug(session, LIBSSH2_DBG_ERROR, "%d - %s", session->err_code, session->err_msg); \
_libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code, session->err_msg); \
}
#else /* ! LIBSSH2DEBUG */
@@ -1161,8 +1137,8 @@ libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf);
void _libssh2_htonu32(unsigned char *buf, unsigned int val);
#ifdef WIN32
ssize_t _libssh2_recv(int socket, void *buffer, size_t length, int flags);
ssize_t _libssh2_send(int socket, const void *buffer, size_t length, int flags);
ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer, size_t length, int flags);
ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer, size_t length, int flags);
#else
#define _libssh2_recv(a,b,c,d) recv(a,b,c,d)
#define _libssh2_send(a,b,c,d) send(a,b,c,d)
@@ -1174,20 +1150,21 @@ ssize_t _libssh2_send(int socket, const void *buffer, size_t length, int flags);
int _libssh2_wait_socket(LIBSSH2_SESSION *session);
/* CAUTION: some of these error codes are returned in the public API and is
there known with other #defined names from the public header file. They
should not be changed. */
/* These started out as private return codes for the transport layer, but was
converted to using the library-wide return codes to easy propagation of the
error reasons all over etc without risking mixups. The PACKET_* names are
left only to reduce the impact of changing the code all over.*/
#define PACKET_TIMEOUT -7
#define PACKET_BADUSE -6
#define PACKET_COMPRESS -5
#define PACKET_TOOBIG -4
#define PACKET_ENOMEM -3
#define PACKET_TIMEOUT LIBSSH2_ERROR_TIMEOUT
#define PACKET_BADUSE LIBSSH2_ERROR_BAD_USE
#define PACKET_COMPRESS LIBSSH2_ERROR_COMPRESS
#define PACKET_TOOBIG LIBSSH2_ERROR_OUT_OF_BOUNDARY
#define PACKET_ENOMEM LIBSSH2_ERROR_ALLOC
#define PACKET_EAGAIN LIBSSH2_ERROR_EAGAIN
#define PACKET_FAIL -1
#define PACKET_NONE 0
#define PACKET_FAIL LIBSSH2_ERROR_SOCKET_NONE
#define PACKET_NONE LIBSSH2_ERROR_NONE
libssh2pack_t _libssh2_packet_read(LIBSSH2_SESSION * session);
int _libssh2_packet_read(LIBSSH2_SESSION * session);
int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned char **data, unsigned long *data_len,
@@ -1292,4 +1269,7 @@ int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
} while(1)
#define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0]))
#endif /* LIBSSH2_H */

View File

@@ -167,6 +167,7 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1_96 = {
mac_method_common_dtor,
};
#if LIBSSH2_MD5
/* mac_method_hmac_md5_hash
* Calculate hash using full md5 value
*/
@@ -235,6 +236,7 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_md5_96 = {
mac_method_hmac_md5_96_hash,
mac_method_common_dtor,
};
#endif /* LIBSSH2_MD5 */
#if LIBSSH2_HMAC_RIPEMD
/* mac_method_hmac_ripemd160_hash
@@ -291,8 +293,10 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160_openssh_com = {
static const LIBSSH2_MAC_METHOD *mac_methods[] = {
&mac_method_hmac_sha1,
&mac_method_hmac_sha1_96,
#if LIBSSH2_MD5
&mac_method_hmac_md5,
&mac_method_hmac_md5_96,
#endif
#if LIBSSH2_HMAC_RIPEMD
&mac_method_hmac_ripemd160,
&mac_method_hmac_ripemd160_openssh_com,

View File

@@ -78,7 +78,7 @@ static int wsa2errno(void)
* to set errno
*/
ssize_t
_libssh2_recv(int socket, void *buffer, size_t length, int flags)
_libssh2_recv(libssh2_socket_t socket, void *buffer, size_t length, int flags)
{
ssize_t rc = recv(socket, buffer, length, flags);
#ifdef WIN32
@@ -97,7 +97,7 @@ _libssh2_recv(int socket, void *buffer, size_t length, int flags)
* to set errno
*/
ssize_t
_libssh2_send(int socket, const void *buffer, size_t length, int flags)
_libssh2_send(libssh2_socket_t socket, const void *buffer, size_t length, int flags)
{
ssize_t rc = send(socket, buffer, length, flags);
#ifdef WIN32
@@ -312,6 +312,14 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
return 0;
}
LIBSSH2_API int
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, libssh2_trace_handler_func callback)
{
session->tracehandler = callback;
session->tracehandler_context = handler_context;
return 0;
}
void
_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
{
@@ -320,7 +328,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
va_list vargs;
struct timeval now;
static int firstsec;
static const char *const contexts[9] = {
static const char *const contexts[] = {
"Unknown",
"Transport",
"Key Ex",
@@ -330,15 +338,24 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
"SFTP",
"Failure Event",
"Publickey",
"Socket",
};
const char* contexttext = contexts[0];
unsigned int contextindex;
if (context < 1 || context > 8) {
context = 0;
}
if (!(session->showmask & (1 << context))) {
if (!(session->showmask & context)) {
/* no such output asked for */
return;
}
/* Find the first matching context string for this message */
for (contextindex = 0; contextindex < ARRAY_SIZE(contexts); contextindex++) {
if ((context & (1 << contextindex)) != 0) {
contexttext = contexts[contextindex];
break;
}
}
gettimeofday(&now, NULL);
if(!firstsec) {
firstsec = now.tv_sec;
@@ -346,14 +363,18 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
now.tv_sec -= firstsec;
len = snprintf(buffer, sizeof(buffer), "[libssh2] %d.%06d %s: ",
(int)now.tv_sec, (int)now.tv_usec, contexts[context]);
(int)now.tv_sec, (int)now.tv_usec, contexttext);
va_start(vargs, format);
len += vsnprintf(buffer + len, 1535 - len, format, vargs);
buffer[len] = '\n';
va_end(vargs);
write(2, buffer, len + 1);
if (session->tracehandler) {
(session->tracehandler)(session, session->tracehandler_context, buffer, len + 1);
} else {
write(2, buffer, len + 1);
}
}
#else
@@ -364,6 +385,15 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
(void) bitmask;
return 0;
}
LIBSSH2_API int
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, libssh2_trace_handler_func callback)
{
(void) session;
(void) handler_context;
(void) callback;
return 0;
}
#endif
/* init the list head */
@@ -426,3 +456,85 @@ void _libssh2_list_remove(struct list_node *entry)
else
entry->head->last = entry->prev;
}
#if 0
/* insert a node before the given 'after' entry */
void _libssh2_list_insert(struct list_node *after, /* insert before this */
struct list_node *entry)
{
/* 'after' is next to 'entry' */
bentry->next = after;
/* entry's prev is then made to be the prev after current has */
entry->prev = after->prev;
/* the node that is now before 'entry' was previously before 'after'
and must be made to point to 'entry' correctly */
if(entry->prev)
entry->prev->next = entry;
else
/* there was no node before this, so we make sure we point the head
pointer to this node */
after->head->first = entry;
/* after's prev entry points back to entry */
after->prev = entry;
/* after's next entry is still the same as before */
/* entry's head is the same as after's */
entry->head = after->head;
}
#endif
#ifdef WIN32
/*
* gettimeofday
* Implementation according to:
* The Open Group Base Specifications Issue 6
* IEEE Std 1003.1, 2004 Edition
*/
/*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Contributed by:
* Danny Smith <dannysmith@users.sourceforge.net>
*/
/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
#define _W32_FT_OFFSET (116444736000000000ULL)
int __cdecl gettimeofday(struct timeval *tp,
void *tzp)
{
union {
unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} _now;
if(tp)
{
GetSystemTimeAsFileTime (&_now.ft);
tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
}
/* Always return 0 as per Open Group Base Specifications Issue 6.
Do not set errno on error. */
return 0;
}
#endif

View File

@@ -38,11 +38,20 @@
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
struct list_head {
struct list_node *last;
struct list_node *first;
};
struct list_node {
struct list_node *next;
struct list_node *prev;
struct list_head *head;
};
void _libssh2_list_init(struct list_head *head);
/* add a node first in the list */
/* add a node last in the list */
void _libssh2_list_add(struct list_head *head,
struct list_node *entry);
@@ -58,6 +67,6 @@ void *_libssh2_list_prev(struct list_node *node);
/* remove this node from the list */
void _libssh2_list_remove(struct list_node *entry);
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
size_t _libssh2_base64_encode(struct _LIBSSH2_SESSION *session,
const char *inp, size_t insize, char **outptr);
#endif /* _LIBSSH2_MISC_H */

View File

@@ -1,7 +1,9 @@
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
* Author: Simon Josefsson
/* Copyright (C) 2009 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
*
* Author: Simon Josefsson
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
@@ -37,15 +39,15 @@
*/
#include "libssh2_priv.h"
#ifndef LIBSSH2_LIBGCRYPT /* compile only if we build with OpenSSL */
#include <string.h>
#ifndef EVP_MAX_BLOCK_LENGTH
#define EVP_MAX_BLOCK_LENGTH 32
#endif
/* Ridiculously large key-file size cap (512KB) */
#define MAX_KEY_FILE_LENGTH 524288
int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
@@ -197,6 +199,110 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
return ret == 1 ? 0 : 1;
}
#if LIBSSH2_AES_CTR
#include <openssl/aes.h>
typedef struct
{
AES_KEY key;
unsigned char ctr[AES_BLOCK_SIZE];
} aes_ctr_ctx;
static int
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) /* init key */
{
aes_ctr_ctx *c = malloc(sizeof(*c));
(void) enc;
if (c == NULL)
return 0;
AES_set_encrypt_key(key, 8 * ctx->key_len, &c->key);
memcpy(c->ctr, iv, AES_BLOCK_SIZE);
EVP_CIPHER_CTX_set_app_data(ctx, c);
return 1;
}
static int
aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in,
unsigned int inl) /* encrypt/decrypt data */
{
aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
unsigned char b1[AES_BLOCK_SIZE];
size_t i;
if (inl != 16) /* libssh2 only ever encrypt one block */
return 0;
/*
To encrypt a packet P=P1||P2||...||Pn (where P1, P2, ..., Pn are each
blocks of length L), the encryptor first encrypts <X> with <cipher>
to obtain a block B1. The block B1 is then XORed with P1 to generate
the ciphertext block C1. The counter X is then incremented
*/
AES_encrypt(c->ctr, b1, &c->key);
for (i = 0; i < 16; i++)
*out++ = *in++ ^ b1[i];
i = 15;
while (c->ctr[i]++ == 0xFF) {
if (i == 0)
break;
i--;
}
return 1;
}
static int
aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
{
free(EVP_CIPHER_CTX_get_app_data(ctx));
return 1;
}
static const EVP_CIPHER *
make_ctr_evp (size_t keylen)
{
static EVP_CIPHER aes_ctr_cipher;
memset(&aes_ctr_cipher, 0, sizeof(aes_ctr_cipher));
aes_ctr_cipher.block_size = 16;
aes_ctr_cipher.key_len = keylen;
aes_ctr_cipher.iv_len = 16;
aes_ctr_cipher.init = aes_ctr_init;
aes_ctr_cipher.do_cipher = aes_ctr_do_cipher;
aes_ctr_cipher.cleanup = aes_ctr_cleanup;
return &aes_ctr_cipher;
}
const EVP_CIPHER *
_libssh2_EVP_aes_128_ctr(void)
{
return make_ctr_evp (16);
}
const EVP_CIPHER *
_libssh2_EVP_aes_192_ctr(void)
{
return make_ctr_evp (24);
}
const EVP_CIPHER *
_libssh2_EVP_aes_256_ctr(void)
{
return make_ctr_evp (32);
}
#endif /* LIBSSH2_AES_CTR */
/* TODO: Optionally call a passphrase callback specified by the
* calling program
*/
@@ -215,79 +321,39 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
return passphrase_len;
}
static int
read_file_into_string(char ** key, LIBSSH2_SESSION * session, FILE * fp)
{
long size;
size_t read;
*key = NULL;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
if (size < 0) {
return -1;
}
fseek(fp, 0, SEEK_SET);
size *= sizeof(char);
if (size > MAX_KEY_FILE_LENGTH) {
return -1;
}
*key = LIBSSH2_ALLOC(session, size + 1);
if (!*key) {
return -1;
}
read = fread(*key, 1, size, fp);
if (read != size) {
LIBSSH2_FREE(session, *key);
return -1;
}
(*key)[size] = '\0';
return 0;
}
typedef void * (*pem_read_bio_func)(BIO *, void **, pem_password_cb *,
void * u);
static int
read_private_key_from_file(void ** key_ctx, LIBSSH2_SESSION * session,
read_private_key_from_file(void ** key_ctx,
pem_read_bio_func read_private_key,
FILE * fp, unsigned const char *passphrase)
const char * filename,
unsigned const char *passphrase)
{
char * key;
BIO * bp;
*key_ctx = NULL;
if(read_file_into_string(&key, session, fp)) {
return -1;
}
bp = BIO_new_mem_buf(key, -1);
bp = BIO_new_file(filename, "r");
if (!bp) {
LIBSSH2_FREE(session, key);
return -1;
}
*key_ctx = read_private_key(bp, NULL, (void *) passphrase_cb,
*key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb,
(void *) passphrase);
BIO_free(bp);
LIBSSH2_FREE(session, key);
return (*key_ctx) ? 0 : -1;
}
int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase)
const char *filename, unsigned const char *passphrase)
{
pem_read_bio_func read_rsa =
(pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
(void) session;
if (!EVP_get_cipherbyname("des")) {
/* If this cipher isn't loaded it's a pretty good indication that none are.
@@ -297,17 +363,18 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
OpenSSL_add_all_ciphers();
}
return read_private_key_from_file((void **) rsa, session, read_rsa, fp,
passphrase);
return read_private_key_from_file((void **) rsa, read_rsa,
filename, passphrase);
}
int
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase)
const char *filename, unsigned const char *passphrase)
{
pem_read_bio_func read_dsa =
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
(void) session;
if (!EVP_get_cipherbyname("des")) {
/* If this cipher isn't loaded it's a pretty good indication that none are.
@@ -317,8 +384,8 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
OpenSSL_add_all_ciphers();
}
return read_private_key_from_file((void **) dsa, session, read_dsa, fp,
passphrase);
return read_private_key_from_file((void **) dsa, read_dsa,
filename, passphrase);
}
int
@@ -358,7 +425,7 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
unsigned long hash_len, unsigned char *signature)
{
DSA_SIG *sig;
int r_len, s_len, rs_pad;
int r_len, s_len;
(void) hash_len;
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
@@ -367,17 +434,24 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
}
r_len = BN_num_bytes(sig->r);
if (r_len < 1 || r_len > 20) {
DSA_SIG_free(sig);
return -1;
}
s_len = BN_num_bytes(sig->s);
rs_pad = (2 * SHA_DIGEST_LENGTH) - (r_len + s_len);
if (rs_pad < 0) {
if (s_len < 1 || s_len > 20) {
DSA_SIG_free(sig);
return -1;
}
BN_bn2bin(sig->r, signature + rs_pad);
BN_bn2bin(sig->s, signature + rs_pad + r_len);
memset(signature, 0, 40);
BN_bn2bin(sig->r, signature + (20 - r_len));
BN_bn2bin(sig->s, signature + 20 + (20 - s_len));
DSA_SIG_free(sig);
return 0;
}
#endif /* !LIBSSH2_LIBGCRYPT */

View File

@@ -1,4 +1,6 @@
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
/* Copyright (C) 2009 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
*
* Author: Simon Josefsson
*
* Redistribution and use in source and binary forms,
@@ -71,6 +73,7 @@
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
# define LIBSSH2_AES_CTR 1
# define LIBSSH2_AES 1
#else
# define LIBSSH2_AES 0
@@ -148,7 +151,8 @@ int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *coeffdata, unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase);
const char *filename,
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig,
unsigned long sig_len,
@@ -176,7 +180,8 @@ int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
const unsigned char *x, unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase);
const char *filename,
unsigned const char *passphrase);
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
const unsigned char *sig,
const unsigned char *m, unsigned long m_len);
@@ -192,6 +197,9 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
#define _libssh2_cipher_aes256 EVP_aes_256_cbc
#define _libssh2_cipher_aes192 EVP_aes_192_cbc
#define _libssh2_cipher_aes128 EVP_aes_128_cbc
#define _libssh2_cipher_aes128ctr _libssh2_EVP_aes_128_ctr
#define _libssh2_cipher_aes192ctr _libssh2_EVP_aes_192_ctr
#define _libssh2_cipher_aes256ctr _libssh2_EVP_aes_256_ctr
#define _libssh2_cipher_blowfish EVP_bf_cbc
#define _libssh2_cipher_arcfour EVP_rc4
#define _libssh2_cipher_cast5 EVP_cast5_cbc
@@ -221,3 +229,7 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
#define _libssh2_bn_bytes(bn) BN_num_bytes(bn)
#define _libssh2_bn_bits(bn) BN_num_bits(bn)
#define _libssh2_bn_free(bn) BN_clear_free(bn)
const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -60,6 +61,7 @@
#include <sys/types.h>
#include "transport.h"
#include "channel.h"
/*
* libssh2_packet_queue_listener
@@ -69,7 +71,7 @@
static inline int
packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long datalen,
packet_queue_listener_state_t * listen_state)
packet_queue_listener_state_t *listen_state)
{
/*
* Look for a matching listener
@@ -78,7 +80,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
/* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1);
unsigned char *p;
LIBSSH2_LISTENER *listen = session->listeners;
LIBSSH2_LISTENER *listen = _libssh2_list_first(&session->listeners);
char failure_code = 1; /* SSH_OPEN_ADMINISTRATIVELY_PROHIBITED */
int rc;
@@ -107,7 +109,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
listen_state->sport = _libssh2_ntohu32(s);
s += 4;
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Remote received connection from %s:%ld to %s:%ld",
listen_state->shost, listen_state->sport,
listen_state->host, listen_state->port);
@@ -119,19 +121,18 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
while (listen) {
if ((listen->port == (int) listen_state->port) &&
(strlen(listen->host) == listen_state->host_len) &&
(memcmp
(listen->host, listen_state->host,
listen_state->host_len) == 0)) {
(memcmp (listen->host, listen_state->host,
listen_state->host_len) == 0)) {
/* This is our listener */
LIBSSH2_CHANNEL *channel = NULL, *last_queued = listen->queue;
LIBSSH2_CHANNEL *channel = NULL;
listen_state->channel = NULL;
last_queued = listen->queue;
if (listen_state->state == libssh2_NB_state_allocated) {
if (listen->queue_maxsize &&
(listen->queue_maxsize <= listen->queue_size)) {
/* Queue is full */
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Listener queue full, ignoring");
listen_state->state = libssh2_NB_state_sent;
break;
@@ -146,6 +147,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
listen_state->state = libssh2_NB_state_sent;
break;
}
listen_state->channel = channel;
memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
channel->session = session;
@@ -181,7 +184,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
listen_state->initial_window_size;
channel->local.packet_size = listen_state->packet_size;
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Connection queued: channel %lu/%lu win %lu/%lu packet %lu/%lu",
channel->local.id, channel->remote.id,
channel->local.window_size,
@@ -206,31 +209,19 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
if (listen_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, listen_state->packet,
17);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel open confirmation",
0);
if (rc == PACKET_EAGAIN)
return rc;
else if (rc) {
libssh2_error(session, rc,
"Unable to send channel "
"open confirmation", 0);
listen_state->state = libssh2_NB_state_idle;
return -1;
return rc;
}
/* Link the channel into the end of the queue list */
if (!last_queued) {
listen->queue = channel;
listen_state->state = libssh2_NB_state_idle;
return 0;
}
while (last_queued->next) {
last_queued = last_queued->next;
}
last_queued->next = channel;
channel->prev = last_queued;
_libssh2_list_add(&listen->queue,
&listen_state->channel->node);
listen->queue_size++;
listen_state->state = libssh2_NB_state_idle;
@@ -238,39 +229,36 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
}
}
listen = listen->next;
listen = _libssh2_list_next(&listen->node);
}
listen_state->state = libssh2_NB_state_sent;
}
/* We're not listening to you */
{
p = listen_state->packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
_libssh2_htonu32(p, listen_state->sender_channel);
p += 4;
_libssh2_htonu32(p, failure_code);
p += 4;
_libssh2_htonu32(p, sizeof(FwdNotReq) - 1);
p += 4;
memcpy(s, FwdNotReq, sizeof(FwdNotReq) - 1);
p += sizeof(FwdNotReq) - 1;
_libssh2_htonu32(p, 0);
p = listen_state->packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
_libssh2_htonu32(p, listen_state->sender_channel);
p += 4;
_libssh2_htonu32(p, failure_code);
p += 4;
_libssh2_htonu32(p, sizeof(FwdNotReq) - 1);
p += 4;
memcpy(s, FwdNotReq, sizeof(FwdNotReq) - 1);
p += sizeof(FwdNotReq) - 1;
_libssh2_htonu32(p, 0);
rc = _libssh2_transport_write(session, listen_state->packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send open failure", 0);
listen_state->state = libssh2_NB_state_idle;
return -1;
}
rc = _libssh2_transport_write(session, listen_state->packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return rc;
} else if (rc) {
libssh2_error(session, rc, "Unable to send open failure", 0);
listen_state->state = libssh2_NB_state_idle;
return 0;
return rc;
}
listen_state->state = libssh2_NB_state_idle;
return 0;
}
/*
@@ -281,14 +269,14 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
static inline int
packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long datalen,
packet_x11_open_state_t * x11open_state)
packet_x11_open_state_t *x11open_state)
{
int failure_code = 2; /* SSH_OPEN_CONNECT_FAILED */
unsigned char *s = data + (sizeof("x11") - 1) + 5;
/* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1);
unsigned char *p;
LIBSSH2_CHANNEL *channel = NULL;
LIBSSH2_CHANNEL *channel = x11open_state->channel;
int rc;
(void) datalen;
@@ -307,7 +295,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
x11open_state->sport = _libssh2_ntohu32(s);
s += 4;
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"X11 Connection Received from %s:%ld on channel %lu",
x11open_state->shost, x11open_state->sport,
x11open_state->sender_channel);
@@ -355,7 +343,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
channel->local.window_size = x11open_state->initial_window_size;
channel->local.packet_size = x11open_state->packet_size;
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"X11 Connection established: channel %lu/%lu win %lu/%lu packet %lu/%lu",
channel->local.id, channel->remote.id,
channel->local.window_size,
@@ -379,7 +367,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
if (x11open_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, x11open_state->packet, 17);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel open confirmation", 0);
@@ -388,21 +376,13 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
}
/* Link the channel into the session */
if (session->channels.tail) {
session->channels.tail->next = channel;
channel->prev = session->channels.tail;
} else {
session->channels.head = channel;
channel->prev = NULL;
}
channel->next = NULL;
session->channels.tail = channel;
_libssh2_list_add(&session->channels, &channel->node);
/*
* Pass control to the callback, they may turn right around and
* free the channel, or actually use it
*/
LIBSSH2_X11_OPEN(channel, (char *) x11open_state->shost,
LIBSSH2_X11_OPEN(channel, (char *)x11open_state->shost,
x11open_state->sport);
x11open_state->state = libssh2_NB_state_idle;
@@ -427,12 +407,11 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
rc = _libssh2_transport_write(session, x11open_state->packet, packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send open failure", 0);
libssh2_error(session, rc, "Unable to send open failure", 0);
x11open_state->state = libssh2_NB_state_idle;
return -1;
return rc;
}
x11open_state->state = libssh2_NB_state_idle;
return 0;
@@ -442,7 +421,10 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
* _libssh2_packet_add
*
* Create a new packet and attach it to the brigade. Called from the transport
* layer when it as received a packet.
* layer when it has received a packet.
*
* The input pointer 'data' is pointing to allocated data that this function
* is asked to deal with so on failure OR success, it must be freed fine.
*/
int
_libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
@@ -465,27 +447,14 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
memset(&session->packAdd_x11open_state, 0,
sizeof(session->packAdd_x11open_state));
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Packet type %d received, length=%d",
(int) data[0], (int) datalen);
if (macstate == LIBSSH2_MAC_INVALID) {
if (session->macerror) {
if (LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) {
/* Calling app has given the OK, Process it anyway */
macstate = LIBSSH2_MAC_CONFIRMED;
} else {
libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
"Invalid Message Authentication Code received",
0);
if (session->ssh_msg_disconnect) {
LIBSSH2_DISCONNECT(session, SSH_DISCONNECT_MAC_ERROR,
"Invalid MAC received",
sizeof("Invalid MAC received") - 1,
"", 0);
}
LIBSSH2_FREE(session, data);
return -1;
}
if (session->macerror &&
LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) {
/* Calling app has given the OK, Process it anyway */
macstate = LIBSSH2_MAC_CONFIRMED;
} else {
libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
"Invalid Message Authentication Code received",
@@ -497,7 +466,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"", 0);
}
LIBSSH2_FREE(session, data);
return -1;
return LIBSSH2_ERROR_INVALID_MAC;
}
}
@@ -515,8 +484,16 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
goto libssh2_packet_add_jump_point2;
} else if (session->packAdd_state == libssh2_NB_state_jump3) {
goto libssh2_packet_add_jump_point3;
} else if (session->packAdd_state == libssh2_NB_state_jump4) {
goto libssh2_packet_add_jump_point4;
} else if (session->packAdd_state == libssh2_NB_state_jump5) {
goto libssh2_packet_add_jump_point5;
}
/* FIXME: I've noticed that DATA is accessed without proper
* out-of-bounds checking (i.e., DATALEN) in many places
* below. --simon */
if (session->packAdd_state == libssh2_NB_state_allocated) {
/* A couple exceptions to the packet adding rule: */
switch (data[0]) {
@@ -544,7 +521,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
message[message_len] = '\0';
language = (char *) data + 9 + message_len + 3;
if (language_len) {
memcpy(language, language + 1, language_len);
memmove(language, language + 1, language_len);
}
language[language_len] = '\0';
@@ -552,27 +529,32 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_DISCONNECT(session, reason, message,
message_len, language, language_len);
}
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Disconnect(%d): %s(%s)", reason,
message, language);
LIBSSH2_FREE(session, data);
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
session->packAdd_state = libssh2_NB_state_idle;
return -1;
libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"socket disconnect", 0);
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
break;
case SSH_MSG_IGNORE:
/* As with disconnect, back it up one and add a trailing NULL */
memcpy(data + 4, data + 5, datalen - 5);
data[datalen] = '\0';
if (session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, (char *) data + 4, datalen - 5);
if (datalen >= 5) {
/* Back it up one and add a trailing NULL */
memmove(data, data + 1, datalen - 1);
data[datalen] = '\0';
if (session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, (char *) data + 4, datalen - 1);
}
} else if (session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, "", 0);
}
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
break;
case SSH_MSG_DEBUG:
{
@@ -598,7 +580,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
message[message_len] = '\0';
language = (char *) data + 6 + message_len + 3;
if (language_len) {
memcpy(language, language + 1, language_len);
memmove(language, language + 1, language_len);
}
language[language_len] = '\0';
@@ -610,7 +592,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
* _libssh2_debug will actually truncate this for us so
* that it's not an inordinate about of data
*/
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Debug Packet: %s", message);
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
@@ -618,6 +600,30 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
}
break;
case SSH_MSG_GLOBAL_REQUEST:
{
uint32_t strlen = _libssh2_ntohu32(data + 1);
unsigned char want_reply = data[5 + strlen];
_libssh2_debug(session,
LIBSSH2_TRACE_CONN,
"Received global request type %.*s (wr %X)",
strlen, data + 5, want_reply);
if (want_reply) {
libssh2_packet_add_jump_point5:
session->packAdd_state = libssh2_NB_state_jump5;
data[0] = SSH_MSG_REQUEST_FAILURE;
rc = _libssh2_transport_write(session, data, 1);
if (rc == PACKET_EAGAIN)
return rc;
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
}
break;
case SSH_MSG_CHANNEL_EXTENDED_DATA:
/* streamid(4) */
session->packAdd_data_head += 4;
@@ -643,7 +649,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
stream_id = _libssh2_ntohu32(data + 5);
}
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"%d bytes packet_add() for %lu/%lu/%lu",
(int) (datalen - session->packAdd_data_head),
session->packAdd_channel->local.id,
@@ -657,21 +663,19 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
/* Pretend we didn't receive this */
LIBSSH2_FREE(session, data);
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Ignoring extended data and refunding %d bytes",
(int) (datalen - 13));
/* Adjust the window based on the block we just freed */
libssh2_packet_add_jump_point1:
session->packAdd_state = libssh2_NB_state_jump1;
rc = libssh2_channel_receive_window_adjust(session->
packAdd_channel,
datalen - 13,
0);
if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
rc = _libssh2_channel_receive_window_adjust(session->
packAdd_channel,
datalen - 13,
0, NULL);
if (rc == PACKET_EAGAIN)
return rc;
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
@@ -731,101 +735,110 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
break;
case SSH_MSG_CHANNEL_EOF:
{
session->packAdd_channel =
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1));
if (!session->packAdd_channel) {
/* We may have freed already, just quietly ignore this... */
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
_libssh2_debug(session,
LIBSSH2_DBG_CONN,
"EOF received for channel %lu/%lu",
session->packAdd_channel->local.id,
session->packAdd_channel->remote.id);
session->packAdd_channel->remote.eof = 1;
session->packAdd_channel =
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1));
if (!session->packAdd_channel) {
/* We may have freed already, just quietly ignore this... */
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
break;
_libssh2_debug(session,
LIBSSH2_TRACE_CONN,
"EOF received for channel %lu/%lu",
session->packAdd_channel->local.id,
session->packAdd_channel->remote.id);
session->packAdd_channel->remote.eof = 1;
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
case SSH_MSG_CHANNEL_REQUEST:
{
if (_libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1
&& !memcmp("exit-status", data + 9,
sizeof("exit-status") - 1)) {
{
uint32_t channel = _libssh2_ntohu32(data + 1);
uint32_t strlen = _libssh2_ntohu32(data + 5);
unsigned char want_reply = data[9 + strlen];
/* we've got "exit-status" packet. Set the session value */
session->packAdd_channel =
_libssh2_channel_locate(session,
_libssh2_ntohu32(data + 1));
_libssh2_debug(session,
LIBSSH2_TRACE_CONN,
"Channel %d received request type %.*s (wr %X)",
channel, strlen, data + 9, want_reply);
if (session->packAdd_channel) {
session->packAdd_channel->exit_status =
_libssh2_ntohu32(data + 9 + sizeof("exit-status"));
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"Exit status %lu received for channel %lu/%lu",
session->packAdd_channel->exit_status,
session->packAdd_channel->local.id,
session->packAdd_channel->remote.id);
}
if (strlen == sizeof("exit-status") - 1
&& !memcmp("exit-status", data + 9,
sizeof("exit-status") - 1)) {
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
}
break;
case SSH_MSG_CHANNEL_CLOSE:
{
/* we've got "exit-status" packet. Set the session value */
session->packAdd_channel =
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1));
_libssh2_channel_locate(session, channel);
if (!session->packAdd_channel) {
/* We may have freed already, just quietly ignore this... */
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
if (session->packAdd_channel) {
session->packAdd_channel->exit_status =
_libssh2_ntohu32(data + 9 + sizeof("exit-status"));
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Exit status %lu received for channel %lu/%lu",
session->packAdd_channel->exit_status,
session->packAdd_channel->local.id,
session->packAdd_channel->remote.id);
}
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"Close received for channel %lu/%lu",
session->packAdd_channel->local.id,
session->packAdd_channel->remote.id);
session->packAdd_channel->remote.close = 1;
session->packAdd_channel->remote.eof = 1;
/* TODO: Add a callback for this */
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
if (want_reply) {
libssh2_packet_add_jump_point4:
session->packAdd_state = libssh2_NB_state_jump4;
data[0] = SSH_MSG_CHANNEL_FAILURE;
rc = _libssh2_transport_write(session, data, 5);
if (rc == PACKET_EAGAIN)
return rc;
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
break;
}
case SSH_MSG_CHANNEL_CLOSE:
session->packAdd_channel =
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1));
if (!session->packAdd_channel) {
/* We may have freed already, just quietly ignore this... */
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Close received for channel %lu/%lu",
session->packAdd_channel->local.id,
session->packAdd_channel->remote.id);
session->packAdd_channel->remote.close = 1;
session->packAdd_channel->remote.eof = 1;
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
case SSH_MSG_CHANNEL_OPEN:
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip") - 1) == _libssh2_ntohu32(data + 1))
&&
(memcmp
(data + 5, "forwarded-tcpip",
sizeof("forwarded-tcpip") - 1) == 0)) {
(memcmp(data + 5, "forwarded-tcpip",
sizeof("forwarded-tcpip") - 1) == 0)) {
libssh2_packet_add_jump_point2:
session->packAdd_state = libssh2_NB_state_jump2;
rc = packet_queue_listener(session, data, datalen,
&session->packAdd_Qlstn_state);
if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
if (rc == PACKET_EAGAIN)
return rc;
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
@@ -839,11 +852,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
session->packAdd_state = libssh2_NB_state_jump3;
rc = packet_x11_open(session, data, datalen,
&session->packAdd_x11open_state);
if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
if (rc == PACKET_EAGAIN)
return rc;
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
@@ -861,7 +871,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
if (session->packAdd_channel && bytestoadd) {
session->packAdd_channel->local.window_size += bytestoadd;
}
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Window adjust received for channel %lu/%lu, adding %lu bytes, new window_size=%lu",
session->packAdd_channel->local.id,
session->packAdd_channel->remote.id,
@@ -879,33 +889,23 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
}
if (session->packAdd_state == libssh2_NB_state_sent) {
session->packAdd_packet =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!session->packAdd_packet) {
LIBSSH2_PACKET *packAdd_packet;
packAdd_packet =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!packAdd_packet) {
_libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for LIBSSH2_PACKET");
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return -1;
}
memset(session->packAdd_packet, 0, sizeof(LIBSSH2_PACKET));
memset(packAdd_packet, 0, sizeof(LIBSSH2_PACKET));
session->packAdd_packet->data = data;
session->packAdd_packet->data_len = datalen;
session->packAdd_packet->data_head = session->packAdd_data_head;
session->packAdd_packet->mac = macstate;
session->packAdd_packet->brigade = &session->packets;
session->packAdd_packet->next = NULL;
packAdd_packet->data = data;
packAdd_packet->data_len = datalen;
packAdd_packet->data_head = session->packAdd_data_head;
packAdd_packet->mac = macstate;
if (session->packets.tail) {
session->packAdd_packet->prev = session->packets.tail;
session->packAdd_packet->prev->next = session->packAdd_packet;
session->packets.tail = session->packAdd_packet;
} else {
session->packets.head = session->packAdd_packet;
session->packets.tail = session->packAdd_packet;
session->packAdd_packet->prev = NULL;
}
_libssh2_list_add(&session->packets, &packAdd_packet->node);
session->packAdd_state = libssh2_NB_state_sent1;
}
@@ -919,7 +919,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
* Well, it's already in the brigade,
* let's just call back into ourselves
*/
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Renegotiating Keys");
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Renegotiating Keys");
session->packAdd_state = libssh2_NB_state_sent2;
}
@@ -948,7 +948,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
*/
rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
}
@@ -968,9 +968,9 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned long match_ofs, const unsigned char *match_buf,
unsigned long match_len)
{
LIBSSH2_PACKET *packet = session->packets.head;
LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Looking for packet of type: %d", (int) packet_type);
while (packet) {
@@ -982,24 +982,14 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
*data = packet->data;
*data_len = packet->data_len;
/* unlink struct */
if (packet->prev) {
packet->prev->next = packet->next;
} else {
session->packets.head = packet->next;
}
if (packet->next) {
packet->next->prev = packet->prev;
} else {
session->packets.tail = packet->prev;
}
/* unlink struct from session->packets */
_libssh2_list_remove(&packet->node);
LIBSSH2_FREE(session, packet);
return 0;
}
packet = packet->next;
packet = _libssh2_list_next(&packet->node);
}
return -1;
}
@@ -1060,13 +1050,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
}
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
libssh2pack_t ret = _libssh2_transport_read(session);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (ret == 0) {
/* There is no data, return that. TODO: is this really correct? */
return PACKET_EAGAIN;
} else if (ret < 0) {
int ret = _libssh2_transport_read(session);
if (ret == PACKET_EAGAIN)
return ret;
else if (ret < 0) {
state->start = 0;
/* an error which is not just because of blocking */
return ret;
@@ -1084,11 +1071,12 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
state->start = 0;
return PACKET_TIMEOUT;
}
return -1; /* no packet available yet */
}
}
/* Only reached if the socket died */
return -1;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
/*
@@ -1121,14 +1109,15 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
return i;
}
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Blocking until packet becomes available to burn");
*state = libssh2_NB_state_created;
}
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
if ((ret = _libssh2_transport_read(session)) == PACKET_EAGAIN) {
return PACKET_EAGAIN;
ret = _libssh2_transport_read(session);
if (ret == PACKET_EAGAIN) {
return ret;
} else if (ret < 0) {
*state = libssh2_NB_state_idle;
return ret;
@@ -1148,7 +1137,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
}
/* Only reached if the socket died */
return -1;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
/*
@@ -1194,7 +1183,7 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
return PACKET_TIMEOUT;
}
else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
}
}
@@ -1208,6 +1197,6 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
/* Only reached if the socket died */
state->start = 0;
return -1;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}

View File

@@ -38,6 +38,8 @@
#include "libssh2_priv.h"
#ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */
static int
readline(char *line, int line_size, FILE * fp)
{
@@ -207,3 +209,5 @@ _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
return 0;
}
#endif /* LIBSSH2_LIBGCRYPT */

View File

@@ -37,6 +37,7 @@
#include "libssh2_priv.h"
#include "libssh2_publickey.h"
#include "channel.h"
#define LIBSSH2_PUBLICKEY_VERSION 2
@@ -168,9 +169,9 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
int rc;
if (pkey->receive_state == libssh2_NB_state_idle) {
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc != 4) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid response from publickey subsystem", 0);
@@ -190,10 +191,10 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
}
if (pkey->receive_state == libssh2_NB_state_sent) {
rc = libssh2_channel_read_ex(channel, 0, (char *) pkey->receive_packet,
pkey->receive_packet_len);
rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet,
pkey->receive_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc != (int)pkey->receive_packet_len) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for publickey subsystem response packet",
@@ -265,7 +266,7 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
while (1) {
rc = publickey_packet_receive(pkey, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from publickey subsystem",
@@ -352,7 +353,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
session->pkeyInit_pkey = NULL;
session->pkeyInit_channel = NULL;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Initializing publickey subsystem");
session->pkeyInit_state = libssh2_NB_state_allocated;
@@ -433,7 +434,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
_libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION);
s += 4;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Sending publickey version packet advertising version %d support",
(int) LIBSSH2_PUBLICKEY_VERSION);
@@ -441,8 +442,8 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
}
if (session->pkeyInit_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_write_ex(session->pkeyInit_channel, 0,
(char *) buffer, (s - buffer));
rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
(char *) buffer, (s - buffer));
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending publickey version packet", 0);
@@ -518,13 +519,13 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
session->pkeyInit_pkey->version = _libssh2_ntohu32(s);
if (session->pkeyInit_pkey->version >
LIBSSH2_PUBLICKEY_VERSION) {
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Truncating remote publickey version from %lu",
session->pkeyInit_pkey->version);
session->pkeyInit_pkey->version =
LIBSSH2_PUBLICKEY_VERSION;
}
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Enabling publickey subsystem version %lu",
session->pkeyInit_pkey->version);
LIBSSH2_FREE(session, session->pkeyInit_data);
@@ -589,7 +590,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
if (pkey->add_state == libssh2_NB_state_idle) {
pkey->add_packet = NULL;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Adding %s publickey",
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, "Adding %s publickey",
name);
if (pkey->version == 1) {
@@ -670,7 +671,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
}
}
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Sending publickey \"add\" packet: type=%s blob_len=%ld num_attrs=%ld",
name, blob_len, num_attrs);
@@ -678,10 +679,10 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
}
if (pkey->add_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->add_packet,
(pkey->add_s - pkey->add_packet));
rc = _libssh2_channel_write(channel, 0, (char *) pkey->add_packet,
(pkey->add_s - pkey->add_packet));
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if ((pkey->add_s - pkey->add_packet) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey add packet", 0);
@@ -697,7 +698,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
rc = publickey_response_success(pkey);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
pkey->add_state = libssh2_NB_state_idle;
@@ -746,7 +747,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
memcpy(pkey->remove_s, blob, blob_len);
pkey->remove_s += blob_len;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Sending publickey \"remove\" packet: type=%s blob_len=%ld",
name, blob_len);
@@ -754,10 +755,10 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
}
if (pkey->remove_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->remove_packet,
(pkey->remove_s - pkey->remove_packet));
rc = _libssh2_channel_write(channel, 0, (char *) pkey->remove_packet,
(pkey->remove_s - pkey->remove_packet));
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if ((pkey->remove_s - pkey->remove_packet) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey remove packet", 0);
@@ -774,7 +775,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
rc = publickey_response_success(pkey);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
pkey->remove_state = libssh2_NB_state_idle;
@@ -808,19 +809,19 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
memcpy(pkey->listFetch_s, "list", sizeof("list") - 1);
pkey->listFetch_s += sizeof("list") - 1;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Sending publickey \"list\" packet");
pkey->listFetch_state = libssh2_NB_state_created;
}
if (pkey->listFetch_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0,
(char *) pkey->listFetch_buffer,
(pkey->listFetch_s -
pkey->listFetch_buffer));
rc = _libssh2_channel_write(channel, 0,
(char *) pkey->listFetch_buffer,
(pkey->listFetch_s -
pkey->listFetch_buffer));
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey list packet", 0);
@@ -835,7 +836,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
rc = publickey_packet_receive(pkey, &pkey->listFetch_data,
&pkey->listFetch_data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from publickey subsystem",
@@ -1040,6 +1041,7 @@ LIBSSH2_API int
libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
{
LIBSSH2_SESSION *session = pkey->channel->session;
int rc;
/*
* Make sure all memory used in the state variables are free
@@ -1061,9 +1063,9 @@ libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
pkey->listFetch_data = NULL;
}
if (libssh2_channel_free(pkey->channel) == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
rc = libssh2_channel_free(pkey->channel);
if (rc == PACKET_EAGAIN)
return rc;
LIBSSH2_FREE(session, pkey);
return 0;

130
src/scp.c
View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -39,6 +40,8 @@
#include <errno.h>
#include <stdlib.h>
#include "channel.h"
/* Max. length of a quoted string after libssh2_shell_quotearg() processing */
#define libssh2_shell_quotedsize(s) (3 * strlen(s) + 2)
@@ -258,13 +261,13 @@ libssh2_shell_quotearg(const char *path, unsigned char *buf,
}
/*
* libssh2_scp_recv
* scp_recv
*
* Open a channel and request a remote file via SCP
*
*/
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
static LIBSSH2_CHANNEL *
scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
{
int cmd_len;
int rc;
@@ -298,7 +301,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
session->scpRecv_command_len - cmd_len);
_libssh2_debug(session, LIBSSH2_DBG_SCP,
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"Opening channel for SCP receive");
session->scpRecv_state = libssh2_NB_state_created;
@@ -347,7 +350,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
LIBSSH2_FREE(session, session->scpRecv_command);
session->scpRecv_command = NULL;
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sending initial wakeup");
_libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sending initial wakeup");
/* SCP ACK */
session->scpRecv_response[0] = '\0';
@@ -355,8 +358,8 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
}
if (session->scpRecv_state == libssh2_NB_state_sent1) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
(char *) session->scpRecv_response, 1);
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->scpRecv_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending initial wakeup", 0);
@@ -378,10 +381,10 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
unsigned char *s, *p;
if (session->scpRecv_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response", 0);
@@ -415,9 +418,9 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
session->scpRecv_err_len + 1);
/* Read the remote error message */
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
session->scpRecv_err_msg,
session->scpRecv_err_len);
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
session->scpRecv_err_msg,
session->scpRecv_err_len);
if (rc <= 0) {
/*
* Since we have alread started reading this packet,
@@ -555,9 +558,9 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
}
if (session->scpRecv_state == libssh2_NB_state_sent3) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting to send SCP ACK", 0);
@@ -566,7 +569,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
goto scp_recv_error;
}
_libssh2_debug(session, LIBSSH2_DBG_SCP,
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"mtime = %ld, atime = %ld",
session->scpRecv_mtime, session->scpRecv_atime);
@@ -591,10 +594,10 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
char *s, *p, *e = NULL;
if (session->scpRecv_state == libssh2_NB_state_sent5) {
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response", 0);
@@ -718,9 +721,9 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
}
if (session->scpRecv_state == libssh2_NB_state_sent6) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending SCP ACK", 0);
@@ -728,7 +731,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
} else if (rc != 1) {
goto scp_recv_error;
}
_libssh2_debug(session, LIBSSH2_DBG_SCP,
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"mode = 0%lo size = %ld", session->scpRecv_mode,
session->scpRecv_size);
@@ -761,14 +764,28 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
}
/*
* libssh2_scp_send_ex
* libssh2_scp_recv
*
* Open a channel and request a remote file via SCP
*
*/
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb)
{
LIBSSH2_CHANNEL *ptr;
BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb));
return ptr;
}
/*
* scp_send()
*
* Send a file using SCP
*
*/
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
size_t size, long mtime, long atime)
static LIBSSH2_CHANNEL *
scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
size_t size, long mtime, long atime)
{
int cmd_len;
unsigned const char *base;
@@ -799,7 +816,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_command[session->scpSend_command_len - 1] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_SCP,
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"Opening channel for SCP send");
/* Allocate a channel */
@@ -857,8 +874,8 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
if (session->scpSend_state == libssh2_NB_state_sent1) {
/* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from remote", 0);
@@ -875,7 +892,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
snprintf((char *) session->scpSend_response,
LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime,
atime);
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
_libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
session->scpSend_response);
}
@@ -885,9 +902,9 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
/* Send mtime and atime to be used for file */
if (mtime || atime) {
if (session->scpSend_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len);
rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending time data for SCP file", 0);
@@ -903,9 +920,8 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
if (session->scpSend_state == libssh2_NB_state_sent3) {
/* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response,
1);
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response", 0);
@@ -937,16 +953,16 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
snprintf((char *) session->scpSend_response,
LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode,
(unsigned long) size, base);
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
_libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
session->scpSend_response);
session->scpSend_state = libssh2_NB_state_sent5;
}
if (session->scpSend_state == libssh2_NB_state_sent5) {
rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len);
rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block send core file data for SCP file", 0);
@@ -962,8 +978,8 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
if (session->scpSend_state == libssh2_NB_state_sent6) {
/* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response", 0);
@@ -990,9 +1006,9 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
/* Read the remote error message */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
session->scpSend_err_msg,
session->scpSend_err_len);
rc = _libssh2_channel_read(session->scpSend_channel, 0,
session->scpSend_err_msg,
session->scpSend_err_len);
if (rc <= 0) {
/*
* Since we have alread started reading this packet, it is
@@ -1021,3 +1037,17 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
return NULL;
}
/*
* libssh2_scp_send_ex
*
* Send a file using SCP
*/
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode,
size_t size, long mtime, long atime)
{
LIBSSH2_CHANNEL *ptr;
BLOCK_ADJUST_ERRNO(ptr, session,
scp_send(session, path, mode, size, mtime, atime));
return ptr;
}

View File

@@ -106,8 +106,17 @@ banner_receive(LIBSSH2_SESSION * session)
|| (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
char c = '\0';
/* no incoming block yet! */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
ret = _libssh2_recv(session->socket_fd, &c, 1,
LIBSSH2_SOCKET_RECV_FLAGS(session));
if (ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error recving %d bytes to %p: %d", 1, &c, errno);
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Recved %d bytes to %p", ret, &c);
if (ret < 0) {
if (errno == EAGAIN) {
@@ -159,7 +168,7 @@ banner_receive(LIBSSH2_SESSION * session)
}
memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
session->remote.banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Received Banner: %s",
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
session->remote.banner);
return 0;
}
@@ -200,17 +209,29 @@ banner_send(LIBSSH2_SESSION * session)
banner[255] = '\0';
}
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending Banner: %s",
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s",
banner_dup);
#endif
session->banner_TxRx_state = libssh2_NB_state_created;
}
/* no outgoing block yet! */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
ret = _libssh2_send(session->socket_fd,
banner + session->banner_TxRx_total_send,
banner_len - session->banner_TxRx_total_send,
LIBSSH2_SOCKET_SEND_FLAGS(session));
if (ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d",
banner_len - session->banner_TxRx_total_send, errno);
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Sent %d/%d bytes at %p+%d", ret,
banner_len - session->banner_TxRx_total_send,
banner, session->banner_TxRx_total_send);
if (ret != (banner_len - session->banner_TxRx_total_send)) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
@@ -238,7 +259,7 @@ banner_send(LIBSSH2_SESSION * session)
* is copied from the libcurl sources with permission.
*/
static int
session_nonblock(int sockfd, /* operate on this */
session_nonblock(libssh2_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */ )
{
#undef SETBLOCK
@@ -389,7 +410,7 @@ libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
memcpy(session->local.banner, banner, banner_len);
session->local.banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting local Banner: %s",
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s",
session->local.banner);
session->local.banner[banner_len++] = '\r';
session->local.banner[banner_len++] = '\n';
@@ -435,7 +456,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
session->realloc = local_realloc;
session->abstract = abstract;
session->api_block_mode = 1; /* blocking API by default */
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"New session resource allocated");
libssh2_crypto_init();
}
@@ -484,7 +505,7 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session,
return oldcb;
}
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting Callback %d", cbtype);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype);
return NULL;
}
@@ -529,15 +550,14 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session)
}
static int
session_startup(LIBSSH2_SESSION *session, int sock)
session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
{
int rc;
if (session->startup_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"session_startup for socket %d", sock);
/* FIXME: on some platforms (like win32) sockets are unsigned */
if (sock < 0) {
if (INVALID_SOCKET == sock) {
/* Did we forget something? */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE,
"Bad socket provided", 0);
@@ -556,35 +576,22 @@ session_startup(LIBSSH2_SESSION *session, int sock)
session->startup_state = libssh2_NB_state_created;
}
/* TODO: Liveness check */
if (session->startup_state == libssh2_NB_state_created) {
rc = banner_send(session);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending banner to remote host", 0);
return LIBSSH2_ERROR_EAGAIN;
} else if (rc) {
/* Unable to send banner? */
libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND,
"Error sending banner to remote host", 0);
return LIBSSH2_ERROR_BANNER_SEND;
if (rc) {
libssh2_error(session, rc,
"Failed sending banner", 0);
return rc;
}
session->startup_state = libssh2_NB_state_sent;
}
if (session->startup_state == libssh2_NB_state_sent) {
rc = banner_receive(session);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for banner", 0);
return LIBSSH2_ERROR_EAGAIN;
} else if (rc) {
/* Unable to receive banner from remote */
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE,
"Timeout waiting for banner", 0);
return LIBSSH2_ERROR_BANNER_NONE;
if (rc) {
libssh2_error(session, rc,
"Failed getting banner", 0);
return rc;
}
session->startup_state = libssh2_NB_state_sent1;
@@ -592,21 +599,17 @@ session_startup(LIBSSH2_SESSION *session, int sock)
if (session->startup_state == libssh2_NB_state_sent1) {
rc = libssh2_kex_exchange(session, 0, &session->startup_key_state);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block exchanging encryption keys", 0);
return LIBSSH2_ERROR_EAGAIN;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
if (rc) {
libssh2_error(session, rc,
"Unable to exchange encryption keys", 0);
return LIBSSH2_ERROR_KEX_FAILURE;
return rc;
}
session->startup_state = libssh2_NB_state_sent2;
}
if (session->startup_state == libssh2_NB_state_sent2) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Requesting userauth service");
/* Request the userauth service */
@@ -622,15 +625,10 @@ session_startup(LIBSSH2_SESSION *session, int sock)
if (session->startup_state == libssh2_NB_state_sent3) {
rc = _libssh2_transport_write(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block asking for ssh-userauth service", 0);
return LIBSSH2_ERROR_EAGAIN;
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
if (rc) {
libssh2_error(session, rc,
"Unable to ask for ssh-userauth service", 0);
return LIBSSH2_ERROR_SOCKET_SEND;
return rc;
}
session->startup_state = libssh2_NB_state_sent4;
@@ -641,11 +639,9 @@ session_startup(LIBSSH2_SESSION *session, int sock)
&session->startup_data,
&session->startup_data_len, 0, NULL, 0,
&session->startup_req_state);
if (rc == PACKET_EAGAIN) {
return LIBSSH2_ERROR_EAGAIN;
} else if (rc) {
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
if (rc)
return rc;
session->startup_service_length =
_libssh2_ntohu32(session->startup_data + 1);
@@ -699,22 +695,27 @@ static int
session_free(LIBSSH2_SESSION *session)
{
int rc;
LIBSSH2_PACKET *pkg;
LIBSSH2_CHANNEL *ch;
LIBSSH2_LISTENER *l;
if (session->free_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource",
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource",
session->remote.banner);
session->state = libssh2_NB_state_created;
}
if (session->free_state == libssh2_NB_state_created) {
while (session->channels.head) {
LIBSSH2_CHANNEL *tmp = session->channels.head;
while ((ch = _libssh2_list_first(&session->channels))) {
rc = libssh2_channel_free(session->channels.head);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
rc = libssh2_channel_free(ch);
if (rc == PACKET_EAGAIN)
return rc;
#if 0
/* Daniel's note: I'm leaving this code here right now since it
looks so weird I'm stumped. Why would libssh2_channel_free()
fail and forces this to be done? */
if (tmp == session->channels.head) {
/* channel_free couldn't do it's job, perform a messy cleanup */
tmp = session->channels.head;
@@ -728,17 +729,17 @@ session_free(LIBSSH2_SESSION *session)
/* reverse linking isn't important here, we're killing the
* structure */
}
#endif
}
session->state = libssh2_NB_state_sent;
}
if (session->state == libssh2_NB_state_sent) {
while (session->listeners) {
rc = libssh2_channel_forward_cancel(session->listeners);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
while ((l = _libssh2_list_first(&session->listeners))) {
rc = libssh2_channel_forward_cancel(l);
if (rc == PACKET_EAGAIN)
return rc;
}
session->state = libssh2_NB_state_sent1;
@@ -908,16 +909,14 @@ session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, session->err_msg);
}
/* Cleanup any remaining packets */
while (session->packets.head) {
LIBSSH2_PACKET *tmp = session->packets.head;
/* unlink */
session->packets.head = tmp->next;
/* Cleanup all remaining packets */
while ((pkg = _libssh2_list_first(&session->packets))) {
/* unlink the node */
_libssh2_list_remove(&pkg->node);
/* free */
LIBSSH2_FREE(session, tmp->data);
LIBSSH2_FREE(session, tmp);
LIBSSH2_FREE(session, pkg->data);
LIBSSH2_FREE(session, pkg);
}
if(session->socket_prev_blockstate)
@@ -961,7 +960,7 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
int rc;
if (session->disconnect_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Disconnecting: reason=%d, desc=%s, lang=%s", reason,
description, lang);
if (description) {
@@ -1007,7 +1006,7 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
rc = _libssh2_transport_write(session, session->disconnect_data,
session->disconnect_data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
LIBSSH2_FREE(session, session->disconnect_data);
@@ -1207,7 +1206,7 @@ int
_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
{
int bl = session->api_block_mode;
_libssh2_debug(session, LIBSSH2_DBG_CONN,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Setting blocking mode %s", blocking?"ON":"OFF");
session->api_block_mode = blocking;
@@ -1245,7 +1244,7 @@ LIBSSH2_API int
libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
{
LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head;
LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
while (packet) {
if ( channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
@@ -1259,7 +1258,7 @@ libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
}
/* else - no data of any type is ready to be read */
}
packet = packet->next;
packet = _libssh2_list_next(&packet->node);
}
return 0;
@@ -1285,7 +1284,7 @@ poll_channel_write(LIBSSH2_CHANNEL * channel)
static inline int
poll_listener_queued(LIBSSH2_LISTENER * listener)
{
return listener->queue ? 1 : 0;
return _libssh2_list_first(&listener->queue) ? 1 : 0;
}
/*
@@ -1346,7 +1345,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
}
#elif defined(HAVE_SELECT)
LIBSSH2_SESSION *session = NULL;
int maxfd = 0;
libssh2_socket_t maxfd = 0;
fd_set rfds, wfds;
struct timeval tv;
@@ -1456,8 +1455,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
/* No connections known of yet */
fds[i].revents |=
poll_listener_queued(fds[i].fd.
listener) ?
poll_listener_queued(fds[i].fd. listener) ?
LIBSSH2_POLLFD_POLLIN : 0;
}
if (fds[i].fd.listener->session->socket_state ==

View File

@@ -118,28 +118,21 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d (len %d)",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet %d (len %d)",
(int) data[0], data_len);
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate datablock for SFTP packet", 0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
memset(packet, 0, sizeof(LIBSSH2_PACKET));
packet->data = data;
packet->data_len = data_len;
packet->data_head = 5;
packet->brigade = &sftp->packets;
packet->next = NULL;
packet->prev = sftp->packets.tail;
if (packet->prev) {
packet->prev->next = packet;
} else {
sftp->packets.head = packet;
}
sftp->packets.tail = packet;
_libssh2_list_add(&sftp->packets, &packet->node);
return 0;
}
@@ -160,7 +153,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
ssize_t bytes_received;
int rc;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "recv packet");
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "recv packet");
/* If there was a previous partial, start using it */
if (sftp->partial_packet) {
@@ -170,37 +163,37 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
packet_received = sftp->partial_received;
sftp->partial_packet = NULL;
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"partial read cont, len: %lu", packet_len);
}
else {
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
else if (4 != rc) {
/* TODO: this is stupid since we can in fact get 1-3 bytes in a
legitimate working case as well if the connection happens to be
super slow or something */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for FXP packet", 0);
return -1;
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Read part of packet", 0);
return LIBSSH2_ERROR_CHANNEL_FAILURE;
}
packet_len = _libssh2_ntohu32(buffer);
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Data begin - Packet Length: %lu", packet_len);
if (packet_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
"SFTP packet too large", 0);
return -1;
return LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED;
}
packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate SFTP packet", 0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
packet_received = 0;
@@ -209,9 +202,9 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
/* Read as much of the packet as we can */
while (packet_len > packet_received) {
bytes_received =
libssh2_channel_read_ex(channel, 0,
(char *) packet + packet_received,
packet_len - packet_received);
_libssh2_channel_read(channel, 0,
(char *) packet + packet_received,
packet_len - packet_received);
if (bytes_received == PACKET_EAGAIN) {
/*
@@ -223,20 +216,21 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
sftp->partial_received = packet_received;
packet = NULL;
return PACKET_EAGAIN;
return bytes_received;
}
else if (bytes_received < 0) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Receive error waiting for SFTP packet", 0);
LIBSSH2_FREE(session, packet);
return -1;
return bytes_received;
}
packet_received += bytes_received;
}
if (sftp_packet_add(sftp, packet, packet_len)) {
rc = sftp_packet_add(sftp, packet, packet_len);
if (rc) {
LIBSSH2_FREE(session, packet);
return -1;
return rc;
}
return packet[0];
@@ -253,11 +247,11 @@ sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
unsigned long *data_len)
{
LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet = sftp->packets.head;
LIBSSH2_PACKET *packet = _libssh2_list_first(&sftp->packets);
unsigned char match_buf[5];
int match_len;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Asking for %d packet",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Asking for %d packet",
(int) packet_type);
match_buf[0] = packet_type;
@@ -277,24 +271,13 @@ sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
*data_len = packet->data_len;
/* unlink and free this struct */
if (packet->prev) {
packet->prev->next = packet->next;
} else {
sftp->packets.head = packet->next;
}
if (packet->next) {
packet->next->prev = packet->prev;
} else {
sftp->packets.tail = packet->prev;
}
_libssh2_list_remove(&packet->node);
LIBSSH2_FREE(session, packet);
return 0;
}
/* check next struct in the list */
packet = packet->next;
packet = _libssh2_list_next(&packet->node);
}
return -1;
}
@@ -310,12 +293,12 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
LIBSSH2_SESSION *session = sftp->channel->session;
int ret;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring packet %d id %ld",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld",
(int) packet_type, request_id);
if (sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) {
/* The right packet was available in the packet brigade */
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Got %d",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
(int) packet_type);
return 0;
}
@@ -323,7 +306,7 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
ret = sftp_packet_read(sftp);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
} else if (ret <= 0) {
return -1;
}
@@ -331,14 +314,14 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
/* data was read, check the queue again */
if (!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) {
/* The right packet was available in the packet brigade */
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Got %d",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
(int) packet_type);
return 0;
}
}
/* Only reached if the socket died */
return -1;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
/* sftp_packet_requirev
@@ -385,7 +368,7 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
return PACKET_TIMEOUT;
}
else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
}
}
}
@@ -547,7 +530,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
LIBSSH2_SFTP *sftp_handle;
if (session->sftpInit_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Initializing SFTP subsystem");
/*
@@ -556,8 +539,8 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
* as the SFTP session is created they are cleared and can thus be
* re-used again to allow any amount of SFTP handles per sessions.
*
* Note that you MUST NOT try to call libssh2_sftp_init() to get
* another handle until the previous one has finished and either
* Note that you MUST NOT try to call libssh2_sftp_init() again to get
* another handle until the previous call has finished and either
* succesffully made a handle or failed and returned error (not
* including *EAGAIN).
*/
@@ -633,7 +616,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_buffer[4] = SSH_FXP_INIT;
_libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION);
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Sending FXP_INIT packet advertising version %d support",
(int) LIBSSH2_SFTP_VERSION);
@@ -678,12 +661,12 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
sftp_handle->version = _libssh2_ntohu32(s);
s += 4;
if (sftp_handle->version > LIBSSH2_SFTP_VERSION) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Truncating remote SFTP version from %lu",
sftp_handle->version);
sftp_handle->version = LIBSSH2_SFTP_VERSION;
}
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Enabling SFTP version %lu compatability",
sftp_handle->version);
while (s < (data + data_len)) {
@@ -715,6 +698,8 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_sftp = NULL;
session->sftpInit_channel = NULL;
_libssh2_list_init(&sftp_handle->sftp_handles);
return sftp_handle;
sftp_init_error:
@@ -798,6 +783,9 @@ sftp_shutdown(LIBSSH2_SFTP *sftp)
sftp->symlink_packet = NULL;
}
/* TODO: We should consider walking over the sftp_handles list and kill
* any remaining sftp handles ... */
rc = _libssh2_channel_free(sftp->channel);
return rc;
@@ -810,8 +798,7 @@ LIBSSH2_API int
libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp)
{
int rc;
BLOCK_ADJUST(rc, sftp->channel->session,
sftp_shutdown(sftp));
BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp));
return rc;
}
@@ -877,7 +864,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
s += sftp_attr2bin(s, &attrs);
}
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Sending %s open request",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Sending %s open request",
(open_type ==
LIBSSH2_SFTP_OPENFILE) ? "file" : "directory");
@@ -920,7 +907,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
return NULL;
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
libssh2_error(session, rc,
"Timeout waiting for status message", 0);
sftp->open_state = libssh2_NB_state_idle;
return NULL;
@@ -938,7 +925,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
sftp->last_errno = _libssh2_ntohu32(data + 5);
if(LIBSSH2_FX_OK == sftp->last_errno) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got HANDLE FXOK!");
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got HANDLE FXOK!");
/* silly situation, but check for a HANDLE */
rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
@@ -956,7 +943,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
if(badness) {
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Failed opening remote file", 0);
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got FXP_STATUS %d",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got FXP_STATUS %d",
sftp->last_errno);
LIBSSH2_FREE(session, data);
return NULL;
@@ -985,16 +972,14 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
memcpy(fp->handle, data + 9, fp->handle_len);
LIBSSH2_FREE(session, data);
/* Link the file and the sftp session together */
fp->next = sftp->handles;
if (fp->next) {
fp->next->prev = fp;
}
fp->sftp = sftp;
/* add this file handle to the list kept in the sftp session */
_libssh2_list_add(&sftp->sftp_handles, &fp->node);
fp->sftp = sftp; /* point to the parent struct */
fp->u.file.offset = 0;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Open command successful");
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Open command successful");
return fp;
}
@@ -1034,7 +1019,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
int retcode;
if (sftp->read_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Reading %lu bytes from SFTP handle",
(unsigned long) buffer_maxlen);
packet = handle->request_packet;
@@ -1072,7 +1057,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 13;
}
#ifdef LIBSSH2_DEBUG_SFTP
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Requesting %lu bytes from SFTP handle",
(unsigned long) bytes_requested);
#endif
@@ -1106,7 +1091,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
sftp->read_packet = packet;
sftp->read_request_id = request_id;
sftp->read_total_read = total_read;
return PACKET_EAGAIN;
return retcode;
} else if (packet_len != retcode) {
/* TODO: a partial write is not a critical error when in
non-blocking mode! */
@@ -1127,9 +1112,11 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
sftp_packet_requirev(sftp, 2, read_responses,
request_id, &data, &data_len);
if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN;
libssh2_error(session, retcode,
"Would block waiting for status message", 0);
return retcode;
} else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
libssh2_error(session, retcode,
"Timeout waiting for status message", 0);
sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle;
@@ -1166,7 +1153,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
return -1;
}
#ifdef LIBSSH2_DEBUG_SFTP
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu bytes returned",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu bytes returned",
(unsigned long) bytes_read);
#endif
memcpy(buffer + total_read, data + 9, bytes_read);
@@ -1270,7 +1257,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
LIBSSH2_FREE(session, handle->u.dir.names_packet);
}
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"libssh2_sftp_readdir_ex() return %d",
filename_len);
return filename_len;
@@ -1301,13 +1288,13 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
}
if (sftp->readdir_state == libssh2_NB_state_created) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Reading entries from directory handle");
retcode = _libssh2_channel_write(channel, 0,
(char *) sftp->readdir_packet,
packet_len);
if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return retcode;
}
else if (packet_len != retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -1329,7 +1316,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
sftp->readdir_request_id, &data,
&data_len);
if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return retcode;
} else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
@@ -1353,7 +1340,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
}
num_names = _libssh2_ntohu32(data + 5);
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu entries returned",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned",
num_names);
if (num_names <= 0) {
LIBSSH2_FREE(session, data);
@@ -1418,7 +1405,8 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
/*
* sftp_write
*
* Write data to an SFTP handle
* Write data to an SFTP handle. Returns the number of bytes written, or
* a negative error code.
*/
static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
size_t count)
@@ -1443,13 +1431,13 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
packet_len = handle->handle_len + count + 25;
if (sftp->write_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Writing %lu bytes",
(unsigned long) count);
s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
if (!sftp->write_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_WRITE", 0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
_libssh2_htonu32(s, packet_len - 4);
s += 4;
@@ -1474,17 +1462,13 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
if (sftp->write_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, (char *)sftp->write_packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
else if(rc < 0) {
/* an actual error */
if(rc < 0) {
/* error */
return rc;
}
else if(0 == rc) {
/* an actual error */
fprintf(stderr, "WEIRDNESS\n");
return -1;
/* nothing sent is an error */
return LIBSSH2_ERROR_SOCKET_SEND;
}
else if (packet_len != rc) {
return rc;
@@ -1497,12 +1481,13 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->write_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
return rc;
}
else if (rc) {
libssh2_error(session, rc,
"Timeout waiting for status message", 0);
sftp->write_state = libssh2_NB_state_idle;
return -1;
return rc;
}
sftp->write_state = libssh2_NB_state_idle;
@@ -1518,7 +1503,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
0);
sftp->last_errno = retcode;
return -1;
return LIBSSH2_ERROR_SFTP_PROTOCOL;
}
/* libssh2_sftp_write
@@ -1556,7 +1541,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
int rc;
if (sftp->fstat_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Issuing %s command",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command",
setstat ? "set-stat" : "stat");
s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
if (!sftp->fstat_packet) {
@@ -1587,7 +1572,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->fstat_packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
(setstat ? "Unable to send FXP_FSETSTAT"
@@ -1607,7 +1592,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
sftp->fstat_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
@@ -1633,6 +1618,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
}
sftp_bin2attr(attrs, data + 5);
LIBSSH2_FREE(session, data);
return 0;
}
@@ -1707,7 +1693,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
int rc;
if (handle->close_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Closing handle");
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle");
s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
if (!handle->close_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
@@ -1733,7 +1719,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
rc = _libssh2_channel_write(channel, 0, (char *) handle->close_packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_CLOSE command", 0);
@@ -1753,7 +1739,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
handle->close_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
@@ -1775,12 +1761,8 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
return -1;
}
if (handle == sftp->handles) {
sftp->handles = handle->next;
}
if (handle->next) {
handle->next->prev = NULL;
}
/* remove this handle from the parent's list */
_libssh2_list_remove(&handle->node);
if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR)
&& handle->u.dir.names_left) {
@@ -1822,7 +1804,7 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
int rc;
if (sftp->unlink_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Unlinking %s", filename);
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename);
s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
if (!sftp->unlink_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
@@ -1849,7 +1831,7 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->unlink_packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_REMOVE command", 0);
@@ -1868,7 +1850,7 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
sftp->unlink_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
@@ -1934,7 +1916,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
}
if (sftp->rename_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Renaming %s to %s",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s",
source_filename, dest_filename);
sftp->rename_s = sftp->rename_packet =
LIBSSH2_ALLOC(session, packet_len);
@@ -1972,7 +1954,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->rename_packet,
sftp->rename_s - sftp->rename_packet);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_RENAME command", 0);
@@ -1991,7 +1973,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
sftp->rename_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
@@ -2070,7 +2052,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
int rc;
if (sftp->mkdir_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Creating directory %s with mode 0%lo", path, mode);
s = packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) {
@@ -2103,7 +2085,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) packet, packet_len);
if (rc == PACKET_EAGAIN) {
sftp->mkdir_packet = packet;
return PACKET_EAGAIN;
return rc;
}
if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -2120,7 +2102,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id,
&data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
@@ -2134,7 +2116,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
LIBSSH2_FREE(session, data);
if (retcode == LIBSSH2_FX_OK) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "OK!");
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!");
return 0;
} else {
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -2174,7 +2156,7 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
int rc;
if (sftp->rmdir_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Removing directory: %s",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s",
path);
s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
if (!sftp->rmdir_packet) {
@@ -2201,7 +2183,7 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->rmdir_packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_RMDIR command", 0);
@@ -2219,7 +2201,7 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
@@ -2276,7 +2258,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
int rc;
if (sftp->stat_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s",
(stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
(stat_type ==
LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
@@ -2320,7 +2302,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->stat_packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send STAT/LSTAT/SETSTAT command", 0);
@@ -2338,7 +2320,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_requirev(sftp, 2, stat_responses,
sftp->stat_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
@@ -2418,7 +2400,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
return -1;
}
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s on %s",
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s on %s",
(link_type ==
LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading",
(link_type ==
@@ -2460,7 +2442,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->symlink_packet,
packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send SYMLINK/READLINK command", 0);
@@ -2479,7 +2461,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
sftp->symlink_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,

View File

@@ -41,6 +41,7 @@
#include "libssh2_priv.h"
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <assert.h>
@@ -57,36 +58,58 @@ debugdump(LIBSSH2_SESSION * session,
{
size_t i;
size_t c;
FILE *stream = stderr;
unsigned int width = 0x10;
char buffer[256]; /* Must be enough for width*4 + about 30 or so */
size_t used;
static const char* hex_chars = "0123456789ABCDEF";
if (!(session->showmask & (1 << LIBSSH2_DBG_TRANS))) {
if (!(session->showmask & LIBSSH2_TRACE_TRANS)) {
/* not asked for, bail out */
return;
}
fprintf(stream, "=> %s (%d bytes)\n", desc, (int) size);
used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n",
desc, (int) size);
if (session->tracehandler)
(session->tracehandler)(session, session->tracehandler_context, buffer, used);
else
write(2 /* stderr */, buffer, used);
for(i = 0; i < size; i += width) {
fprintf(stream, "%04lx: ", (long)i);
used = snprintf(buffer, sizeof(buffer), "%04lx: ", (long)i);
/* hex not disabled, show it */
for(c = 0; c < width; c++) {
if (i + c < size)
fprintf(stream, "%02x ", ptr[i + c]);
else
fputs(" ", stream);
if (i + c < size) {
buffer[used++] = hex_chars[(ptr[i+c] >> 4) & 0xF];
buffer[used++] = hex_chars[ptr[i+c] & 0xF];
}
else {
buffer[used++] = ' ';
buffer[used++] = ' ';
}
buffer[used++] = ' ';
if ((width/2) - 1 == c)
buffer[used++] = ' ';
}
buffer[used++] = ':';
buffer[used++] = ' ';
for(c = 0; (c < width) && (i + c < size); c++) {
fprintf(stream, "%c",
(ptr[i + c] >= 0x20) &&
(ptr[i + c] < 0x80) ? ptr[i + c] : UNPRINTABLE_CHAR);
buffer[used++] = isprint(ptr[i + c]) ?
ptr[i + c] : UNPRINTABLE_CHAR;
}
fputc('\n', stream); /* newline */
buffer[used++] = '\n';
buffer[used] = 0;
if (session->tracehandler)
(session->tracehandler)(session, session->tracehandler_context, buffer, used);
else
write(2, buffer, used);
}
fflush(stream);
}
#else
#define debugdump(a,x,y,z)
@@ -95,10 +118,10 @@ debugdump(LIBSSH2_SESSION * session,
/* decrypt() decrypts 'len' bytes from 'source' to 'dest'.
*
* returns PACKET_NONE on success and PACKET_FAIL on failure
* returns 0 on success and negative on failure
*/
static libssh2pack_t
static int
decrypt(LIBSSH2_SESSION * session, unsigned char *source,
unsigned char *dest, int len)
{
@@ -134,7 +157,7 @@ decrypt(LIBSSH2_SESSION * session, unsigned char *source,
* fullpacket() gets called when a full packet has been received and properly
* collected.
*/
static libssh2pack_t
static int
fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
{
unsigned char macbuf[MAX_MACSIZE];
@@ -232,11 +255,8 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
rc = _libssh2_packet_add(session, p->payload,
session->fullpacket_payload_len,
session->fullpacket_macstate);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc < 0) {
return PACKET_FAIL;
}
if (rc)
return rc;
}
session->fullpacket_state = libssh2_NB_state_idle;
@@ -248,22 +268,21 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
/*
* _libssh2_transport_read
*
* Collect a packet into the input brigade block only controls whether or not
* to wait for a packet to start.
* Collect a packet into the input queue.
*
* Returns packet type added to input brigade (PACKET_NONE if nothing added),
* or PACKET_FAIL on failure and PACKET_EAGAIN if it couldn't process a full
* packet.
* Returns packet type added to input queue (0 if nothing added), or a
* negative error number.
*/
/*
* This function reads the binary stream as specified in chapter 6 of RFC4253
* "The Secure Shell (SSH) Transport Layer Protocol"
*
* DOES NOT call libssh2_error() for ANY error case.
*/
libssh2pack_t
_libssh2_transport_read(LIBSSH2_SESSION * session)
int _libssh2_transport_read(LIBSSH2_SESSION * session)
{
libssh2pack_t rc = -1;
int rc = LIBSSH2_ERROR_SOCKET_NONE;
struct transportpacket *p = &session->packet;
int remainbuf;
int remainpack;
@@ -272,7 +291,6 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
unsigned char block[MAX_BLOCKSIZE];
int blocksize;
int encrypted = 1;
int status;
/* default clear the bit */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
@@ -295,18 +313,11 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
/* Whoever wants a packet won't get anything until the key re-exchange
* is done!
*/
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the"
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
" key re-exchange");
status = libssh2_kex_exchange(session, 1, &session->startup_key_state);
if (status == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block exchanging encryption keys", 0);
return PACKET_EAGAIN;
} else if (status) {
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
"Unable to exchange encryption keys",0);
return LIBSSH2_ERROR_KEX_FAILURE;
}
rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
if (rc)
return rc;
}
/*
@@ -367,11 +378,20 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
_libssh2_recv(session->socket_fd, &p->buf[remainbuf],
PACKETBUFSIZE - remainbuf,
LIBSSH2_SOCKET_RECV_FLAGS(session));
if (nread < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error recving %d bytes to %p+%d: %d",
PACKETBUFSIZE - remainbuf, p->buf, remainbuf,
errno);
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Recved %d/%d bytes to %p+%d", nread,
PACKETBUFSIZE - remainbuf, p->buf, remainbuf);
if (nread <= 0) {
/* check if this is due to EAGAIN and return the special
return code if so, error out normally otherwise */
if ((nread < 0) && (errno == EAGAIN)) {
session->socket_block_directions =
session->socket_block_directions |=
LIBSSH2_SESSION_BLOCK_INBOUND;
return PACKET_EAGAIN;
}
@@ -400,6 +420,8 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
check is only done for the initial block since once we have
got the start of a block we can in fact deal with fractions
*/
session->socket_block_directions |=
LIBSSH2_SESSION_BLOCK_INBOUND;
return PACKET_EAGAIN;
}
@@ -570,7 +592,7 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
session->readPack_state = libssh2_NB_state_jump1;
}
return PACKET_EAGAIN;
return rc;
}
p->total_num = 0; /* no packet buffer available */
@@ -582,7 +604,7 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
return PACKET_FAIL; /* we never reach this point */
}
static libssh2pack_t
static int
send_existing(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len, ssize_t * ret)
{
@@ -612,6 +634,13 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
rc = _libssh2_send(session->socket_fd, &p->outbuf[p->osent], length,
LIBSSH2_SOCKET_SEND_FLAGS(session));
if (rc < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d", length, errno);
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Sent %d/%d bytes at %p+%d", rc, length, p->outbuf,
p->osent);
if(rc > 0) {
debugdump(session, "libssh2_transport_write send()",
@@ -630,13 +659,13 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
/* send failure! */
return PACKET_FAIL;
}
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
p->osent += rc; /* we sent away this much data */
return PACKET_NONE;
return rc < length ? PACKET_EAGAIN : PACKET_NONE;
}
/*
@@ -653,6 +682,8 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
* NOTE: this function does not verify that 'data_len' is less than ~35000
* which is what all implementations should support at least as packet size.
* (RFC4253 section 6.1)
*
* This function DOES not call libssh2_error() on any errors.
*/
int
_libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
@@ -673,21 +704,21 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
int encrypted;
int i;
ssize_t ret;
libssh2pack_t rc;
int rc;
unsigned char *orgdata = data;
unsigned long orgdata_len = data_len;
debugdump(session, "libssh2_transport_write plain", data, data_len);
/* default clear the bit */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
/* FIRST, check if we have a pending write to complete */
rc = send_existing(session, data, data_len, &ret);
if (rc || ret) {
return rc;
}
/* default clear the bit */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
/* check if we should compress */
@@ -784,6 +815,12 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
ret = _libssh2_send(session->socket_fd, p->outbuf, total_length,
LIBSSH2_SOCKET_SEND_FLAGS(session));
if (ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d", total_length, errno);
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p",
ret, total_length, p->outbuf);
if (ret != -1) {
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
@@ -791,7 +828,7 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
if (ret != total_length) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
/* the whole packet could not be sent, save the rest */
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
p->odata = orgdata;
p->olen = orgdata_len;
p->osent = (ret == -1) ? 0 : ret;

View File

@@ -75,6 +75,6 @@ int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
* This function reads the binary stream as specified in chapter 6 of RFC4253
* "The Secure Shell (SSH) Transport Layer Protocol"
*/
libssh2pack_t _libssh2_transport_read(LIBSSH2_SESSION * session);
int _libssh2_transport_read(LIBSSH2_SESSION * session);
#endif /* __LIBSSH2_TRANSPORT_H */

View File

@@ -41,6 +41,8 @@
#include <ctype.h>
#include <stdio.h>
#include <assert.h>
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
@@ -104,7 +106,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
if (session->userauth_list_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_list_data,
session->userauth_list_data_len);
session->userauth_list_data_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting userauth list", 0);
@@ -155,7 +157,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
memmove(session->userauth_list_data, session->userauth_list_data + 5,
methods_len);
session->userauth_list_data[methods_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Permitted auth methods: %s",
_libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Permitted auth methods: %s",
session->userauth_list_data);
}
@@ -206,8 +208,8 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
unsigned char *s;
static const unsigned char reply_codes[4] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0
};
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0
};
int rc;
if (session->userauth_pswd_state == libssh2_NB_state_idle) {
@@ -256,7 +258,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
memcpy(s, password, password_len);
s += password_len;
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Attempting to login using password authentication");
session->userauth_pswd_state = libssh2_NB_state_created;
@@ -264,9 +266,9 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
if (session->userauth_pswd_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_pswd_data,
session->userauth_pswd_data_len);
session->userauth_pswd_data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-password request", 0);
@@ -294,20 +296,31 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
&session->
userauth_pswd_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
session->userauth_pswd_state = libssh2_NB_state_idle;
return -1;
}
if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Password authentication successful");
LIBSSH2_FREE(session, session->userauth_pswd_data);
session->userauth_pswd_data = NULL;
session->state |= LIBSSH2_STATE_AUTHENTICATED;
session->userauth_pswd_state = libssh2_NB_state_idle;
return 0;
} else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Password authentication failed");
LIBSSH2_FREE(session, session->userauth_pswd_data);
session->userauth_pswd_data = NULL;
session->userauth_pswd_state = libssh2_NB_state_idle;
libssh2_error(session,
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
"Authentication failed (username/password)",
0);
return -1;
}
session->userauth_pswd_newpw = NULL;
@@ -325,7 +338,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
if ((session->userauth_pswd_state == libssh2_NB_state_sent1) ||
(session->userauth_pswd_state == libssh2_NB_state_sent2)) {
if (session->userauth_pswd_state == libssh2_NB_state_sent1) {
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Password change required");
LIBSSH2_FREE(session, session->userauth_pswd_data);
session->userauth_pswd_data = NULL;
@@ -398,11 +411,11 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_write(session,
session->userauth_pswd_data,
session->
userauth_pswd_data_len);
session->userauth_pswd_data,
session->
userauth_pswd_data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-password-change request",
@@ -469,7 +482,10 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
*
* Read a public key from an id_???.pub style file
*
* Returns an allocated string in *pubkeydata on success.
* Returns an allocated string containing the decoded key in *pubkeydata
* on success.
* Returns an allocated string containing the key method (e.g. "ssh-dss")
* in method on success.
*/
static int
file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
@@ -484,7 +500,7 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
size_t pubkey_len = 0;
unsigned int tmp_len;
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading public key file: %s",
_libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s",
pubkeyfile);
/* Read Public Key */
fd = fopen(pubkeyfile, "r");
@@ -542,15 +558,10 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
LIBSSH2_FREE(session, pubkey);
return -1;
}
/* Wasting some bytes here (okay, more than some),
* but since it's likely to be freed soon anyway,
* we'll just avoid the extra free/alloc and call it a wash */
*method = pubkey;
*method_len = sp1 - pubkey;
sp1++;
if ((sp2 = memchr(sp1, ' ', pubkey_len - *method_len)) == NULL) {
if ((sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey - 1))) == NULL) {
/* Assume that the id string is missing, but that it's okay */
sp2 = pubkey + pubkey_len;
}
@@ -562,6 +573,13 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
LIBSSH2_FREE(session, pubkey);
return -1;
}
/* Wasting some bytes here (okay, more than some), but since it's likely
* to be freed soon anyway, we'll just avoid the extra free/alloc and call
* it a wash */
*method = pubkey;
*method_len = sp1 - pubkey - 1;
*pubkeydata = tmp;
*pubkeydata_len = tmp_len;
@@ -583,7 +601,7 @@ file_read_privatekey(LIBSSH2_SESSION * session,
const LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail =
libssh2_hostkey_methods();
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading private key file: %s",
_libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading private key file: %s",
privkeyfile);
*hostkey_method = NULL;
*hostkey_abstract = NULL;
@@ -613,6 +631,45 @@ file_read_privatekey(LIBSSH2_SESSION * session,
return 0;
}
struct privkey_file {
const char *filename;
const char *passphrase;
};
static int
sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
const unsigned char *data, size_t data_len, void **abstract)
{
struct privkey_file *privkey_file = (struct privkey_file *) (*abstract);
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
void *hostkey_abstract;
struct iovec datavec;
if (file_read_privatekey(session, &privkeyobj, &hostkey_abstract,
session->userauth_pblc_method,
session->userauth_pblc_method_len,
privkey_file->filename,
privkey_file->passphrase)) {
return -1;
}
datavec.iov_base = (unsigned char *)data;
datavec.iov_len = data_len;
if (privkeyobj->signv(session, sig, (unsigned long *)sig_len, 1, &datavec,
&hostkey_abstract)) {
if (privkeyobj->dtor) {
privkeyobj->dtor(session, abstract);
}
return -1;
}
if (privkeyobj->dtor) {
privkeyobj->dtor(session, &hostkey_abstract);
}
return 0;
}
/* userauth_hostbased_fromfile
@@ -627,8 +684,6 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
const char *local_username,
unsigned int local_username_len)
{
static const unsigned char reply_codes[3] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
int rc;
if (session->userauth_host_state == libssh2_NB_state_idle) {
@@ -797,7 +852,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
session->userauth_host_s += sig_len;
LIBSSH2_FREE(session, sig);
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Attempting hostbased authentication");
session->userauth_host_state = libssh2_NB_state_created;
@@ -808,7 +863,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
session->userauth_host_s -
session->userauth_host_packet);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-hostbased request", 0);
@@ -824,6 +879,8 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
}
if (session->userauth_host_state == libssh2_NB_state_sent) {
static const unsigned char reply_codes[3] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned long data_len;
rc = _libssh2_packet_requirev(session, reply_codes,
&session->userauth_host_data,
@@ -831,7 +888,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
&session->
userauth_host_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
session->userauth_host_state = libssh2_NB_state_idle;
@@ -839,7 +896,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
return -1;
if (session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Hostbased authentication successful");
/* We are us and we've proved it. */
LIBSSH2_FREE(session, session->userauth_host_data);
@@ -885,37 +942,47 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
/*
* userauth_publickey_fromfile
* Authenticate using a keypair found in the named files
*/
static int
userauth_publickey_fromfile(LIBSSH2_SESSION *session,
const char *username,
unsigned int username_len,
const char *publickey,
const char *privatekey,
const char *passphrase)
userauth_publickey(LIBSSH2_SESSION *session,
const char *username,
unsigned int username_len,
const unsigned char *pubkeydata,
unsigned long pubkeydata_len,
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
void *abstract)
{
unsigned long pubkeydata_len = 0;
unsigned char reply_codes[4] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
SSH_MSG_USERAUTH_PK_OK, 0
};
SSH_MSG_USERAUTH_PK_OK, 0
};
int rc;
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
unsigned char *pubkeydata;
/* Zero the whole thing out */
memset(&session->userauth_pblc_packet_requirev_state, 0,
sizeof(session->userauth_pblc_packet_requirev_state));
if (file_read_publickey(session, &session->userauth_pblc_method,
&session->userauth_pblc_method_len,
&pubkeydata, &pubkeydata_len,publickey)) {
return -1;
/*
* As an optimisation, userauth_publickey_fromfile reuses a
* previously allocated copy of the method name to avoid an extra
* allocation/free.
* For other uses, we allocate and populate it here.
*/
if (!session->userauth_pblc_method) {
session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata);
session->userauth_pblc_method =
LIBSSH2_ALLOC(session, session->userauth_pblc_method_len);
if (!session->userauth_pblc_method) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for public key "
"data", 0);
return -1;
}
memcpy(session->userauth_pblc_method, pubkeydata + 4,
session->userauth_pblc_method_len);
}
assert( /* preallocated method len should match what we expect */
session->userauth_pblc_method_len == _libssh2_ntohu32(pubkeydata));
/*
* 45 = packet_type(1) + username_len(4) + servicename_len(4) +
@@ -940,7 +1007,6 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
if (!session->userauth_pblc_packet) {
LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL;
LIBSSH2_FREE(session, pubkeydata);
return -1;
}
@@ -965,7 +1031,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
*(session->userauth_pblc_s++) = 0;
_libssh2_htonu32(session->userauth_pblc_s,
session->userauth_pblc_method_len);
session->userauth_pblc_method_len);
session->userauth_pblc_s += 4;
memcpy(session->userauth_pblc_s, session->userauth_pblc_method,
session->userauth_pblc_method_len);
@@ -975,9 +1041,8 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
session->userauth_pblc_s += 4;
memcpy(session->userauth_pblc_s, pubkeydata, pubkeydata_len);
session->userauth_pblc_s += pubkeydata_len;
LIBSSH2_FREE(session, pubkeydata);
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Attempting publickey authentication");
session->userauth_pblc_state = libssh2_NB_state_created;
@@ -985,9 +1050,9 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
if (session->userauth_pblc_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
session->userauth_pblc_packet_len);
session->userauth_pblc_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-publickey request", 0);
@@ -1003,13 +1068,6 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
}
if (session->userauth_pblc_state == libssh2_NB_state_sent) {
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
void *abstract;
unsigned char buf[5];
struct iovec datavec[4];
unsigned char *sig;
unsigned long sig_len;
rc = _libssh2_packet_requirev(session, reply_codes,
&session->userauth_pblc_data,
&session->userauth_pblc_data_len, 0,
@@ -1017,7 +1075,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
&session->
userauth_pblc_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
@@ -1028,7 +1086,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
}
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Pubkey authentication prematurely successful");
/*
* God help any SSH server that allows an UNVERIFIED
@@ -1053,7 +1111,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
session->userauth_pblc_packet = NULL;
LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL;
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED,
libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED,
"Username/PublicKey combination invalid", 0);
session->userauth_pblc_state = libssh2_NB_state_idle;
return -1;
@@ -1063,44 +1121,45 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, session->userauth_pblc_data);
session->userauth_pblc_data = NULL;
if (file_read_privatekey(session, &privkeyobj, &abstract,
session->userauth_pblc_method,
session->userauth_pblc_method_len,
privatekey, passphrase)) {
LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL;
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
session->userauth_pblc_state = libssh2_NB_state_idle;
return -1;
}
*session->userauth_pblc_b = 0x01;
session->userauth_pblc_state = libssh2_NB_state_sent1;
}
_libssh2_htonu32(buf, session->session_id_len);
datavec[0].iov_base = buf;
datavec[0].iov_len = 4;
datavec[1].iov_base = session->session_id;
datavec[1].iov_len = session->session_id_len;
datavec[2].iov_base = session->userauth_pblc_packet;
datavec[2].iov_len = session->userauth_pblc_packet_len;
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
unsigned char *buf, *s;
unsigned char *sig;
size_t sig_len;
if (privkeyobj->signv(session, &sig, &sig_len, 3, datavec, &abstract)) {
s = buf = LIBSSH2_ALLOC(session, 4 + session->session_id_len
+ session->userauth_pblc_packet_len);
if (!buf) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for userauth-publickey "
"signed data", 0);
return -1;
}
_libssh2_htonu32(s, session->session_id_len);
s += 4;
memcpy (s, session->session_id, session->session_id_len);
s += session->session_id_len;
memcpy (s, session->userauth_pblc_packet,
session->userauth_pblc_packet_len);
s += session->userauth_pblc_packet_len;
rc = sign_callback(session, &sig, &sig_len, buf, s - buf, abstract);
LIBSSH2_FREE(session, buf);
if (rc == PACKET_EAGAIN) {
return rc;
} else if (rc) {
LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL;
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
if (privkeyobj->dtor) {
privkeyobj->dtor(session, &abstract);
}
session->userauth_pblc_state = libssh2_NB_state_idle;
return -1;
}
if (privkeyobj->dtor) {
privkeyobj->dtor(session, &abstract);
}
/*
* If this function was restarted, pubkeydata_len might still be 0
* which will cause an unnecessary but harmless realloc here.
@@ -1152,18 +1211,18 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
session->userauth_pblc_s += sig_len;
LIBSSH2_FREE(session, sig);
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Attempting publickey authentication -- phase 2");
session->userauth_pblc_state = libssh2_NB_state_sent1;
session->userauth_pblc_state = libssh2_NB_state_sent2;
}
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
if (session->userauth_pblc_state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
session->userauth_pblc_s -
session->userauth_pblc_packet);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-publickey request", 0);
@@ -1175,7 +1234,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
session->userauth_pblc_state = libssh2_NB_state_sent2;
session->userauth_pblc_state = libssh2_NB_state_sent3;
}
/* PK_OK is no longer valid */
@@ -1186,14 +1245,14 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
&session->userauth_pblc_data_len, 0, NULL, 0,
&session->userauth_pblc_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
session->userauth_pblc_state = libssh2_NB_state_idle;
return -1;
}
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Publickey authentication successful");
/* We are us and we've proved it. */
LIBSSH2_FREE(session, session->userauth_pblc_data);
@@ -1214,6 +1273,44 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
return -1;
}
/*
* userauth_publickey_fromfile
* Authenticate using a keypair found in the named files
*/
static int
userauth_publickey_fromfile(LIBSSH2_SESSION *session,
const char *username,
unsigned int username_len,
const char *publickey,
const char *privatekey,
const char *passphrase)
{
unsigned char *pubkeydata = NULL;
unsigned long pubkeydata_len = 0;
struct privkey_file privkey_file;
void *abstract = &privkey_file;
int rc;
privkey_file.filename = privatekey;
privkey_file.passphrase = passphrase;
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
if (file_read_publickey(session, &session->userauth_pblc_method,
&session->userauth_pblc_method_len,
&pubkeydata, &pubkeydata_len, publickey)) {
return -1;
}
}
rc = userauth_publickey(session, username, username_len,
pubkeydata, pubkeydata_len,
sign_fromfile, &abstract);
if(pubkeydata)
LIBSSH2_FREE(session, pubkeydata);
return rc;
}
/* libssh2_userauth_publickey_fromfile_ex
* Authenticate using a keypair found in the named files
*/
@@ -1233,6 +1330,25 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
return rc;
}
/* libssh2_userauth_publickey_ex
* Authenticate using an external callback function
*/
LIBSSH2_API int
libssh2_userauth_publickey(LIBSSH2_SESSION *session,
const char *user,
const unsigned char *pubkeydata,
size_t pubkeydata_len,
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
void **abstract)
{
int rc;
BLOCK_ADJUST(rc, session,
userauth_publickey(session, user, strlen(user),
pubkeydata, pubkeydata_len,
sign_callback, abstract));
return rc;
}
/*
@@ -1249,7 +1365,8 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
unsigned char *s;
int rc;
static const unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS,
static const unsigned char reply_codes[4] = {
SSH_MSG_USERAUTH_SUCCESS,
SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_INFO_REQUEST, 0
};
unsigned int language_tag_len;
@@ -1316,7 +1433,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
_libssh2_htonu32(s, 0);
s += 4;
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Attempting keyboard-interactive authentication");
session->userauth_kybd_state = libssh2_NB_state_created;
@@ -1324,9 +1441,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
if (session->userauth_kybd_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len);
session->userauth_kybd_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send keyboard-interactive request", 0);
@@ -1350,14 +1467,14 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
&session->
userauth_kybd_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
session->userauth_kybd_state = libssh2_NB_state_idle;
return -1;
}
if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Keyboard-interactive authentication successful");
LIBSSH2_FREE(session, session->userauth_kybd_data);
session->userauth_kybd_data = NULL;
@@ -1367,9 +1484,15 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
}
if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Keyboard-interactive authentication failed");
LIBSSH2_FREE(session, session->userauth_kybd_data);
session->userauth_kybd_data = NULL;
session->userauth_kybd_state = libssh2_NB_state_idle;
libssh2_error(session,
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
"Authentication failed (keyboard-interactive)",
0);
return -1;
}
@@ -1482,7 +1605,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_responses,
&session->abstract);
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Keyboard-interactive response callback function"
" invoked");
@@ -1525,9 +1648,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len);
session->userauth_kybd_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,

View File

@@ -1,8 +0,0 @@
.deps
.libs
*.gcno
*.gcda
Makefile
Makefile.in
simple
ssh2

7
tests/.gitignore vendored
View File

@@ -1 +1,8 @@
.deps
.libs
*.gcno
*.gcda
Makefile
Makefile.in
simple
ssh2

View File

@@ -6,7 +6,7 @@ noinst_PROGRAMS = ssh2
ssh2_SOURCES = ssh2.c
endif
ctests = simple
ctests = simple$(EXEEXT)
TESTS = $(ctests)
if SSHD
TESTS += ssh2.sh

View File

@@ -1,4 +1,4 @@
/* Self test, based on examples/simple/ssh2.c. */
/* Self test, based on examples/ssh2.c. */
#include "libssh2_config.h"
#include <libssh2.h>
@@ -10,12 +10,12 @@
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -59,7 +59,7 @@ int main(int argc, char *argv[])
if (getenv ("PRIVKEY"))
privkeyfile = getenv ("PRIVKEY");
if (getenv ("PRIVKEY"))
if (getenv ("PUBKEY"))
pubkeyfile = getenv ("PUBKEY");
hostaddr = htonl(0x7F000001);
@@ -90,9 +90,9 @@ int main(int argc, char *argv[])
* The first thing to do is check the hostkey's fingerprint against our known hosts
* Your app may have it hard coded, may go to a file, may present it to the user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

View File

@@ -9,21 +9,26 @@ srcdir=${srcdir:-$PWD}
SSHD=${SSHD:-/usr/sbin/sshd}
cmd="./ssh2${EXEEXT}"
srcdir=`cd $srcdir; pwd`
srcdir=`cd "$srcdir"; pwd`
PRIVKEY=$srcdir/etc/user
export PRIVKEY
PUBKEY=$srcdir/etc/user.pub
export PUBKEY
chmod go-r $srcdir/etc/host*
$SSHD -f /dev/null -h $srcdir/etc/host \
if test -n "$DEBUG"; then
libssh2_sshd_params="-d -d"
fi
chmod go-rwx "$srcdir"/etc/host*
$SSHD -f /dev/null -h "$srcdir"/etc/host \
-o 'Port 4711' \
-o 'Protocol 2' \
-o "AuthorizedKeysFile $srcdir/etc/user.pub" \
-o 'UsePrivilegeSeparation no' \
-o 'StrictModes no' \
-D &
-D \
$libssh2_sshd_params &
sshdpid=$!
trap "kill ${sshdpid}; echo signal killing sshd; exit 1;" EXIT

View File

@@ -121,8 +121,7 @@ endif
CFLAGS += $(INCLUDES)
#ifeq ($(findstring msys,$(OSTYPE)),msys)
ifdef __MSYS__
ifeq ($(findstring /sh,$(SHELL)),/sh)
DL = '
DS = /
else
@@ -131,24 +130,10 @@ endif
vpath %.c . ../src
OBJECTS = \
channel.o \
comp.o \
crypt.o \
hostkey.o \
kex.o \
mac.o \
misc.o \
openssl.o \
packet.o \
pem.o \
publickey.o \
scp.o \
session.o \
sftp.o \
transport.o \
userauth.o
# include Makefile.inc to get CSOURCES define
include ../Makefile.inc
OBJECTS := $(patsubst %.c,%.o,$(CSOURCES))
OBJS := $(addprefix $(OBJDIR)/,$(OBJECTS))
OBJL = $(OBJS) $(OBJDIR)/$(TARGET).res

View File

@@ -125,7 +125,7 @@ else
DS = \\
endif
vpath %.c ../../example/simple
vpath %.c ../../example
.PRECIOUS: $(OBJDIR)/%.o $(OBJDIR)/%.rc $(OBJDIR)/%.res