Compare commits

..

184 Commits

Author SHA1 Message Date
Daniel Stenberg
355fbf4d5b prepared for 1.2.2 2009-11-16 22:43:55 +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
Daniel Stenberg
291ac7d433 Version 1.2 (August 10, 2009) 2009-08-10 20:07:17 +02:00
Daniel Stenberg
cccaa868f5 revert parts of the b95fe985af commit
Alexander Lamaison tracked down that my previous commit broke SFTP
reads in some aspects. The reversion now gets back to always recv()
until EAGAIN is returned so that the code no longer treats a short
read as an indication that it is "enough for now".

The bad commit in particular had another independent change included,
which is to clear the direction-bits first in the transport read
and write functions, but this reversion does not revert that change.
Clearing those bits first is a good thing.
2009-08-07 11:33:59 +02:00
Daniel Stenberg
08b0183d8e Fix some nroff formatting
Patch by Sofian Brabez
2009-08-06 15:56:27 +02:00
Alexander Lamaison
231a97a95f Replaced calls to OpenSSL FILE-pointer functions.
Passing a FILE* argument across a DLL boundary causes problems on Windows.  Instead the keys are read into memory by libssh2 and passed to the OpenSSL functions as BIO* arguments.
2009-08-02 23:20:20 +01:00
Daniel Stenberg
6c46bb4719 Add missing names
I went over the NEWS and git log outputs and added all mentioned
contributors through the project's history. I want us to make an
effort to give credit to everyone who contributes, big or small.
2009-07-31 16:07:33 +02:00
Daniel Stenberg
8a0ba6f5f6 fix the C99 variadic macro use for _libssh2_debug()
George Neill pointed out that the C99 vararg marcro use was
wrong, and I edited his suggested patch slightly and unified
both prec99-GCC and C99 into the same macro.
2009-07-29 22:03:40 +02:00
Daniel Stenberg
143720e922 Include RELEASE-NOTES in the release package 2009-07-29 14:38:06 +02:00
Daniel Stenberg
0cad4c08e9 Release notes for the pending release
I hope to maintain this file during development so that we also add
changes and bugfixes to it when we change things. Makes the daily
snapshots better and makes less of a hurdle when the release day
comes.
2009-07-29 14:35:42 +02:00
Daniel Stenberg
dd38d0a929 bad debugdump() causes SIGSEGV, partial sends not done right
The anonymous bug report #2822910 pointed out that debugdump() was
stupidly called within the send_existing() function. At closer
inspection was the report not only right, but it also revealed
another problem to me: when the _libssh2_send() function returns
after sending only a part of the buffer, it would then misbehave.
This probably is very rare though, which must be the reason we
haven't seen a bigger problem with this.
2009-07-28 19:57:02 +02:00
Simon Josefsson
ba57d5ae3c Silcen compiler warnings. 2009-07-28 13:27:43 +02:00
Daniel Stenberg
5ac67d1268 added two new issues to fix: socket type and better windowing
* make sure the windowing code adapts better to slow situations so that it
  doesn't then use as much memory as today

* Introduce a 'libssh2_socket_t' type for sockets in internal code
2009-07-27 23:58:06 +02:00
Daniel Stenberg
6f4463e81f remove superfluous check for large packets
as we're already doing the correct check further down anyway there's no point
in doing the (wrong) check further up as well. Paul Veldkamp pointed this out.
2009-07-27 22:54:18 +02:00
Simon Josefsson
690c3d42db Fix make distcheck problems. 2009-07-22 23:34:31 +02:00
Daniel Stenberg
2b780fa02d parts of the previous VS project files commit 2009-07-18 00:35:38 +02:00
Daniel Stenberg
b363c84366 From: Neil Gierman <ngierman@roadrunn.com>
Makefile changes to generate MSVS project files

- I integrated the libssh2_lib.dsp and libssh2_dll.dsp into a single
libssh2.dsp with different targets for lib vs dll
- Since I run Visual Studio 2008 with VC++9 I did not do vcproj files since
I would have newer vc8proj.head|foot than what others will be running
- My patch only has changes to Makefile.am's. I noticed that Makefile.in's
are included in the daily snapshots but they should be generated from the
.am's
- The 3 new files are msvcproj.head and msvcproj.foot for the beginning and
ending of the dsp file, and a new Makefile.inc that will have the source and
header file names. NOTE: All new source files will need to be added to
Makefile.inc and NOT Makefile.am now.
- I moved the win32 dir before the include dir
- I modified the dsw file so it points to the new libssh2.dsp project file
2009-07-18 00:23:25 +02:00
Daniel Stenberg
35a9d4bc62 From: Alexander Lamaison <swish@lammy.co.uk>
Make the public headers includable on their own
2009-07-17 23:40:32 +02:00
Daniel Stenberg
686db51284 From: Steven Van Ingelgem <steven@vaningelgem.be>
check first for libtoolize, and then for glibtoolize

Mac OS X (and others?) needs this
2009-07-17 23:38:41 +02:00
Daniel Stenberg
2361f50e9a Fix knownhost checking of non-hashed hosts
From: Ben Kibbey <bjk@luxsci.net>
2009-07-12 07:05:00 +02:00
Daniel Stenberg
e5d76b5468 Fix the functionality again with hashed host names again.
The breakage came with commit 8b46528c04.
2009-07-12 00:03:37 +02:00
Peter Stuge
7eead1461b Update mailing list URL to new address 2009-07-10 20:11:29 +02:00
Daniel Stenberg
c0d032a45c const'ify two arguments to libssh2_knownhost_check() 2009-07-10 00:54:59 +02:00
Daniel Stenberg
0751067c2f Fix compiler warnings appearing with VS2008. Based on Steven Van Ingelgem's
patch in #2787839 with a bunch of additional edits by yours truly.
2009-07-07 13:44:17 +02:00
Daniel Stenberg
acbdbb8914 Applied Francois Dupoux's extra checks for weird packet or padding length in
incoming packets. We really need to bail out this way on weird input.
bug report #2814613
2009-07-07 13:26:42 +02:00
Daniel Stenberg
bea1beb4fd Mark McPherson posted bug report #2815836 pointing out that the custom memory
functions were not given the correct data as argument. This is now fixed even
if I personally don't quite grasp why abstract is passed as a pointer to
pointer all over libssh2...
2009-07-07 13:09:11 +02:00
Daniel Stenberg
5b599fbf40 Ben Kibbey added a type parameter to the libssh2_session_hostkey() function,
which hasn't yet been in a public release so changing the API is fine!
2009-07-07 00:25:17 +02:00
Daniel Stenberg
75bec57c94 Guenter Knauf fixed this example to build on win32 2009-07-02 11:46:51 +02:00
Daniel Stenberg
b9b5e5fea5 corrected (again) 2009-07-02 11:44:54 +02:00
Daniel Stenberg
91bca481b5 clarify 2009-07-02 00:11:33 +02:00
Daniel Stenberg
9a6ce012cc Neil Gierman pointed out in bug report #2809163 that these two files cannot
include the public libssh2.h header as it breaks the compile on window. I'll
adapt to this now, but in the long run I think we should rather fix the
includes so that we _can_ include the public headers properly.
2009-06-26 20:43:56 +02:00
Daniel Stenberg
a4c3f0d0a3 fixed the length check in knownhost_writeline() since <= is actually good
enough when the size includes the trailing zero
2009-06-14 14:29:15 +02:00
Daniel Stenberg
320450201a After a mention from Ben Kibbey we now let knownhost_writeline() return the
length of the actual data it returns, excluding the trailing zero. I also
updated the man page for libssh2_knownhost_writeline() accordingly.
2009-06-14 14:27:15 +02:00
Daniel Stenberg
9f5c1caa81 empty line removed 2009-06-14 14:26:27 +02:00
Daniel Stenberg
8b46528c04 Ben Kibbey fixed the hostline() when parsing lines using only one hostname 2009-06-10 20:46:11 +02:00
Daniel Stenberg
aeaf07576e Merge branch 'master' of ssh://bagder@git.stuge.se/var/lib/git/libssh2 2009-06-09 00:00:26 +02:00
Daniel Stenberg
c01e147a40 Provide a libssh2_scp_send() API for files larger than 4GB (32bit size) 2009-06-08 16:10:37 +02:00
Daniel Stenberg
32080def94 Olivier Hervieu provided this x11 forwarding example. This is the version
after my initial cleanup that I posted to the list on May 26th 2009. It still
has a few ugly spots that should be cleaned up, but until then it's will at
least be found in the repo. For this reason I don't add this to the makefile.
2009-06-05 09:04:24 +02:00
Daniel Stenberg
da1230b35b New man page for libssh2_session_hostkey(3). We probably need to improve this
to also return the type of the key.
2009-06-05 09:02:56 +02:00
Daniel Stenberg
d440995a80 Add check for and use of the _REENTRANT define for Solaris so that libssh2
is then properly thread-safe on that OS. These autuconf macros are straight
from the cURL project and were mostly written by Yang Tse. They were only
very slightly edited by me when imported to here.
2009-06-04 20:23:23 +02:00
Tor Arntsen
2a142a6524 Ignore generated files 2009-06-04 18:20:29 +02:00
Daniel Stenberg
afcf63b433 use the correct #if condition for strtoll(), pointed out in bug report 2009-06-04 00:36:34 +02:00
Daniel Stenberg
bc4c258842 define the HAVE_LIBSSH2_KNOWNHOST_API to the version number 1.1.1 to make apps
know that when this define exists, the API exists. And the version number can
be used for run-time checks. 1.1.1 is not likely to be the release version as
I think we'll go with 1.2 instead but 1.1.1 OR LATER should still work.
2009-05-29 23:04:52 +02:00
Daniel Stenberg
e52a1057fd libssh2_knownhost_add() got an additional argument: 'store' so that an
application can get a pointer back to the internal representation of the host
it just added. Useful for example when the app wants to add a host, and then
convert that exact same host to a line for storing in a known host file.
'store' can also be set to NULL to simple not care.
2009-05-29 18:40:29 +02:00
Daniel Stenberg
517909d37a Added a call to libssh2_knownhost_writefile()
Updated to the slightly modified libssh2_knownhost_check() proto
2009-05-29 14:10:54 +02:00
Daniel Stenberg
8cd76af353 "struct libssh2_knownhost" is now part of the internal struct for each known
host so we now only return pointers to structs instead of having the app
allocate a full struct

I moved the private struct definition into knownhosts.c instead of exposing it
wider in libssh2_priv.h

I thus modified the proto for two functions that previously used 'struct
libssh2_knownhost *' to receive data.
2009-05-29 14:08:24 +02:00
Daniel Stenberg
1d31dadc1e when a host is added, we must make sure the app also provides a key *type* even
though we don't use the type in this function
2009-05-29 13:58:04 +02:00
Daniel Stenberg
2e990194ab Added man pages for the two newest members of the knownhosts API family:
libssh2_knownhost_readline() and libssh2_knownhost_writeline()
2009-05-29 10:12:22 +02:00
Daniel Stenberg
1afbbf4507 introducing libssh2_knownhost_writeline() and some cleanups to use more
defined error codes instead of the simplified -1 previously used a little too
much here
2009-05-29 10:00:45 +02:00
Daniel Stenberg
82bdd12a8b I think *readline() makes a better name 2009-05-29 00:19:02 +02:00
Daniel Stenberg
4df48aef41 clarify that the key "string" needs to be zero terminated too 2009-05-29 00:14:41 +02:00
Daniel Stenberg
bc28d0146d introducing libssh2_knownhost_read() that makes libssh2 read a single given
line
const'ified a few args to libssh2_knownhost_add() as well
2009-05-29 00:08:00 +02:00
Daniel Stenberg
8b1ec197b2 fix a warning for a comparison mixing signed and unsigned types 2009-05-28 22:54:37 +02:00
Daniel Stenberg
2436a4de60 After review/feedback/discussions on the mailing list. Rename two functions:
s/libssh2_knownhost_parsefile/libssh2_knownhost_readfile
s/libssh2_knownhost_dumpfile/libssh2_knownhost_writefile
2009-05-28 19:57:54 +02:00
Daniel Stenberg
22014f074b define removed 2009-05-28 16:12:24 +02:00
Daniel Stenberg
f35dbff3c4 LIBSSH2_KNOWNHOST_TYPE_DEFAULT is not a good idea, scrap it 2009-05-28 14:36:16 +02:00
Daniel Stenberg
703fbd9d11 Added the initial man pages for the 7 new functions for known host handling 2009-05-28 14:35:13 +02:00
Daniel Stenberg
5207690edf first shot at implementing libssh2_knownhost_dumpfile() and some minor
cleanups
2009-05-28 13:14:32 +02:00
Daniel Stenberg
eaa95e0331 introducing libssh2_knownhost_get() to the public API 2009-05-27 16:00:52 +02:00
Daniel Stenberg
d965dda027 clarified a comment 2009-05-26 11:18:29 +02:00
Daniel Stenberg
bf884488ae slighty better behavior and comments 2009-05-26 11:18:00 +02:00
Daniel Stenberg
28b08e0b4d remove include since we don't use struct iovec in this file 2009-05-26 11:14:07 +02:00
Daniel Stenberg
1ffa2cb519 These examples no longer need to explictly set the socket to non-blocking state
as libssh2 itself will always do that by itself.
2009-05-26 09:41:13 +02:00
Daniel Stenberg
279d6dd82a add myself as copyright owner 2009-05-25 11:35:06 +02:00
Daniel Stenberg
49192598d2 mention conversion of code to the new linked list code 2009-05-25 11:29:39 +02:00
Daniel Stenberg
6b7c19ec26 remove #if 0'ed code 2009-05-25 11:23:06 +02:00
Daniel Stenberg
160e5aa763 clarify the fix, as it wasn't a leak 2009-05-25 11:03:24 +02:00
Daniel Stenberg
42e9f02025 spell fix a comment 2009-05-25 10:58:13 +02:00
Daniel Stenberg
5a162ad9f8 Added some clarifying comments on how the 'sftpInit_sftp' and
'sftpInit_channel' struct fields within the session struct are used. And made
sure to clear them both correctly when sftp_init() returns instead of at
shutdown time, as it must not touch them at shutdown time. This should make it
possible to properly make more than one SFTP handle.
2009-05-25 10:50:49 +02:00
Daniel Stenberg
6ff83eab1b no need for LIBSSH2_ERROR_MEMORY when LIBSSH2_ERROR_ALLOC already exist!
added my own copyright line too now
2009-05-25 10:41:07 +02:00
Daniel Stenberg
8df3222d91 use LIBSSH2_ERROR_ALLOC instead of introducing a new error code 2009-05-25 10:40:36 +02:00
Daniel Stenberg
0357ce6c48 clear session->sftpInit_sftp unconditionally 2009-05-24 23:51:59 +02:00
Daniel Stenberg
c5f335ad4f Fix my recent session->sftpInit_sftp fix which wasn't correct. The memory area
does not need to be freed (it already gets freed) but clearing the pointer is
a good idea. And it should be done _after_ the channel_free() call.
2009-05-24 23:44:52 +02:00
Daniel Stenberg
fdc043e7b1 add an assert to help debugging 2009-05-24 23:44:23 +02:00
Daniel Stenberg
fdaa5ad5b4 Without CVS we must not use cvs tools to generate the changelog. I'm not
confident enough with git to attempt to make one so I'll just make a dummy for
now.
2009-05-23 23:03:31 +02:00
Daniel Stenberg
f1f49c3cce - Anonymous bug report #2795816 revealed that libssh2_sftp_shutdown() did not
properly free/cleanup the SFTP handle so libssh2 leaked memory and caused
   an assert() on subsequent libssh2_sftp_init() calls on the same session.
2009-05-23 22:30:43 +02:00
Daniel Stenberg
ad13de92d4 Fix _libssh2_channel_write(): fixed the write loop to also read from the
transport layer better, to avoid draining the window size when sending large
packets. I also fixed the return code for it to return the number of bytes
handled in this single invoke (and not the cumulative amount).
2009-05-20 14:34:30 +02:00
Daniel Stenberg
b755f3eb10 First, only try to send max packet size *4 to channel write, as trying to send
much larger packages only cause internal problems and much larger allocations.

Also fix sftp_write() when _libssh2_channel_write() returns that a packet was
only partially sent as that is not an error.

Fixed a few error messages to more accurately point out the problem
2009-05-20 14:31:46 +02:00
Daniel Stenberg
b95fe985af If recv() returns something less than the full buffer we know we're done for
now, so skip looping and doing another read that then simply will cause an
EAGAIN as it may trick the user into believing things that aren't true.
2009-05-20 14:30:05 +02:00
daniel
035cb24fa0 remove the old style as it makes little sense to mention here anymore 2009-05-14 17:01:54 +02:00
Daniel Stenberg
18e03739be typo 2009-05-12 10:10:55 +00:00
Daniel Stenberg
e367e1ad4e comment typo and some indent fixes 2009-05-12 10:07:30 +00:00
Daniel Stenberg
f7149d1830 Partial fix based on the patch and discussions in #2788319 2009-05-12 09:33:22 +00:00
Daniel Stenberg
042b545247 clear the passed in struct when the entry has been removed to help prevent
mistakes due to re-use
2009-05-12 09:32:51 +00:00
Daniel Stenberg
4490c6b434 use a better example file name for the known_hosts file 2009-05-07 20:30:22 +00:00
Daniel Stenberg
d3542e6f7d split out the knownhost code from hostkey.c into its own separate source file
now: knownhost.c
2009-05-07 17:21:56 +00:00
Daniel Stenberg
0cee15dc0c this was never supposed to be added for real 2009-05-07 17:21:14 +00:00
Daniel Stenberg
4b991b232d My knownhost work as of right now. It works at least partly. More tests and
tweaks will come.
2009-05-07 13:09:48 +00:00
Daniel Stenberg
4bc1b8a1d7 get host, user, password and command from the command line 2009-05-05 12:30:19 +00:00
Daniel Stenberg
755e213ae6 Added ssh2_exec as a new example, showing how to run a command remotely with
libssh2
2009-05-05 12:27:02 +00:00
Daniel Stenberg
9412588373 bug #2785173 pointed out that we really must call _libssh2_transport_read()
in loops until it returns < 0 when we call it, as if we just call it once we
may drain the socket for data and then leave unused in-memory data that we
won't detect because the socket is back to idle...
2009-05-01 19:07:20 +00:00
Daniel Stenberg
9f104cd883 Markus posted a bug report about a bad 0-return from libssh2_channel_read:
http://libssh2.haxx.se/mail/libssh2-devel-archive-2009-04/0076.shtml

  And it was indeed a bad loop that terminated too early due to a receveived
  close packet.
2009-04-30 10:30:26 +00:00
Daniel Stenberg
6409bb53ba remove pointless sleeps 2009-04-28 10:35:30 +00:00
Daniel Stenberg
c306119dd6 edited 2009-04-14 21:43:39 +00:00
Daniel Stenberg
2b8038e175 libssh2_poll() and libssh2_poll_channel_read() are now considered and
documented deprecated and they will be removed at next soname bump. It also
  saves us from fixing some rather quirky bugs in libssh2_poll()...
2009-04-14 21:38:36 +00:00
Guenter Knauf
2a39b32b1a some minor Makefile tweaks; mainly for crosscompiling. 2009-04-09 03:13:51 +00:00
Daniel Stenberg
e63cbd907f Jussi Mononen pointed out we used an unsigned variable to store negative
values in, when a plain int is much better anyway since it matches the return
type.
2009-04-06 14:50:29 +00:00
Daniel Stenberg
cb66b7b94f and we're now on the 1.1.1 track 2009-04-02 09:35:02 +00:00
96 changed files with 4623 additions and 1925 deletions

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

View File

@@ -26,3 +26,8 @@ ssh2_sample
libssh2-*.tar.gz
INSTALL
install-sh
*.o
*.lo
*.la
mkinstalldirs
tags

58
AUTHORS
View File

@@ -1,15 +1,47 @@
* Sara Golemon: Author / Project Manager
libssh2 is the result of many friendly people. This list is an attempt to
mention all contributors. If we've missed anyone, tell us!
* Daniel Stenberg: Co-maintainer
This list of names is a-z sorted.
* James Housleys: Nonblocking conversion
* Simon Josefsson: libgcrypt support
* Mikhail Gusarov: Keyboard Interactive Authentication
* Wez Furlong & Edink Kadribasic: Windows Port
* Dan Fandrich: bug fixes, cleanups
* Guenter Knauf: win32 work and more
Adam Gobiowski
Alexander Holyapin
Alexander Lamaison
Ben Kibbey
Bjorn Stenborg
Carlo Bramini
Dan Casey
Dan Fandrich
Daniel Stenberg
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
Sara Golemon
Satish Mittal
Sean Peterson
Selcuk Gueney
Simon Hart
Simon Josefsson
Steven Ayre
Steven Van Ingelgem
Tor Arntsen
Vincent Jaulin
Vlad Grachov
Wez Furlong
Yang Tse

View File

@@ -1,5 +1,7 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (C) 2006-2007 The Written Word, Inc.
* 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,

21
HACKING
View File

@@ -9,24 +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
------------
Older libssh2 code that still hasn't quite transitioned to the above
mentioned style, used a different style:
- indented with tabs (only)
- no line length limits
- See libssh2-style.el for how to achieve this within Emacs

View File

@@ -1,5 +1,10 @@
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 \
@@ -11,20 +16,25 @@ NETWAREFILES = nw/keepscreen.c \
nw/nwlib.c \
nw/test/Makefile.netware
WIN32FILES = win32/libssh2_dll.dsp win32/libssh2.dsw win32/Makefile.win32 \
win32/config.mk win32/Makefile win32/test/Makefile.win32 win32/libssh2_lib.dsp \
win32/libssh2_config.h win32/tests.dsp win32/rules.mk
DSP = win32/libssh2.dsp
VCPROJ = win32/libssh2.vcproj
DISTCLEANFILES = $(DSP)
WIN32FILES = win32/Makefile.win32 win32/libssh2.dsw \
win32/config.mk win32/Makefile win32/test/Makefile.win32 \
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
maketgz NMakefile TODO RELEASE-NOTES libssh2.pc.in
ACLOCAL_AMFLAGS = -I m4
.PHONY: ChangeLog
ChangeLog:
if test -f .cvsusers; then \
cvs2cl --utc --fsf --FSF --usermap .cvsusers -I ChangeLog -I .cvs; \
fi
echo "see NEWS" > ./ChangeLog
DISTCLEANFILES += ChangeLog
dist-hook:
rm -rf $(top_builddir)/tests/log
@@ -57,3 +67,62 @@ gen-coverage:
--title "$(PACKAGE_NAME)"
coverage: init-coverage build-coverage gen-coverage
# DSP/VCPROJ generation adapted from libcurl
# Makefile.inc provides the CSOURCES and HHEADERS defines
include Makefile.inc
WIN32SOURCES = $(CSOURCES)
WIN32HEADERS = $(HHEADERS) libssh2_config.h
$(DSP): win32/msvcproj.head win32/msvcproj.foot Makefile.am
echo "creating $(DSP)"
@( (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"; \
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"; \
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)"
@( (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\">"; \
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) | \
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )

5
Makefile.inc Normal file
View File

@@ -0,0 +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 openssl.c libgcrypt.c pem.c
HHEADERS = libssh2_priv.h openssl.h libgcrypt.h transport.h channel.h comp.h mac.h misc.h

119
NEWS
View File

@@ -1,3 +1,122 @@
Version 1.2.2 (unreleased)
* 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.
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)
-----------------------------
* (August 02 2009) Alexander Lamaison:
- changed _libssh2_rsa_new_private and _libssh2_rsa_new_private so that they
no longer use the OpenSSL functions that take a FILE* argument. Passing
CRT-created objects across a DLL boundary causes crashes on Windows of the
DLL and the client aren't linked to the exact same verison of the CRT. Now
we pass the keys as strings to avoid this issue.
* (May 29 2009) Daniel Stenberg:
- Updated the knownhost API and there are now 9 functions, and all of them
have man pages. The libssh2.h now defines HAVE_LIBSSH2_KNOWNHOST_API to
ease things for applications to check for the correct release before trying
to use it.
* (May 23 2009) Daniel Stenberg:
- Anonymous bug report #2795816 revealed that doing subsequent
libssh2_sftp_init() calls on the same session failed.
* (May 20 2009) Daniel Stenberg:
- made libssh2_sftp_write() properly deal with huge/any sized input buffers.
- fixed libssh2_channel_write_ex() to return the correct return code, and
deal with sending off huge buffers better
* (May 7 2009) Daniel Stenberg:
- linked list code. I got a bit tired of the fact that we don't have any
generic linked-list functions within libssh2 so I wrote up the first embryo
for one that I use for this new functionality. The plan would then be to
move all existing code that uses linked lists to use this new set.
- base64 encode. I had to add a base64 encoding function which was missing
in the code base so it helps to "bloat" my patch.
- The knownhost API is currently:
_init() - init a bundle of known hosts
_add() - add a known host
_del() - delete a known host
_free() - free an entire bundle of known hosts
_check() - check if a host+key is present in the bundle
The convenience function:
_parsefile() - reads a ~/.ssh/known_hosts file and add all entries to the
given bundle
- there's no docs other than some comments in the code/headers yet
- the patch includes changes to example/simple/ssh2_exec.c that makes use of
a few of these functions. Using that I've verified that the functions in
fact can verify my localhost's key agains my ~/.ssh/known_hosts file
* (Apr 30 2009) Daniel Stenberg:
Markus posted a bug report about a bad 0-return from libssh2_channel_read:
http://libssh2.haxx.se/mail/libssh2-devel-archive-2009-04/0076.shtml
And it was indeed a bad loop that terminated too early due to a receveived
close packet.
* (Apr 14 2009) Daniel Stenberg:
libssh2_poll() and libssh2_poll_channel_read() are now considered and
documented deprecated and they will be removed at next soname bump. It also
saves us from fixing some rather quirky bugs in libssh2_poll()...
Version 1.1 (April 2, 2009)
---------------------------

2
README
View File

@@ -6,7 +6,7 @@ the revised BSD license.
Web site: http://www.libssh2.org/
Mailing list: https://lists.sourceforge.net/lists/listinfo/libssh2-devel
Mailing list: http://cool.haxx.se/mailman/listinfo/libssh2-devel
Generic installation instructions are in INSTALL. Some ./configure
options deserve additional comments:

18
RELEASE-NOTES Normal file
View File

@@ -0,0 +1,18 @@
libssh2 1.2.2
This release includes the following changes:
o Support for the "aes128-ctr", "aes192-ctr", "aes256-ctr" ciphers
o Support for the "arcfour128" cipher
This release includes the following bugfixes:
o Fix crash when server sends an invalid SSH_MSG_IGNORE message
This release would not have looked like this without help, code, reports and
advice from friends like these:
Simon Josefsson, Bob Alexander
Thanks! (and sorry if I forgot to mention someone)

32
TODO
View File

@@ -1,19 +1,14 @@
Things TODO
===========
* Add one of the missing man pages:
* make sure the windowing code adapts better to slow situations so that it
doesn't then use as much memory as today
libssh2_channel_receive_window_adjust
libssh2_channel_request_pty_size_ex
libssh2_channel_window_read_ex
libssh2_channel_window_write_ex
libssh2_publickey_add_ex
libssh2_publickey_init
libssh2_publickey_list_fetch
libssh2_publickey_list_free
libssh2_publickey_remove_ex
libssh2_publickey_shutdown
libssh2_userauth_hostbased_fromfile_ex
* Introduce a 'libssh2_socket_t' type for sockets in internal code
* Provide a libssh2_scp_send() API for files larger than 4GB (32bit size)
* Add more info to the man pages.
* Decrease the number of mallocs. Everywhere.
@@ -21,8 +16,7 @@ Things TODO
* Extend the test suite to actually test lots of aspects of libssh2
* libssh2_channel_receive_window_adjust() can return EAGAIN while documented
to return the window as an "unsigned long".
* Fix all compiler warnings (some can't be done without API changes)
At next SONAME bump
===================
@@ -30,9 +24,19 @@ At next SONAME bump
* stop using #defined macros as part of the official API. The macros should
either be turned into real functions or discarded from the API.
* fix the parts of the API where object pointers and function pointers are
mixed like libssh2_session_callback_set()
* remove the following functions from the API/ABI
libssh2_base64_decode()
libssh2_session_flag()
libssh2_channel_handle_extended_data()
libssh2_channel_receive_window_adjust()
libssh2_poll()
libssh2_poll_channel_read()
* Rename a few function:
libssh2_hostkey_hash => libssh2_session_hostkey_hash
libssh2_banner_set => libssh2_session_banner_set

View File

@@ -288,3 +288,97 @@ dnl end of non-blocking try-compile test
AC_MSG_WARN([non-block sockets disabled])
fi
])
dnl CURL_CHECK_NEED_REENTRANT_SYSTEM
dnl -------------------------------------------------
dnl Checks if the preprocessor _REENTRANT definition
dnl must be unconditionally done for this platform.
dnl Internal macro for CURL_CONFIGURE_REENTRANT.
AC_DEFUN([CURL_CHECK_NEED_REENTRANT_SYSTEM], [
case $host in
*-*-solaris* | *-*-hpux*)
tmp_need_reentrant="yes"
;;
*)
tmp_need_reentrant="no"
;;
esac
])
dnl CURL_CONFIGURE_FROM_NOW_ON_WITH_REENTRANT
dnl -------------------------------------------------
dnl This macro ensures that configuration tests done
dnl after this will execute with preprocessor symbol
dnl _REENTRANT defined. This macro also ensures that
dnl the generated config file defines NEED_REENTRANT
dnl and that in turn setup.h will define _REENTRANT.
dnl Internal macro for CURL_CONFIGURE_REENTRANT.
AC_DEFUN([CURL_CONFIGURE_FROM_NOW_ON_WITH_REENTRANT], [
AC_DEFINE(NEED_REENTRANT, 1,
[Define to 1 if _REENTRANT preprocessor symbol must be defined.])
cat >>confdefs.h <<_EOF
#ifndef _REENTRANT
# define _REENTRANT
#endif
_EOF
])
dnl CURL_CONFIGURE_REENTRANT
dnl -------------------------------------------------
dnl This first checks if the preprocessor _REENTRANT
dnl symbol is already defined. If it isn't currently
dnl defined a set of checks are performed to verify
dnl if its definition is required to make visible to
dnl the compiler a set of *_r functions. Finally, if
dnl _REENTRANT is already defined or needed it takes
dnl care of making adjustments necessary to ensure
dnl that it is defined equally for further configure
dnl tests and generated config file.
AC_DEFUN([CURL_CONFIGURE_REENTRANT], [
AC_PREREQ([2.50])dnl
#
AC_MSG_CHECKING([if _REENTRANT is already defined])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
]],[[
#ifdef _REENTRANT
int dummy=1;
#else
force compilation error
#endif
]])
],[
AC_MSG_RESULT([yes])
tmp_reentrant_initially_defined="yes"
],[
AC_MSG_RESULT([no])
tmp_reentrant_initially_defined="no"
])
#
if test "$tmp_reentrant_initially_defined" = "no"; then
AC_MSG_CHECKING([if _REENTRANT is actually needed])
CURL_CHECK_NEED_REENTRANT_SYSTEM
if test "$tmp_need_reentrant" = "yes"; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
fi
#
AC_MSG_CHECKING([if _REENTRANT is onwards defined])
if test "$tmp_reentrant_initially_defined" = "yes" ||
test "$tmp_need_reentrant" = "yes"; then
CURL_CONFIGURE_FROM_NOW_ON_WITH_REENTRANT
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
#
])

View File

@@ -1,6 +1,22 @@
#!/bin/sh
${LIBTOOLIZE:-libtoolize} --copy --automake --force
LIBTOOLIZE="libtoolize"
if [ "x`which $LIBTOOLIZE`" == "x" ];
then
LIBTOOLIZE="glibtoolize";
fi
if [ "x`which $LIBTOOLIZE`" == "x" ];
then
echo "Neither libtoolize nor glibtoolize could be found!";
exit 1
fi
${LIBTOOLIZE} --copy --automake --force
${ACLOCAL:-aclocal} -I m4 $ACLOCAL_FLAGS
${AUTOHEADER:-autoheader}
# copy the private libssh2_config.h.in to the examples dir so that

View File

@@ -50,6 +50,10 @@ AC_CHECK_TYPE(long long,
[Define to 1 if the compiler supports the 'long long' data type.])]
longlong="yes"
)
dnl Our configure and build reentrant settings
CURL_CONFIGURE_REENTRANT
# Some systems (Solaris?) have socket() in -lsocket.
AC_SEARCH_LIBS(socket, socket)
@@ -158,6 +162,45 @@ 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])
@@ -210,5 +253,6 @@ AC_CONFIG_FILES([Makefile
tests/Makefile
example/Makefile
example/simple/Makefile
docs/Makefile])
docs/Makefile
libssh2.pc])
AC_OUTPUT

View File

View File

@@ -4,6 +4,7 @@ EXTRA_DIST = template.3
dist_man_MANS = \
libssh2_banner_set.3 \
libssh2_base64_decode.3 \
libssh2_channel_close.3 \
libssh2_channel_direct_tcpip_ex.3 \
libssh2_channel_eof.3 \
@@ -21,23 +22,48 @@ dist_man_MANS = \
libssh2_channel_receive_window_adjust.3 \
libssh2_channel_receive_window_adjust2.3 \
libssh2_channel_request_pty_ex.3 \
libssh2_channel_request_pty_size_ex.3 \
libssh2_channel_send_eof.3 \
libssh2_channel_set_blocking.3 \
libssh2_channel_setenv_ex.3 \
libssh2_channel_wait_eof.3 \
libssh2_channel_wait_closed.3 \
libssh2_channel_wait_eof.3 \
libssh2_channel_window_read_ex.3 \
libssh2_channel_window_write_ex.3 \
libssh2_channel_write_ex.3 \
libssh2_channel_x11_req_ex.3 \
libssh2_free_host_entry.3 \
libssh2_host_entry_match.3 \
libssh2_hostkey_hash.3 \
libssh2_knownhost_add.3 \
libssh2_knownhost_check.3 \
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 \
libssh2_knownhost_writeline.3 \
libssh2_new_host_entry.3 \
libssh2_poll.3 \
libssh2_poll_channel_read.3 \
libssh2_publickey_add_ex.3 \
libssh2_publickey_init.3 \
libssh2_publickey_list_fetch.3 \
libssh2_publickey_list_free.3 \
libssh2_publickey_remove_ex.3 \
libssh2_publickey_shutdown.3 \
libssh2_scp_recv.3 \
libssh2_scp_send_ex.3 \
libssh2_session_abstract.3 \
libssh2_session_block_directions.3 \
libssh2_session_callback_set.3 \
libssh2_session_free.3 \
libssh2_session_disconnect_ex.3 \
libssh2_session_flag.3 \
libssh2_session_free.3 \
libssh2_session_get_blocking.3 \
libssh2_session_hostkey.3 \
libssh2_session_init_ex.3 \
libssh2_session_last_errno.3 \
libssh2_session_last_error.3 \
@@ -45,14 +71,12 @@ dist_man_MANS = \
libssh2_session_methods.3 \
libssh2_session_set_blocking.3 \
libssh2_session_startup.3 \
libssh2_poll.3 \
libssh2_poll_channel_read.3 \
libssh2_sftp_close_handle.3 \
libssh2_sftp_fstat_ex.3 \
libssh2_sftp_last_error.3 \
libssh2_sftp_init.3 \
libssh2_sftp_open_ex.3 \
libssh2_sftp_last_error.3 \
libssh2_sftp_mkdir_ex.3 \
libssh2_sftp_open_ex.3 \
libssh2_sftp_read.3 \
libssh2_sftp_readdir_ex.3 \
libssh2_sftp_rename_ex.3 \
@@ -65,24 +89,11 @@ dist_man_MANS = \
libssh2_sftp_tell64.3 \
libssh2_sftp_unlink_ex.3 \
libssh2_sftp_write.3 \
libssh2_trace.3 \
libssh2_userauth_authenticated.3 \
libssh2_userauth_hostbased_fromfile_ex.3 \
libssh2_userauth_keyboard_interactive_ex.3 \
libssh2_userauth_list.3 \
libssh2_userauth_password_ex.3 \
libssh2_userauth_publickey_fromfile_ex.3 \
libssh2_base64_decode.3 \
libssh2_trace.3 \
libssh2_version.3
libssh2_channel_request_pty_size_ex.3 \
libssh2_free_host_entry.3 \
libssh2_host_entry_match.3 \
libssh2_new_host_entry.3 \
libssh2_publickey_add_ex.3 \
libssh2_publickey_init.3 \
libssh2_publickey_list_fetch.3 \
libssh2_publickey_list_free.3 \
libssh2_publickey_remove_ex.3 \
libssh2_publickey_shutdown.3 \
libssh2_session_flag.3 \
libssh2_session_get_blocking.3 \
libssh2_userauth_hostbased_fromfile_ex.3

View File

@@ -13,16 +13,16 @@ LIBSSH2_CHANNEL *
libssh2_channel_direct_tcpip(LIBSSH2_SESSION *session, const char *host, int port);
.SH DESCRIPTION
/fIsession/fP - Session instance as returned by
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
/fIhost/fP - Third party host to connect to using the SSH host as a proxy.
\fIhost\fP - Third party host to connect to using the SSH host as a proxy.
/fIport/fP - Port on third party host to connect to.
\fIport\fP - Port on third party host to connect to.
/fIshost/fP - Host to tell the SSH server the connection originated on.
\fIshost\fP - Host to tell the SSH server the connection originated on.
/fIsport/fP - Port to tell the SSH server the connection originated from.
\fIsport\fP - Port to tell the SSH server the connection originated from.
Tunnel a TCP/IP connection through the SSH transport via the remote host to
a third party. Communication from the client to the SSH server remains

View File

@@ -10,7 +10,7 @@ int
libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
.SH DESCRIPTION
/fIlistener/fP - Forwarding listener instance as returned by
\fIlistener\fP - Forwarding listener instance as returned by
.BR libssh2_channel_forward_listen_ex(3)
Instruct the remote host to stop listening for new connections on a previously requested host/port.

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,58 @@
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_add 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_add - add a known host
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
char *host, char *salt,
char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **store);
.SH DESCRIPTION
Adds a known host to the collection of known hosts identified by the 'hosts'
handle.
\fIhost\fP is a pointer the host name in plain text or hashed. If hashed, it
must be provided base64 encoded. The host name can be the IP numerical address
of the host or the full name.
\fIsalt\P is a pointer to the salt used for the host hashing, if the host is
provided hashed. If the host is provided in plain text, salt has no meaning.
The salt has to be provided base64 encoded with a trailing zero byte.
\fIkey\fP is a pointer to the key for the given host.
\fIkeylen\fP is the total size in bytes of the key pointed to by the \fIkey\fP
argument
\fItypemask\fP is a bitmask that specifies format and info about the data
passed to this function. Specificly, it details what format the host name is,
what format the key is and what key type it is.
The host name is given as one of the following types:
LIBSSH2_KNOWNHOST_TYPE_PLAIN, LIBSSH2_KNOWNHOST_TYPE_SHA1 or
LIBSSH2_KNOWNHOST_TYPE_CUSTOM.
The key is encoded using one of the following encodings:
LIBSSH2_KNOWNHOST_KEYENC_RAW or LIBSSH2_KNOWNHOST_KEYENC_BASE64.
The key is using one of these algorithms:
LIBSSH2_KNOWNHOST_KEY_RSA1, LIBSSH2_KNOWNHOST_KEY_SSHRSA or
LIBSSH2_KNOWNHOST_KEY_SSHDSS.
\fIstore\fP should point to a pointer that gets filled in to point to the
known host data after the addition. NULL can be passed if you don't care about
this pointer.
.SH RETURN VALUE
Returns a regular libssh2 error code, where negative values are error codes
and 0 indicates success.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_init(3)
.BR libssh2_knownhost_free(3)
.BR libssh2_knownhost_check(3)

View File

@@ -0,0 +1,57 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_check 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_check - check a host+key against the list of known hosts
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
char *host, char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **knownhost);
.SH DESCRIPTION
Checks a host and its associated key against the collection of known hosts,
and returns info back about the (partially) matched entry.
\fIhost\fP is a pointer the host name in plain text. The host name can be the
IP numerical address of the host or the full name.
\fIkey\fP is a pointer to the key for the given host.
\fIkeylen\fP is the total size in bytes of the key pointed to by the \fIkey\fP
argument
\fItypemask\fP is a bitmask that specifies format and info about the data
passed to this function. Specificly, it details what format the host name is,
what format the key is and what key type it is.
The host name is given as one of the following types:
LIBSSH2_KNOWNHOST_TYPE_PLAIN or LIBSSH2_KNOWNHOST_TYPE_CUSTOM.
The key is encoded using one of the following encodings:
LIBSSH2_KNOWNHOST_KEYENC_RAW or LIBSSH2_KNOWNHOST_KEYENC_BASE64.
\fIknownhost\fP if set to non-NULL, it must be a pointer to a 'struct
libssh2_knownhost' pointer that gets filled in to point to info about a known
host that matches or partially matches.
.SH RETURN VALUE
\fIlibssh2_knownhost_check(3)\fP returns info about how well the provided
host + key pair matched one of the entries in the list of known hosts.
LIBSSH2_KNOWNHOST_CHECK_FAILURE - something prevented the check to be made
LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - no host match was found
LIBSSH2_KNOWNHOST_CHECK_MATCH - hosts and keys match.
LIBSSH2_KNOWNHOST_CHECK_MISMATCH - host was found, but the keys didn't match!
.SH AVAILABILITY
Added in libssh2 1.2
.SH EXAMPLE
See the ssh2_exec.c example as provided in the tarball.
.SH SEE ALSO
.BR libssh2_knownhost_init(3)
.BR libssh2_knownhost_free(3)
.BR libssh2_knownhost_add(3)

View File

@@ -0,0 +1,26 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_del 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_del - delete a known host entry
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost *entry);
.SH DESCRIPTION
Delete a known host entry from the collection of known hosts.
\fIentry\fP is a pointer to a struct that you can extract with
\fIlibssh2_knownhost_check(3)\fP or \fIlibssh2_knownhost_get(3)\fP.
.SH RETURN VALUE
Returns a regular libssh2 error code, where negative values are error codes
and 0 indicates success.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_init(3)
.BR libssh2_knownhost_free(3)
.BR libssh2_knownhost_add(3)
.BR libssh2_knownhost_check(3)

View File

@@ -0,0 +1,21 @@
.\"
.\" 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
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.
.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

@@ -0,0 +1,35 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_get 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_get - get a known host off the collection of known hosts
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost **store,
struct libssh2_knownhost *prev):
.SH DESCRIPTION
\fIlibssh2_knownhost_get(3)\fP allows an application to iterate over all known
hosts in the collection.
\fIstore\fP should point to a pointer that gets filled in to point to the
known host data.
\fIprev\fP is a pointer to a previous 'struct libssh2_knownhost' 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 hosts.
Returns negative values for error
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_readfile(3)
.BR libssh2_knownhost_writefile(3)
.BR libssh2_knownhost_add(3)

View File

@@ -0,0 +1,25 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_init 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_init - init a collection of known hosts
.SH SYNOPSIS
#include <libssh2.h>
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.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_free(3)
.BR libssh2_knownhost_add(3)
.BR libssh2_knownhost_check(3)

View File

@@ -0,0 +1,29 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_readfile 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_readfile - parse a file of known hosts
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
const char *filename, int type);
.SH DESCRIPTION
Reads a collection of known hosts from a specified file and adds them to the
collection of known hosts.
\fIfilename\fP specifies which file to read
\fItype\fP specifies what file type it is, and
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
format. This file is normally found named ~/.ssh/known_hosts
.SH RETURN VALUE
Returns a regular libssh2 error code, where negative values are error codes
and 0 indicates success.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_init(3)
.BR libssh2_knownhost_free(3)
.BR libssh2_knownhost_check(3)

View File

@@ -0,0 +1,30 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_readline 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_readline - read a known host line
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
const char *line, size_t len, int type):
.SH DESCRIPTION
Tell libssh2 to read a buffer as it if is a line from a known hosts file.
\fIline\fP points to the start of the line
\fIlen\fP is the length of the line in bytes
\fItype\fP specifies what file type it is, and
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
format. This file is normally found named ~/.ssh/known_hosts
.SH RETURN VALUE
Returns a regular libssh2 error code, where negative values are error codes
and 0 indicates success.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_get(3)
.BR libssh2_knownhost_writeline(3)
.BR libssh2_knownhost_readfile(3)

View File

@@ -0,0 +1,29 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_writefile 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_writefile - write a collection of known hosts to a file
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
const char *filename, int type);
.SH DESCRIPTION
Writes all the known hosts to the specified file using the specified file
format.
\fIfilename\fP specifies what filename to create
\fItype\fP specifies what file type it is, and
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
format.
.SH RETURN VALUE
Returns a regular libssh2 error code, where negative values are error codes
and 0 indicates success.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_readfile(3)
.BR libssh2_knownhost_add(3)

View File

@@ -0,0 +1,46 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_writeline 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_writeline - convert a known host to a line for storage
.SH SYNOPSIS
#include <libssh2.h>
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost *known,
char *buffer, size_t buflen,
size_t *outlen,
int type);
.SH DESCRIPTION
Converts a single known host to a single line of output for storage, using
the 'type' output format.
\fIknown\fP identifies which particular known host
\fIbuffer\fP points to an allocated buffer
\fIbuflen\fP is the size of the \fIbuffer\fP. See RETURN VALUE about the size.
\fIoutlen\fP must be a pointer to a size_t variable that will get the output
length of the stored data chunk. The number does not included the trailing
zero!
\fItype\fP specifies what file type it is, and
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
format.
.SH RETURN VALUE
Returns a regular libssh2 error code, where negative values are error codes
and 0 indicates success.
If the provided buffer is deemed too small to fit the data libssh2 wants to
store in it, LIBSSH2_ERROR_BUFFER_TOO_SMALL will be returned. The application
is then adviced to call the function again with a larger buffer. The
\fIoutlen\fP size will then hold the requested size.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_get(3)
.BR libssh2_knownhost_readline(3)
.BR libssh2_knownhost_writefile(3)

View File

@@ -1,4 +1,4 @@
.\" $Id: libssh2_poll.3,v 1.3 2007/06/13 12:51:11 jehousley Exp $
.\" $Id: libssh2_poll.3,v 1.4 2009/04/14 21:38:36 bagder Exp $
.\"
.TH libssh2_poll 3 "14 Dec 2006" "libssh2 0.15" "libssh2 manual"
.SH NAME
@@ -8,6 +8,8 @@ libssh2_poll - poll for activity on a socket, channel or listener
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
.SH DESCRIPTION
This function is deprecated. Do note use.
Poll for activity on a socket, channel, listener, or any combination of these
three types. The calling semantics for this function generally match
\fIpoll(2)\fP however the structure of fds is somewhat more complex in order

View File

@@ -1,4 +1,4 @@
.\" $Id: libssh2_poll_channel_read.3,v 1.2 2007/06/13 12:51:11 jehousley Exp $
.\" $Id: libssh2_poll_channel_read.3,v 1.3 2009/04/14 21:38:36 bagder Exp $
.\"
.TH libssh2_poll_channel_read 3 "14 Dec 2006" "libssh2 0.15" "libssh2 manual"
.SH NAME
@@ -8,6 +8,8 @@ libssh2_poll_channel_read - check if data is available
int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended);
.SH DESCRIPTION
This function is deprecated. Do note use.
\fIlibssh2_poll_channel_read(3)\fP checks to see if data is available in the
\fIchannel\fP's read buffer. No attempt is made with this method to see if
packets are available to be processed. For full polling support, use

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

@@ -0,0 +1,23 @@
.\" $Id: session_hostkey.3,v 1.4 2007/06/13 16:41:33 jehousley Exp $
.\"
.TH libssh2_session_hostkey 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME
libssh2_session_hostkey - get the remote key
.SH SYNOPSIS
#include <libssh2.h>
const char *libssh2_session_hostkey(LIBSSH2_SESSION *session,
size_t *len, int *type);
.SH DESCRIPTION
Returns a pointer to the current host key, the value \fIlen\fP points to will
get the length of the key.
The value \fItype\fP points to the type of hostkey which is one of:
LIBSSH2_HOSTKEY_TYPE_RSA, LIBSSH2_HOSTKEY_TYPE_DSS, or
LIBSSH2_HOSTKEY_TYPE_UNKNOWN.
.SH RETURN VALUE
A pointer, or NULL if something went wrong.
.SH SEE ALSO
.BR libssh2_knownhost_check(3)
.BR libssh2_knownhost_add(3)

View File

@@ -20,14 +20,10 @@ libssh2_sftp_closedir(LIBSSH2_SFTP_HANDLE *handle);
\fIhandle\fP - SFTP File Handle as returned by \fBlibssh2_sftp_open_ex(3)\fP
or \fBlibssh2_sftp_opendir(3)\fP (which is a macro).
Close an active LIBSSH2_SFTP_HANDLE. Because files and directories
share the same underlying storage mechanism these methods may be used
interchangably. It is recommended that
.BR libssh2_sftp_closedir()
be used for files and that
.BR libssh2_sftp_closedir()
be used for directories so that future changes in the library may cause
minimal disruption. Both are macros for \fBlibssh2_sftp_close_handle\fP.
Close an active LIBSSH2_SFTP_HANDLE. Because files and directories share the
same underlying storage mechanism these methods may be used
interchangably. \fBlibssh2_sftp_close(3)\fP and \fBlibssh2_sftp_closedir(3)\fP
are macros for \fBlibssh2_sftp_close_handle(3)\fP.
.SH RETURN VALUE
Return 0 on success or negative on failure. It returns

View File

@@ -1,7 +1,3 @@
Makefile
Makefile.in
.deps
.libs
*.gcno
*.gcda
scp
@@ -18,4 +14,5 @@ sftp_mkdir
sftp_mkdir_nonblock
sftp_write
sftp_write_nonblock
config.h.in
ssh2_exec

View File

@@ -8,7 +8,7 @@ noinst_PROGRAMS = ssh2 \
sftp_write sftp_write_nonblock \
sftp_mkdir sftp_mkdir_nonblock \
sftp_RW_nonblock \
sftpdir sftpdir_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

View File

@@ -1,5 +1,5 @@
/*
* $Id: scp.c,v 1.11 2008/11/10 16:48:41 bagder Exp $
* $Id: scp.c,v 1.12 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do a simple SCP transfer.
*/
@@ -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
@@ -164,10 +164,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
fprintf(stderr, "all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: scp_nonblock.c,v 1.15 2009/03/25 22:52:32 bagder Exp $
* $Id: scp_nonblock.c,v 1.16 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SCP transfers in a non-blocking manner.
*
@@ -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>
@@ -132,23 +135,6 @@ int main(int argc, char *argv[])
return -1;
}
/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* Create a session instance */
session = libssh2_session_init();
if (!session)
@@ -276,10 +262,8 @@ shutdown:
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
fprintf(stderr, "all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: scp_write.c,v 1.6 2008/11/10 16:48:41 bagder Exp $
* $Id: scp_write.c,v 1.7 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do a simple SCP transfer.
*/
@@ -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;
@@ -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");
@@ -186,10 +193,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
fprintf(stderr, "all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: scp_write_nonblock.c,v 1.9 2008/11/10 16:48:41 bagder Exp $
* $Id: scp_write_nonblock.c,v 1.10 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do a simple SCP transfer.
*/
@@ -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;
@@ -102,23 +102,6 @@ int main(int argc, char *argv[])
return -1;
}
/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* Create a session instance
*/
session = libssh2_session_init();
@@ -170,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) !=
@@ -193,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");
@@ -225,10 +213,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
fprintf(stderr, "all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftp.c,v 1.16 2009/03/31 12:20:36 bagder Exp $
* $Id: sftp.c,v 1.17 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP transfers.
*
@@ -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
@@ -236,10 +236,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
fprintf(stderr, "all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftp_RW_nonblock.c,v 1.12 2008/11/10 16:48:41 bagder Exp $
* $Id: sftp_RW_nonblock.c,v 1.13 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP transfers in a non-blocking manner.
*
@@ -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>
@@ -84,23 +87,6 @@ int main(int argc, char *argv[])
return -1;
}
/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* Create a session instance
*/
session = libssh2_session_init();
@@ -293,10 +279,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftp_mkdir.c,v 1.8 2008/11/10 16:48:41 bagder Exp $
* $Id: sftp_mkdir.c,v 1.9 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP mkdir
*
@@ -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
@@ -155,10 +155,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftp_mkdir_nonblock.c,v 1.11 2008/11/10 16:48:41 bagder Exp $
* $Id: sftp_mkdir_nonblock.c,v 1.12 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP non-blocking mkdir.
*
@@ -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
@@ -88,23 +88,6 @@ int main(int argc, char *argv[])
return -1;
}
/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* Create a session instance
*/
session = libssh2_session_init();
@@ -178,10 +161,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftp_nonblock.c,v 1.17 2009/03/13 22:14:47 bagder Exp $
* $Id: sftp_nonblock.c,v 1.18 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP non-blocking transfers.
*
@@ -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>
@@ -133,23 +136,6 @@ int main(int argc, char *argv[])
return -1;
}
/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* Create a session instance */
session = libssh2_session_init();
if (!session)
@@ -278,10 +264,8 @@ shutdown:
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
fprintf(stderr, "all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftp_write.c,v 1.10 2009/03/31 12:20:36 bagder Exp $
* $Id: sftp_write.c,v 1.11 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP write transfers.
*
@@ -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
@@ -195,10 +195,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftp_write_nonblock.c,v 1.13 2009/03/31 12:20:36 bagder Exp $
* $Id: sftp_write_nonblock.c,v 1.14 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP non-blocking write transfers.
*
@@ -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
@@ -103,23 +103,6 @@ int main(int argc, char *argv[])
return -1;
}
/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* Create a session instance
*/
session = libssh2_session_init();
@@ -139,10 +122,10 @@ int main(int argc, char *argv[])
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
/* 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_MD5);
printf("Fingerprint: ");
@@ -224,10 +207,8 @@ shutdown:
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftpdir.c,v 1.10 2008/11/10 16:48:41 bagder Exp $
* $Id: sftpdir.c,v 1.11 2009/04/28 10:35:30 bagder Exp $
*
* Sample doing an SFTP directory listing.
*
@@ -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
@@ -207,10 +207,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: sftpdir_nonblock.c,v 1.12 2008/11/10 16:48:41 bagder Exp $
* $Id: sftpdir_nonblock.c,v 1.13 2009/04/28 10:35:30 bagder Exp $
*
* Sample doing an SFTP directory listing.
*
@@ -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
@@ -88,23 +88,6 @@ int main(int argc, char *argv[])
return -1;
}
/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* Create a session instance
*/
session = libssh2_session_init();
@@ -236,10 +219,8 @@ int main(int argc, char *argv[])
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");

View File

@@ -1,5 +1,5 @@
/*
* $Id: ssh2.c,v 1.18 2008/11/10 16:48:41 bagder Exp $
* $Id: ssh2.c,v 1.19 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SSH2 connect.
*
@@ -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
@@ -46,7 +46,8 @@ const char *password="password";
static void kbd_callback(const char *name, int name_len,
const char *instruction, int instruction_len, int num_prompts,
const char *instruction, int instruction_len,
int num_prompts,
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
void **abstract)
@@ -92,13 +93,11 @@ int main(int argc, char *argv[])
password = argv[3];
}
/* Ultra basic "connect to port 22 on localhost"
* Your code is responsible for creating the socket establishing the connection
/* 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);
#ifndef WIN32
fcntl(sock, F_SETFL, 0);
#endif
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
@@ -108,8 +107,8 @@ int main(int argc, char *argv[])
return -1;
}
/* Create a session instance and start it up
* This will trade welcome banners, exchange keys, and setup crypto, compression, and MAC layers
/* 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)) {
@@ -117,9 +116,10 @@ int main(int argc, char *argv[])
return -1;
}
/* 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
/* 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_MD5);
printf("Fingerprint: ");
@@ -164,7 +164,8 @@ int main(int argc, char *argv[])
}
} else if (auth_pw & 2) {
/* Or via keyboard-interactive */
if (libssh2_userauth_keyboard_interactive(session, username, &kbd_callback) ) {
if (libssh2_userauth_keyboard_interactive(session, username,
&kbd_callback) ) {
printf("\tAuthentication by keyboard-interactive failed!\n");
goto shutdown;
} else {
@@ -172,7 +173,8 @@ int main(int argc, char *argv[])
}
} else if (auth_pw & 4) {
/* Or by public key */
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) {
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1,
keyfile2, password)) {
printf("\tAuthentication by public key failed!\n");
goto shutdown;
} else {
@@ -235,14 +237,13 @@ int main(int argc, char *argv[])
shutdown:
libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done!\n");

294
example/simple/ssh2_exec.c Normal file
View File

@@ -0,0 +1,294 @@
/*
* $Id: ssh2_exec.c,v 1.4 2009/05/07 20:30:22 bagder Exp $
*
* Sample showing how to use libssh2 to execute a command remotely.
*
* The sample code has fixed values for host name, user name, password
* and command to run.
*
* Run it like this:
*
* $ ./ssh2_exec 127.0.0.1 user password "uptime"
*
*/
#include "libssh2_config.h"
#include <libssh2.h>
#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_SELECT_H
# include <sys/select.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
{
struct timeval timeout;
int rc;
fd_set fd;
fd_set *writefd = NULL;
fd_set *readfd = NULL;
int dir;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
FD_ZERO(&fd);
FD_SET(socket_fd, &fd);
/* now make sure we wait in the correct direction */
dir = libssh2_session_block_directions(session);
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
readfd = &fd;
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
writefd = &fd;
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
return rc;
}
int main(int argc, char *argv[])
{
const char *hostname = "127.0.0.1";
const char *commandline = "uptime";
const char *username = "user";
const char *password = "password";
unsigned long hostaddr;
int sock;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
int rc;
int exitcode;
int bytecount = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
int type;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1)
/* must be ip address only */
hostname = argv[1];
if (argc > 2) {
username = argv[2];
}
if (argc > 3) {
password = argv[3];
}
if (argc > 4) {
commandline = argv[4];
}
hostaddr = inet_addr(hostname);
/* 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);
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");
return -1;
}
/* Create a session instance */
session = libssh2_session_init();
if (!session)
return -1;
/* tell libssh2 we want it all done non-blocking */
libssh2_session_set_blocking(session, 0);
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
while ((rc = libssh2_session_startup(session, sock)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1;
}
nh = libssh2_knownhost_init(session);
if(!nh) {
/* eeek, do cleanup here */
return 2;
}
/* read all hosts from here */
libssh2_knownhost_readfile(nh, "known_hosts",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
/* store all known hosts to here */
libssh2_knownhost_writefile(nh, "dumpfile",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
fingerprint = libssh2_session_hostkey(session, &len, &type);
if(fingerprint) {
struct libssh2_knownhost *host;
int check = libssh2_knownhost_check(nh, (char *)hostname,
(char *)fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
fprintf(stderr, "Host check: %d, key: %s\n", check,
(check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
host->key:"<none>");
/*****
* At this point, we could verify that 'check' tells us the key is
* fine or bail out.
*****/
}
else {
/* eeek, do cleanup here */
return 3;
}
libssh2_knownhost_free(nh);
if ( strlen(password) != 0 ) {
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username, password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Authentication by password failed.\n");
goto shutdown;
}
}
else {
/* Or by public key */
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
"/home/user/"
".ssh/id_rsa.pub",
"/home/user/"
".ssh/id_rsa",
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "\tAuthentication by public key failed\n");
goto shutdown;
}
}
#if 0
libssh2_trace(session, ~0 );
#endif
/* Exec non-blocking on the remove host */
while( (channel = libssh2_channel_open_session(session)) == NULL &&
libssh2_session_last_error(session,NULL,NULL,0) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( channel == NULL )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
while( (rc = libssh2_channel_exec(channel, commandline)) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( rc != 0 )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
bytecount += rc;
fprintf(stderr, "We read:\n");
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
fprintf(stderr, "\n");
}
else {
fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else
break;
}
exitcode = 127;
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
waitsocket(sock, session);
if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );
}
printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
libssh2_channel_free(channel);
channel = NULL;
shutdown:
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
fprintf(stderr, "all done\n");
return 0;
}

433
example/simple/x11.c Normal file
View File

@@ -0,0 +1,433 @@
/*
*
* Sample showing how to makes SSH2 with X11 Forwarding works.
*
* Usage :
* "ssh2 host user password [DEBUG]"
*/
#include <string.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <termios.h>
#include <libssh2.h>
#define _PATH_UNIX_X "/tmp/.X11-unix/X%d"
/*
* Chained list that contains channels and associated X11 socket for each X11
* connections
*/
struct chan_X11_list {
LIBSSH2_CHANNEL *chan;
int sock;
struct chan_X11_list *next;
};
struct chan_X11_list * gp_x11_chan = NULL;
struct termios _saved_tio;
/*
* Utility function to remove a Node of the chained list
*/
static void remove_node(struct chan_X11_list *elem)
{
struct chan_X11_list *current_node = NULL;
current_node = gp_x11_chan;
if (gp_x11_chan == elem) {
/* Removing the only one element in the list */
free(gp_x11_chan);
gp_x11_chan = NULL;
}
while( current_node->next != NULL) {
if (current_node->next ==elem) {
current_node->next = current_node->next->next;
current_node = current_node->next;
free(current_node);
break;
}
}
}
static void session_shutdown(LIBSSH2_SESSION *session)
{
libssh2_session_disconnect(session,
"Session Shutdown, Thank you for playing");
libssh2_session_free(session);
}
static int _raw_mode(void)
{
int rc;
struct termios tio;
rc = tcgetattr(fileno(stdin), &tio);
if (rc != -1) {
_saved_tio = tio;
cfmakeraw(&tio);
rc = tcsetattr(fileno(stdin), TCSADRAIN, &tio);
}
return rc;
}
static int _normal_mode(void)
{
int rc;
rc = tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio);
return rc;
}
/*
* CallBack to initialize the forwarding.
* Save the channel to loop on it, save the X11 forwarded socket to send
* and receive info from our X server.
*/
static void x11_callback(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel,
char *shost, int sport, void **abstract)
{
const char * display = NULL;
char * ptr = NULL;
char * temp_buff = NULL;
int display_port = 0;
int sock = 0;
int rc = 0;
struct sockaddr_un addr;
struct chan_X11_list *new;
struct chan_X11_list *chan_iter;
/*
* Connect to the display
* Inspired by x11_connect_display in openssh
*/
display = getenv("DISPLAY");
if ( display != NULL) {
if (strncmp( display, "unix:", 5) == 0 ||
display[0] == ':') {
/* Connect to the local unix domain */
ptr = strrchr(display, ':');
temp_buff = (char *) calloc(strlen(ptr+1), sizeof(char));
memcpy(temp_buff, ptr+1, strlen(ptr+1));
display_port = atoi(temp_buff);
sock = socket(AF_UNIX,SOCK_STREAM, 0);
if (sock <0)
return;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path),
_PATH_UNIX_X, display_port);
rc = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
if (rc != -1){
/* Connection Successfull */
if (gp_x11_chan == NULL) {
/* Calloc ensure that gp_X11_chan is full of 0 */
gp_x11_chan = (struct chan_X11_list *)
calloc(1, sizeof(struct chan_X11_list));
gp_x11_chan->sock = sock;
gp_x11_chan->chan = channel;
gp_x11_chan->next = NULL;
}
else {
chan_iter = gp_x11_chan;
while (chan_iter->next != NULL)
chan_iter = chan_iter->next;
/* Create the new Node */
new = (struct chan_X11_list *)
malloc(sizeof(struct chan_X11_list));
new->sock = sock;
new->chan = channel;
new->next = NULL;
chan_iter->next = new;
}
}
else
close(sock);
}
}
return;
}
/*
* Send and receive Data for the X11 channel.
* If the connection is closed, returns -1, 0 either.
*/
static int x11_send_receive(LIBSSH2_CHANNEL *channel, int sock)
{
char * buf = NULL;
int bufsize = 8192;
int rc = 0;
int nfds = 1;
LIBSSH2_POLLFD *fds = NULL;
fd_set set;
struct timeval timeval_out;
timeval_out.tv_sec = 0;
timeval_out.tv_usec = 0;
FD_ZERO(&set);
FD_SET(sock,&set);
if ((buf = calloc (bufsize, sizeof(char))) == NULL)
return 0;
if ((fds = malloc (sizeof (LIBSSH2_POLLFD))) == NULL) {
free(buf);
return 0;
}
fds[0].type = LIBSSH2_POLLFD_CHANNEL;
fds[0].fd.channel = channel;
fds[0].events = LIBSSH2_POLLFD_POLLIN;
fds[0].revents = LIBSSH2_POLLFD_POLLIN;
rc = libssh2_poll(fds, nfds, 0);
if (rc >0) {
rc = libssh2_channel_read(channel, buf,sizeof(buf));
rc = write(sock, buf, rc);
}
rc = select(sock+1,&set,NULL,NULL,&timeval_out);
if (rc > 0) {
memset((void *)buf,0,bufsize);
/* Data in sock*/
rc = read(sock, buf,sizeof(buf));
if (rc > 0)
rc = libssh2_channel_write(channel,buf, rc);
else
return -1;
}
free(fds);
free(buf);
if (libssh2_channel_eof (channel) == 1) {
return -1;
}
return 0;
}
/*
* Main, more than inspired by ssh2.c by Bagder
*/
int
main (int argc, char *argv[])
{
unsigned long hostaddr = 0;
int sock = 0;
int rc = 0;
struct sockaddr_in sin;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
char *username = NULL;
char *password = NULL;
size_t bufsiz = 8193;
char *buf = NULL;
int set_debug_on = 0;
int nfds = 1;
LIBSSH2_POLLFD *fds = NULL;
/* Chan List struct */
struct chan_X11_list *current_node = NULL;
/* Struct winsize for term size */
struct winsize w_size;
struct winsize w_size_bck;
/* For select on stdin */
fd_set set;
struct timeval timeval_out;
timeval_out.tv_sec = 0;
timeval_out.tv_usec = 10;
if (argc > 3) {
hostaddr = inet_addr(argv[1]);
username = argv[2];
password = argv[3];
}
else {
fprintf(stderr, "Usage: %s destination username password",
argv[0]);
return -1;
}
if (argc > 4) {
set_debug_on = 1;
fprintf (stderr, "DEBUG is ON: %d\n", set_debug_on);
}
sock = socket (AF_INET, SOCK_STREAM, 0);
sin.sin_family = AF_INET;
sin.sin_port = htons (22);
sin.sin_addr.s_addr = hostaddr;
rc = connect(sock, (struct sockaddr *) &sin,
sizeof(struct sockaddr_in));
if (rc != 0) {
fprintf (stderr, "Failed to established connection!\n");
return -1;
}
/* Open a session */
session = libssh2_session_init ();
rc = libssh2_session_startup (session, sock);
if (rc != 0) {
fprintf(stderr, "Failed Start the SSH session\n");
return -1;
}
if (set_debug_on == 1)
libssh2_trace(session, LIBSSH2_TRACE_CONN);
/* Set X11 Callback */
libssh2_session_callback_set(session, LIBSSH2_CALLBACK_X11,
(void *)x11_callback);
/* Authenticate via password */
rc = libssh2_userauth_password(session, username, password);
if (rc != 0) {
fprintf(stderr, "Failed to authenticate\n");
session_shutdown(session);
close(sock);
return -1;
}
/* Open a channel */
channel = libssh2_channel_open_session(session);
if ( channel == NULL ) {
fprintf(stderr, "Failed to open a new channel\n");
session_shutdown(session);
close(sock);
return -1;
}
/* Request a PTY */
rc = libssh2_channel_request_pty( channel, "xterm");
if (rc != 0) {
fprintf(stderr, "Failed to request a pty\n");
session_shutdown(session);
close(sock);
return -1;
}
/* Request X11 */
rc = libssh2_channel_x11_req(channel,0);
if(rc!=0) {
fprintf(stderr, "Failed to request X11 forwarding\n");
session_shutdown(session);
close(sock);
return -1;
}
/* Request a shell */
rc = libssh2_channel_shell(channel);
if (rc!=0) {
fprintf(stderr, "Failed to open a shell\n");
session_shutdown(session);
close(sock);
return -1;
}
rc = _raw_mode();
if (rc != 0) {
fprintf(stderr, "Failed to entered in raw mode\n");
session_shutdown(session);
close(sock);
return -1;
}
while (1) {
FD_ZERO(&set);
FD_SET(fileno(stdin),&set);
/* Search if a resize pty has to be send */
ioctl(fileno(stdin), TIOCGWINSZ, &w_size);
if ((w_size.ws_row != w_size_bck.ws_row) ||
(w_size.ws_col != w_size_bck.ws_col)) {
w_size_bck = w_size;
libssh2_channel_request_pty_size(channel,
w_size.ws_col,
w_size.ws_row);
}
if ((buf = calloc (bufsiz, sizeof(char))) == NULL)
break;
if ((fds = malloc (sizeof (LIBSSH2_POLLFD))) == NULL) {
free(buf);
break;
}
fds[0].type = LIBSSH2_POLLFD_CHANNEL;
fds[0].fd.channel = channel;
fds[0].events = LIBSSH2_POLLFD_POLLIN;
fds[0].revents = LIBSSH2_POLLFD_POLLIN;
rc = libssh2_poll(fds, nfds, 0);
if (rc >0) {
rc = libssh2_channel_read(channel, buf,sizeof(buf));
fprintf(stdout, "%s", buf);
fflush(stdout);
}
/* Looping on X clients */
if (gp_x11_chan != NULL) {
current_node = gp_x11_chan;
}
else
current_node = NULL;
while (current_node != NULL) {
rc = x11_send_receive(current_node->chan, current_node->sock);
if (rc == -1){
shutdown(current_node->sock,SHUT_RDWR);
close(current_node->sock);
remove_node(current_node);
}
current_node = current_node->next;
}
rc = select(fileno(stdin)+1,&set,NULL,NULL,&timeval_out);
if (rc > 0) {
/* Data in stdin*/
rc = read(fileno(stdin), buf,1);
if (rc > 0)
libssh2_channel_write(channel,buf, sizeof(buf));
}
free (fds);
free (buf);
if (libssh2_channel_eof (channel) == 1) {
break;
}
}
if (channel) {
libssh2_channel_free (channel);
channel = NULL;
}
_normal_mode();
return 0;
}

View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -83,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_CVS"
#define LIBSSH2_VERSION "1.2.2_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 0
#define LIBSSH2_VERSION_MINOR 2
#define LIBSSH2_VERSION_PATCH 2
/* This is the numeric version of the libssh2 version number, meant for easier
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
@@ -110,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 0x010100
#define LIBSSH2_VERSION_NUM 0x010202
/*
* 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
@@ -240,6 +241,7 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
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_POLLFD {
unsigned char type; /* LIBSSH2_POLLFD_* below */
@@ -292,6 +294,11 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_HOSTKEY_HASH_MD5 1
#define LIBSSH2_HOSTKEY_HASH_SHA1 2
/* Hostkey Types */
#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0
#define LIBSSH2_HOSTKEY_TYPE_RSA 1
#define LIBSSH2_HOSTKEY_TYPE_DSS 2
/* Disconnect Codes (defined by SSH protocol) */
#define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
#define SSH_DISCONNECT_PROTOCOL_ERROR 2
@@ -348,6 +355,10 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35
#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
/* Session API */
LIBSSH2_API LIBSSH2_SESSION *
@@ -377,6 +388,9 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session);
LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session,
int hash_type);
LIBSSH2_API const char *libssh2_session_hostkey(LIBSSH2_SESSION *session,
size_t *len, int *type);
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session,
int method_type,
const char *prefs);
@@ -663,6 +677,198 @@ LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest,
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 */
void *node; /* handle to the internal representation of this host */
char *name; /* this is NULL if no plain text host name exists */
char *key; /* key in base64/printable format */
int typemask;
};
/*
* libssh2_knownhost_init
*
* Init a collection of known hosts. Returns the pointer to a collection.
*
*/
LIBSSH2_API LIBSSH2_KNOWNHOSTS *
libssh2_knownhost_init(LIBSSH2_SESSION *session);
/*
* libssh2_knownhost_add
*
* Add a host and its associated key to the collection of known hosts.
*
* The 'type' argument specifies on what format the given host is:
*
* plain - ascii "hostname.domain.tld"
* sha1 - SHA1(<salt> <host>) base64-encoded!
* custom - another hash
*
* If 'sha1' is selected as type, the salt must be provided to the salt
* argument. This too base64 encoded.
*
* The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If
* a custom type is used, salt is ignored and you must provide the host
* pre-hashed when checking for it in the libssh2_knownhost_check() function.
*
*/
/* host format (2 bits) */
#define LIBSSH2_KNOWNHOST_TYPE_MASK 0xffff
#define LIBSSH2_KNOWNHOST_TYPE_PLAIN 1
#define LIBSSH2_KNOWNHOST_TYPE_SHA1 2 /* always base64 encoded */
#define LIBSSH2_KNOWNHOST_TYPE_CUSTOM 3
/* key format (2 bits) */
#define LIBSSH2_KNOWNHOST_KEYENC_MASK (3<<16)
#define LIBSSH2_KNOWNHOST_KEYENC_RAW (1<<16)
#define LIBSSH2_KNOWNHOST_KEYENC_BASE64 (2<<16)
/* type of key (2 bits) */
#define LIBSSH2_KNOWNHOST_KEY_MASK (3<<18)
#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18
#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18)
#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18)
#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18)
LIBSSH2_API int
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
const char *host,
const char *salt,
const char *key, size_t keylen, int typemask,
struct libssh2_knownhost **store);
/*
* libssh2_knownhost_check
*
* Check a host and its associated key against the collection of known hosts.
*
* The type is the type/format of the given host name.
*
* plain - ascii "hostname.domain.tld"
* custom - prehashed base64 encoded. Note that this cannot use any salts.
*
*
* 'knownhost' may be set to NULL if you don't care about that info.
*
* Returns:
*
* LIBSSH2_KNOWNHOST_CHECK_* values, see below
*
*/
#define LIBSSH2_KNOWNHOST_CHECK_MATCH 0
#define LIBSSH2_KNOWNHOST_CHECK_MISMATCH 1
#define LIBSSH2_KNOWNHOST_CHECK_NOTFOUND 2
#define LIBSSH2_KNOWNHOST_CHECK_FAILURE 3
LIBSSH2_API int
libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, const char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **knownhost);
/*
* libssh2_knownhost_del
*
* Remove a host from the collection of known hosts. The 'entry' struct is
* retrieved by a call to libssh2_knownhost_check().
*
*/
LIBSSH2_API int
libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost *entry);
/*
* libssh2_knownhost_free
*
* Free an entire collection of known hosts.
*
*/
LIBSSH2_API void
libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
/*
* libssh2_knownhost_readline()
*
* Pass in a line of a file of 'type'. It makes libssh2 read this line.
*
* LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
*
*/
LIBSSH2_API int
libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
const char *line, size_t len, int type);
/*
* libssh2_knownhost_readfile
*
* Add hosts+key pairs from a given file.
*
* Returns a negative value for error or number of successfully added hosts.
*
* This implementation currently only knows one 'type' (openssh), all others
* are reserved for future use.
*/
#define LIBSSH2_KNOWNHOST_FILE_OPENSSH 1
LIBSSH2_API int
libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
const char *filename, int type);
/*
* libssh2_knownhost_writeline()
*
* Ask libssh2 to convert a known host to an output line for storage.
*
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
* output buffer is too small to hold the desired output.
*
* This implementation currently only knows one 'type' (openssh), all others
* are reserved for future use.
*
*/
LIBSSH2_API int
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost *known,
char *buffer, size_t buflen,
size_t *outlen, /* the amount of written data */
int type);
/*
* libssh2_knownhost_writefile
*
* Write hosts+key pairs to a given file.
*
* This implementation currently only knows one 'type' (openssh), all others
* are reserved for future use.
*/
LIBSSH2_API int
libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
const char *filename, int type);
/*
* libssh2_knownhost_get()
*
* Traverse the internal list of known hosts. 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 host was stored in 'store'
* 1 if end of hosts
* [negative] on errors
*/
LIBSSH2_API int
libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost **store,
struct libssh2_knownhost *prev);
/* NOTE NOTE NOTE
libssh2_trace() has no function in builds that aren't built with debug

View File

@@ -46,6 +46,8 @@
#ifndef LIBSSH2_PUBLICKEY_H
#define LIBSSH2_PUBLICKEY_H 1
#include "libssh2.h"
typedef struct _LIBSSH2_PUBLICKEY LIBSSH2_PUBLICKEY;
typedef struct _libssh2_publickey_attribute {

View File

@@ -38,6 +38,8 @@
#ifndef LIBSSH2_SFTP_H
#define LIBSSH2_SFTP_H 1
#include "libssh2.h"
#ifndef WIN32
#include <unistd.h>
#endif

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}

5
m4/.gitignore vendored Normal file
View File

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

View File

@@ -5,7 +5,7 @@
##
## Comments to: Guenter Knauf <eflash@gmx.net>
##
## $Id: Makefile.netware,v 1.13 2009/03/06 07:25:37 gknauf Exp $
## $Id: Makefile.netware,v 1.14 2009/04/09 03:13:51 gknauf Exp $
#
#########################################################################
@@ -21,7 +21,7 @@ endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../openssl-0.9.8j
OPENSSL_PATH = ../../openssl-0.9.8k
endif
# Edit the path below to point to your Distribution folder.
@@ -76,7 +76,7 @@ ifdef METROWERKS
MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support/Metrowerks Support
CC = mwccnlm
else
CC = gcc
CC = $(CROSSPREFIX)gcc
endif
CP = cp -afv
# RM = rm -f
@@ -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)
@@ -119,12 +119,12 @@ else
CFLAGS += -align 1
endif
else
LD = nlmconv
LD = $(CROSSPREFIX)nlmconv
LDFLAGS = -T
AR = ar
AR = $(CROSSPREFIX)ar
ARFLAGS = -cq
LIBEXT = a
RANLIB = ranlib
RANLIB = $(CROSSPREFIX)ranlib
CFLAGS += -fno-builtin -fpcc-struct-return -fno-strict-aliasing
CFLAGS += -Wall # -pedantic
#CFLAGS += -Wno-pointer-sign
@@ -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

@@ -5,7 +5,7 @@
##
## Comments to: Guenter Knauf <eflash@gmx.net>
##
## $Id: Makefile.netware,v 1.9 2009/03/06 07:25:37 gknauf Exp $
## $Id: Makefile.netware,v 1.10 2009/04/09 03:13:52 gknauf Exp $
#
#########################################################################
@@ -21,7 +21,7 @@ endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../../openssl-0.9.8j
OPENSSL_PATH = ../../../openssl-0.9.8k
endif
# Edit the var below to enable static linking of libssh2 and libz
@@ -29,7 +29,7 @@ LINK_STATIC = 1
# Edit the vars below to change NLM target settings.
SAMPLES = ../../example/simple
TARGETS := $(patsubst $(SAMPLES)/%.c,%.nlm,$(strip $(wildcard $(SAMPLES)/*.c)))
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/
@@ -70,7 +70,7 @@ ifdef METROWERKS
MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support/Metrowerks Support
CC = mwccnlm
else
CC = gcc
CC = $(CROSSPREFIX)gcc
endif
CP = cp -afv
# RM = rm -f
@@ -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
@@ -131,10 +134,17 @@ SDK_CLIB = $(NDK_ROOT)/nwsdk
SDK_LIBC = $(NDK_ROOT)/libc
SNPRINTF = $(NDKBASE)/snprintf
INCLUDES = -I. -I../../include
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)
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) >> $@

3
src/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
libssh2_config.h
libssh2_config.h.in
stamp-h1

View File

@@ -1,15 +1,10 @@
# $Id: Makefile.am,v 1.19 2009/03/26 22:25:23 bagder Exp $
# $Id: Makefile.am,v 1.21 2009/05/07 17:21:56 bagder Exp $
AUTOMAKE_OPTIONS = foreign nostdinc
libssh2_la_SOURCES = 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 libssh2_priv.h \
openssl.h libgcrypt.h transport.c version.c transport.h channel.h comp.h mac.h
# Makefile.inc provides the CSOURCES and HHEADERS defines
include ../Makefile.inc
if LIBGCRYPT
libssh2_la_SOURCES += libgcrypt.c pem.c
else
libssh2_la_SOURCES += openssl.c
endif
libssh2_la_SOURCES = $(CSOURCES) $(HHEADERS)
EXTRA_DIST = libssh2_config.h.in NMakefile

View File

@@ -45,6 +45,7 @@
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <assert.h>
#include "channel.h"
#include "transport.h"
@@ -60,13 +61,13 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session)
unsigned long id = session->next_channel;
LIBSSH2_CHANNEL *channel;
channel = session->channels.head;
channel = _libssh2_list_first(&session->channels);
while (channel) {
if (channel->local.id > id) {
id = channel->local.id;
}
channel = channel->next;
channel = _libssh2_list_next(&channel->node);
}
/* This is a shortcut to avoid waiting for close packets on channels we've
@@ -90,31 +91,32 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session)
LIBSSH2_CHANNEL *
_libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id)
{
LIBSSH2_CHANNEL *channel = session->channels.head;
while (channel) {
if (channel->local.id == channel_id) {
LIBSSH2_CHANNEL *channel;
LIBSSH2_LISTENER *l;
for(channel = _libssh2_list_first(&session->channels);
channel;
channel = _libssh2_list_next(&channel->node)) {
if (channel->local.id == channel_id)
return channel;
}
/* We didn't find the channel in the session, let's then check its
listeners since each listener may have its own set of pending channels
*/
for(l = _libssh2_list_first(&session->listeners); l;
l = _libssh2_list_next(&l->node)) {
for(channel = _libssh2_list_first(&l->queue);
channel;
channel = _libssh2_list_next(&channel->node)) {
if (channel->local.id == channel_id)
return channel;
}
channel = channel->next;
}
return NULL;
}
#define CHANNEL_ADD(session, channel) \
{ \
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); \
(channel)->session = (session); \
}
/*
* _libssh2_channel_open
*
@@ -177,8 +179,10 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
session->open_channel->remote.window_size = window_size;
session->open_channel->remote.window_size_initial = window_size;
session->open_channel->remote.packet_size = packet_size;
session->open_channel->session = session;
CHANNEL_ADD(session, session->open_channel);
_libssh2_list_add(&session->channels,
&session->open_channel->node);
s = session->open_packet =
LIBSSH2_ALLOC(session, session->open_packet_len);
@@ -288,18 +292,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
unsigned char channel_id[4];
LIBSSH2_FREE(session, session->open_channel->channel_type);
if (session->open_channel->next) {
session->open_channel->next->prev = session->open_channel->prev;
}
if (session->open_channel->prev) {
session->open_channel->prev->next = session->open_channel->next;
}
if (session->channels.head == session->open_channel) {
session->channels.head = session->open_channel->next;
}
if (session->channels.tail == session->open_channel) {
session->channels.tail = session->open_channel->prev;
}
_libssh2_list_remove(&session->open_channel->node);
/* Clear out packets meant for this channel */
_libssh2_htonu32(channel_id, session->open_channel->local.id);
@@ -406,18 +399,12 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
/* by default we set (keep?) idle state... */
session->direct_state = libssh2_NB_state_idle;
if (!channel) {
if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
/* The error code is still set to LIBSSH2_ERROR_EAGAIN,
set our state to created to avoid re-creating the package
on next invoke */
if (!channel &&
libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
/* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state
to created to avoid re-creating the package on next invoke */
session->direct_state = libssh2_NB_state_created;
return NULL;
} else {
LIBSSH2_FREE(session, session->direct_message);
session->direct_message = NULL;
return NULL;
}
}
LIBSSH2_FREE(session, session->direct_message);
@@ -575,12 +562,8 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
listener->queue_size = 0;
listener->queue_maxsize = queue_maxsize;
listener->next = session->listeners;
listener->prev = NULL;
if (session->listeners) {
session->listeners->prev = listener;
}
session->listeners = listener;
/* append this to the parent's list of listeners */
_libssh2_list_add(&session->listeners, &listener->node);
if (bound_port) {
*bound_port = listener->port;
@@ -632,7 +615,7 @@ libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host,
static int channel_forward_cancel(LIBSSH2_LISTENER *listener)
{
LIBSSH2_SESSION *session = listener->session;
LIBSSH2_CHANNEL *queued = listener->queue;
LIBSSH2_CHANNEL *queued;
unsigned char *packet, *s;
unsigned long host_len = strlen(listener->host);
/* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) +
@@ -650,7 +633,7 @@ static int channel_forward_cancel(LIBSSH2_LISTENER *listener)
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memeory for setenv packet", 0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
*(s++) = SSH_MSG_GLOBAL_REQUEST;
@@ -685,32 +668,27 @@ static int channel_forward_cancel(LIBSSH2_LISTENER *listener)
0);
LIBSSH2_FREE(session, packet);
listener->chanFwdCncl_state = libssh2_NB_state_idle;
return -1;
return LIBSSH2_ERROR_SOCKET_SEND;
}
LIBSSH2_FREE(session, packet);
listener->chanFwdCncl_state = libssh2_NB_state_sent;
}
queued = _libssh2_list_first(&listener->queue);
while (queued) {
LIBSSH2_CHANNEL *next = queued->next;
LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node);
rc = libssh2_channel_free(queued);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
queued = next;
}
LIBSSH2_FREE(session, listener->host);
if (listener->next) {
listener->next->prev = listener->prev;
}
if (listener->prev) {
listener->prev->next = listener->next;
} else {
session->listeners = listener->next;
}
/* remove this entry from the parent's list of listeners */
_libssh2_list_remove(&listener->node);
LIBSSH2_FREE(session, listener);
@@ -743,42 +721,33 @@ libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
static LIBSSH2_CHANNEL *
channel_forward_accept(LIBSSH2_LISTENER *listener)
{
libssh2pack_t rc;
int rc;
do {
rc = _libssh2_transport_read(listener->session);
if (rc == PACKET_EAGAIN) {
libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for packet", 0);
return NULL;
}
} while (rc > 0);
if (listener->queue) {
LIBSSH2_SESSION *session = listener->session;
LIBSSH2_CHANNEL *channel;
if (_libssh2_list_first(&listener->queue)) {
LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue);
channel = listener->queue;
/* detach channel from listener's queue */
_libssh2_list_remove(&channel->node);
listener->queue = listener->queue->next;
if (listener->queue) {
listener->queue->prev = NULL;
}
channel->prev = NULL;
channel->next = session->channels.head;
session->channels.head = channel;
if (channel->next) {
channel->next->prev = channel;
} else {
session->channels.tail = channel;
}
listener->queue_size--;
/* add channel to session's channel list */
_libssh2_list_add(&channel->session->channels, &channel->node);
return channel;
}
if (rc == PACKET_EAGAIN) {
libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for packet", 0);
}
else
libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
"Channel not found", 0);
return NULL;
}
@@ -832,7 +801,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
if (!channel->setenv_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memeory for setenv packet", 0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
*(s++) = SSH_MSG_CHANNEL_REQUEST;
@@ -862,7 +831,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
rc = _libssh2_transport_write(session, channel->setenv_packet,
channel->setenv_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel-request packet for "
@@ -871,7 +840,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
LIBSSH2_FREE(session, channel->setenv_packet);
channel->setenv_packet = NULL;
channel->setenv_state = libssh2_NB_state_idle;
return -1;
return LIBSSH2_ERROR_SOCKET_SEND;
}
LIBSSH2_FREE(session, channel->setenv_packet);
channel->setenv_packet = NULL;
@@ -887,11 +856,11 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
&channel->
setenv_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
if (rc) {
channel->setenv_state = libssh2_NB_state_idle;
return -1;
return rc;
}
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
@@ -906,7 +875,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
"Unable to complete request for channel-setenv", 0);
channel->setenv_state = libssh2_NB_state_idle;
return -1;
return LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED;
}
/*
@@ -1005,14 +974,14 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
rc = _libssh2_transport_write(session, channel->reqPTY_packet,
channel->reqPTY_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 pty-request packet", 0);
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
return rc;
}
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
@@ -1027,7 +996,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
1, channel->reqPTY_local_channel, 4,
&channel->reqPTY_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
@@ -1044,7 +1013,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
"Unable to complete request for channel request-pty", 0);
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
return LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED;
}
/*
@@ -1119,14 +1088,14 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
rc = _libssh2_transport_write(session, channel->reqPTY_packet,
channel->reqPTY_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 window-change packet", 0);
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
return rc;
}
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
@@ -1245,15 +1214,15 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
rc = _libssh2_transport_write(session, channel->reqX11_packet,
channel->reqX11_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, rc,
"Unable to send x11-req packet", 0);
LIBSSH2_FREE(session, channel->reqX11_packet);
channel->reqX11_packet = NULL;
channel->reqX11_state = libssh2_NB_state_idle;
return -1;
return rc;
}
LIBSSH2_FREE(session, channel->reqX11_packet);
channel->reqX11_packet = NULL;
@@ -1268,10 +1237,11 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
1, channel->reqX11_local_channel, 4,
&channel->reqX11_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
/* TODO: call libssh2_error() here! */
channel->reqX11_state = libssh2_NB_state_idle;
return -1;
return rc;
}
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
@@ -1319,7 +1289,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
static const unsigned char reply_codes[3] =
{ SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
unsigned long data_len;
libssh2pack_t rc;
int rc;
if (channel->process_state == libssh2_NB_state_idle) {
/* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
@@ -1343,7 +1313,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for channel-process request",
0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
*(s++) = SSH_MSG_CHANNEL_REQUEST;
@@ -1370,15 +1340,15 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
rc = _libssh2_transport_write(session, channel->process_packet,
channel->process_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 channel request", 0);
LIBSSH2_FREE(session, channel->process_packet);
channel->process_packet = NULL;
channel->process_state = libssh2_NB_state_idle;
return -1;
return rc;
}
LIBSSH2_FREE(session, channel->process_packet);
channel->process_packet = NULL;
@@ -1393,10 +1363,12 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1, channel->process_local_channel, 4,
&channel->process_packet_requirev_state);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
} else if (rc) {
channel->process_state = libssh2_NB_state_idle;
return -1;
libssh2_error(session, rc,
"Failed waiting for channel success", 0);
return rc;
}
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
@@ -1410,7 +1382,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
"Unable to complete request for channel-process-startup", 0);
channel->process_state = libssh2_NB_state_idle;
return -1;
return LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED;
}
/*
@@ -1452,14 +1424,14 @@ libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
int
_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
{
LIBSSH2_PACKET *packet = channel->session->packets.head;
if (channel->flush_state == libssh2_NB_state_idle) {
LIBSSH2_PACKET *packet =
_libssh2_list_first(&channel->session->packets);
channel->flush_refund_bytes = 0;
channel->flush_flush_bytes = 0;
while (packet) {
LIBSSH2_PACKET *next = packet->next;
LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
unsigned char packet_type = packet->data[0];
if (((packet_type == SSH_MSG_CHANNEL_DATA)
@@ -1467,9 +1439,8 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
&& (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) {
/* It's our channel at least */
long packet_stream_id =
(packet_type ==
SSH_MSG_CHANNEL_DATA) ? 0 : _libssh2_ntohu32(packet->data +
5);
(packet_type == SSH_MSG_CHANNEL_DATA) ? 0 :
_libssh2_ntohu32(packet->data + 5);
if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
|| ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
&& ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
@@ -1489,16 +1460,9 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
channel->flush_flush_bytes += bytes_to_flush;
LIBSSH2_FREE(channel->session, packet->data);
if (packet->prev) {
packet->prev->next = packet->next;
} else {
channel->session->packets.head = packet->next;
}
if (packet->next) {
packet->next->prev = packet->prev;
} else {
channel->session->packets.tail = packet->prev;
}
/* remove this packet from the parent's list */
_libssh2_list_remove(&packet->node);
LIBSSH2_FREE(channel->session, packet);
}
}
@@ -1514,9 +1478,8 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
rc = _libssh2_channel_receive_window_adjust(channel,
channel->flush_refund_bytes,
0, NULL);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
if (rc == PACKET_EAGAIN)
return rc;
}
channel->flush_state = libssh2_NB_state_idle;
@@ -1603,7 +1566,7 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
rc = _libssh2_transport_write(channel->session, channel->adjust_adjust, 9);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
else if (rc) {
libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -1626,6 +1589,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
/*
* libssh2_channel_receive_window_adjust
*
* DEPRECATED
*
* Adjust the receive window for a channel by adjustment bytes. If the amount
* to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
* adjustment amount will be queued for a later packet.
@@ -1689,11 +1654,11 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
if (channel->extData2_state == libssh2_NB_state_idle) {
if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
if (_libssh2_channel_flush(channel,
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) ==
PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
int rc =
_libssh2_channel_flush(channel,
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
if(PACKET_EAGAIN == rc)
return rc;
}
}
@@ -1735,7 +1700,7 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
/*
* channel_read
* _libssh2_channel_read
*
* Read data from a channel
*
@@ -1743,14 +1708,16 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
* 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.
*/
static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
char *buf, size_t buflen)
{
LIBSSH2_SESSION *session = channel->session;
libssh2pack_t rc;
int rc;
int bytes_read = 0;
int bytes_want;
int unlink_packet;
LIBSSH2_PACKET *read_packet;
LIBSSH2_PACKET *read_next;
if (channel->read_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_CONN,
@@ -1758,27 +1725,19 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
"stream #%d",
(int) buflen, channel->local.id, channel->remote.id,
stream_id);
channel->read_state = libssh2_NB_state_created;
}
rc = 1; /* set to >0 to let the while loop start */
/* process all pending incoming packets */
/* Process all pending incoming packets in all states in order to "even
out" the network readings. Tests prove that this way produces faster
transfers. */
while (rc > 0)
rc = _libssh2_transport_read(session);
if ((rc < 0) && (rc != PACKET_EAGAIN))
return -1;
channel->read_state = libssh2_NB_state_created;
}
else {
/* We're not in the idle state, but in order to "even out" the network
readings we do a single shot read here as well. Tests prove that
this way produces faster transfers. */
rc = _libssh2_transport_read(session);
/* ignore PACKET_EAGAIN but return failure for the rest */
if ((rc < 0) && (rc != PACKET_EAGAIN))
return -1;
if ((rc < 0) && (rc != PACKET_EAGAIN)) {
libssh2_error(session, rc, "tranport read", 0);
return rc;
}
/*
@@ -1790,16 +1749,20 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
goto channel_read_ex_point1;
}
rc = 0;
read_packet = _libssh2_list_first(&session->packets);
while (read_packet && (bytes_read < (int) buflen)) {
/* previously this loop condition also checked for
!channel->remote.close but we cannot let it do this:
channel->read_packet = session->packets.head;
while (channel->read_packet &&
!channel->remote.close &&
(bytes_read < (int) buflen)) {
LIBSSH2_PACKET *readpkt = channel->read_packet;
We may have a series of packets to read that are still pending even
if a close has been received. Acknowledging the close too early
makes us flush buffers prematurely and loose data.
*/
LIBSSH2_PACKET *readpkt = read_packet;
/* In case packet gets destroyed during this iteration */
channel->read_next = readpkt->next;
read_next = _libssh2_list_next(&readpkt->node);
channel->read_local_id =
_libssh2_ntohu32(readpkt->data + 1);
@@ -1850,42 +1813,30 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
/* if drained, remove from list */
if (unlink_packet) {
if (readpkt->prev) {
readpkt->prev->next = readpkt->next;
} else {
session->packets.head = readpkt->next;
}
if (readpkt->next) {
readpkt->next->prev = readpkt->prev;
} else {
session->packets.tail = readpkt->prev;
}
/* detach readpkt from session->packets list */
_libssh2_list_remove(&readpkt->node);
LIBSSH2_FREE(session, readpkt->data);
LIBSSH2_FREE(session, readpkt);
}
}
/* check the next struct in the chain */
channel->read_packet = channel->read_next;
read_packet = read_next;
}
if (bytes_read == 0) {
if (!bytes_read) {
channel->read_state = libssh2_NB_state_idle;
if (channel->remote.close) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED,
"Remote end has closed this channel", 0);
/* If the channel is already at EOF or even closed, 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. */
if(channel->remote.eof || channel->remote.close)
return 0;
}
else {
/*
* when non-blocking, we must return PACKET_EAGAIN if we haven't
* completed reading the channel
*/
if (!libssh2_channel_eof(channel)) {
return PACKET_EAGAIN;
}
return 0;
}
else
/* if the transport layer said EAGAIN then we say so as well */
return (rc == PACKET_EAGAIN)?rc:0;
}
else
/* make sure we remain in the created state to focus on emptying the
@@ -1902,9 +1853,9 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
this special state here */
rc = _libssh2_channel_receive_window_adjust(channel,
(LIBSSH2_CHANNEL_WINDOW_DEFAULT*600), 0, NULL);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
if (rc == PACKET_EAGAIN)
return rc;
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"channel_read() filled %d adjusted %d",
bytes_read, buflen);
@@ -1931,8 +1882,8 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
size_t buflen)
{
int rc;
BLOCK_ADJUST(rc, channel->session, channel_read(channel, stream_id,
buf, buflen));
BLOCK_ADJUST(rc, channel->session,
_libssh2_channel_read(channel, stream_id, buf, buflen));
return rc;
}
@@ -1949,9 +1900,9 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
LIBSSH2_PACKET *read_packet;
uint32_t read_local_id;
if ((read_packet = session->packets.head) == NULL) {
read_packet = _libssh2_list_first(&session->packets);
if (read_packet == NULL)
return 0;
}
while (read_packet) {
read_local_id = _libssh2_ntohu32(read_packet->data + 1);
@@ -1980,7 +1931,7 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
{
return (read_packet->data_len - read_packet->data_head);
}
read_packet = read_packet->next;
read_packet = _libssh2_list_next(&read_packet->node);
}
return 0;
@@ -1989,14 +1940,28 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
/*
* _libssh2_channel_write
*
* Send data to a channel
* Send data to a channel. Note that if this returns EAGAIN or simply didn't
* send the entire packet, the caller must call this function again with the
* SAME input arguments.
*
* Returns: number of bytes sent, or if it returns a negative number, that is
* the error code!
*/
ssize_t
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
const char *buf, size_t buflen)
{
LIBSSH2_SESSION *session = channel->session;
libssh2pack_t rc;
int rc;
ssize_t wrote = 0; /* counter for this specific this call */
/* In theory we could split larger buffers into several smaller packets,
* but for now we instead only deal with the first 32K in this call and
* assume the app will call it again with the rest! The 32K is a
* conservative limit based on the text in RFC4253 section 6.1.
*/
if(buflen > 32768)
buflen = 32768;
if (channel->write_state == libssh2_NB_state_idle) {
channel->write_bufwrote = 0;
@@ -2009,7 +1974,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
if (channel->local.close) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED,
"We've already closed this channel", 0);
return -1;
return LIBSSH2_ERROR_CHANNEL_CLOSED;
}
if (channel->local.eof) {
@@ -2027,7 +1992,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocte space for data transmission packet",
0);
return -1;
return LIBSSH2_ERROR_ALLOC;
}
channel->write_state = libssh2_NB_state_allocated;
@@ -2052,29 +2017,14 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->write_s += 4;
}
/* twiddle our thumbs until there's window space available */
while (channel->local.window_size <= 0) {
/* Don't worry -- This is never hit unless it's a
blocking channel anyway */
/* drain the incoming flow first */
do
rc = _libssh2_transport_read(session);
while (rc > 0);
if (rc < 0) {
/* Error or EAGAIN occurred, disconnect? */
if (rc != PACKET_EAGAIN) {
LIBSSH2_FREE(session, channel->write_packet);
channel->write_state = libssh2_NB_state_idle;
}
return rc;
}
if (rc == 0) {
/*
* if rc == 0, then fake EAGAIN to prevent busyloops until
* data arriaves on the network which seemed like a very
* bad idea
*/
return PACKET_EAGAIN;
}
if(channel->local.window_size <= 0) {
/* there's no more room for data so we stop sending now */
break;
}
/* Don't exceed the remote end's limits */
@@ -2113,17 +2063,17 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->write_s -
channel->write_packet);
if (rc == PACKET_EAGAIN) {
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"libssh2_transport_write returned EAGAIN");
return PACKET_EAGAIN;
libssh2_error(session, rc,
"Unable to send channel data", 0);
return rc;
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, rc,
"Unable to send channel data", 0);
LIBSSH2_FREE(session, channel->write_packet);
channel->write_packet = NULL;
channel->write_state = libssh2_NB_state_idle;
return -1;
return rc;
}
/* Shrink local window size */
channel->local.window_size -= channel->write_bufwrite;
@@ -2132,15 +2082,9 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
buflen -= channel->write_bufwrite;
buf += channel->write_bufwrite;
channel->write_bufwrote += channel->write_bufwrite;
wrote += channel->write_bufwrite;
channel->write_state = libssh2_NB_state_allocated;
/*
* Not sure this is still wanted
if (!channel->session->socket_block) {
break;
}
*/
}
}
@@ -2149,7 +2093,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->write_state = libssh2_NB_state_idle;
return channel->write_bufwrote;
return wrote;
}
/*
@@ -2184,12 +2128,12 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel)
_libssh2_htonu32(packet + 1, channel->remote.id);
rc = _libssh2_transport_write(session, packet, 5);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send EOF on channel", 0);
return -1;
return LIBSSH2_ERROR_SOCKET_SEND;
}
channel->local.eof = 1;
@@ -2218,7 +2162,7 @@ LIBSSH2_API int
libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
{
LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head;
LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
while (packet) {
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA)
@@ -2227,7 +2171,7 @@ libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
/* There's data waiting to be read yet, mask the EOF status */
return 0;
}
packet = packet->next;
packet = _libssh2_list_next(&packet->node);
}
return channel->remote.eof;
@@ -2261,7 +2205,7 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
}
rc = _libssh2_transport_read(session);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return rc;
}
else if (rc < 0) {
channel->wait_eof_state = libssh2_NB_state_idle;
@@ -2314,12 +2258,12 @@ channel_close(LIBSSH2_CHANNEL * channel)
if (channel->close_state == libssh2_NB_state_created) {
retcode = _libssh2_transport_write(session, channel->close_packet, 5);
if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return retcode;
} else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, retcode,
"Unable to send close-channel request", 0);
channel->close_state = libssh2_NB_state_idle;
return -1;
return retcode;
}
channel->close_state = libssh2_NB_state_sent;
@@ -2330,16 +2274,10 @@ channel_close(LIBSSH2_CHANNEL * channel)
while (!channel->remote.close && !rc) {
rc = _libssh2_transport_read(session);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
else if (rc < 0)
rc = -1;
else
rc = 0;
}
}
if(rc != LIBSSH2_ERROR_EAGAIN) {
/* set the local close state first when we're perfectly confirmed to not
do any more EAGAINs */
channel->local.close = 1;
@@ -2351,8 +2289,10 @@ channel_close(LIBSSH2_CHANNEL * channel)
}
channel->close_state = libssh2_NB_state_idle;
}
return rc;
/* return 0 or an error */
return rc>=0?0:rc;
}
/*
@@ -2401,6 +2341,9 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
if (!channel->remote.close) {
do {
rc = _libssh2_transport_read(session);
if (channel->remote.close)
/* it is now closed, move on! */
break;
} while (rc > 0);
if(rc < 0)
return rc;
@@ -2440,6 +2383,8 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
unsigned long data_len;
int rc;
assert(session);
if (channel->free_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"Freeing channel %lu/%lu resources", channel->local.id,
@@ -2452,12 +2397,12 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
if (!channel->local.close
&& (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
rc = channel_close(channel);
if(rc == PACKET_EAGAIN)
return rc;
if (rc) {
else if (rc < 0) {
channel->free_state = libssh2_NB_state_idle;
return -1;
return rc;
}
}
@@ -2484,17 +2429,8 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
LIBSSH2_FREE(session, channel->channel_type);
}
/* Unlink from channel brigade */
if (channel->prev) {
channel->prev->next = channel->next;
} else {
session->channels.head = channel->next;
}
if (channel->next) {
channel->next->prev = channel->prev;
} else {
session->channels.tail = channel->prev;
}
/* Unlink from channel list */
_libssh2_list_remove(&channel->node);
/*
* Make sure all memory used in the state variables are free
@@ -2555,7 +2491,8 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
if (read_avail) {
unsigned long bytes_queued = 0;
LIBSSH2_PACKET *packet = channel->session->packets.head;
LIBSSH2_PACKET *packet =
_libssh2_list_first(&channel->session->packets);
while (packet) {
unsigned char packet_type = packet->data[0];
@@ -2566,7 +2503,7 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
bytes_queued += packet->data_len - packet->data_head;
}
packet = packet->next;
packet = _libssh2_list_next(&packet->node);
}
*read_avail = bytes_queued;

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

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -36,6 +37,7 @@
*/
#include "libssh2_priv.h"
#include "misc.h"
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
@@ -112,7 +114,6 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
void **abstract)
{
libssh2_rsa_ctx *rsactx;
FILE *fp;
int ret;
if (*abstract) {
@@ -120,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;
}
@@ -294,7 +289,6 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
void **abstract)
{
libssh2_dsa_ctx *dsactx;
FILE *fp;
int ret;
if (*abstract) {
@@ -302,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;
}
@@ -453,3 +441,47 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
return NULL;
}
}
static int hostkey_type(const unsigned char *hostkey, size_t len)
{
const unsigned char rsa[] = {
0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a'
};
const unsigned char dss[] = {
0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's'
};
if (len < 11)
return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
if (!memcmp(rsa, hostkey, 11))
return LIBSSH2_HOSTKEY_TYPE_RSA;
if (!memcmp(dss, hostkey, 11))
return LIBSSH2_HOSTKEY_TYPE_DSS;
return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
}
/*
* libssh2_session_hostkey()
*
* Returns the server key and length.
*
*/
LIBSSH2_API const char *
libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type)
{
if(session->server_hostkey_len) {
if(len)
*len = session->server_hostkey_len;
if (type)
*type = hostkey_type(session->server_hostkey,
session->server_hostkey_len);
return (char *) session->server_hostkey;
}
if(len)
*len = 0;
return NULL;
}

159
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,
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 packet_type_init,
unsigned char packet_type_reply,
unsigned char *midhash,
unsigned long midhash_len,
kmdhgGPsha1kex_state_t
* exchange_state)
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;
@@ -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;
@@ -168,10 +166,10 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
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;
@@ -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,
@@ -263,12 +261,12 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
}
#endif /* LIBSSH2DEBUG */
if (session->hostkey->
init(session, session->server_hostkey, session->server_hostkey_len,
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,
@@ -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,11 +435,10 @@ 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,
@@ -457,7 +453,9 @@ 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,
@@ -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;
}
@@ -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;
}
@@ -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,
@@ -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,
@@ -641,11 +639,6 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
exchange_state->k_value = NULL;
}
if (session->server_hostkey) {
LIBSSH2_FREE(session, session->server_hostkey);
session->server_hostkey = NULL;
}
exchange_state->state = libssh2_NB_state_idle;
return ret;
@@ -696,18 +689,11 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
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);
@@ -779,18 +765,11 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
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;
@@ -844,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;
}
@@ -860,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;
}
@@ -883,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,
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);
@@ -1061,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;
@@ -1144,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) {
@@ -1667,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,
@@ -1709,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;
@@ -1730,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) {
@@ -1751,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;
}
@@ -1763,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,
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;
}
}
}

843
src/knownhost.c Normal file
View File

@@ -0,0 +1,843 @@
/*
* Copyright (c) 2009 by Daniel Stenberg
* 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"
struct known_host {
struct list_node node;
char *name; /* points to the name or the hash (allocated) */
size_t name_len; /* needed for hashed data */
int typemask; /* plain, sha1, custom, ... */
char *salt; /* points to binary salt (allocated) */
size_t salt_len; /* size of salt */
char *key; /* the (allocated) associated key. This is kept base64
encoded in memory. */
/* this is the struct we expose externally */
struct libssh2_knownhost external;
};
struct _LIBSSH2_KNOWNHOSTS
{
LIBSSH2_SESSION *session; /* the session this "belongs to" */
struct list_head head;
};
static void free_host(LIBSSH2_SESSION *session, struct known_host *entry)
{
if(entry) {
if(entry->key)
LIBSSH2_FREE(session, entry->key);
if(entry->salt)
LIBSSH2_FREE(session, entry->salt);
if(entry->name)
LIBSSH2_FREE(session, entry->name);
LIBSSH2_FREE(session, entry);
}
}
/*
* libssh2_knownhost_init
*
* Init a collection of known hosts. Returns the pointer to a collection.
*
*/
LIBSSH2_API LIBSSH2_KNOWNHOSTS *
libssh2_knownhost_init(LIBSSH2_SESSION *session)
{
LIBSSH2_KNOWNHOSTS *knh =
LIBSSH2_ALLOC(session, sizeof(struct _LIBSSH2_KNOWNHOSTS));
if(!knh)
return NULL;
knh->session = session;
_libssh2_list_init(&knh->head);
return knh;
}
#define KNOWNHOST_MAGIC 0xdeadcafe
/*
* knownhost_to_external()
*
* Copies data from the internal to the external representation struct.
*
*/
static struct libssh2_knownhost *knownhost_to_external(struct known_host *node)
{
struct libssh2_knownhost *ext = &node->external;
ext->magic = KNOWNHOST_MAGIC;
ext->node = node;
ext->name = ((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
LIBSSH2_KNOWNHOST_TYPE_PLAIN)? node->name:NULL;
ext->key = node->key;
ext->typemask = node->typemask;
return ext;
}
/*
* libssh2_knownhost_add
*
* Add a host and its associated key to the collection of known hosts.
*
* The 'type' argument specifies on what format the given host and keys are:
*
* plain - ascii "hostname.domain.tld"
* sha1 - SHA1(<salt> <host>) base64-encoded!
* custom - another hash
*
* If 'sha1' is selected as type, the salt must be provided to the salt
* argument. This too base64 encoded.
*
* The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If
* a custom type is used, salt is ignored and you must provide the host
* pre-hashed when checking for it in the libssh2_knownhost_check() function.
*
*/
LIBSSH2_API int
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, const char *salt,
const char *key, size_t keylen,
int typemask, struct libssh2_knownhost **store)
{
struct known_host *entry =
LIBSSH2_ALLOC(hosts->session, sizeof(struct known_host));
size_t hostlen = strlen(host);
int rc = LIBSSH2_ERROR_ALLOC;
char *ptr;
unsigned int ptrlen;
if(!entry)
return rc;
if(!(typemask & LIBSSH2_KNOWNHOST_KEY_MASK))
/* make sure we have a key type set */
return LIBSSH2_ERROR_INVAL;
memset(entry, 0, sizeof(struct known_host));
entry->typemask = typemask;
switch(entry->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
entry->name = LIBSSH2_ALLOC(hosts->session, hostlen+1);
if(!entry)
goto error;
memcpy(entry->name, host, hostlen+1);
break;
case LIBSSH2_KNOWNHOST_TYPE_SHA1:
rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen,
host, hostlen);
if(rc)
goto error;
entry->name = ptr;
entry->name_len = ptrlen;
rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen,
salt, strlen(salt));
if(rc)
goto error;
entry->salt = ptr;
entry->salt_len = ptrlen;
break;
default:
rc = LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
goto error;
}
if(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64) {
/* the provided key is base64 encoded already */
if(!keylen)
keylen = strlen(key);
entry->key = LIBSSH2_ALLOC(hosts->session, keylen+1);
if(!entry)
goto error;
memcpy(entry->key, key, keylen+1);
entry->key[keylen]=0; /* force a terminating zero trailer */
}
else {
/* key is raw, we base64 encode it and store it as such */
size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
&ptr);
if(!nlen)
goto error;
entry->key = ptr;
}
/* add this new host to the big list of known hosts */
_libssh2_list_add(&hosts->head, &entry->node);
if(store)
*store = knownhost_to_external(entry);
return LIBSSH2_ERROR_NONE;
error:
free_host(hosts->session, entry);
return rc;
}
/*
* libssh2_knownhost_check
*
* Check a host and its associated key against the collection of known hosts.
*
* The typemask is the type/format of the given host name and key
*
* plain - ascii "hostname.domain.tld"
* sha1 - NOT SUPPORTED AS INPUT
* custom - prehashed base64 encoded. Note that this cannot use any salts.
*
* Returns:
*
* LIBSSH2_KNOWNHOST_CHECK_FAILURE
* LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
* LIBSSH2_KNOWNHOST_CHECK_MATCH
* LIBSSH2_KNOWNHOST_CHECK_MISMATCH
*/
LIBSSH2_API int
libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, const char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **ext)
{
struct known_host *node = _libssh2_list_first(&hosts->head);
struct known_host *badkey = NULL;
int type = typemask & LIBSSH2_KNOWNHOST_TYPE_MASK;
char *keyalloc = NULL;
int rc = LIBSSH2_KNOWNHOST_CHECK_NOTFOUND;
if(type == LIBSSH2_KNOWNHOST_TYPE_SHA1)
/* we can't work with a sha1 as given input */
return LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
if(!(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64)) {
/* we got a raw key input, convert it to base64 for the checks below */
size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
&keyalloc);
if(!nlen)
return LIBSSH2_KNOWNHOST_CHECK_FAILURE;
/* make the key point to this */
key = keyalloc;
keylen = nlen;
}
while (node) {
int match = 0;
switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN)
match = !strcmp(host, node->name);
break;
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
if(type == LIBSSH2_KNOWNHOST_TYPE_CUSTOM)
match = !strcmp(host, node->name);
break;
case LIBSSH2_KNOWNHOST_TYPE_SHA1:
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) {
/* when we have the sha1 version stored, we can use a plain
input to produce a hash to compare with the stored hash.
*/
libssh2_hmac_ctx ctx;
unsigned char hash[SHA_DIGEST_LENGTH];
if(SHA_DIGEST_LENGTH != node->name_len) {
/* the name hash length must be the sha1 size or
we can't match it */
break;
}
libssh2_hmac_sha1_init(&ctx, node->salt, node->salt_len);
libssh2_hmac_update(ctx, (unsigned char *)host, strlen(host));
libssh2_hmac_final(ctx, hash);
libssh2_hmac_cleanup(&ctx);
if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH))
/* this is a node we're interested in */
match = 1;
}
break;
default: /* unsupported type */
break;
}
if(match) {
/* host name match, now compare the keys */
if(!strcmp(key, node->key)) {
/* they match! */
*ext = knownhost_to_external(node);
badkey = NULL;
rc = LIBSSH2_KNOWNHOST_CHECK_MATCH;
break;
}
else {
/* remember the first node that had a host match but a failed
key match since we continue our search from here */
if(!badkey)
badkey = node;
}
}
node= _libssh2_list_next(&node->node);
}
if(badkey) {
/* key mismatch */
*ext = knownhost_to_external(badkey);
rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
}
if(keyalloc)
LIBSSH2_FREE(hosts->session, keyalloc);
return rc;
}
/*
* libssh2_knownhost_del
*
* Remove a host from the collection of known hosts.
*
*/
LIBSSH2_API int
libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost *entry)
{
struct known_host *node;
if(!entry || (entry->magic != KNOWNHOST_MAGIC))
/* check that this was retrieved the right way or get out */
return LIBSSH2_ERROR_INVAL;
/* get the internal node pointer */
node = entry->node;
/* unlink from the list of all hosts */
_libssh2_list_remove(&node->node);
/* free all resources */
free_host(hosts->session, node);
/* clear the struct now since this host entry has been removed! */
memset(entry, 0, sizeof(struct libssh2_knownhost));
return 0;
}
/*
* libssh2_knownhost_free
*
* Free an entire collection of known hosts.
*
*/
LIBSSH2_API void
libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts)
{
struct known_host *node;
struct known_host *next;
for(node = _libssh2_list_first(&hosts->head); node; node = next) {
next = _libssh2_list_next(&node->node);
free_host(hosts->session, node);
}
LIBSSH2_FREE(hosts->session, hosts);
}
/*
* hostline()
*
* Parse a single known_host line pre-split into host and key.
*
*/
static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, size_t hostlen,
const char *key, size_t keylen)
{
const char *p;
const char *orig = host;
const char *salt = NULL;
int rc;
int type = LIBSSH2_KNOWNHOST_TYPE_PLAIN;
const char *sep = NULL;
size_t seplen = 0;
char saltbuf[32];
char hostbuf[256];
/* Figure out host format */
if((hostlen >2) && memcmp(host, "|1|", 3)) {
/* old style plain text: [name][,][ip-address]
for the sake of simplicity, we add them as two hosts with the same
key
*/
size_t scan = hostlen;
while(scan && (*host != ',')) {
host++;
scan--;
}
if(scan) {
sep = host+1;
seplen = scan-1;
hostlen -= scan; /* deduct what's left to scan from the first
host name */
}
else
host = orig;
}
else {
/* |1|[salt]|[hash] */
type = LIBSSH2_KNOWNHOST_TYPE_SHA1;
salt = &host[3]; /* skip the magic marker */
hostlen -= 3; /* deduct the marker */
/* this is where the salt starts, find the end of it */
for(p = salt; *p && (*p != '|'); p++)
;
if(*p=='|') {
const char *hash = NULL;
size_t saltlen = p - salt;
if(saltlen >= (sizeof(saltbuf)-1))
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED; /* weird length */
memcpy(saltbuf, salt, saltlen);
saltbuf[saltlen] = 0; /* zero terminate */
salt = saltbuf; /* point to the stack based buffer */
hash = p+1; /* the host hash is after the separator */
/* now make the host point to the hash */
host = hash;
hostlen -= saltlen+1; /* deduct the salt and separator */
}
else
return 0;
}
/* make some checks that the lenghts seem sensible */
if((keylen < 20) ||
(seplen >= sizeof(hostbuf)-1) ||
(hostlen >= sizeof(hostbuf)-1))
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
switch(key[0]) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
type |= LIBSSH2_KNOWNHOST_KEY_RSA1;
/* Note that the old-style keys (RSA1) aren't truly base64, but we
* claim it is for now since we can get away with strcmp()ing the
* entire anything anyway! We need to check and fix these to make them
* work properly.
*/
break;
case 's': /* ssh-dss or ssh-rsa */
if(!strncmp(key, "ssh-dss", 7))
type |= LIBSSH2_KNOWNHOST_KEY_SSHDSS;
else if(!strncmp(key, "ssh-rsa", 7))
type |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
else
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED; /* unknown key type */
key += 7;
keylen -= 7;
/* skip whitespaces */
while((*key ==' ') || (*key == '\t')) {
key++;
keylen--;
}
break;
default: /* unknown key format */
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
}
if(sep) {
/* The second host after the comma, add this first. Copy it to the
temp buffer and zero terminate */
memcpy(hostbuf, sep, seplen);
hostbuf[seplen]=0;
rc = libssh2_knownhost_add(hosts, hostbuf, salt, key, keylen,
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
NULL);
if(rc)
return rc;
}
if (!salt)
host = orig;
memcpy(hostbuf, host, hostlen);
hostbuf[hostlen]=0;
rc = libssh2_knownhost_add(hosts, hostbuf, salt, key, keylen,
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
NULL);
return rc;
}
/*
* libssh2_knownhost_readline()
*
* Pass in a line of a file of 'type'.
*
* LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
*
* OpenSSH line format:
*
* <host> <key>
*
* Where the two parts can be created like:
*
* <host> can be either
* <name> or <hash>
*
* <name> consists of
* [name,address] or just [name] or just [address]
*
* <hash> consists of
* |1|<salt>|hash
*
* <key> can be one of:
* [RSA bits] [e] [n as a decimal number]
* 'ssh-dss' [base64-encoded-key]
* 'ssh-rsa' [base64-encoded-key]
*
*/
LIBSSH2_API int
libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
const char *line, size_t len, int type)
{
const char *cp;
const char *hostp;
const char *keyp;
size_t hostlen;
size_t keylen;
int rc;
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
cp = line;
/* skip leading whitespaces */
while(len && ((*cp==' ') || (*cp == '\t'))) {
cp++;
len--;
}
if(!len || !*cp || (*cp == '#') || (*cp == '\n'))
/* comment or empty line */
return LIBSSH2_ERROR_NONE;
/* the host part starts here */
hostp = cp;
/* move over the host to the separator */
while(len && *cp && (*cp!=' ') && (*cp != '\t')) {
cp++;
len--;
}
hostlen = cp - hostp;
/* the key starts after the whitespaces */
while(len && *cp && ((*cp==' ') || (*cp == '\t'))) {
cp++;
len--;
}
if(!*cp || !len)
/* illegal line */
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
keyp = cp; /* the key starts here */
keylen = len;
/* check if the line (key) ends with a newline and if so kill it */
while(len && *cp && (*cp != '\n')) {
cp++;
len--;
}
/* zero terminate where the newline is */
if(*cp == '\n')
keylen--; /* don't include this in the count */
/* deal with this one host+key line */
rc = hostline(hosts, hostp, hostlen, keyp, keylen);
if(rc)
return rc; /* failed */
return LIBSSH2_ERROR_NONE; /* success */
}
/*
* libssh2_knownhost_readfile
*
* Read hosts+key pairs from a given file.
*
* Returns a negative value for error or number of successfully added hosts.
*
*/
LIBSSH2_API int
libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
const char *filename, int type)
{
FILE *file;
int num = 0;
char buf[2048];
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
file = fopen(filename, "r");
if(file) {
while(fgets(buf, sizeof(buf), file)) {
if(libssh2_knownhost_readline(hosts, buf, strlen(buf), type))
break;
num++;
}
fclose(file);
}
else
return LIBSSH2_ERROR_FILE;
return num;
}
/*
* knownhost_writeline()
*
* Ask libssh2 to convert a known host to an output line for storage.
*
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
* output buffer is too small to hold the desired output. The 'outlen' field
* will then contain the size libssh2 wanted to store, which then is the
* smallest sufficient buffer it would require.
*
*/
static int
knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
struct known_host *node,
char *buf, size_t buflen,
size_t *outlen, int type)
{
int rc = LIBSSH2_ERROR_NONE;
int tindex;
const char *keytypes[4]={
"", /* not used */
"", /* this type has no name in the file */
" ssh-rsa",
" ssh-dss"
};
const char *keytype;
size_t nlen;
/* we only support this single file type for now, bail out on all other
attempts */
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
tindex = (node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) >>
LIBSSH2_KNOWNHOST_KEY_SHIFT;
/* set the string used in the file */
keytype = keytypes[tindex];
if((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
LIBSSH2_KNOWNHOST_TYPE_SHA1) {
char *namealloc;
char *saltalloc;
nlen = _libssh2_base64_encode(hosts->session, node->name,
node->name_len, &namealloc);
if(!nlen)
return LIBSSH2_ERROR_ALLOC;
nlen = _libssh2_base64_encode(hosts->session,
node->salt, node->salt_len,
&saltalloc);
if(!nlen) {
free(namealloc);
return LIBSSH2_ERROR_ALLOC;
}
nlen = strlen(saltalloc) + strlen(namealloc) + strlen(keytype) +
strlen(node->key) + 7; /* |1| + | + ' ' + \n + \0 = 7 */
if(nlen <= buflen)
sprintf(buf, "|1|%s|%s%s %s\n", saltalloc, namealloc, keytype,
node->key);
else
rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
free(namealloc);
free(saltalloc);
}
else {
nlen = strlen(node->name) + strlen(keytype) + strlen(node->key) + 3;
/* ' ' + '\n' + \0 = 3 */
if(nlen <= buflen)
/* these types have the plain name */
sprintf(buf, "%s%s %s\n", node->name, keytype, node->key);
else
rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
/* we report the full length of the data with the trailing zero excluded */
*outlen = nlen-1;
return rc;
}
/*
* libssh2_knownhost_writeline()
*
* Ask libssh2 to convert a known host to an output line for storage.
*
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
* output buffer is too small to hold the desired output.
*/
LIBSSH2_API int
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost *known,
char *buffer, size_t buflen,
size_t *outlen, /* the amount of written data */
int type)
{
struct known_host *node;
if(known->magic != KNOWNHOST_MAGIC)
return LIBSSH2_ERROR_INVAL;
node = known->node;
return knownhost_writeline(hosts, node, buffer, buflen, outlen, type);
}
/*
* libssh2_knownhost_writefile()
*
* Write hosts+key pairs to the given file.
*/
LIBSSH2_API int
libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
const char *filename, int type)
{
struct known_host *node;
FILE *file;
int rc = LIBSSH2_ERROR_NONE;
char buffer[2048];
/* we only support this single file type for now, bail out on all other
attempts */
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
file = fopen(filename, "w");
if(!file)
return LIBSSH2_ERROR_FILE;
for(node = _libssh2_list_first(&hosts->head);
node;
node= _libssh2_list_next(&node->node) ) {
size_t wrote;
size_t nwrote;
rc = knownhost_writeline(hosts, node, buffer, sizeof(buffer), &wrote,
type);
if(rc)
break;
nwrote = fwrite(buffer, 1, wrote, file);
if(nwrote != wrote) {
/* failed to write the whole thing, bail out */
rc = LIBSSH2_ERROR_FILE;
break;
}
}
fclose(file);
return rc;
}
/*
* libssh2_knownhost_get()
*
* Traverse the internal list of known hosts. Pass NULL to 'prev' to get
* the first one.
*
* Returns:
* 0 if a fine host was stored in 'store'
* 1 if end of hosts
* [negative] on errors
*/
LIBSSH2_API int
libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost **ext,
struct libssh2_knownhost *oprev)
{
struct known_host *node;
if(oprev && oprev->node) {
/* we have a starting point */
struct known_host *prev = oprev->node;
/* get the next node in the list */
node = _libssh2_list_next(&prev->node);
}
else
node = _libssh2_list_first(&hosts->head);
if(!node)
/* no (more) node */
return 1;
*ext = knownhost_to_external(node);
return 0;
}

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;
}
@@ -507,16 +524,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,8 +542,11 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
return -1;
}
if (algo != GCRY_CIPHER_ARCFOUR) {
int blklen = gcry_cipher_get_algo_blklen(algo);
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);
@@ -544,8 +562,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 +578,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

@@ -39,6 +39,12 @@
#ifndef LIBSSH2_PRIV_H
#define LIBSSH2_PRIV_H 1
#ifdef _WIN32
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif /* _CRT_SECURE_NO_DEPRECATE */
#endif /* WIN32 */
#define LIBSSH2_LIBRARY
#include "libssh2_config.h"
@@ -79,6 +85,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
@@ -90,10 +97,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
@@ -143,6 +149,12 @@ 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;
#endif /* WIN32 */
/* RFC4253 section 6.1 Maximum Packet Length says:
*
* "All implementations MUST be able to process packets with
@@ -181,10 +193,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
{
@@ -282,6 +290,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"
@@ -296,10 +305,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) */
@@ -312,15 +324,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
@@ -337,6 +340,8 @@ typedef struct _libssh2_channel_data
struct _LIBSSH2_CHANNEL
{
struct list_node node;
unsigned char *channel_type;
unsigned channel_type_len;
@@ -349,8 +354,6 @@ struct _LIBSSH2_CHANNEL
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *next, *prev;
void *abstract;
LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb));
@@ -393,8 +396,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;
@@ -423,24 +424,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;
@@ -541,8 +539,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,
@@ -580,9 +579,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;
@@ -707,18 +707,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
@@ -805,7 +806,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;
@@ -854,7 +855,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;
@@ -865,7 +865,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;
@@ -881,7 +881,7 @@ struct _LIBSSH2_SESSION
unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
unsigned long scpRecv_response_len;
long scpRecv_mode;
#if defined(HAVE_LONGLONG) && defined(strtoll)
#if defined(HAVE_LONGLONG) && defined(HAVE_STRTOLL)
/* we have the type and we can parse such numbers */
long long scpRecv_size;
#define scpsize_strtol strtoll
@@ -922,7 +922,10 @@ struct _LIBSSH2_SESSION
#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
#endif
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */
/* --------- */
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional
methods via .so/.dll */
struct _LIBSSH2_KEX_METHOD
{
@@ -1023,11 +1026,8 @@ struct _LIBSSH2_MAC_METHOD
void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
...);
#else
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
/* C99 style */
#define _libssh2_debug(x,y,z, __VA_ARGS__) do {} while (0)
#elif defined(__GNUC__)
/* GNU style */
#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__)
/* C99 supported and also by older GCC */
#define _libssh2_debug(x,y,z,...) do {} while (0)
#else
/* no gcc and not C99, do static and hopefully inline */
@@ -1139,8 +1139,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)
@@ -1152,20 +1152,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,

View File

@@ -37,6 +37,8 @@
*/
#include "libssh2_priv.h"
#include "misc.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -76,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
@@ -95,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
@@ -222,6 +224,86 @@ libssh2_base64_decode(LIBSSH2_SESSION * session, char **data,
return 0;
}
/* ---- Base64 Encoding/Decoding Table --- */
static const char table64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
* _libssh2_base64_encode()
*
* Returns the length of the newly created base64 string. The third argument
* is a pointer to an allocated area holding the base64 data. If something
* went wrong, 0 is returned.
*
*/
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
const char *inp, size_t insize, char **outptr)
{
unsigned char ibuf[3];
unsigned char obuf[4];
int i;
int inputparts;
char *output;
char *base64data;
const char *indata = inp;
*outptr = NULL; /* set to NULL in case of failure before we reach the end */
if(0 == insize)
insize = strlen(indata);
base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4);
if(NULL == output)
return 0;
while(insize > 0) {
for (i = inputparts = 0; i < 3; i++) {
if(insize > 0) {
inputparts++;
ibuf[i] = *indata;
indata++;
insize--;
}
else
ibuf[i] = 0;
}
obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
((ibuf[1] & 0xF0) >> 4));
obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
((ibuf[2] & 0xC0) >> 6));
obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
switch(inputparts) {
case 1: /* only one byte read */
snprintf(output, 5, "%c%c==",
table64[obuf[0]],
table64[obuf[1]]);
break;
case 2: /* two bytes read */
snprintf(output, 5, "%c%c%c=",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]]);
break;
default:
snprintf(output, 5, "%c%c%c%c",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
table64[obuf[3]] );
break;
}
output += 4;
}
*output=0;
*outptr = base64data; /* make it return the actual data memory */
return strlen(base64data); /* return the length of the new data */
}
/* ---- End of Base64 Encoding ---- */
#ifdef LIBSSH2DEBUG
LIBSSH2_API int
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
@@ -283,3 +365,142 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
return 0;
}
#endif
/* init the list head */
void _libssh2_list_init(struct list_head *head)
{
head->first = head->last = NULL;
}
/* add a node to the list */
void _libssh2_list_add(struct list_head *head,
struct list_node *entry)
{
/* store a pointer to the head */
entry->head = head;
/* we add this entry at the "top" so it has no next */
entry->next = NULL;
/* make our prev point to what the head thinks is last */
entry->prev = head->last;
/* and make head's last be us now */
head->last = entry;
/* make sure our 'prev' node points to us next */
if(entry->prev)
entry->prev->next = entry;
else
head->first = entry;
}
/* return the "first" node in the list this head points to */
void *_libssh2_list_first(struct list_head *head)
{
return head->first;
}
/* return the next node in the list */
void *_libssh2_list_next(struct list_node *node)
{
return node->next;
}
/* return the prev node in the list */
void *_libssh2_list_prev(struct list_node *node)
{
return node->prev;
}
/* remove this node from the list */
void _libssh2_list_remove(struct list_node *entry)
{
if(entry->prev)
entry->prev->next = entry->next;
else
entry->head->first = entry->next;
if(entry->next)
entry->next->prev = entry->prev;
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;
/* 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

72
src/misc.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef __LIBSSH2_MISC_H
#define __LIBSSH2_MISC_H
/* Copyright (c) 2009 by Daniel Stenberg
*
* 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.
*/
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 last in the list */
void _libssh2_list_add(struct list_head *head,
struct list_node *entry);
/* return the "first" node in the list this head points to */
void *_libssh2_list_first(struct list_head *head);
/* return the next node in the list */
void *_libssh2_list_next(struct list_node *node);
/* return the prev node in the list */
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(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,6 +39,9 @@
*/
#include "libssh2_priv.h"
#ifndef LIBSSH2_LIBGCRYPT /* compile only if we build with OpenSSL */
#include <string.h>
#ifndef EVP_MAX_BLOCK_LENGTH
@@ -194,6 +199,106 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
return ret == 1 ? 0 : 1;
}
#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));
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);
}
/* TODO: Optionally call a passphrase callback specified by the
* calling program
*/
@@ -212,12 +317,40 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
return passphrase_len;
}
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,
pem_read_bio_func read_private_key,
const char * filename,
unsigned const char *passphrase)
{
BIO * bp;
*key_ctx = NULL;
bp = BIO_new_file(filename, "r");
if (!bp) {
return -1;
}
*key_ctx = read_private_key(bp, NULL, (void *) passphrase_cb,
(void *) passphrase);
BIO_free(bp);
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.
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
@@ -225,20 +358,19 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
*/
OpenSSL_add_all_ciphers();
}
*rsa = PEM_read_RSAPrivateKey(fp, NULL, (void *) passphrase_cb,
(void *) passphrase);
if (!*rsa) {
return -1;
}
return 0;
return read_private_key_from_file((void **) rsa, session, 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)
{
(void) session;
pem_read_bio_func read_dsa =
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
if (!EVP_get_cipherbyname("des")) {
/* If this cipher isn't loaded it's a pretty good indication that none are.
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
@@ -246,12 +378,9 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
*/
OpenSSL_add_all_ciphers();
}
*dsa = PEM_read_DSAPrivateKey(fp, NULL, (void *) passphrase_cb,
(void *) passphrase);
if (!*dsa) {
return -1;
}
return 0;
return read_private_key_from_file((void **) dsa, session, read_dsa,
filename, passphrase);
}
int
@@ -314,3 +443,5 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
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

@@ -60,6 +60,7 @@
#include <sys/types.h>
#include "transport.h"
#include "channel.h"
/*
* libssh2_packet_queue_listener
@@ -78,7 +79,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;
@@ -119,13 +120,12 @@ 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,
(memcmp (listen->host, listen_state->host,
listen_state->host_len) == 0)) {
/* This is our listener */
LIBSSH2_CHANNEL *channel, *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)) {
@@ -146,6 +146,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;
@@ -206,31 +208,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,14 +228,13 @@ 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);
@@ -261,17 +250,15 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
rc = _libssh2_transport_write(session, listen_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);
listen_state->state = libssh2_NB_state_idle;
return -1;
return rc;
}
listen_state->state = libssh2_NB_state_idle;
return 0;
}
}
/*
* packet_x11_open
@@ -288,7 +275,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
/* 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;
LIBSSH2_CHANNEL *channel = x11open_state->channel;
int rc;
(void) datalen;
@@ -379,7 +366,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,15 +375,7 @@ 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
@@ -427,12 +406,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;
@@ -443,6 +421,9 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
*
* Create a new packet and attach it to the brigade. Called from the transport
* layer when it as 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,
@@ -469,8 +450,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"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) {
if (session->macerror &&
LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) {
/* Calling app has given the OK, Process it anyway */
macstate = LIBSSH2_MAC_CONFIRMED;
} else {
@@ -484,20 +465,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"", 0);
}
LIBSSH2_FREE(session, data);
return -1;
}
} 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;
return LIBSSH2_ERROR_INVALID_MAC;
}
}
@@ -544,7 +512,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';
@@ -558,21 +526,26 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
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);
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 - 5);
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 +571,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';
@@ -663,15 +636,13 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
/* 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->
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;
}
0, NULL);
if (rc == PACKET_EAGAIN)
return rc;
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
@@ -731,7 +702,6 @@ _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));
@@ -752,11 +722,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
break;
case SSH_MSG_CHANNEL_REQUEST:
{
if (_libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1
&& !memcmp("exit-status", data + 9,
sizeof("exit-status") - 1)) {
@@ -780,11 +747,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *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));
@@ -801,31 +766,24 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
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;
}
break;
case SSH_MSG_CHANNEL_OPEN:
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip") - 1) == _libssh2_ntohu32(data + 1))
&&
(memcmp
(data + 5, "forwarded-tcpip",
(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 +797,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;
@@ -879,33 +834,23 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
}
if (session->packAdd_state == libssh2_NB_state_sent) {
session->packAdd_packet =
LIBSSH2_PACKET *packAdd_packet;
packAdd_packet =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!session->packAdd_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;
}
@@ -948,7 +893,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,7 +913,7 @@ _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,
"Looking for packet of type: %d", (int) packet_type);
@@ -982,24 +927,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 +995,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;
@@ -1078,17 +1010,18 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
return ret;
} else if (ret == 0) {
/* nothing available, wait until data arrives or we time out */
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - state->start);
if (left <= 0) {
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;
}
/*
@@ -1127,8 +1060,9 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
}
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 +1082,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
}
/* Only reached if the socket died */
return -1;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
/*
@@ -1187,14 +1121,14 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
return ret;
}
if (ret <= 0) {
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - state->start);
if (left <= 0) {
state->start = 0;
return PACKET_TIMEOUT;
}
else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
}
}
@@ -1208,6 +1142,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,
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",
@@ -441,7 +442,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
}
if (session->pkeyInit_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_write_ex(session->pkeyInit_channel, 0,
rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
(char *) buffer, (s - buffer));
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -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,
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;
@@ -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,
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;
@@ -815,12 +816,12 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
}
if (pkey->listFetch_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0,
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;

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;
@@ -355,7 +358,7 @@ 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,
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->scpRecv_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -378,7 +381,7 @@ 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,
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
@@ -415,7 +418,7 @@ 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,
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
session->scpRecv_err_msg,
session->scpRecv_err_len);
if (rc <= 0) {
@@ -555,7 +558,7 @@ 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,
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
if (rc == PACKET_EAGAIN) {
@@ -591,7 +594,7 @@ 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,
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
@@ -718,7 +721,7 @@ 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,
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
if (rc == PACKET_EAGAIN) {
@@ -761,13 +764,27 @@ 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,
static LIBSSH2_CHANNEL *
scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
size_t size, long mtime, long atime)
{
int cmd_len;
@@ -857,7 +874,7 @@ 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,
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -885,7 +902,7 @@ 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,
rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len);
if (rc == PACKET_EAGAIN) {
@@ -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);
@@ -944,7 +960,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
}
if (session->scpSend_state == libssh2_NB_state_sent5) {
rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len);
if (rc == PACKET_EAGAIN) {
@@ -962,7 +978,7 @@ 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,
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -990,7 +1006,7 @@ 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,
rc = _libssh2_channel_read(session->scpSend_channel, 0,
session->scpSend_err_msg,
session->scpSend_err_len);
if (rc <= 0) {
@@ -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,6 +106,9 @@ 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));
@@ -207,6 +210,9 @@ banner_send(LIBSSH2_SESSION * session)
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,
@@ -238,7 +244,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
@@ -427,7 +433,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
local_realloc = my_realloc;
}
session = local_alloc(sizeof(LIBSSH2_SESSION), abstract);
session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract);
if (session) {
memset(session, 0, sizeof(LIBSSH2_SESSION));
session->alloc = local_alloc;
@@ -529,7 +535,7 @@ 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;
@@ -556,35 +562,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,14 +585,10 @@ 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;
@@ -622,15 +611,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 +625,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,6 +681,9 @@ 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",
@@ -708,13 +693,15 @@ session_free(LIBSSH2_SESSION *session)
}
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 +715,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,22 +895,24 @@ 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)
/* if the socket was previously blocking, put it back so */
session_nonblock(session->socket_fd, 0);
if (session->server_hostkey) {
LIBSSH2_FREE(session, session->server_hostkey);
}
LIBSSH2_FREE(session, session);
return 0;
@@ -1003,7 +992,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);
@@ -1164,7 +1153,8 @@ libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
return session->err_code;
}
/* libssh2_session_last_error
/* libssh2_session_last_errno
*
* Returns error code
*/
LIBSSH2_API int
@@ -1174,8 +1164,11 @@ libssh2_session_last_errno(LIBSSH2_SESSION * session)
}
/* libssh2_session_flag
*
* Set/Get session flags
* Passing flag==0 will avoid changing session->flags while still returning its current value
*
* Passing flag==0 will avoid changing session->flags while still returning
* its current value
*/
LIBSSH2_API int
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
@@ -1237,7 +1230,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)) {
@@ -1251,7 +1244,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;
@@ -1277,7 +1270,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;
}
/*
@@ -1338,7 +1331,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;
@@ -1448,8 +1441,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 ==
@@ -1594,7 +1586,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
}
/*
* libssh2_session_block_direction
* libssh2_session_block_directions
*
* Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
* Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked

View File

@@ -93,17 +93,17 @@ static int sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
static void
_libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
{
unsigned long msl = ((libssh2_uint64_t)value >> 32);
unsigned long msl = (unsigned long)(value >> 32);
buf[0] = (msl >> 24) & 0xFF;
buf[1] = (msl >> 16) & 0xFF;
buf[2] = (msl >> 8) & 0xFF;
buf[3] = msl & 0xFF;
buf[0] = (unsigned char)((msl >> 24) & 0xFF);
buf[1] = (unsigned char)((msl >> 16) & 0xFF);
buf[2] = (unsigned char)((msl >> 8) & 0xFF);
buf[3] = (unsigned char)( msl & 0xFF);
buf[4] = (value >> 24) & 0xFF;
buf[5] = (value >> 16) & 0xFF;
buf[6] = (value >> 8) & 0xFF;
buf[7] = value & 0xFF;
buf[4] = (unsigned char)((value >> 24) & 0xFF);
buf[5] = (unsigned char)((value >> 16) & 0xFF);
buf[6] = (unsigned char)((value >> 8) & 0xFF);
buf[7] = (unsigned char)( value & 0xFF);
}
/*
@@ -124,22 +124,15 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
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;
}
@@ -174,17 +167,17 @@ sftp_packet_read(LIBSSH2_SFTP *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);
@@ -193,14 +186,14 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
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,7 +202,7 @@ 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,
_libssh2_channel_read(channel, 0,
(char *) packet + packet_received,
packet_len - packet_received);
@@ -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,7 +247,7 @@ 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;
@@ -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;
}
@@ -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;
}
@@ -338,7 +321,7 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
}
/* Only reached if the socket died */
return -1;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
/* sftp_packet_requirev
@@ -378,14 +361,14 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
} else if (ret <= 0) {
/* prevent busy-looping */
long left =
LIBSSH2_READ_TIMEOUT - (time(NULL) - sftp->requirev_start);
LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - sftp->requirev_start);
if (left <= 0) {
sftp->requirev_start = 0;
return PACKET_TIMEOUT;
}
else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
return ret;
}
}
}
@@ -521,20 +504,6 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
(void) session_abstract;
(void) channel;
#if 0
/* EEEK! While it might sound like a neat idea to make this code loop over
all the outstanding handles and close them, that is going to cause
EAGAIN to get returned and this callback system is not designed to
handle this very nicely so thus we now DEMAND that the app closes its
handles instead!
*/
/* Loop through handles closing them */
while (sftp->handles) {
sftp_close_handle(sftp->handles);
}
#endif
/* Free the partial packet storage for sftp_packet_read */
if (sftp->partial_packet) {
LIBSSH2_FREE(session, sftp->partial_packet);
@@ -558,18 +527,31 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
unsigned char *data, *s;
unsigned long data_len;
int rc;
LIBSSH2_SFTP *sftp_handle;
if (session->sftpInit_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
"Initializing SFTP subsystem");
/*
* The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the
* session struct are only to be used during the setup phase. As soon
* 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() 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).
*/
assert(session->sftpInit_sftp == NULL);
session->sftpInit_sftp = NULL;
session->sftpInit_state = libssh2_NB_state_created;
}
sftp_handle = session->sftpInit_sftp;
if (session->sftpInit_state == libssh2_NB_state_created) {
session->sftpInit_channel =
_libssh2_channel_open(session, "session", sizeof("session") - 1,
@@ -618,15 +600,17 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
return NULL;
}
session->sftpInit_sftp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP));
if (!session->sftpInit_sftp) {
sftp_handle =
session->sftpInit_sftp =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP));
if (!sftp_handle) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a new SFTP structure", 0);
goto sftp_init_error;
}
memset(session->sftpInit_sftp, 0, sizeof(LIBSSH2_SFTP));
session->sftpInit_sftp->channel = session->sftpInit_channel;
session->sftpInit_sftp->request_id = 0;
memset(sftp_handle, 0, sizeof(LIBSSH2_SFTP));
sftp_handle->channel = session->sftpInit_channel;
sftp_handle->request_id = 0;
_libssh2_htonu32(session->sftpInit_buffer, 5);
session->sftpInit_buffer[4] = SSH_FXP_INIT;
@@ -655,7 +639,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_state = libssh2_NB_state_sent3;
}
rc = sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION,
0, &data, &data_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -674,17 +658,17 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
}
s = data + 1;
session->sftpInit_sftp->version = _libssh2_ntohu32(s);
sftp_handle->version = _libssh2_ntohu32(s);
s += 4;
if (session->sftpInit_sftp->version > LIBSSH2_SFTP_VERSION) {
if (sftp_handle->version > LIBSSH2_SFTP_VERSION) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
"Truncating remote SFTP version from %lu",
session->sftpInit_sftp->version);
session->sftpInit_sftp->version = LIBSSH2_SFTP_VERSION;
sftp_handle->version);
sftp_handle->version = LIBSSH2_SFTP_VERSION;
}
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
"Enabling SFTP version %lu compatability",
session->sftpInit_sftp->version);
sftp_handle->version);
while (s < (data + data_len)) {
unsigned char *extension_name, *extension_data;
unsigned long extname_len, extdata_len;
@@ -705,11 +689,18 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
/* Make sure that when the channel gets closed, the SFTP service is shut
down too */
session->sftpInit_sftp->channel->abstract = session->sftpInit_sftp;
session->sftpInit_sftp->channel->close_cb = libssh2_sftp_dtor;
sftp_handle->channel->abstract = sftp_handle;
sftp_handle->channel->close_cb = libssh2_sftp_dtor;
session->sftpInit_state = libssh2_NB_state_idle;
return session->sftpInit_sftp;
/* clear the sftp and channel pointers in this session struct now */
session->sftpInit_sftp = NULL;
session->sftpInit_channel = NULL;
_libssh2_list_init(&sftp_handle->sftp_handles);
return sftp_handle;
sftp_init_error:
while (_libssh2_channel_free(session->sftpInit_channel) == PACKET_EAGAIN);
@@ -792,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;
@@ -804,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;
}
@@ -914,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;
@@ -979,12 +972,10 @@ 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;
@@ -1100,12 +1091,12 @@ 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! */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_READ command", 0);
"_libssh2_channel_write() failed", 0);
sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle;
return -1;
@@ -1121,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;
@@ -1301,11 +1294,11 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
(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,
"Unable to send FXP_READ command", 0);
"_libssh2_channel_write() failed", 0);
LIBSSH2_FREE(session, sftp->readdir_packet);
sftp->readdir_packet = NULL;
sftp->readdir_state = libssh2_NB_state_idle;
@@ -1323,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);
@@ -1409,8 +1402,11 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
return rc;
}
/* sftp_write
* Write data to a file handle
/*
* sftp_write
*
* 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)
@@ -1421,20 +1417,28 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
unsigned long data_len, retcode;
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
offset(8) + count(4) */
ssize_t packet_len = handle->handle_len + count + 25;
ssize_t packet_len;
unsigned char *s, *data;
int rc;
/* There's no point in us accepting a VERY large packet here since we
cannot send it anyway. We just accept 4 times the big size to fill up
the queue somewhat. */
if(count > (MAX_SSH_PACKET_LEN*4))
count = MAX_SSH_PACKET_LEN*4;
packet_len = handle->handle_len + count + 25;
if (sftp->write_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_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 packet", 0);
return -1;
"Unable to allocate memory for FXP_WRITE", 0);
return LIBSSH2_ERROR_ALLOC;
}
_libssh2_htonu32(s, packet_len - 4);
s += 4;
*(s++) = SSH_FXP_WRITE;
@@ -1458,16 +1462,16 @@ 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;
if(rc < 0) {
/* error */
return rc;
}
if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, sftp->write_packet);
sftp->write_packet = NULL;
sftp->write_state = libssh2_NB_state_idle;
return -1;
else if(0 == rc) {
/* nothing sent is an error */
return LIBSSH2_ERROR_SOCKET_SEND;
}
else if (packet_len != rc) {
return rc;
}
LIBSSH2_FREE(session, sftp->write_packet);
sftp->write_packet = NULL;
@@ -1477,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;
@@ -1498,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
@@ -1567,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"
@@ -1587,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);
@@ -1654,7 +1659,10 @@ libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE * handle, libssh2_uint64_t offset)
LIBSSH2_API size_t
libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)
{
return handle->u.file.offset;
/* NOTE: this may very well truncate the size if it is larger than what
size_t can hold, so libssh2_sftp_tell64() is really the function you
should use */
return (size_t)(handle->u.file.offset);
}
/* libssh2_sftp_tell64
@@ -1710,7 +1718,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);
@@ -1730,7 +1738,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);
@@ -1752,12 +1760,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) {
@@ -1826,7 +1830,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);
@@ -1845,7 +1849,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,
@@ -1894,7 +1898,8 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
{
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
unsigned long data_len, retcode;
unsigned long data_len;
int retcode;
ssize_t packet_len =
source_filename_len + dest_filename_len + 17 + (sftp->version >=
5 ? 4 : 0);
@@ -1948,7 +1953,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);
@@ -1967,7 +1972,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);
@@ -2079,11 +2084,11 @@ 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,
"Unable to send FXP_READ command", 0);
"_libssh2_channel_write() failed", 0);
LIBSSH2_FREE(session, packet);
sftp->mkdir_state = libssh2_NB_state_idle;
return -1;
@@ -2096,7 +2101,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);
@@ -2177,7 +2182,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);
@@ -2195,7 +2200,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);
@@ -2296,7 +2301,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);
@@ -2314,7 +2319,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);
@@ -2436,7 +2441,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);
@@ -2455,7 +2460,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

@@ -1,374 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "libssh2_priv.h"
static int
ssh_host_parse_hostnames (LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
char *end
);
static int
ssh_host_parse_key (LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
int is_base64_encoded
);
/* Returns zero if successful, > zero for malformed data, < 0 not supported. */
LIBSSH2_API int
libssh2_new_host_entry(LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS ** s,
char *line)
{
char *tmp = NULL;
LIBSSH2_KNOWNHOSTS *t = NULL;
int i;
if (line == NULL || *line == 0)
return 1;
if (s == NULL)
return 2;
tmp = strchr (line, ' ');
if (tmp == NULL)
return 3;
t = (LIBSSH2_KNOWNHOSTS *)
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_KNOWNHOSTS));
t->hostname_line = NULL;
t->hostnames = NULL;
t->hostnames_size = t->bits = t->exponent = -1;
t->modulus = NULL;
t->modulus_length = -1;
t->ssh_version = -1;
t->md5 = NULL;
i = ssh_host_parse_hostnames (session, t, line, tmp);
if (i != 0) {
libssh2_free_host_entry (session, t);
return ((i > 0) ? 4 : -1);
}
line = tmp + 1;
tmp = strchr (line, ' ');
if (tmp != NULL)
tmp = strchr (tmp + 1, ' ');
i = ssh_host_parse_key (session, t, line, tmp == NULL ? 1 : 0);
if (i != 0) {
libssh2_free_host_entry (session, t);
return ((i > 0) ? 5 : -2);
}
*s = t;
return 0;
}
static int
ssh_host_parse_hostnames(LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
char *end)
{
char *start;
char *comma = NULL;
int i;
/* TODO: we don't handle the hashed name format because the hashing
* mechanism isnt defined (at least based on the man page)
*/
if (*line == '|')
return -1;
if (line == end || *line == ' ')
return 1;
s->hostname_line = (char *) LIBSSH2_ALLOC (session, (end - line) + 1);
strncpy (s->hostname_line, line, (end - line) + 1);
start = end = s->hostname_line + (end - line);
*end = 0;
s->hostnames_size = 1;
comma = s->hostname_line;
while ((comma = strchr (comma, ',')) != NULL) {
comma++;
if (*comma == ',' || *comma == 0) {
LIBSSH2_FREE (session, s->hostname_line);
s->hostname_line = NULL;
return 2;
}
s->hostnames_size++;
}
s->hostnames = (char **) LIBSSH2_ALLOC
(session, sizeof (char *) * s->hostnames_size);
start = comma = s->hostname_line;
i = 0;
while ((comma = strchr (comma, ',')) != NULL) {
*comma = 0;
s->hostnames[i] = start;
comma++;
start = comma;
i++;
}
s->hostnames[i] = start;
return 0;
}
/** Returns the number of bytes read or -1. */
static int
ssh_proto_str_read(LIBSSH2_SESSION * session,
char *line,
char **val,
char *end
)
{
unsigned int len;
if (line + 4 > end)
return -1;
len = (line[0] << 24) + (line[1] << 16) + (line[2] << 8) + line[3];
if (line + 4 + len > end)
return -1;
*val = LIBSSH2_ALLOC (session, len);
memcpy (*val, line + 4, len);
return len + 4;
}
static int
ssh_host_parse_key(LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
int is_base64_encoded)
{
int i, j;
char *tmp, *tmp2;
/* workaround for the MD5 stuff */
libssh2_md5_ctx ctx;
/* the bits, exponent, modulus format */
if (is_base64_encoded == 0) {
s->ssh_version = 1;
s->key_type = 0;
if (!isdigit (*line))
return -1;
if (sscanf (line, "%hu %hu ", &(s->bits), &(s->exponent)) != 2)
return -2;
/* TODO:
* There's probably an acceptable range...
*/
if (s->bits <= 0 || s->exponent <= 0)
return 1;
line = strchr (line, ' ');
if (line == NULL)
return -3;
line++;
line = strchr (line, ' ');
if (line == NULL)
return -4;
line++;
/* TODO:
* figure out what format modulus is in since its not clear
* from the man page
*/
return -5;
}
else {
s->ssh_version = 2;
/* we only handle the rsa type */
if (strstr (line, "ssh-rsa") != line)
return -6;
s->key_type = 0;
line += 7;
if (*line != ' ')
return 2;
line++;
i = 0;
while (*line) {
if ((line[i] >= 0x30 && line[i] <= 0x39) ||
(line[i] >= 0x41 && line[i] <= 0x5a) ||
(line[i] >= 0x61 && line[i] <= 0x7a) ||
(line[i] == '+') || (line[i] == '/') || (line[i] == '='))
i++;
else
break;
}
if (i == 0)
return 3;
tmp = LIBSSH2_ALLOC (session, sizeof (char) * (i + 5));
strncpy (tmp, line, i);
/* this should hopefully avoid any issues with reading
* past the array if its malformed */
tmp[i] = tmp[i + 1] = tmp[i + 2] = tmp[i + 3] = tmp[i + 4] = 0;
{
/* TODO: rework the api interface instead of making a local
instance */
i = libssh2_base64_decode(session, &tmp2, (unsigned int *)&j,
tmp, strlen(tmp));
LIBSSH2_FREE(session, tmp);
if (i != 0)
return 4;
}
/* printf("Decode Size: %d\n", i); */
/* free (tmp); */
#if LIBSSH2_MD5
s->md5 = LIBSSH2_ALLOC (session, 16);
libssh2_md5_init (&ctx);
libssh2_md5_update (ctx, tmp2, j);
libssh2_md5_final (ctx, s->md5);
#endif
line = tmp2;
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
if (i < 0) {
LIBSSH2_FREE (session, tmp2);
return 5;
}
/* TODO: verify that its ssh-rsa -- its the only one
* supported
*/
if (!(i == 11 && tmp[0] == 's' && tmp[1] == 's' &&
tmp[2] == 'h' && tmp[3] == '-' && tmp[4] == 'r' &&
tmp[5] == 's' && tmp[6] == 'a')) {
free (tmp);
free (tmp2);
return 8;
}
LIBSSH2_FREE (session, tmp);
line += i;
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
if (i < 0) {
LIBSSH2_FREE (session, tmp2);
return 6;
}
/* TODO: verify that the exponent is valid */
if (i == 5)
s->exponent = (unsigned short) ((unsigned char) *tmp);
else {
LIBSSH2_FREE (session, tmp);
LIBSSH2_FREE (session, tmp2);
return 9;
}
LIBSSH2_FREE (session, tmp);
line += i;
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
if (i < 0) {
LIBSSH2_FREE (session, tmp2);
return 7;
}
/* TODO: the modulus may need to be converted to
* big integer format
*/
s->modulus_length = i - 4;
s->modulus = tmp;
s->bits = (s->modulus_length - 1) * 8;
LIBSSH2_FREE (session, tmp2);
return 0;
}
}
LIBSSH2_API void
libssh2_free_host_entry(LIBSSH2_SESSION * session, LIBSSH2_KNOWNHOSTS * s)
{
/* int i; */
if (s == NULL)
return;
if (s->hostname_line != NULL) {
LIBSSH2_FREE (session, s->hostname_line);
s->hostname_line = NULL;
}
if (s->hostnames != NULL && s->hostnames_size > 0) {
LIBSSH2_FREE (session, s->hostnames);
s->hostnames = NULL;
}
s->hostnames_size = s->bits = s->exponent = -1;
if (s->modulus != NULL) {
LIBSSH2_FREE (session, s->modulus);
s->modulus = NULL;
}
s->modulus_length = -1;
s->ssh_version = -1;
if (s->md5 != NULL) {
LIBSSH2_FREE (session, s->md5);
s->md5 = NULL;
}
LIBSSH2_FREE (session, s);
}
#ifdef SSH_HOSTNAME_TESTS
int
ssh_unit_tests (int argc, char **argv)
{
char *l[] = {
"closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net",
"cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
" cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
"",
",",
"f, ",
"cvs.example.net ssh-rsa AAAA1234.....=",
"192.168.30.118 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwWVqxKm2Biwilakq9Ex8/tzHVQjRrzEkwlrWTDneptodVgqAzXUFQSa6Oj9AwzdDPhKe71vTv7RhXYg0ZvB1a5dIkzgCdoF/mIuTb80LvK7f0NxCaAHWODuHbwlJeMmjHV0WFsjsdOf690fPqeinD/8jfBQB950M1K3Qesib9H75gsnawF06MzZ52nC1HHi8mG2tGy2PMyP+mJs7KN1v4T+nobZ10ePe1dMqYXMdro/PB0JQmuGL7bBR5GRDEkK6nFcp2HsvuzXSeWZJcmWDdo+1n0cNg2th5VEIxrrFG5iy0CA2AXVPMqkf3VrAXGXV66dJTGtBqZ5GoxJCxDgW6w==",
"|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsaAAAA1234.....="
};
int s;
int cases = sizeof (l) / sizeof (char *);
if (argc == 2) {
s = atoi (argv[1]);
if (s >= 0 && s < cases) {
LIBSSH2_KNOWNHOSTS *x = NULL;
printf ("%d\n", s = new_ssh_host_entry (&x, l[s]));
libssh2_free_host_entry (x);
return s;
}
}
}
#endif
/** Returns 0 for a match, non-zero otherwise. */
LIBSSH2_API int
libssh2_host_entry_match(LIBSSH2_KNOWNHOSTS * x, char *host)
{
/* TODO: Add pattern matching and/or DNS matching against
* to entries found in x
*/
int i;
if (host == NULL || x == NULL)
return -1;
/* FIXME: this should use a case-insensitive compare as dns hostnames
* are generally case insensitive anyways
*/
for (i = 0; i < x->hostnames_size; i++)
if (!strcmp (x->hostnames[i], host))
return 0;
return 1;
}

View File

@@ -95,10 +95,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 +134,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 +232,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 +245,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;
int rc = LIBSSH2_ERROR_SOCKET_NONE;
struct transportpacket *p = &session->packet;
int remainbuf;
int remainpack;
@@ -273,7 +269,8 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
int blocksize;
int encrypted = 1;
int status;
/* default clear the bit */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
/*
* All channels, systems, subsystems, etc eventually make it down here
@@ -295,16 +292,9 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
*/
_libssh2_debug(session, LIBSSH2_DBG_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;
}
/*
@@ -369,12 +359,13 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
/* 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;
}
return PACKET_FAIL;
}
debugdump(session, "libssh2_transport_read() raw",
&p->buf[remainbuf], nread);
/* advance write pointer */
@@ -397,6 +388,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;
}
@@ -421,7 +414,12 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
* and we can extract packet and padding length from it
*/
p->packet_length = _libssh2_ntohu32(block);
if (p->packet_length < 1)
return PACKET_FAIL;
p->padding_length = block[4];
if (p->padding_length < 0)
return PACKET_FAIL;
/* total_num is the number of bytes following the initial
(5 bytes) packet length and padding length fields */
@@ -562,7 +560,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 */
@@ -574,7 +572,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)
{
@@ -605,26 +603,30 @@ 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) {
debugdump(session, "libssh2_transport_write send()",
&p->outbuf[p->osent], rc);
}
if (rc == length) {
/* the remainder of the package was sent */
LIBSSH2_FREE(session, p->outbuf);
p->outbuf = NULL;
p->ototal_num = 0;
} else if (rc < 0) {
}
else if (rc < 0) {
/* nothing was sent */
if (errno != EAGAIN) {
/* send failure! */
return PACKET_FAIL;
}
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
debugdump(session, "libssh2_transport_write send()", &p->outbuf[p->osent],
length);
p->osent += length; /* we sent away this much data */
p->osent += rc; /* we sent away this much data */
return PACKET_NONE;
return p->osent < data_len ? PACKET_EAGAIN : PACKET_NONE;
}
/*
@@ -641,6 +643,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,
@@ -661,12 +665,15 @@ _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) {
@@ -776,7 +783,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;
@@ -794,6 +801,3 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
return PACKET_NONE; /* all is good */
}

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

@@ -266,7 +266,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
rc = _libssh2_transport_write(session, 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 request", 0);
@@ -294,7 +294,7 @@ 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;
@@ -402,7 +402,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
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",
@@ -808,7 +808,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);
@@ -831,7 +831,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;
@@ -987,7 +987,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
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);
@@ -1017,7 +1017,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;
@@ -1163,7 +1163,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
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);
@@ -1186,7 +1186,7 @@ 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;
@@ -1326,7 +1326,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
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,7 +1350,7 @@ 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;
@@ -1527,7 +1527,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
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

@@ -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

@@ -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

View File

@@ -9,15 +9,15 @@ 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 \
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" \

View File

@@ -5,7 +5,7 @@
##
## Comments to: Guenter Knauf <eflash@gmx.net>
##
## $Id: Makefile.win32,v 1.10 2009/03/06 07:25:37 gknauf Exp $
## $Id: Makefile.win32,v 1.11 2009/04/09 03:13:52 gknauf Exp $
#
#########################################################################
@@ -18,7 +18,7 @@ WITH_ZLIB = 1
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../openssl-0.9.8j
OPENSSL_PATH = ../../openssl-0.9.8k
endif
# Edit the path below to point to your Distribution folder.
@@ -63,7 +63,7 @@ endif
ifdef METROWERKS
CC = mwcc
else
CC = $(CRPREFIX)gcc
CC = $(CROSSPREFIX)gcc
endif
CP = cp -afv
# RM = rm -f
@@ -91,13 +91,13 @@ CFLAGS += -nostdinc -gccinc -msgstyle gcc -inline off -opt nointrinsics -proc 58
CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support"
CFLAGS += -w on,nounused,nounusedexpr # -ansi strict
else
LD = $(CRPREFIX)gcc
RC = $(CRPREFIX)windres
LD = $(CROSSPREFIX)gcc
RC = $(CROSSPREFIX)windres
LDFLAGS = -s -shared -Wl,--out-implib,$(TARGET)dll.a
AR = $(CRPREFIX)ar
AR = $(CROSSPREFIX)ar
ARFLAGS = -cq
LIBEXT = a
RANLIB = $(CRPREFIX)ranlib
RANLIB = $(CROSSPREFIX)ranlib
#LDLIBS += -lwsock32
LDLIBS += -lws2_32
RCFLAGS = -O coff -i
@@ -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

3
win32/msvcproj.foot Normal file
View File

@@ -0,0 +1,3 @@
# End Target
# End Project

145
win32/msvcproj.head Normal file
View File

@@ -0,0 +1,145 @@
# Microsoft Developer Studio Project File - Name="libssh2" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=libssh2 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "libssh2.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "libssh2.mak" CFG="libssh2 - Win32 DLL Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "libssh2 - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "libssh2 - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "libssh2 - Win32 LIB Release" (based on "Win32 (x86) Static Library")
!MESSAGE "libssh2 - Win32 LIB Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "libssh2 - Win32 DLL Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_dll"
# PROP BASE Intermediate_Dir "Release_dll"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_dll"
# PROP Intermediate_Dir "Release_dll"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\win32" /I "..\include" /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib ws2_32.lib libeay32.lib ssleay32.lib zlib.lib /nologo /dll /map /debug /machine:I386 /out:"Release_dll/libssh2.dll"
!ELSEIF "$(CFG)" == "libssh2 - Win32 DLL Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_dll"
# PROP BASE Intermediate_Dir "Debug_dll"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_dll"
# PROP Intermediate_Dir "Debug_dll"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\win32" /I "..\include" /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# SUBTRACT CPP /WX /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib ws2_32.lib libeay32.lib ssleay32.lib zlib.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug_dll/libssh2.dll" /pdbtype:sept
# SUBTRACT LINK32 /nodefaultlib
!ELSEIF "$(CFG)" == "libssh2 - Win32 LIB Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_lib"
# PROP BASE Intermediate_Dir "Release_lib"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_lib"
# PROP Intermediate_Dir "Release_lib"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\win32" /I "..\include" /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
# ADD LIB32 /nologo /out:"Release_lib\libssh.lib"
!ELSEIF "$(CFG)" == "libssh2 - Win32 LIB Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_lib"
# PROP BASE Intermediate_Dir "Debug_lib"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_lib"
# PROP Intermediate_Dir "Debug_lib"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\win32" /I "..\include" /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"Debug_lib\libssh2d.lib"
!ENDIF
# Begin Target
# Name "libssh2 - Win32 DLL Release"
# Name "libssh2 - Win32 DLL Debug"
# Name "libssh2 - Win32 LIB Release"
# Name "libssh2 - Win32 LIB Debug"

View File

@@ -5,7 +5,7 @@
##
## Comments to: Guenter Knauf <eflash@gmx.net>
##
## $Id: Makefile.win32,v 1.7 2009/03/06 07:25:49 gknauf Exp $
## $Id: Makefile.win32,v 1.8 2009/04/09 03:14:05 gknauf Exp $
#
#########################################################################
@@ -16,7 +16,7 @@ endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../../openssl-0.9.8j
OPENSSL_PATH = ../../../openssl-0.9.8k
endif
# Edit the var below to enable static linking of libssh2 and libz
@@ -51,7 +51,7 @@ endif
ifdef METROWERKS
CC = mwcc
else
CC = gcc
CC = $(CROSSPREFIX)gcc
endif
CP = cp -afv
# RM = rm -f
@@ -79,19 +79,20 @@ CFLAGS += -nostdinc -gccinc -msgstyle gcc -inline off -opt nointrinsics -proc 58
CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support"
CFLAGS += -w on,nounused,nounusedexpr # -ansi strict
else
LD = gcc
RC = windres
LD = $(CROSSPREFIX)gcc
RC = $(CROSSPREFIX)windres
LDFLAGS = -s
AR = ar
AR = $(CROSSPREFIX)ar
ARFLAGS = -cq
LIBEXT = a
#LDLIBS += -lwsock32
LDLIBS += -lws2_32
RCFLAGS = -O coff -i
CFLAGS += -fno-strict-aliasing -Wall -Wno-unused # -pedantic
CFLAGS += -fno-strict-aliasing
CFLAGS += -Wall #-Wno-unused #-pedantic
endif
INCLUDES = -I. -I.. -I../../include
INCLUDES = -I.. -I../../include
INCLUDES += -I$(OPENSSL_PATH)/outinc -I$(OPENSSL_PATH)/outinc/openssl
#LIBPATH += -L$(OPENSSL_PATH)/out
LIBPATH += -L..