Compare commits

...

146 Commits

Author SHA1 Message Date
Daniel Stenberg
5633bb4a3b RELEASE-NOTES: synced with fabf1a45ee 2011-04-04 13:32:58 +02:00
Daniel Stenberg
fabf1a45ee NEWS: auto-generated from git
Starting now, the NEWS file is generated from git using the git2news.pl
script. This makes it always accurate and up-to-date, even for daily
snapshots etc.
2011-04-04 13:31:33 +02:00
Daniel Stenberg
2e352d3085 sftp_write: handle FXP_WRITE errors
When an sftp server returns an error back on write, make sure the
function bails out and returns the proper error.
2011-03-30 11:35:37 +02:00
Daniel Stenberg
8c9571b7ba configure: stop using the deprecated AM_INIT_AUTOMAKE syntax 2011-03-15 11:34:41 +01:00
Alexander Lamaison
527c1b2def Support unlimited number of host names in a single line of the known_hosts file.
Previously the code assumed either a single host name or a hostname,ip-address pair.  However, according to the spec [1], there can be any number of comma separated host names or IP addresses.

[1] http://www.openbsd.org/cgi-bin/man.cgi?query=sshd&sektion=8
2011-03-13 00:29:39 +00:00
Daniel Stenberg
ec934f6dab libssh2_knownhost_readfile.3: clarify return value
This function returns the number of parsed hosts on success, not just
zero as previously documented.
2011-02-26 10:57:56 +01:00
Peter Stuge
516fa7fdd9 Don't save allocated packet size until it has actually been allocated
The allocated packet size is internal state which needs to match reality
in order to avoid problems. This commit fixes #211.
2011-02-26 05:21:01 +01:00
Alfred Gebert
3ce2628140 session_startup: manage server data before server identification
Fix the bug that libssh2 could not connect if the sftp server
sends data before sending the version string.

http://tools.ietf.org/html/rfc4253#section-4.2

"The server MAY send other lines of data before sending the version
string.  Each line SHOULD be terminated by a Carriage Return and Line
Feed.  Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
in ISO-10646 UTF-8 [RFC3629] (language is not specified).  Clients
MUST be able to process such lines."
2011-02-21 23:19:27 +01:00
Alfred Gebert
ad88325b3f fullpacket: decompression only after init
The buffer for the decompression (remote.comp_abstract) is initialised
in time when it is needed.  With this fix decompression is disabled when
the buffer (remote.comp_abstract) is not initialised.

Bug: http://trac.libssh2.org/ticket/200
2011-02-16 13:57:58 +01:00
Daniel Stenberg
2db4863e6e _libssh2_channel_read: store last error
When the transport layer returns EAGAIN this function didn't call
_libssh2_error() which made the last_error not get set.
2011-02-15 23:21:38 +01:00
Daniel Stenberg
691cabc048 sftp_write: clarified the comment header 2011-01-20 09:01:59 +01:00
Daniel Stenberg
90b4b4073f sftp_read: avoid wrapping counter to insanity
As pointed out in bug #206, if a second invoke of libssh2_sftp_read()
would shrink the buffer size, libssh2 would go nuts and send out read
requests like crazy. This was due to an unsigned variable turning
"negative" by some wrong math, and that value would be the amount of
data attempt to pre-buffer!

Bug: http://trac.libssh2.org/ticket/206
2011-01-17 22:39:47 +01:00
Daniel Stenberg
8ce9a66ccf sftp_packet_read: use 32bit variables for 32bit data 2011-01-09 00:34:09 +01:00
Daniel Stenberg
7015488150 libssh2_sftp_stat_ex.3: cleaned up, extended
Removed the macros from it as they have their own man pages.

Added the LIBSSH2_SFTP_ATTRIBUTES struct in here for easier reference.
2011-01-06 00:30:32 +01:00
Daniel Stenberg
164838c7dd sftp_readdir: return error if buffer is too small
If asked to read data into a buffer and the buffer is too small to hold
the data, this function now returns an error instead of as previously
just copy as much as fits.
2011-01-04 14:30:04 +01:00
Daniel Stenberg
f9b1b95059 sftp_symlink: return error if receive buffer too small
and clean up some variable type mismatches

Discussion: http://www.libssh2.org/mail/libssh2-devel-archive-2011-01/0001.shtml
2011-01-04 14:15:57 +01:00
Daniel Stenberg
59207291fc docs: clarify what happens with a too small buffer
This flaw is subject to change, but I figured it might be valuable to
users of existing code to know how it works.
2011-01-03 00:07:44 +01:00
Daniel Stenberg
0da37e0924 channel_request_pty_size: fix reqPTY_state
The state variable isn't properly set so every other call to the
function fails!

Bug: http://libssh2.org/mail/libssh2-devel-archive-2010-12/0096.shtml
Reported by: Steve Legg
2011-01-01 16:16:32 +01:00
Daniel Stenberg
4552c73cd5 data size: cleanup
Fix 64bit warnings by using (s)size_t and dedicated uint32_t types more.
2010-12-30 00:09:53 +01:00
Pierre Joye
306929ee80 ssize_t: proper typedef with MSVC compilers
As discussed on the mailing list, it was wrong for win64 and using the
VC-provided type is the safest approach instead of second- guessing
which one it should be.
2010-12-29 23:22:00 +01:00
Guenter Knauf
326f741a52 Updated OpenSSL version. 2010-12-22 14:39:59 +01:00
Guenter Knauf
aa4f861643 Expanded tabs to spaces. 2010-12-22 14:27:55 +01:00
Joey Degges
fd691deb17 _libssh2_ntohu64: fix conversion from network bytes to uint64
Cast individual bytes to uint64 to avoid overflow in arithmetic.
2010-12-21 13:15:42 +01:00
Daniel Stenberg
20da09932e libssh2_userauth_list: language fix
"faily" is not a good English word, and I also cleaned up some other minor
mistakes
2010-12-20 14:22:07 +01:00
Daniel Stenberg
3ab7af095a crypto: unify the generic functions
Added crypto.h that is the unified header to include when using crypto
functionality. It should be the only header that needs to adapt to the
underlying crypto library in use. It provides the set of prototypes that
are library agnostic.
2010-12-19 00:00:50 +01:00
Mark Smith
5b1a7ec2f1 userauth: derive publickey from private
Pass a NULL pointer for the publickey parameter of
libssh2_userauth_publickey_fromfile and
libssh2_userauth_hostbased_fromfile functions.  In this case, the
functions recompute the public key from the private key file data.

This is work done by Jean-Louis CHARTON
<Jean-Louis.CHARTON@oikialog.com>, then adapted by Mark Smith and
slightly edited further by me Daniel.

WARNING: this does leave the feature NOT WORKING when libssh2 is built
to use libgcrypt instead of OpenSSL simply due to lack of
implementation.
2010-12-18 23:38:08 +01:00
Daniel Stenberg
5ee38702a0 ssh2_echo: Value stored to 'exitcode' is never read 2010-12-15 21:58:43 +01:00
Daniel Stenberg
2165ceacd3 _libssh2_packet_add: fix SSH_MSG_DEBUG weirdness
I believe I may have caused this weird typo style error when I cleaned
up this function a while ago. Corrected now.
2010-12-15 21:57:06 +01:00
Daniel Stenberg
121237ce2f uint32: more longs converted to proper types
I also moved the MAC struct over to the mac.h header file and made sure
that the users of that struct include that file.
2010-12-15 09:52:18 +01:00
Daniel Stenberg
b3e832172b SFTP: more types to uint32_t
The 'num_names' field in the SSH_FXP_NAME response is an unsigned 32bit
value so we make sure to treat it like that.
2010-12-15 09:31:37 +01:00
Daniel Stenberg
3faa8bc940 SFTP: request_ids are uint32_t
I went over the code and made sure we use uint32_t all over for the
request_id data. It is an unsigned 32bit value on the wire.
2010-12-15 09:27:00 +01:00
Daniel Stenberg
2f0c0cef76 SFTP: store request_id separately in packets
By using a new separate struct for incoming SFTP packets and not sharing
the generic packet struct, we can get rid of an unused field and add a
new one dedicated for holding the request_id for the incoming
package. As sftp_packet_ask() is called fairly often, a "mere" integer
comparison is MUCH faster than the previous memcmp() of (typically) 5
bytes.
2010-12-14 23:49:51 +01:00
Daniel Stenberg
75909e05a9 libssh2_sftp_open_ex: man page extended and cleaned up
I added the missing documentation for the 'flags' argument.
2010-12-14 15:06:04 +01:00
Daniel Stenberg
47b4e62780 SFTP: unify the READ/WRITE chunk structs 2010-12-14 13:29:41 +01:00
Daniel Stenberg
1b1ff333e4 SFTP: fix memory leaks
Make sure that we cleanup remainders when the handle is closed and when
the subsystem is shutdown.

Existing flaw: if a single handle sends packets that haven't been
replied to yet at the time when the handle is closed, those packets will
arrive later and end up in the generic packet brigade queue and they
will remain in there until flushed. They will use unnecessary memory,
make things slower and they will ruin the SFTP handling if the
request_id counter ever wraps (highly unlikely to every happen).
2010-12-14 11:46:53 +01:00
Daniel Stenberg
c1683ae92c sftp_close_handle: packet list is generic
Fix comment, simplify the loop logic
2010-12-14 09:33:58 +01:00
Daniel Stenberg
1b65c6ae26 sftp_read: pipeline reads
The SFTP read function now does transfers the same way the SFTP write
function was made to recently: it creates a list of many outgoing
FXP_READ packets that each asks for a small data chunk. The code then
tries to keep sending read request while collecting the acks for the
previous requests and returns the received data.
2010-12-14 09:30:25 +01:00
Daniel Stenberg
92ea3bda60 sftp_write: removed unused variable 2010-12-13 19:02:19 +01:00
Daniel Stenberg
811cce09b5 _libssh2_channel_close: don't call transport read if disconnected
The loop that waits for remote.close to get set may end up looping
forever since session->socket_state gets set to
LIBSSH2_SOCKET_DISCONNECTED by the packet_add() function called from the
transport_read() function and after having been set to
LIBSSH2_SOCKET_DISCONNECTED, the transport_read() function will only
return 0.

Bug: http://trac.libssh2.org/ticket/198
2010-12-11 22:43:22 +01:00
Daniel Stenberg
6875285b71 libssh2_sftp_seek64: new man page
Split off libssh2_sftp_seek64 from the libssh2_sftp_seek man page, and
mentioned that we consider the latter deprecated. Also added a mention
about the dangers of doing seek during writing or reading.
2010-12-11 00:03:42 +01:00
Daniel Stenberg
0cc14be09d sftp_seek: fix
The new SFTP write code caused a regression as the seek function no
longer worked as it didn't set the write position properly.

It should be noted that seeking is STRONGLY PROHIBITED during upload, as
the upload magic uses two different offset positions and the multiple
outstanding packets etc make them sensitive to change in the midst of
operations.

This functionality was just verified with the new example code
sftp_append. This bug was filed as bug #202:

Bug: http://trac.libssh2.org/ticket/202
2010-12-10 23:51:20 +01:00
Daniel Stenberg
499b989d46 sftp_append: new example doing SFTP append 2010-12-10 23:49:16 +01:00
Daniel Stenberg
fa07d9fefc MAX_SFTP_OUTGOING_SIZE: 30000
I ran SFTP upload tests against localhost. It showed that to make the
app reach really good speeds, I needed to do a little code tweak and
change MAX_SFTP_OUTGOING_SIZE from 4000 to 30000. The tests I did before
with the high latency tests didn't show any real difference whatever I
had that size set to.

This number is the size in bytes that libssh2 cuts off the large input
buffer and sends off as an individual sftp packet.
2010-12-06 21:10:10 +01:00
Daniel Stenberg
b0c32a85fc sftp_write_sliding.c: new example
This is an example that is very similar to sftp_write_nonblock.c, with
the exception that this uses

1 - a larger upload buffer

2 - a sliding buffer mechnism to allow the app to keep sending lots of
data to libssh2 without having to first drain the buffer.

These are two key issues to make libssh2 SFTP uploads really perform
well at this point in time.
2010-12-05 00:06:39 +01:00
Daniel Stenberg
7ed7dad3b4 cpp: s/#elsif/#elif
This looks like a typo as #elsif is not really C...
2010-12-02 12:40:59 +01:00
Daniel Stenberg
b215ec0af5 _libssh2_channel_write: revert channel_write() use
The attempts made to have _libssh2_channel_write() accept larger pieces
of data and split up the data by itself into 32700 byte chunks and pass
them on to channel_write() in a loop as a way to do faster operations on
larger data blocks was a failed attempt.

The reason why it is difficult:

The API only allows EAGAIN or a length to be returned. When looping over
multiple blocks to get sent, one block can get sent and the next might
not. And yet: when transport_send() has returned EAGAIN we must not call
it again with new data until it has returned OK on the existing data it
is still working on. This makes it a mess and we do get a much easier
job by simply returning the bytes or EAGAIN at once, as in the EAGAIN
case we can assume that we will be called with the same arguments again
and transport_send() will be happy.

Unfortunately, I think we take a small performance hit by not being able
to do this.
2010-11-13 23:13:21 +01:00
Daniel Stenberg
ac6d0fb706 ssh2_echo: new example
This is a new example snippet. The code is largely based on ssh2_exec,
and is written by Tommy Lindgren. I edited it into C90 compliance and to
conform to libssh2 indent style and some more.
2010-11-13 23:11:39 +01:00
Daniel Stenberg
e87293d480 send_existing: return after send_existing
When a piece of data is sent from the send_existing() function we must
make the parent function return afterwards. Otherwise we risk that the
parent function tries to send more data and ends up getting an EGAIN for
that more data and since it can only return one return code it doesn't
return info for the successfully sent data.

As this change is a regression I now added a larger comment explaining
why it has to work like this.
2010-11-13 12:25:06 +01:00
Daniel Stenberg
a3ce1073c4 _libssh2_channel_write: count resent data as written
In the logic that resends data that was kept for that purpose due to a
previous EAGAIN, the data was not counted as sent causing badness.
2010-11-13 12:23:23 +01:00
Peter Stuge
97a1881749 Use fprintf(stderr, ) instead of write(2, ) for debugging 2010-11-13 02:06:41 +01:00
Peter Stuge
80f7508d55 session/transport: Correctly handle when _libssh2_send() returns -EAGAIN 2010-11-13 01:53:39 +01:00
Peter Stuge
e8c44e789f src/agent.c: Simplify _libssh2_send() error checking ever so slightly 2010-11-13 01:50:24 +01:00
Daniel Stenberg
ca2e81eb1f send/recv: use _libssh2_recv and _libssh2_send now
Starting now, we unconditionally use the internal replacement functions
for send() and recv() - creatively named _libssh2_recv() and
_libssh2_send().

On errors, these functions return the negative 'errno' value instead of
the traditional -1. This design allows systems that have no "natural"
errno support to not have to invent it. It also means that no code
outside of these two transfer functions should use the errno variable.
2010-11-12 21:53:35 +01:00
Daniel Stenberg
aff9c825c8 channel_write: move some logic to _libssh2_channel_write
Some checks are better done in _libssh2_channel_write just once per
write instead of in channel_write() since the looping will call the
latter function multiple times per _libssh2_channel_write() invoke.
2010-11-12 15:15:46 +01:00
Daniel Stenberg
7899d28ecb sftp_write: handle "left over" acked data
The SFTP handle struct now buffers number of acked bytes that haven't
yet been returned. The way this is used is as following:

1. sftp_write() gets called with a buffer of let say size 32000. We
split 32000 into 8 smaller packets and send them off one by one. One of
them gets acked before the function returns so 4000 is returned.

2. sftp_write() gets called again a short while after the previous one,
now with a much smaller size passed in to the function. Lets say 8000.
In the mean-time, all of the remaining packets from the previous call
have been acked (7*4000 = 28000). This function then returns 8000 as all
data passed in are already sent and it can't return any more than what
it got passed in. But we have 28000 bytes acked. We now store the
remaining 20000 in the handle->u.file.acked struct field to add up in
the next call.

3. sftp_write() gets called again, and now there's a backlogged 20000
bytes to return as fine and that will get skipped from the beginning
of the buffer that is passed in.
2010-11-11 11:57:35 +01:00
Daniel Stenberg
2f5a2ff8e6 sftp_write: polished and simplified
Removed unnecessary struct fields and state changes within the function.

Made the loop that checks for ACKs only check chunks that were fully
sent.
2010-11-10 23:29:16 +01:00
Daniel Stenberg
160453cee4 SCP: on failure, show the numerical error reason
By calling libssh2_session_last_errno()
2010-11-10 17:26:38 +01:00
Daniel Stenberg
82fa5d2167 SFTP: provide the numerical error reason on failure 2010-11-10 17:26:02 +01:00
Daniel Stenberg
1c3e1c4d25 SCP: clean up failure treatment
When SCP send or recv fails, it gets a special message from the server
with a warning or error message included. We have no current API to
expose that message but the foundation is there. Removed unnecessary use
of session struct fields.
2010-11-10 17:17:32 +01:00
Daniel Stenberg
1d2a5b8456 sftp_write: enlarge buffer to perform better 2010-11-10 15:00:55 +01:00
Daniel Stenberg
1d11d02aa9 packets: code cleanup
I added size checks in several places. I fixed the code flow to be easier
to read in some places.

I removed unnecessary zeroing of structs. I removed unused struct fields.
2010-11-10 14:56:14 +01:00
Daniel Stenberg
f4ad3e0120 LIBSSH2_CALLBACK_MACERROR: clarify return code use 2010-11-10 14:41:56 +01:00
Daniel Stenberg
772564650d _libssh2_userauth_publickey: avoid shadowing 2010-11-10 13:28:33 +01:00
Daniel Stenberg
05ba8db8aa packet: avoid shadowing global symbols 2010-11-10 13:06:39 +01:00
Daniel Stenberg
1964ccb557 sftp_readdir: avoid shadowing 2010-11-10 13:05:08 +01:00
Daniel Stenberg
bef0ce5392 shadowing: don't shadow the global compress 2010-11-10 13:04:30 +01:00
Daniel Stenberg
fb6afd01a1 _libssh2_packet_add: turn ifs into a single switch 2010-11-10 12:21:48 +01:00
Daniel Stenberg
a302428335 _libssh2_packet_add: check SSH_MSG_GLOBAL_REQUEST packet 2010-11-09 19:59:18 +01:00
Daniel Stenberg
7ad152a6b2 _libssh2_packet_add: SSH_MSG_DEBUG length checks
Verify lengths before using them. Read always_display from the correct
index. Don't copy stuff around just to provide zero-termination of the
strings.
2010-11-09 15:07:32 +01:00
Daniel Stenberg
075ff19574 _libssh2_packet_add: SSH_MSG_IGNORE skip memmove
There's no promise of a zero termination of the data in the callback so
no longer perform ugly operation in order to provide it.
2010-11-09 14:57:36 +01:00
Daniel Stenberg
16f46c1cfc _libssh2_packet_add: SSH_MSG_DISCONNECT length checks
Verify lengths before trying to read data.
2010-11-09 14:53:44 +01:00
Daniel Stenberg
aa2fdb3e7e indent: break lines at 80 columns 2010-11-09 14:32:02 +01:00
Daniel Stenberg
8f10da89c5 SSH_MSG_CHANNEL_OPEN_FAILURE: used defined values
We don't like magic numbers in the code. Now the acceptable failure
codes sent in the SSH_MSG_CHANNEL_OPEN_FAILURE message are added as
defined values in the private header file.
2010-11-09 14:28:29 +01:00
Daniel Stenberg
2dfa5d38cb sftp_write: don't return EAGAIN if no EAGAIN was received
This function now only returns EAGAIN if a lower layer actually returned
EAGAIN to it. If nothing was acked and no EAGAIN was received, it will
now instead return 0.
2010-11-09 13:09:08 +01:00
Daniel Stenberg
095e9e7b3e _libssh2_wait_socket: detect nothing-to-wait-for
If _libssh2_wait_socket() gets called but there's no direction set to
wait for, this causes a "hang". This code now detects this situation,
set a 1 second timeout instead and outputs a debug output about it.
2010-11-09 13:07:15 +01:00
Daniel Stenberg
588c8946fc decomp: remove the free_dest argument
Since the decompress function ALWAYS returns allocated memory we get a
lot simpler code by removing the ability to return data unallocated.
2010-11-03 15:03:57 +01:00
Daniel Stenberg
a6fc9aeec9 decomp: cleaned off old compression stuff
I cleared off legacy code from when the compression and decompression
functions were a single unified function. Makes the code easier to read
too.
2010-11-03 14:52:42 +01:00
TJ Saunders
7603c0f854 decomp: increase decompression buffer sizes 2010-11-03 14:45:52 +01:00
TJ Saunders
8974dc05ae zlib: Add debug tracing of zlib errors 2010-11-03 14:42:44 +01:00
Daniel Stenberg
6395a738fd sftp_packet_read: handle partial reads of the length field
SFTP packets come as [32 bit length][payload] and the code didn't
previously handle that the initial 32 bit field was read only partially
when it was read.
2010-11-02 19:14:33 +01:00
Jasmeet Bagga
73be9fab04 kex_agree_hostkey: fix NULL pointer derefence
While setting up the session, ssh tries to determine the type of
encryption method it can use for the session. This requires looking at
the keys offered by the remote host and comparing these with the methods
supported by libssh2 (rsa & dss). To do this there is an iteration over
the array containing the methods supported by libssh2.

If there is no agreement on the type of encryption we come to the 3rd
entry of the hostkeyp array. Here hostkeyp is valid but *hostkep is
NULL. Thus when we dereference that in (*hostkeyp)->name there is a
crash
2010-11-02 00:02:25 +01:00
Daniel Stenberg
753e55ef23 _libssh2_transport_send: remove dead assignment
'data' isn't accessed beyond this point so there's no need to assign it.
2010-11-01 23:00:07 +01:00
Daniel Stenberg
4760e4d051 scp_recv: remove dead assignment
Instead of assigning a variable we won't read, we now use the more
explicit (void) prefix.
2010-11-01 22:59:15 +01:00
Daniel Stenberg
57af0da9f7 sftp_write: removed superfluous assignment 2010-11-01 22:58:47 +01:00
Daniel Stenberg
024b5d29f5 bugfix: avoid use of uninitialized value 2010-11-01 22:58:12 +01:00
Daniel Stenberg
a0dd0c5992 sftp_packet_require: propagate error codes better
There were some chances that they would cause -1 to get returned by
public functions and as we're hunting down all such occurances and since
the underlying functions do return valuable information the code now
passes back proper return codes better.
2010-11-01 09:33:36 +01:00
Alfred Gebert
92d308c157 fix memory leaks (two times cipher_data) for each sftp session 2010-10-27 23:17:16 +02:00
Daniel Stenberg
4ae71b4838 libssh2_userauth_authenticated: make it work as documented
The man page clearly says it returns 1 for "already authenticated" but
the code said non-zero. I changed the code to use 1 now, as that is also
non-zero but it gets the benefit that it now matches the documentation.

Using 1 instead of non-zero is better for two reasons:

1. We have the opportunity to introduce other return codes in the future for
   things like error and what not.
2. We don't expose the internal bitmask variable value.
2010-10-27 22:59:32 +02:00
Daniel Stenberg
ba190d34c6 userauth_keyboard_interactive: fix indent 2010-10-27 22:58:39 +02:00
Alfred Gebert
b84f69c960 fix memory leak in userauth_keyboard_interactive()
First I wanted to free the memory in session_free() but then
I had still memory leaks because in my test case the function
userauth_keyboard_interactive() is called twice. It is called
twice perhaps because the server has this authentication
methods available: publickey,gssapi-with-mic,keyboard-interactive
The keyboard-interactive method is successful.
2010-10-27 22:47:34 +02:00
Daniel Stenberg
a7aee34522 dist: include sftp.h in dist archives 2010-10-27 14:51:25 +02:00
Simon Josefsson
1dc366109d Update header to match new function prototype, see c48840ba88. 2010-10-27 11:45:07 +02:00
Daniel Stenberg
e1ea2eb7c2 bugfixes: the transport rearrange left some subtle flaws now gone 2010-10-26 00:14:31 +02:00
Daniel Stenberg
610a8ab919 libssh2_userauth_publickey_fromfile_ex.3: cleaned up looks 2010-10-25 23:44:39 +02:00
Daniel Stenberg
8ec21e0afe libssh2_userauth_publickey: add man page
I found an undocumented public function and we can't have it like
that. The description here is incomplete, but should serve as a template
to allow filling in...
2010-10-25 23:18:50 +02:00
Daniel Stenberg
8e0983347b libssh2_sftp_write.3: added blurb about the "write ahead"
Documented the new SFTP write concept
2010-10-25 16:38:37 +02:00
Daniel Stenberg
95db6cc62c sftp_close_handle: free any trailing write chunks 2010-10-25 16:30:09 +02:00
Daniel Stenberg
727043074a _libssh2_channel_write: fix warnings 2010-10-25 16:07:46 +02:00
Daniel Stenberg
5b4ed2717b SFTP: bufgix, move more sftp stuff to sftp.h
The sftp_write function shouldn't assume that the buffer pointer will be
the same in subsequent calls, even if it assumes that the data already
passed in before haven't changed.

The sftp structs are now moved to sftp.h (which I forgot to add before)
2010-10-25 16:05:53 +02:00
Daniel Stenberg
59f74de157 SFTP: use multiple outgoing packets when writing
sftp_write was rewritten to split up outgoing data into multiple packets
and deal with the acks in a more asynchronous manner. This is meant to
help overcome latency and round-trip problems with the SFTP protocol.
2010-10-25 01:43:54 +02:00
Daniel Stenberg
d87562976a TODO: implemented a lot of the ideas now 2010-10-24 23:38:26 +02:00
Daniel Stenberg
a94886f157 _libssh2_channel_write: removed 32500 size limit
Neither _libssh2_channel_write nor sftp_write now have the 32500 size
limit anymore and instead the channel writing function now has its own
logic to send data in multiple calls until everything is sent.
2010-10-23 01:16:12 +02:00
Daniel Stenberg
dec0ea9e70 send_existing: don't tell parent to return when drained
That will just cause unnecessary code execution.
2010-10-23 00:47:51 +02:00
Daniel Stenberg
030b2d9b60 _libssh2_channel_write: general code cleanup
simplified the function and removed some unused struct fields
2010-10-23 00:35:10 +02:00
Daniel Stenberg
c48840ba88 _libssh2_transport_send: replaces _libssh2_transport_write
The new function takes two data areas, combines them and sends them as a
single SSH packet. This allows several functions to allocate and copy
less data.

I also found and fixed a mixed up use of the compression function
arguments that I introduced in my rewrite in a recent commit.
2010-10-23 00:11:59 +02:00
Daniel Stenberg
d9cdd8c0a7 scp_write_nonblock: use select() instead of busyloop
Make this example nicer by not busylooping.
2010-10-22 13:37:14 +02:00
Daniel Stenberg
c49061e708 send_existing: clear olen when the data is sent off 2010-10-22 13:37:14 +02:00
Daniel Stenberg
d674b1a09a _libssh2_transport_write: allow 256 extra bytes around the packet 2010-10-22 13:37:13 +02:00
Daniel Stenberg
5ede32a826 _libssh2_transport_write: remade to send without malloc 2010-10-22 13:37:13 +02:00
Daniel Stenberg
3a391f6cf2 compress: compression disabled by default
We now allow libssh2_session_flag() to enable compression with a new
flag and I added documentation for the previous LIBSSH2_FLAG_SIGPIPE
flag which I wasn't really aware of!
2010-10-22 13:37:13 +02:00
Daniel Stenberg
64063d5f0b comp: split the compress function
It is now made into two separate compress and decompress functions. In
preparation for upcoming further modficications.
2010-10-22 13:37:13 +02:00
Dan Fandrich
784db8e987 Added header file to allow compiling in older environments 2010-10-20 22:19:38 -07:00
Daniel Stenberg
84efbf788f TODO: add a possible new API for SFTP transfers 2010-10-20 23:16:26 +02:00
Daniel Stenberg
f805c2db2a TODO: "New Transport API" added 2010-10-20 23:16:26 +02:00
Daniel Stenberg
08ce6425f6 TODO: add buffering plans 2010-10-20 23:16:26 +02:00
Simon Josefsson
fac9412a74 Mention libssh2_channel_get_exit_signal and give kudos. 2010-10-13 15:33:13 +02:00
Tommy Lindgren
4d15e0c9d1 Add libssh2_channel_get_exit_signal man page.
Signed-off-by: Simon Josefsson <simon@josefsson.org>
2010-10-13 15:31:53 +02:00
Tommy Lindgren
6140ec2de3 Add libssh2_channel_get_exit_signal.
Signed-off-by: Simon Josefsson <simon@josefsson.org>
2010-10-13 15:31:06 +02:00
Simon Josefsson
70d6bd6c6f Add libssh2_free man page and fix typo. 2010-10-13 15:24:18 +02:00
Simon Josefsson
98e38c4f3a Add libssh2_free. 2010-10-13 15:19:12 +02:00
Daniel Stenberg
cd6d41b806 scp_recv: improved treatment of channel_read() returning zero
As a zero return code from channel_read() is not an error we must make
sure that the SCP functions deal with that properly. channel_read()
always returns 0 if the channel is EOFed already so we check for EOF
after 0-reads to be able to return error properly.
2010-10-11 22:54:24 +02:00
Daniel Stenberg
c36f379b88 libssh2_session_methods.3: detail what can be asked for 2010-10-10 23:51:22 +02:00
Daniel Stenberg
77a9335515 compression: send zlib before none
As the list of algorithms in a preferred order we should send zlib
before none to increase the chances that the server will let us do
compression.
2010-10-08 17:06:55 +02:00
Daniel Stenberg
59636cc11e compress: faster check, better return codes
In the transport functions we avoid a strcmp() now and just check a
boolean instead.

The compress/decompress function's return code is now acknowledged and
used as actual return code in case of failures.
2010-10-08 16:26:50 +02:00
Daniel Stenberg
0d58af6aec libssh2_session_handshake: replaces libssh2_session_startup()
The function libssh2_session_startup() is now considered deprecated due
to the portability issue with the socket argument.
libssh2_session_handshake() is the name of the replacement.
2010-10-07 19:56:12 +02:00
Daniel Stenberg
c34e1d8735 libssh2_socket_t: now externally visible
In preparation for upcominig changes, the libssh2_socket_t type is now
typedef'ed in the public header.
2010-10-07 15:33:24 +02:00
Daniel Stenberg
861fc75fa3 _libssh2_transport_drain: removed
This function proved not to be used nor useful.
2010-10-07 13:30:05 +02:00
Daniel Stenberg
f4d302fdfe _libssh2_channel_write: don't iterate over transport writes
When a call to _libssh2_transport_write() succeeds, we must return from
_libssh2_channel_write() to allow the caller to provide the next chunk
of data.

We cannot move on to send the next piece of data that may already have
been provided in this same function call, as we risk getting EAGAIN for
that and we can't return information both about sent data as well as
EAGAIN. So, by returning short now, the caller will call this function
again with new data to send.
2010-10-07 13:28:49 +02:00
Daniel Stenberg
4faf67d3e9 _libssh2_transport_write: updated documentation blurb 2010-10-07 13:17:28 +02:00
Daniel Stenberg
76a30f2c6f _libssh2_transport_write: remove fprintf remainder
Mistake from previous debugging
2010-10-07 12:57:08 +02:00
Daniel Stenberg
bcd7eee1d2 session: improved errors
Replaced -1/SOCKET_NONE errors with appropriate error defines instead.

Made the verbose trace output during banner receiving less annoying for
non-blocking sessions.
2010-10-07 11:21:56 +02:00
Daniel Stenberg
046ad88d88 crypt_init: use correct error define 2010-10-07 11:21:20 +02:00
Daniel Stenberg
9887c01103 _libssh2_error: hide EAGAIN for non-blocking sessions
In an attempt to make the trace output less cluttered for non-blocking
sessions the error function now avoids calling the debug function if the
error is the EAGAIN and the session is non-blocking.
2010-10-07 11:19:51 +02:00
Daniel Stenberg
822f9e8689 agent: use better error defines 2010-10-07 11:19:35 +02:00
Daniel Stenberg
3ee2aabd7a comp_method_zlib_init: use correct error defines 2010-10-07 11:19:15 +02:00
Daniel Stenberg
7c49c8be58 transport: better error codes
LIBSSH2_SOCKET_NONE (-1) should no longer be used as error code as it is
(too) generic and we should instead use specific and dedicated error
codes to better describe the error.
2010-10-07 11:18:14 +02:00
Daniel Stenberg
665d9ee885 channel: return code and _libssh2_error cleanup
Made sure that all transport_write() call failures get _libssh2_error
called.
2010-10-07 11:16:49 +02:00
Daniel Stenberg
b3d6c6567d _libssh2_channel_write: limit to 32700 bytes
The well known and used ssh server Dropbear has a maximum SSH packet
length at 32768 by default. Since the libssh2 design current have a
fixed one-to-one mapping from channel_write() to the packet size created
by transport_write() the previous limit of 32768 in the channel layer
caused the transport layer to create larger packets than 32768 at times
which Dropbear rejected forcibly (by closing the connection).

The long term fix is of course to remove the hard relation between the
outgoing SSH packet size and what the input length argument is in the
transport_write() function call.
2010-10-07 11:11:59 +02:00
Daniel Stenberg
7dd574c353 libssh.h: add more dedicated error codes 2010-10-07 11:10:28 +02:00
Daniel Stenberg
018602cb34 SCP: allow file names with bytes > 126
When parsing the SCP protocol and verifying that the data looks like a
valid file name, byte values over 126 must not be consider illegal since
UTF-8 file names will use such codes.

Reported by: Uli Zappe
Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2010-08/0112.shtml
2010-08-31 19:56:00 +02:00
Dan Fandrich
eec7f2fb63 Document the three sftp stat constants 2010-08-25 17:10:06 -07:00
Guenter Knauf
c32b0d164e Fixed Win32 makefile which was now broken at resource build. 2010-08-18 17:22:33 +02:00
Guenter Knauf
835c03e076 It is sufficient to pipe stderr to NUL to get rid of the nasty messages. 2010-08-18 16:59:21 +02:00
Author: Guenter Knauf
6c6c43f92c Removed Win32 ifdef completely for sys/uio.h.
No idea why we had this ifdef at all but MSVC, MingW32, Watcom
and Borland all have no sys/uio.h header; so if there's another
Win32 compiler which needs it then it should be added explicitely
instead of this negative list.
2010-08-18 16:40:03 +02:00
Guenter Knauf
5af87e8c80 New files should also be added to Makefile.am.
Otherwise they will never be included with release and snapshot tarballs ...
2010-08-18 14:59:03 +02:00
Daniel Stenberg
10a65fda01 version: bump to 1.2.8_DEV 2010-08-18 00:20:10 +02:00
72 changed files with 4471 additions and 2901 deletions

View File

@@ -29,7 +29,8 @@ vms/readme.vms vms/libssh2_config.h
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
win32/msvcproj.head win32/msvcproj.foot win32/libssh2.rc \
win32/Makefile.Watcom
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \
maketgz NMakefile TODO RELEASE-NOTES libssh2.pc.in $(VMSFILES)

View File

@@ -4,4 +4,4 @@ CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
global.c
HHEADERS = libssh2_priv.h openssl.h libgcrypt.h transport.h channel.h \
comp.h mac.h misc.h packet.h userauth.h session.h
comp.h mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h

787
NEWS
View File

@@ -1,786 +1,3 @@
libssh2 1.2.7 (August 17, 2010)
The old NEWS file.
This release includes the following changes:
o Added Watcom makefile
This release includes the following bugfixes:
o Better handling of invalid key files
o inputchecks: make lots of API functions check for NULL pointers
o libssh2_session_callback_set: extended the man page
o SFTP: limit write() to not produce overly large packets
o agent: make libssh2_agent_userauth() work blocking properly
o _libssh2_userauth_publickey: reject method names longer than the data
o channel_free: ignore problems with channel_close()
o typedef: make ssize_t get typedef without LIBSSH2_WIN32
o _libssh2_wait_socket: poll needs milliseconds
o libssh2_wait_socket: reset error code to "leak" EAGAIN less
o Added include for sys/select.h to get fd.set on some platforms
o session_free: free more data to avoid memory leaks
o openssl: make use of the EVP interface
o Fix underscore typo for 64-bit printf format specifiers on Windows
o Make libssh2_debug() create a correctly terminated string
o userauth_hostbased_fromfile: packet length too short
o handshake: Compression enabled at the wrong time
o Don't overflow MD5 server hostkey
libssh2 1.2.6 (June 10, 2010)
This release includes the following changes:
o Added libssh2_sftp_statvfs() and libssh2_sftp_fstatvfs()
o Added libssh2_knownhost_checkp()
o Added libssh2_scp_send64()
This release includes the following bugfixes:
o wait_socket: make c89 compliant and use two fd_sets for select()
o OpenSSL AES-128-CTR detection
o proper keyboard-interactive user dialog in the sftp.c example
o build procedure for VMS
o fixed libssh2.dsw to use the generated libssh2.dsp
o several Windows-related build fixes
o fail to init SFTP if session isn't already authenticated
o many tiny fixes that address clang-analyzer warnings
o sftp_open: deal with short channel_write calls
o libssh2_publickey_init: fixed to work better non-blocking
o sftp_close_handle: add precation to not access NULL pointer
o sftp_readdir: simplified and bugfixed
o channel_write: if data has been sent, don't return EAGAIN
Version 1.2.5 (April 13, 2010)
This release includes the following changes:
o Added Add keep-alive support: libssh2_keepalive_config() and
libssh2_keepalive_send()
o Added libssh2_knownhost_addc(), libssh2_init() and libssh2_exit()
o Added LIBSSH2_SFTP_S_IS***() macros
This release includes the following bugfixes:
o fix memory leak in libssh2_session_startup()
o added missing error codes - shown as hangs in blocking mode
o fix memory leak in userauth_keyboard_interactive()
o libssh2_knownhost_del: fix write to freed memory
o Send and receive channel EOF before sending SSH_MSG_CHANNEL_CLOSE
o Use AES-CTR from OpenSSL when available
o Fixed gettimeofday to compile with Visual C++ 6
o NULL dereference when window adjusting a non-existing channel
o avoid using poll on interix and mac os x systems
o fix scp memory leak
o Correctly clear blocking flag after sending multipart packet
o Reduce used window sizes by factor 10
o libssh2_userauth_publickey_fromfile_ex() handles a NULL password
o sftp_init() deal with _libssh2_channel_write() short returns
o Use poll instead of select when available. By Paul Querna.
o Add APIs to have libssh2 automatically send keep-alive requests.
The APIs are libssh2_keepalive_config, and libssh2_keepalive_send.
By Simon Josefsson.
o Add global init/exit points, to do crypto initialization in one place.
The APIs are libssh2_init and libssh2_exit. By Lars Nordin.
* (February 15 2010) Daniel Stenberg:
- Added 46 new man pages for public convenience macros. The man pages are
just short redirects to the actual underlying function. The were all
initially created by a script.
- Committed the patch by Yoichi Iwaki in bug #2929647, which fixed a memory
leak when an 'outbuf' was still allocated when a session was freed.
Version 1.2.4 (February 13, 2010)
o Resolve compile issues on Solaris x64 and UltraSPARC
o Allow compiling with OpenSSL when AES isn't available
o Fix Tru64 socklen_t compile issue with example/direct_tcpip.c
Version 1.2.3 (February 3, 2010)
o Added libssh2_trace_sethandler()
o Added the direct_tcpip.c example
o Fixed memory leak in userauth_publickey
o Added support for authentication via SSH-Agent. By Daiki Ueno.
o Respond to unknown SSH_MSG_GLOBAL_REQUEST/SSH_MSG_CHANNEL_REQUEST
with SSH_MSG_REQUEST_FAILURE/SSH_MSG_CHANNEL_FAILURE in order to
make (at least) OpenSSH server keepalive work. Before OpenSSH
servers (configured with a positive ClientAliveInterval) would
terminate connections against libssh2 clients because libssh2 did
not respond properly to the request. By Simon Josefsson.
Version 1.2.2 (November 16, 2009)
* This release includes the following changes:
o Fix crash when server sends an invalid SSH_MSG_IGNORE message.
Reported by Bob Alexander <balexander@expressor-software.com> in
<http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
By Simon Josefsson.
o Support for the "aes128-ctr", "aes192-ctr", "aes256-ctr" ciphers
as per RFC 4344 for libgcrypt and OpenSSL. They are now the
preferred ciphers. By Simon Josefsson.
o Support for the "arcfour128" cipher as per RFC 4345 for libgcrypt
and OpenSSL. It is preferred over the normal "arcfour" cipher
which is somewhat broken. By Simon Josefsson.
o Add support for GCC visibility features. By Cristian Rodr<64>guez.
o Fix libssh2_channel_forward_accept. By Juzna.
o Generate Win32 files correctly. By Peter Stuge.
o Fix permission issue in ssh2 self test. By Dan Fandrich.
o Use memmove instead of memcpy in one place which copies
overlapping memory areas.
o Cleanup hard coding of cipher modes in libgcrypt backend. By Simon.
o Added man page for libssh2_knownhost_free. By Daniel.
Version 1.2.1 (September 28, 2009)
* This release includes the following changes:
o generate and install libssh2.pc
... and the following bugfixes:
o proper return codes returned from several functions
o return EAGAIN internal cleanup
o added knownhost.c to windows makefiles
o pass private-key to OpenSSL as a filename with BIO_new_file().
o make libssh2_scp_send/recv do blocking mode correctly
o libssh2_channel_wait_closed() could hang
o libssh2_channel_read_ex() must return 0 when closed
o added gettimeofday() function for win32 for the debug trace outputs
o transport layer bug causing invalid -39 (LIBSSH2_ERROR_BAD_USE) errors
o scp examples now loop correctly over libssh2_channel_write()
* (August 29 2009) Daniel Stenberg:
- I fixed all code to use the recently added dedicated linked list functions
instead of doing the same stuff spread out all over.
- I also fixed a few cases where local variables where used to keep memory
but was used to keep state for re-invokes due to non-blocking situations
which would lead to segfaults.
Version 1.2 (August 10, 2009)
-----------------------------
* (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)
---------------------------
- (Mar 28 2009) Daniel Stenberg:
Jean-Louis Charton found a memory leak in
libssh2_userauth_hostbased_fromfile_ex()
- (Mar 25 2009) Daniel Stenberg:
* Renamed the functions in src/transport.c to be _libssh2_transport_ prefixed
and introduced a transport.h header.
* Fixed the blocking mode to only change behavior not the actual underlying
socket mode so we now always work with non-blocking sockets. This also
introduces a new rule of thumb in libssh2 code: we don't call the
external function calls internally. We use the internal (non-blocking)
ones!
* libssh2_channel_receive_window_adjust2 was added and
libssh2_channel_receive_window_adjust is now deprecated
* Introduced "local" header files with prototypes etc for different parts
instead of cramming everything into libssh2_priv.h. channel.h is the
first.
- (Mar 19 2009) Daniel Stenberg: based on a patch by "E L" we now use errno
properly after recv() and send() calls (that internally are now known as
_libssh2_recv() and _libssh2_send()) so that the API and more works fine on
windows too!
- (Mar 17 2009) Simon Josefsson:
Added a Libtool -export-symbols-regex flag to reduce the number of
exported symbols in shared libraries. Reported by Mikhail Gusarov.
- (Mar 16 2009) Daniel Stenberg:
I renamed a few man pages to match the exact name of the functions they
describe. I also added template versions for the 13 functions that
previously lacked man pages. While these don't contain any docs just yet, it
will now be easier to add the info as the foundation is there!
- (Mar 15 2009) Daniel Stenberg:
* libssh2_channel_read_ex() was simplified and enhanced. It now adjusts the
window less frequent and uses much larger window that now allows MUCH
faster transfers.
* SCP send/recv now allow file names with whitespaces etc, thanks to a patch
by Heiner Steven
- (Mar 13 2009) Daniel Stenberg: Cleanups, that do seem to have boosted SFTP
download performance up to 300% in some tests:
* cut off "_ex" from several internal function names
* corrected some log outputs
* simplified libssh2_channel_read_ex() and made it much faster in the process
* cut out {{{ and }}} comments that were incorrect anyway
* fixed sftp_packet_ask() to return the correct packet by using memcmp() and
not strncmp()
* fixed mkdir()'s wait for packet to use the correct request_id - it
semi-worked previously because strncmp() in sftp_packet_ask() made it
match far too easily.
* took away the polling functionality from sftp_packet_ask() since it wasn't
used
- (Mar 7 2009) Olivier Hervieu pointed out a flaw in the
libssh2_channel_x11_req_ex() function that made it produce a crappy random
chunk of data. Peter Stuge improved the fix to not do out-of-boundary
writes. I (Daniel Stenberg) replaced the snprintf() with a plain sprintf()
since the size argument wasn't adding anything anyway.
- (Feb 23 2009) Added libssh2_version()
- (Feb 20 2009) libssh2_channel_direct_tcpip_ex() bug #1902169 fixed, which
caused it to fail when called a second time.
- (Feb 12 2009) Romain Bondue extended Markus Moeller fix from Feb 8, based on
a previous (uncommitted) patch by Erik Brossler. It improves
libssh2_channel_write_ex in blocking situations when the socket is set non-
blocking.
- (Feb 8 2009) Markus Moeller fixed a flaw in libssh2_channel_write_ex() that
would occur on EAGAIN situations.
Version 1.0 (December 26 2008)
------------------------------
- (Dec 20 2008) Based on Alexander Lamaison's patch, there's now a new
function called libssh2_sftp_tell64() that returns the 64 bit file offset,
as the existing libssh2_sftp_tell() only returns a size_t.
- (Dec 18 2008) Markus Moeller fixed the issue also reported by Alexander
Lamaison which caused SFTP reads with large buffers to fail.
- Several flaws were fixed that prevented at least SFTP to work reliably
- Vlad Grachov brought the new function called
libssh2_session_block_directions() which returns a bitmask for what
directions the connection blocks. It is to be used applications that use
non-blocking sockets and when a libssh2 function returns
LIBSSH2_ERROR_EAGAIN this function can be used to figure out in which
direction the socket would block and thus it can wait for the socket to
again be ready for communication in that direction before it calls libssh2
again.
- Vincent Jaulin brought the new libssh2_channel_request_pty_size_ex()
function.
- Carlo Bramini fixed the build for msys+mingw. Bug #1943976.
- Neil Gierman provided improved Visual Studio 2008 code in bug #1946268
- Bug #1862727 fixed libssh2_poll() to work on windows (by defining
HAVE_SELECT).
- Based on bug #1815692, we introduce libssh2_sftp_seek64() that allows
seeking beyond the 2GB margin even on 32bit machines.
- Based on a patch in bug #1878059 by Steven Ayre libssh2 now parses >2GB file
sizes when downloading SCP files.
- Bug #2064371 pointed out that the SSH2 banner may not use dash
('-'). Reported by Bjorn Stenborg.
- Sean Peterson fixed a key re-exchange bug:
http://daniel.haxx.se/projects/libssh2/mail/libssh2-devel-archive-2008-06/0002.shtml
- Mike Protts filed the bug report #1908724 that identified and fixed a problem
with SFTP stat on files >4GB in size. Previously it used 32bit math only.
- Removed a stderr debug message that was accidentally left in (bug #1863153)
- OpenSSL and libz detection changed to make cross-compiling to Mingw
work. See README for parameters to use if the auto-detection does
not work for you. From Simon Josefsson.
- Simon Josefsson added a self-test that uses libssh2 to connect to a
local sshd (only enabled if if OpenSSH is installed).
Version 0.18 (November 11 2007)
-------------------------------
- Various changes that improve non-blocking operations and prevent stalls.
Especially noticable on Windows since libssh2 just didn't work properly
non-blocking on Windows before.
- Peter O'Gorman reported how a SCP transfer would hang for him, and it was
fairly easy reproducable. One bug was in the transport layer, ignoring to
read more data while there was data left even though it couldn't decrypt the
data that was left due to it being too little... The other bug was in the
channel layer, where the libssh2_channel_receive_window_adjust() function
missed to set the state variables at times and thus this function would
misbehave on repeated invokes.
- Changed the signature of libssh2_channel_setenv_ex to add const to the
"varname" parameter (Dan Fandrich)
- Satish Mittal and David J Sullivan fixed an infinit recv() loop in
libssh2_banner_receive()
Version 0.17 (August 6 2007)
----------------------------
Changes since previous version include:
o Re-indented the source code with this GNU indent setup:
--braces-on-if-line
--braces-after-struct-decl-line
--space-after-cast
--line-length 79
--comment-line-length 79
--cuddle-else
--no-tabs
--tab-size 8
--indent-level 4
--no-space-after-for
--space-after-if
--space-after-while
--no-space-after-function-call-names
Version 0.16 (August 6 2007)
----------------------------
Changes since previous version include:
o CRLF stripping fix for PEM reading
o libssh2_scp_recv() error message fix
o added HACKING as an initial attempt to describe our source code format
o new public defines in include/libssh2.h to allow applictions to figure out
version number etc
o new script (maketgz) to build releases with
o updated files for building with MSVC and mingw
o keyboard-interactive would always fail due to claimed memory problem
o a few minor memory leaks fixed
o libssh2_poll() no longer relies on C99 features
o AIX 4 and 5 now supports non-blocking sockets
o large file magic checks in configure
o LIBSSH2_APINO was removed from the public header file
This release would not have been possible without these friendly contributors:
James Housley, Simon Josefsson, Dan Fandrich, Guenter Knauf and I too did
some poking. (Sorry if I forgot anyone I should've mentioned here.)
Of course we would have nothing without the great work by Sara Golemon that
we're extending and building upon.
Version 0.15 (June 15 2007)
---------------------------
Added libssh2_sftp_readdir_ex() and updated LIBSSH2_APINO to
200706151200 (James Housley)
Converted all of the libssh2 code to be able to work in non-blocking
mode. This included some public API changes, listed below (James Housley)
Changed function return values:
int libssh2_session_free()
int libssh2_publickey_shutdown()
ssize_t libssh2_channel_read_ex()
ssize_t libssh2_channel_write_ex()
Added functions:
libssh2_session_last_errno(), libssh2_channel_handle_extended_data2(),
libssh2_channel_wait_closed(), libssh2_channel_wait_eof(),
libssh2_session_set_blocking()
Removed functions:
libssh2_channel_readnb_ex(), libssh2_channel_writenb_ex(),
libssh2_sftp_readnb(), libssh2_sftp_writenb(),
libssh2_sftp_mkdirnb_ex()
Added the following functions for non-blocking operations: (Daniel Stenberg)
libssh2_channel_readnb_ex()
libssh2_channel_writenb_ex()
libssh2_sftp_readnb()
libssh2_sftp_writenb()
Size parameter changed from 'int' to 'unsigned int' in several
public APIs.
Added (a few) man pages in docs/. (Daniel Stenberg)
Maximum SSH packet size is now some 35000 bytes.
Private include files are now in src/ and only public headers are in
include/. (Daniel Stenberg)
Automake and libtool are being used (increased portability). (Daniel
Stenberg)
Fixed OpenSSL detection using pkg-config. (Daniel Stenberg)
Simple self test added to tests/. (Simon Josefsson)
Libgcrypt can now be used instead of OpenSSL if you specify
--with-libgcrypt. (Simon Josefsson)
Fixed a memory leak in the packet handling, and better handle out of
memory situations. (Dan Fandrich)
Made libssh2 build with OpenSSL 0.9.6. (Dan Fandrich)
Improved portability to Solaris related to -lsocket and
-lnsl. (Simon Josefsson)
Clean up of README, INSTALL, NEWS, added ChangeLog. (Simon
Josefsson)
Improve debugging code. Avoids many #ifdef's.
Improved session closing to avoid potentially truncated files on
OpenSSH servers (Dan Fandrich)
Made some function parameters in the API const (Dan Fandrich)
Version 0.14
------------
Plug leaks in EVP cipher init/shutdown. (Selcuk Gueney)
Allow socket_fd == 0 in libssh2_session_startup(). (puudeli)
Swap ordering of packet_add/packet-inspection to avoid inspect after
free. (Selcuk)
Swap KEX_INIT ordering, send our KEX_INIT first.
Add check for oportunistic KEX_INIT packets. Burn bad guess if necessary.
Fix OpenSSL detection using pkg-config. (Dan Casey)
Version 0.13
------------
Fixed channel not being marked closed when CHANNEL_CLOSE package cannot be
sent. (David Robins)
Fixed payload packet allocation bug when invalid packet length
received. (David Robins)
Fixed `make install' target for MacOSX.
Add terminating NULL character to readlink()/realpath() results.
BugFix#1436593: Apply build options for HPUX targets.
Version 0.12
------------
Added support for publickey subsytem (not the same as publickey auth).
Fix x11_req. Multiple packet_len issues and error handling logic.
(Thanks Simon Hart)
Fix generation of 'e' portion of Diffie-Hellman keyset.
Use appropriate order for BN_rand() rather than fixed group1-specific value.
Re-fixed libssh2_sftp_rename_ex()
Transport had right packet_len, but sftp layer still had extra 4 bytes.
Fixed build with newer OpenSSL headers.
Added extern "C" declarations to libssh2_sftp.h for C++ compatability.
Version 0.11
------------
Added libssh2_chnnale_get_exit_status() -- Mikhail
Added libssh2_channel_wait_closed() -- Mikhail
Added libssh2_userauth_keyboard_interactive_ex() -- Mikhail
Added libssh2_channel_receive_window_adjust() to be able to increase the
size of the receive window.
Added queueing for small window_adjust packets to avoid unnecessary packet
conversation.
Fixed libssh2_sftp_rename_ex() to only send flags parameter if version >= 5
negotiated (not currently possible, but will be and might as well keep the
API consistent).
Version 0.10
------------
Added developer debugging hooks. See --enable-debug-* options to ./configure
Ignore extended data in the SFTP layer. With no other mechanism to deal
with that data it'd just fill up and get stuck.
(Re)Fixed channel_write() to provide an opportunity for window space to
become available again.
(Re)Fixed SFTP INIT to send the correct SFTP packet length.
Fixed segfault when client and host can't agree on a hostkey/crypt/mac/comp
method. (Thanks puudeli)
Fixed major issue with sftp packet buffering mechanism. Using wrong
blocking semantics. (No puudeli, YOU the man)
Reduced busy-looping of libssh2_sftp_packet_requirev.
Version 0.9
-----------
Changed blocking_read to only block as much as necessary and not an
arbitrary length of time. (Thanks Felix)
Fixed SFTP INIT/VERSION to exclude request_id and send correct maximum
version number.
Fixed SFTP to be properly BC with version 1 and 2 servers.
Fixed libssh2_poll() to recognized closed sessions/channels.
Fixed libssh2_channel_write_ex() to fully block when set to blocking mode.
Return actual bytes written as well. (Thanks deadem)
Added tests for -lm and -lsocket and add them when necessary.
Added libssh2_channel_window_read_ex() and libssh2_channel_window_write_ex()
for examining the ssh transport windowing states.
Version 0.8
-----------
Fix potential segfault in compression/decompression.
Fix compatability with older versions of OpenSSL
Swapped order of none,zlib compression modes to prefer no compression by
default.
Added sys/uio.h for platforms (FBSD) which need it in order to define struct
iovec.
Added libssh2_poll() to check status of sockets/channels/listeners.
Removed unnecessary inclusion of stdio.h (holdover from debugging)
Version 0.7
-----------
Added libssh2_userauth_hostbased_fromfile_ex() for authenticating from hostkey.
Added configure recognition for MacOSX (Darwin) (Thanks Gabe)
Fixed extended data identification in libssh2_channel_read().
Fixed window adjust code. Hadn't acknowledged adjustments correctly.
Removed initial_window_size requirement for sending window adjust packet.
Version 0.6
-----------
Added LIBSSH2_FLAG_SIGPIPE to enable/disable SIGPIPE generated by
send()/recv() calls. Default off.
Added libssh2_session_flag() to set optional session flags.
Collapsed exchanging_keys/newkeys/authenticated flags into single state
attribute.
Fix zlib compression issue when internal buffer state misses partial sync.
Fix segfault when libssh2_session_methods() is called prior to
session_startup().
Fixed client to server channel windowing. Pervent send queue overruns.
Swapped banner send/receive order (send first, then wait for response).
Version 0.5
-----------
*** BC Break ***
Reimplemented libssh2_session_methods() to match
libssh2_session_method_pref() style
Fixed libssh2_attr2bin() (effects any setstat style call).
Fixed authenticating with encrypted private key.
Fixed authenticating via ssh-dss public key.
Fixed KEX_INIT cookie and packet padding to use actual random data
Added DESTDIR support to makefiles (Adam Go<47><6F>biowski -- I hope that
character set translates right)
Added libssh2_channel_forward_listen_ex(), libssh2_channel_forward_cancel(),
and libssh2_channel_forward_accept().
Added ./configure option '--disable-gex-new' to allow using the older
group-exchange format
Added MAC methods hmac-md5 and hmac-md5-96.
Version 0.4
-----------
Fixed crash when trying to free sftp_dirhandle data from a filehandle struct.
Fixed leak in sftp_open_ex(), handle->handle not freed in handle_close().
Fixed leak in sftp_symlink_ex(), result for READLINK and REALPATH not freed unless there was an error.
Added libssh2_banner_set(), specify an arbitrary banner to send on introduction.
Version 0.3
-----------
Fixed libssh2_channel_read_ex(). Packet loop initialized BEFORE transport polled for new packets (should have been after).
Fixed blocking issues in scp_send()/scp_recv().
Fixed degree of indirection in macerror callback.
Changed packet read mechanism to use a fixed buffer and avoid unnecessary alloc/free calls. (especially while non-block looping)
Added channel close callback.
Added SFTP support (Using its own header file: libssh2_sftp.h)
Version 0.2
-----------
Changed extended data ignorance mechanism:
libssh2_channel_ignore_extended_data() changed to libssh2_channel_handle_extended_data()
Macro introduced for backward compatability during beta phase.
*** THE LIBSSH2_CHANNEL_IGNORE_EXTENDED_DATA() MACRO WILL BE REMOVED PRIOR TO 1.0 RELEASE ***
libssh2_channel_handle_extended_data() may be passed one of three "ignore_mode" constants
LIBSSH2_CHANNEL_EXTENDED_DATA_NONE Default behavior, queue ED packets and return them with read_ex
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE Equivalent to libssh2_channel_ignore_extended_data()
IGNORE will implicitly flush the extended data stream(s)
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE Calls to channel_read() will check both the standard data stream
and the extended data stream(s) for the first available packet
Changed libssh2_session_disconnect_ex() to return an error code when alloc fails
Added libssh2_channel_flush_ex() and basic macros: ..._flush() ..._flush_stderr()
flush_ex accepts either the streamid (0 for standard data, 1 for stderr) or one of the two following constants:
LIBSSH2_CHANNEL_FLUSH_ALL Flush all streams
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA Flush all streams EXCEPT the standard data stream
Added libssh2_session_callback_set() for setting ignore/debug/disconnect/macerror callbacks
Added libssh2_session_method_pref() to selectively set methods and method preferences.
Added libssh2_session_methods() to determine what methods were negotiated.
Added libssh2_session_abstract() for retreiving &session->abstract
Added libssh2_session_last_error() for retreiving error codes/messages
Version 0.1
-----------
Initial Release:
KEX methods: diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1
Hostkey methods: ssh-rsa, ssh-dss
Cipher methods: aes256-cbc, rijndael-cbc@lysator.liu.se, aes192-cbc, aes128-cbc, blowfish-cbc, arcfour, cast128-cbc, 3des-cbc, none*
Compression methods: zlib, none
MAC methods: hmac-sha1, hmac-sha1-96, hmac-ripemd160, hmac-ripemd160@openssh.com none*
*Cipher/MAC "none" is disabled by default for security purposes,
Use --enable-crypt-none and/or --enable-mac-none with ./configure to enable
NEWS is now generated from git and put into the release tarballs.

View File

@@ -1,34 +1,44 @@
libssh2 1.2.7
libssh2 1.2.8
This release includes the following changes:
o Added Watcom makefile
o added libssh2_free, libssh2_channel_get_exit_signal and
libssh2_session_handshake
o SFTP read/write remade and now MUCH faster, especially on high latency
connections
o added new examples: ssh2_echo.c, sftp_append.c and sftp_write_sliding.c
o userauth: derive publickey from private
o NEWS: now generated from git
This release includes the following bugfixes:
o Better handling of invalid key files
o inputchecks: make lots of API functions check for NULL pointers
o libssh2_session_callback_set: extended the man page
o SFTP: limit write() to not produce overly large packets
o agent: make libssh2_agent_userauth() work blocking properly
o _libssh2_userauth_publickey: reject method names longer than the data
o channel_free: ignore problems with channel_close()
o typedef: make ssize_t get typedef without LIBSSH2_WIN32
o _libssh2_wait_socket: poll needs milliseconds
o libssh2_wait_socket: reset error code to "leak" EAGAIN less
o Added include for sys/select.h to get fd.set on some platforms
o session_free: free more data to avoid memory leaks
o openssl: make use of the EVP interface
o Fix underscore typo for 64-bit printf format specifiers on Windows
o Make libssh2_debug() create a correctly terminated string
o userauth_hostbased_fromfile: packet length too short
o handshake: Compression enabled at the wrong time
o Don't overflow MD5 server hostkey
o Support unlimited number of host names in a single line of the
known_hosts file.
o fix memory leak in userauth_keyboard_interactive()
o fix memory leaks (two times cipher_data) for each sftp session
o session_startup: manage server data before server identification
o SCP: allow file names with bytes > 126
o scp_recv: improved treatment of channel_read() returning zero
o libssh2_userauth_authenticated: make it work as documented
o variable size cleanup: match internal variable sizes better with the sizes
of the fields used on the wire
o channel_request_pty_size: fix reqPTY_state
o sftp_symlink: return error if receive buffer too small
o sftp_readdir: return error if buffer is too small
o libssh2_knownhost_readfile.3: clarify return value
o configure: stop using the deprecated AM_INIT_AUTOMAKE syntax
o Fixed Win32 makefile which was now broken at resource build
o kex_agree_hostkey: fix NULL pointer derefence
o _libssh2_ntohu64: fix conversion from network bytes to uint64
o ssize_t: proper typedef with MSVC compilers
o zlib: Add debug tracing of zlib errors
o decomp: increase decompression buffer sizes
This release would not have looked like this without help, code, reports and
advice from friends like these:
Alexander Lamaison, Guenter Knauf, Peter Stuge, Simon Josefsson, Lars Nordin,
John Little, Daniel Stenberg, TJ Saunders, Tor Arntsen
Alexander Lamaison, Alfred Gebert, Guenter Knauf, Dan Fandrich,
Daniel Stenberg, Jasmeet Bagga, Joey Degges, Mark Smith, Peter Stuge,
Pierre Joye, Simon Josefsson, TJ Saunders, Tommy Lindgren
Thanks! (and sorry if I forgot to mention someone)

127
TODO
View File

@@ -1,6 +1,9 @@
Things TODO
===========
* Fix the numerous malloc+copy operations for sending data, see "Buffering
Improvements" below for details
* make sure the windowing code adapts better to slow situations so that it
doesn't then use as much memory as today. Possibly by an app-controllable
"Window mode"?
@@ -11,9 +14,11 @@ Things TODO
* Add more info to the man pages.
* Decrease the number of mallocs. Everywhere.
* Decrease the number of mallocs. Everywhere. Will get easier once the
buffering improvements have been done.
* Use SO_NOSIGPIPE for Mac OS/BSD systems where MSG_NOSIGNAL doesn't exist/work
* Use SO_NOSIGPIPE for Mac OS/BSD systems where MSG_NOSIGNAL doesn't
exist/work
* Extend the test suite to actually test lots of aspects of libssh2
@@ -21,6 +26,13 @@ Things TODO
* Expose error messages sent by the server
* Make SFTP transfers ask for and send several packages at once so that it
doesn't have to send-waitforack-send-waitforack as much. This will be
easier/smoother if we implement the "New SFTP API" described below.
* select() is troublesome with libssh2 when using multiple channels over
the same session. See "New Transport API" below for more details.
At next SONAME bump
===================
@@ -38,6 +50,7 @@ At next SONAME bump
libssh2_channel_receive_window_adjust()
libssh2_poll()
libssh2_poll_channel_read()
libssh2_session_startup() (libssh2_session_handshake() is the replacement)
* Rename a few function:
@@ -58,3 +71,113 @@ At next SONAME bump
* remove the existing libssh2_knownhost_check() functin and rename
libssh2_knownhost_checkp() to become the new libssh2_knownhost_check instead
Buffering Improvements
======================
transport_write
- If this function gets called with a total packet size that is larger than
32K, it should create more than one SSH packet so that it keeps the largest
one below 32K
sftp_write
- should not copy/allocate anything for the data, only create a header chunk
and pass on the payload data to channel_write "pointed to"
New Transport API
=================
THE PROBLEM
The problem in a nutshell is that when an application opens up multiple
channels over a single session, those are all using the same socket. If the
application is then using select() to wait for traffic (like any sensible app
does) and wants to act on the data when select() tells there is something to
for example read, what does an application do?
With our current API, you have to loop over all the channels and read from
them to see if they have data. This effectively makes blocking reads
impossible. If the app has many channels in a setup like this, it even becomes
slow. (The original API had the libssh2_poll_channel_read() and libssh2_poll()
to somewhat overcome this hurdle, but they too have pretty much the same
problems plus a few others.)
Traffic in the other direction is similarly limited: the app has to try
sending to all channels, even though some of them may very well not accept any
data at that point.
A SOLUTION
I suggest we introduce two new helper functions:
libssh2_transport_read()
- Read "a bunch" of data from the given socket and returns information to the
app about what channels that are now readable (ie they will not block when
read from). The function can be called over and over and it will repeatedly
return info about what channels that are readable at that moment.
libssh2_transport_write()
- Returns information about what channels that are writable, in the sense
that they have windows set from the remote side that allows data to get
sent. Writing to one of those channels will not block. Of course, the
underlying socket may only accept a certain amount of data, so at the first
short return, nothing more should be attempted to get sent until select()
(or equivalent) has been used on the master socket again.
I haven't yet figured out a sensible API for how these functions should return
that info, but if we agree on the general principles I guess we can work that
out.
VOLUNTARY
I wanted to mention that these two helper functions would not be mandatory
in any way. They would just be there for those who want them, and existing
programs can remain using the old functions only if they prefer to.
New SFTP API
============
PURPOSE
Provide API functions that explicitly tells at once that a (full) SFTP file
transfer is wanted, to allow libssh2 to leverage on that knowledge to speed
up things internally. It can for example do read ahead, buffer writes (merge
small writes into larger chunks), better tune the SSH window and more. This
sort of API is already provided for SCP transfers.
API
New functions:
LIBSSH2_SFTP_HANDLE *libssh2_sftp_send(SFTP_SESSION *sftp,
uint64_t filesize,
char *remote_path,
size_t remote_path_len,
long mode);
Tell libssh2 that a local file with a given size is about to get sent to
the SFTP server.
LIBSSH2_SFTP_HANDLE *libssh2_sftp_recv();
Tell libssh2 that a remote file is requested to get downloaded from the SFTP
server.
Only the setup of the file transfer is different from an application's point
of view. Depending on direction of the transfer(s), the following already
existing functions should then be used until the transfer is complete:
libssh2_sftp_read()
libssh2_sftp_write()
HOW TO USE
1. Setup the transfer using one of the two new functions.
2. Loop through the reading or writing of data.
3. Cleanup the transfer

View File

@@ -16,7 +16,7 @@ fi
dnl figure out the libssh2 version
VERSION=`$SED -ne 's/^#define LIBSSH2_VERSION *"\(.*\)"/\1/p' ${srcdir}/include/libssh2.h`
AM_INIT_AUTOMAKE(libssh2,$VERSION)
AM_INIT_AUTOMAKE
AC_MSG_CHECKING([libssh2 version])
AC_MSG_RESULT($VERSION)

View File

@@ -26,6 +26,7 @@ dist_man_MANS = \
libssh2_channel_forward_listen_ex.3 \
libssh2_channel_free.3 \
libssh2_channel_get_exit_status.3 \
libssh2_channel_get_exit_signal.3 \
libssh2_channel_handle_extended_data.3 \
libssh2_channel_handle_extended_data2.3 \
libssh2_channel_ignore_extended_data.3 \
@@ -59,6 +60,7 @@ dist_man_MANS = \
libssh2_channel_x11_req.3 \
libssh2_channel_x11_req_ex.3 \
libssh2_exit.3 \
libssh2_free.3 \
libssh2_free_host_entry.3 \
libssh2_host_entry_match.3 \
libssh2_hostkey_hash.3 \
@@ -133,6 +135,7 @@ dist_man_MANS = \
libssh2_sftp_rmdir.3 \
libssh2_sftp_rmdir_ex.3 \
libssh2_sftp_seek.3 \
libssh2_sftp_seek64.3 \
libssh2_sftp_setstat.3 \
libssh2_sftp_shutdown.3 \
libssh2_sftp_stat.3 \
@@ -155,6 +158,7 @@ dist_man_MANS = \
libssh2_userauth_list.3 \
libssh2_userauth_password.3 \
libssh2_userauth_password_ex.3 \
libssh2_userauth_publickey.3 \
libssh2_userauth_publickey_fromfile.3 \
libssh2_userauth_publickey_fromfile_ex.3 \
libssh2_version.3

View File

@@ -0,0 +1,36 @@
.\" $Id$
.\"
.TH libssh2_channel_get_exit_signal 3 "4 Oct 2010" "libssh2 1.2.8" "libssh2 manual"
.SH NAME
libssh2_channel_get_exit_signal - get the remote exit signal
.SH SYNOPSIS
#include <libssh2.h>
int
libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel, char **exitsignal, size_t *exitsignal_len, char **errmsg, size_t *errmsg_len, char **langtag, size_t *langtag_len);
.SH DESCRIPTION
\fIchannel\fP - Closed channel stream to retrieve exit signal from.
\fIexitsignal\fP - If not NULL, is populated by reference with the exit signal
(without leading "SIG"). Note that the string is stored in a newly allocated
buffer. If the remote program exited cleanly, the referenced string pointer
will be set to NULL.
\fIexitsignal_len\fP - If not NULL, is populated by reference with the length
of exitsignal.
\fIerrmsg\fP - If not NULL, is populated by reference with the error message
(if provided by remote server, if not it will be set to NULL). Note that the
string is stored in a newly allocated buffer.
\fIerrmsg_len\fP - If not NULL, is populated by reference with the length of errmsg.
\fIlangtag\fP - If not NULL, is populated by reference with the language tag
(if provided by remote server, if not it will be set to NULL). Note that the
string is stored in a newly allocated buffer.
\fIlangtag_len\fP - If not NULL, is populated by reference with the length of langtag.
.SH RETURN VALUE
Numeric error code corresponding to the the Error Code constants.

19
docs/libssh2_free.3 Normal file
View File

@@ -0,0 +1,19 @@
.TH libssh2_exit 3 "13 Oct 2010" "libssh2 1.2.8" "libssh2 manual"
.SH NAME
libssh2_free - deallocate libssh2 memory
.SH SYNOPSIS
#include <libssh2.h>
void
libssh2_free(LIBSSH2_SESSION *session, void *ptr);
.SH DESCRIPTION
Deallocate memory allocated by earlier call to libssh2 functions. It
uses the memory allocation callbacks provided by the application, if
any. Otherwise, this will just call free().
This function is mostly useful under Windows when libssh2 is linked to
one run-time library and the application to another.
.SH AVAILABILITY
Added in libssh2 1.2.8
.SH SEE ALSO
.BR libssh2_session_init_ex(3)

View File

@@ -1,5 +1,5 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\" Copyright (c) 2009-2011 by Daniel Stenberg
.\"
.TH libssh2_knownhost_readfile 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
@@ -19,8 +19,8 @@ collection of known hosts.
\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.
Returns a negative value, a regular libssh2 error code for errors, or a
positive number as number of parsed known hosts in the file.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO

View File

@@ -29,7 +29,8 @@ Called when a SSH_MSG_DEBUG message is received
.IP LIBSSH2_CALLBACK_DISCONNECT
Called when a SSH_MSG_DISCONNECT message is received
.IP LIBSSH2_CALLBACK_MACERROR
Called when a mismatched MAC has been detected in the transport layer
Called when a mismatched MAC has been detected in the transport layer. If the
function returns 0, the packet will be accepted nonetheless.
.IP LIBSSH2_CALLBACK_X11
Called when an X11 connection has been accepted
.SH RETURN VALUE

View File

@@ -5,11 +5,21 @@
libssh2_session_flag - TODO
.SH SYNOPSIS
int
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value);
libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value);
.SH DESCRIPTION
This function has no purpose and no documented flags can be set nor read.
Set options for the created session. \fIflag\fP is the option to set, while
\fIvalue\fP is typically set to 1 or 0 to enable or disable the option.
.SH FLAGS
.IP LIBSSH2_FLAG_SIGPIPE
If set, libssh2 will not attempt to block SIGPIPEs but will let them trigger
from the underlying socket layer.
.IP LIBSSH2_FLAG_COMPRESS
If set - before the connection negotiation is performed - libssh2 will try to
negotiate compression enabling for this connection. By default libssh2 will
not attempt to use compression.
.SH RETURN VALUE
0
.SH ERRORS
Its mere existence is an error
Returns regular libssh2 error code.
.SH AVAILABILITY
This function has existed since the age of dawn. LIBSSH2_FLAG_COMPRESS was
added in version 1.2.8.
.SH SEE ALSO

View File

@@ -0,0 +1,42 @@
.\" $Id: libssh2_session_handshake.3,v 1.7 2009/03/16 23:25:14 bagder Exp $
.\"
.TH libssh2_session_handshake 3 "7 Oct 2010" "libssh2 1.2.8" "libssh2 manual"
.SH NAME
libssh2_session_handshake - perform the SSH handshake
.SH SYNOPSIS
#include <libssh2.h>
int
libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t socket);
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
\fIsocket\fP - Connected socket descriptor. Typically a TCP connection
though the protocol allows for any reliable transport and the library will
attempt to use any berkeley socket.
Begin transport layer protocol negotiation with the connected host.
.SH RETURN VALUE
Returns 0 on success, negative on failure.
.SH ERRORS
\fILIBSSH2_ERROR_SOCKET_NONE\fP - The socket is invalid.
\fILIBSSH2_ERROR_BANNER_SEND\fP - Unable to send banner to remote host.
\fILIBSSH2_ERROR_KEX_FAILURE\fP - >Encryption key exchange with the remote
host failed.
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.
\fILIBSSH2_ERROR_SOCKET_DISCONNECT\fP - The socket was disconnected.
\fILIBSSH2_ERROR_PROTO\fP - An invalid SSH protocol response was received on
the socket.
\fILIBSSH2_ERROR_EAGAIN\fP - Marked for non-blocking I/O but the call would block.
.SH AVAILABILITY
Added in 1.2.8
.SH SEE ALSO
.BR libssh2_session_free(3)
.BR libssh2_session_init_ex(3)

View File

@@ -13,17 +13,17 @@ libssh2_session_methods(LIBSSH2_SESSION *session, int method_type);
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
\fImethod_type\fP - One of the Method Type constants.
Return the actual method negotiated for a particular transport parameter.
\fImethod_type\fP - one of the method type constants: LIBSSH2_METHOD_KEX,
LIBSSH2_METHOD_HOSTKEY, LIBSSH2_METHOD_CRYPT_CS, LIBSSH2_METHOD_CRYPT_SC,
LIBSSH2_METHOD_MAC_CS, LIBSSH2_METHOD_MAC_SC, LIBSSH2_METHOD_COMP_CS,
LIBSSH2_METHOD_COMP_SC, LIBSSH2_METHOD_LANG_CS, LIBSSH2_METHOD_LANG_SC.
Returns the actual method negotiated for a particular transport parameter.
.SH RETURN VALUE
Negotiated method or NULL if the session has not yet been started.
.SH ERRORS
\fILIBSSH2_ERROR_INVAL\fP - The requested method type was invalid.
\fILIBSSH2_ERROR_METHOD_NONE\fP -
\fILIBSSH2_ERROR_METHOD_NONE\fP - no method has been set
.SH SEE ALSO
.BR libssh2_session_init_ex(3)

View File

@@ -8,8 +8,10 @@ libssh2_session_startup - begin transport layer
int
libssh2_session_startup(LIBSSH2_SESSION *session, int socket);
.SH DESCRIPTION
Starting in libssh2 version 1.2.8 this function is considered deprecated. Use
\fIlibssh2_session_handshake(3)\fP instead.
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)

View File

@@ -4,31 +4,45 @@
.SH NAME
libssh2_sftp_open - open filehandle for file on SFTP.
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename, unsigned int filename_len, unsigned long flags, long mode, int open_type);
LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open(LIBSSH2_SFTP *sftp, const char *filename, unsigned long flags, long mode);
LIBSSH2_SFTP_HANDLE *
libssh2_sftp_opendir(LIBSSH2_SFTP *sftp, const char *path);
libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename,
unsigned int filename_len, unsigned long flags,
long mode, int open_type);
.SH DESCRIPTION
\fIsftp\fP - SFTP instance as returned by
.BR libssh2_sftp_init(3)
\fIsftp\fP - SFTP instance as returned by \fIlibssh2_sftp_init(3)\fP
\fIfilename\fP - Remote file/directory resource to open
\fIfilename_len\fP - Length of filename
\fIflags\fP - Any (reasonable) combination of the LIBSSH2_FXF_* constants
corresponding fopen modes.
\fIflags\fP - Any reasonable combination of the LIBSSH2_FXF_* constants:
.RS
.IP LIBSSH2_FXF_READ
Open the file for reading.
.IP LIBSSH2_FXF_WRITE
Open the file for writing. If both this and LIBSSH2_FXF_READ are specified,
the file is opened for both reading and writing.
.IP LIBSSH2_FXF_APPEND
Force all writes to append data at the end of the file.
.IP LIBSSH2_FXF_CREAT,
If this flag is specified, then a new file will be created if one does not
already exist (if LIBSSH2_FXF_TRUNC is specified, the new file will be
truncated to zero length if it previously exists)
.IP LIBSSH2_FXF_TRUNC
Forces an existing file with the same name to be truncated to zero length when
creating a file by specifying LIBSSH2_FXF_CREAT. LIBSSH2_FXF_CREAT MUST also
be specified if this flag is used.
.IP LIBSSH2_FXF_EXCL
Causes the request to fail if the named file already exists.
LIBSSH2_FXF_CREAT MUST also be specified if this flag is used.
.RE
\fImode\fP - POSIX file permissions to assign if the file is being newly
created.
created. See the LIBSSH2_SFTP_S_* convenience defines in <libssh2_sftp.h>
\fIopen_type\fP - Either of LIBSSH2_SFTP_OPENFILE (to open a file) or
LIBSSH2_SFTP_OPENDIR (to open a directory).

View File

@@ -13,9 +13,6 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle,
char *buffer, size_t buffer_maxlen,
char *longentry, size_t longentry_maxlen,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
#define libssh2_sftp_readdir(h, b, bl, a) \\
libssh2_sftp_readdir_ex((h), (b), (bl), NULL, 0, (a))
.SH DESCRIPTION
Reads a block of data from a LIBSSH2_SFTP_HANDLE and returns file entry
information for the next entry, if any.
@@ -47,6 +44,10 @@ Number of bytes actually populated into buffer (not counting the terminating
zero), 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.
.SH BUG
Passing in a too small buffer for 'buffer' or 'longentry' when receiving data
only results in libssh2 1.2.7 or earlier to not copy the entire data amount,
and it is not possible for the application to tell when it happens!
.SH ERRORS
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
@@ -57,6 +58,10 @@ really a failure per se.
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response was
received on the socket, or an SFTP operation caused an errorcode to be
returned by the server.
From 1.2.8, LIBSSH2_ERROR_BUFFER_TOO_SMALL is returned if any of the
given 'buffer' or 'longentry' buffers are too small to fit the requested
object name.
.SH SEE ALSO
.BR libssh2_sftp_open_ex(3),
.BR libssh2_sftp_close_handle(3)

View File

@@ -4,16 +4,14 @@
.SH NAME
libssh2_sftp_seek - set the read/write position indicator within a file
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
void
libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
void
libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset);
void libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
.SH DESCRIPTION
Deprecated function. Use \fIlibssh2_sftp_seek64(3)\fP instead!
\fIhandle\fP - SFTP File Handle as returned by
.BR libssh2_sftp_open_ex(3)
@@ -24,7 +22,6 @@ Note that libssh2 implements file pointers as a localized concept to make
file access appear more POSIX like. No packets are exchanged with the server
during a seek operation. The localized file pointer is simply used as a
convenience offset during read/write operations.
.SH AVAILABILITY
libssh2_sftp_seek64(3) was added in 1.0
.SH SEE ALSO
.BR libssh2_sftp_open_ex(3)
.BR libssh2_sftp_open_ex(3),
.BR libssh2_sftp_seek64(3)

View File

@@ -0,0 +1,31 @@
.\" $Id: libssh2_sftp_seek.3,v 1.5 2009/03/17 10:34:27 bagder Exp $
.\"
.TH libssh2_sftp_seek64 3 "22 Dec 2008" "libssh2 1.0" "libssh2 manual"
.SH NAME
libssh2_sftp_seek64 - set the read/write position within a file
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
void libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle,
libssh2_uint64_t offset);
.SH DESCRIPTION
\fIhandle\fP - SFTP File Handle as returned by
.BR libssh2_sftp_open_ex(3)
\fIoffset\fP - Number of bytes from the beginning of file to seek to.
Move the file handle's internal pointer to an arbitrary location. libssh2
implements file pointers as a localized concept to make file access appear
more POSIX like. No packets are exchanged with the server during a seek
operation. The localized file pointer is simply used as a convenience offset
during read/write operations.
You MUST NOT seek during writing or reading a file with SFTP, as the internals
use outstanding packets and changing the "file position" during transit will
results in badness.
.SH AVAILABILITY
Added in 1.0
.SH SEE ALSO
.BR libssh2_sftp_open_ex(3)

View File

@@ -4,21 +4,13 @@
.SH NAME
libssh2_sftp_stat_ex - get status about an SFTP file
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
int
libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned int path_len, int stat_type, LIBSSH2_SFTP_ATTRIBUTES *attrs);
int
libssh2_sftp_stat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUTES *attrs);
int
libssh2_sftp_lstat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUTES *attrs);
int
libssh2_sftp_setstat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUTES *attrs);
int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path,
unsigned int path_len, int stat_type,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
.SH DESCRIPTION
\fIsftp\fP - SFTP instance as returned by
.BR libssh2_sftp_init(3)
@@ -29,24 +21,47 @@ libssh2_sftp_setstat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUT
to stat/lstat/setstat.
\fIstat_type\fP - One of the three constants specifying the type of
stat operation to perform.
stat operation to perform:
\fIattrs\fP - Pointer to attribute structure to set file metadata
from or into depending on the value of stat_type.
.br
\fBLIBSSH2_SFTP_STAT\fP: performs stat(2) operation
.br
\fBLIBSSH2_SFTP_LSTAT\fP: performs lstat(2) operation
.br
\fBLIBSSH2_SFTP_SETSTAT\fP: performs operation to set stat info on file
Get or Set statbuf type data on a remote filesystem object. When
getting statbuf data,
\fIattrs\fP - Pointer to a \fBLIBSSH2_SFTP_ATTRIBUTES\fP structure to set file
metadata from or into depending on the value of stat_type.
Get or Set statbuf type data on a remote filesystem object. When getting
statbuf data,
.BR libssh2_sftp_stat(3)
will follow all symlinks, while
.BR libssh2_sftp_lstat(3)
will return data about the object encountered, even if that object
happens to be a symlink.
.SH RETURN VALUE
Return 0 on success 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.
The LIBSSH2_SFTP_ATTRIBUTES struct looks like this:
.nf
struct LIBSSH2_SFTP_ATTRIBUTES {
/* If flags & ATTR_* bit is set, then the value in this struct will be
* meaningful Otherwise it should be ignored
*/
unsigned long flags;
libssh2_uint64_t filesize;
unsigned long uid;
unsigned long gid;
unsigned long permissions;
unsigned long atime;
unsigned long mtime;
};
.fi
.SH RETURN VALUE
Returns 0 on success 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.
.SH ERRORS
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
@@ -57,6 +72,5 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response was
received on the socket, or an SFTP operation caused an errorcode to
be returned by the server.
.SH SEE ALSO
.BR libssh2_sftp_init(3)

View File

@@ -12,9 +12,6 @@ int
libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path,
unsigned int path_len, char *target,
unsigned int target_len, int link_type);
int
libssh2_sftp_realpath(LIBSSH2_SFTP *sftp, const char *path, char *target,
unsigned int target_len);
.SH DESCRIPTION
Create a symlink or read out symlink information from the remote side.
@@ -62,6 +59,13 @@ zero) 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.
From 1.2.8, LIBSSH2_ERROR_BUFFER_TOO_SMALL is returned if the given 'target'
buffer is too small to fit the requested object name.
.SH BUG
Passing in a too small buffer when receiving data only results in libssh2
1.2.7 or earlier to not copy the entire data amount, and it is not possible
for the application to tell when it happens!
.SH ERRORS
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.

View File

@@ -27,6 +27,28 @@ possible to write all bytes as requested.
put it into a single SFTP protocol packet. This means that to get maximum
performance when sending larger files, you should try to always pass in at
least 32K of data to this function.
.SH WRITE AHEAD
Starting in libssh2 version 1.2.8, the default behavior of libssh2 is to
create several smaller outgoing packets for all data you pass to this function
and it will return a positive number as soon as the first packet is
acknowledged from the server.
This has the effect that sometimes more data has been sent off but isn't acked
yet when this function returns, and when this function is subsequently called
again to write more data, libssh2 will immediately figure out that the data is
already received remotely.
In most normal situation this should not cause any problems, but it should be
noted that if you've once called libssh2_sftp_write() with data and it returns
short, you MUST still assume that the rest of the data might've been cached so
you need to make sure you don't alter that data and think that the version you
have in your next function invoke will be detected or used.
The reason for this funny behavior is that SFTP can only send 32K data in each
packet and it gets all packets acked individually. This means we cannot use a
simple serial approach if we want to reach high performance even on high
latency connections. And we want that.
.SH RETURN VALUE
Actual number of bytes written or negative on failure.

View File

@@ -2,42 +2,40 @@
.\"
.TH libssh2_userauth_list 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME
libssh2_userauth_list - list the authentication methods supported by a server
libssh2_userauth_list - list supported authentication methods
.SH SYNOPSIS
.nf
#include <libssh2.h>
char *
libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned int username_len);
libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username,
unsigned int username_len);
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
\fIusername\fP - Username which will be used while authenticating. Note
that most server implementations do not permit attempting authentication
with different usernames between requests. Therefore this must be the
same username you will use on later userauth calls.
\fIusername\fP - Username which will be used while authenticating. Note that
most server implementations do not permit attempting authentication with
different usernames between requests. Therefore this must be the same username
you will use on later userauth calls.
\fIusername_len\fP - Length of username parameter.
Send a \fBSSH_USERAUTH_NONE\fP request to the remote host. Unless the
remote host is configured to accept none as a viable authentication
scheme (unlikely), it will return \fBSSH_USERAUTH_FAILURE\fB along with a
listing of what authentication schemes it does support. In the unlikely
event that none authentication succeeds, this method with return NULL. This
case may be distinguished from faily by examining
.BR libssh2_userauth_authenticated(3)
Send a \fBSSH_USERAUTH_NONE\fP request to the remote host. Unless the remote
host is configured to accept none as a viable authentication scheme
(unlikely), it will return \fBSSH_USERAUTH_FAILURE\fP along with a listing of
what authentication schemes it does support. In the unlikely event that none
authentication succeeds, this method with return NULL. This case may be
distinguished from a failing case by examining
\fIlibssh2_userauth_authenticated(3)\fP.
.SH RETURN VALUE
On success a comma delimited list of supported authentication schemes. This list is
internally managed by libssh2. On failure ruturns NULL.
On success a comma delimited list of supported authentication schemes. This
list is internally managed by libssh2. On failure ruturns NULL.
.SH ERRORS
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.
\fILIBSSH2_ERROR_EAGAIN\fP - Marked for non-blocking I/O but the call
.SH SEE ALSO
.BR libssh2_session_init_ex(3)

View File

@@ -0,0 +1,29 @@
.\" $Id: template.3,v 1.4 2007/06/13 16:41:33 jehousley Exp $
.\"
.TH libssh2_userauth_publickey 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME
libssh2_userauth_publickey - authenticate using a callback function
.SH SYNOPSIS
#include <libssh2.h>
.NF
int libssh2_userauth_publickey(LIBSSH2_SESSION *session,
const char *user,
const unsigned char *pubkeydata,
size_t pubkeydata_len,
sign_callback,
void **abstract);
.SH DESCRIPTION
Authenticate with the \fIsign_callback\fP callback that matches the prototype
below
.SH CALLBACK
.nf
int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
const unsigned char *data, size_t data_len, void **abstract);
.fi
This function gets called...
.SH RETURN VALUE
Return 0 on success or negative on failure.
.SH SEE ALSO
.BR libssh2_userauth_publickey_fromfile_ex(3)

View File

@@ -6,12 +6,12 @@ libssh2_userauth_publickey_fromfile - authenticate a session with a public key,
.SH SYNOPSIS
#include <libssh2.h>
int
libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const char *publickey, const char *privatekey, const char *passphrase);
int
libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, const char *username, const char *publickey, const char *privatekey, const char *passphrase);
.nf
int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
const char *username,
const char *publickey,
const char *privatekey,
const char *passphrase);
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)

View File

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

View File

@@ -137,7 +137,8 @@ int main(int argc, char *argv[])
channel = libssh2_scp_recv(session, scppath, &fileinfo);
if (!channel) {
fprintf(stderr, "Unable to open a session\n");
fprintf(stderr, "Unable to open a session: %d\n",
libssh2_session_last_errno(session));
goto shutdown;
}

View File

@@ -34,6 +34,36 @@
#include <ctype.h>
#include <time.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[])
{
unsigned long hostaddr;
@@ -58,6 +88,7 @@ int main(int argc, char *argv[])
time_t start;
long total = 0;
int duration;
size_t prev;
#ifdef WIN32
WSADATA wsadata;
@@ -190,15 +221,23 @@ int main(int argc, char *argv[])
total += nread;
prev = 0;
do {
/* 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);
while ((rc = libssh2_channel_write(channel, ptr, nread)) ==
LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
prev = 0;
}
if (rc < 0) {
fprintf(stderr, "ERROR %d total %ld / %d prev %d\n", rc,
total, (int)nread, (int)prev);
break;
} else {
}
else {
prev = nread;
if(rc > nread) {
fprintf(stderr, "MOO %d > %d\n", (int)rc, (int)nread);
}
/* rc indicates how many bytes were written this time */
nread -= rc;
ptr += rc;

View File

@@ -245,7 +245,8 @@ int main(int argc, char *argv[])
libssh2_sftp_open(sftp_session, sftppath, LIBSSH2_FXF_READ, 0);
if (!sftp_handle) {
fprintf(stderr, "Unable to open file with SFTP\n");
fprintf(stderr, "Unable to open file with SFTP: %ld\n",
libssh2_sftp_last_error(sftp_session));
goto shutdown;
}
fprintf(stderr, "libssh2_sftp_open() is done, now receive data!\n");

232
example/sftp_append.c Normal file
View File

@@ -0,0 +1,232 @@
/*
* $Id: sftp_write.c,v 1.11 2009/04/28 10:35:30 bagder Exp $
*
* Sample showing how to do SFTP append of a local file onto a remote one.
*
* The sample code has default values for host name, user name, password
* and path to copy, but you can specify them on the command line like:
*
* sftp_append 192.168.0.1 user password localfile /tmp/remotefile
*/
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.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_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
unsigned long hostaddr;
int sock, i, auth_pw = 1;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
const char *username="username";
const char *password="password";
const char *loclfile="sftp_write.c";
const char *sftppath="/tmp/TEST";
int rc;
FILE *local;
LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle;
LIBSSH2_SFTP_ATTRIBUTES attrs;
char mem[1024*100];
size_t nread;
char *ptr;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
hostaddr = inet_addr(argv[1]);
} else {
hostaddr = htonl(0x7F000001);
}
if(argc > 2) {
username = argv[2];
}
if(argc > 3) {
password = argv[3];
}
if(argc > 4) {
loclfile = argv[4];
}
if(argc > 5) {
sftppath = argv[5];
}
rc = libssh2_init (0);
if (rc != 0) {
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}
local = fopen(loclfile, "rb");
if (!local) {
printf("Can't local file %s\n", loclfile);
return -1;
}
/*
* The application code is responsible for creating the socket
* and 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;
/* Since we have set non-blocking, tell libssh2 we are blocking */
libssh2_session_set_blocking(session, 1);
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
rc = libssh2_session_startup(session, sock);
if(rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1;
}
/* At this point we havn't yet authenticated. The first thing to do
* is check the hostkey's fingerprint against our known hosts Your app
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");
if (auth_pw) {
/* We could authenticate via password */
if (libssh2_userauth_password(session, username, password)) {
printf("Authentication by password failed.\n");
goto shutdown;
}
} else {
/* Or by public key */
if (libssh2_userauth_publickey_fromfile(session, username,
"/home/username/.ssh/id_rsa.pub",
"/home/username/.ssh/id_rsa",
password)) {
printf("\tAuthentication by public key failed\n");
goto shutdown;
}
}
fprintf(stderr, "libssh2_sftp_init()!\n");
sftp_session = libssh2_sftp_init(session);
if (!sftp_session) {
fprintf(stderr, "Unable to init SFTP session\n");
goto shutdown;
}
fprintf(stderr, "libssh2_sftp_open() for READ and WRITE!\n");
/* Request a file via SFTP */
sftp_handle =
libssh2_sftp_open(sftp_session, sftppath,
LIBSSH2_FXF_WRITE|LIBSSH2_FXF_READ,
LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
if (!sftp_handle) {
fprintf(stderr, "Unable to open file with SFTP\n");
goto shutdown;
}
if(libssh2_sftp_fstat_ex(sftp_handle, &attrs, 0) < 0) {
printf("libssh2_sftp_fstat_ex failed\n");
goto shutdown;
}
else
libssh2_sftp_seek64(sftp_handle, attrs.filesize);
printf("Did a seek to position %ld\n", (long) attrs.filesize);
fprintf(stderr, "libssh2_sftp_open() a handle for APPEND\n");
if (!sftp_handle) {
fprintf(stderr, "Unable to open file with SFTP\n");
goto shutdown;
}
fprintf(stderr, "libssh2_sftp_open() is done, now send data!\n");
do {
nread = fread(mem, 1, sizeof(mem), local);
if (nread <= 0) {
/* end of file */
break;
}
ptr = mem;
do {
/* write data in a loop until we block */
rc = libssh2_sftp_write(sftp_handle, ptr, nread);
if(rc < 0)
break;
ptr += rc;
nread -= rc;
} while (nread);
} while (rc > 0);
libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);
shutdown:
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
if (local)
fclose(local);
printf("all done\n");
libssh2_exit();
return 0;
}

View File

@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
FILE *local;
LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle;
char mem[1024];
char mem[1024*100];
size_t nread;
char *ptr;

View File

@@ -31,6 +31,9 @@
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/types.h>
#include <fcntl.h>

View File

@@ -0,0 +1,290 @@
/*
* $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.
*
* The sample code has default values for host name, user name, password
* and path to copy, but you can specify them on the command line like:
*
* "sftp 192.168.0.1 user password sftp_write_nonblock.c /tmp/sftp_write_nonblock.c"
*/
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.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
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <time.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[])
{
unsigned long hostaddr;
int sock, i, auth_pw = 1;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
const char *username="username";
const char *password="password";
const char *loclfile="sftp_write_nonblock.c";
const char *sftppath="/tmp/sftp_write_nonblock.c";
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
FILE *local;
LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle;
char mem[1024 * 1000];
size_t nread;
size_t memuse;
time_t start;
long total = 0;
int duration;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
hostaddr = inet_addr(argv[1]);
} else {
hostaddr = htonl(0x7F000001);
}
if (argc > 2) {
username = argv[2];
}
if (argc > 3) {
password = argv[3];
}
if (argc > 4) {
loclfile = argv[4];
}
if (argc > 5) {
sftppath = argv[5];
}
rc = libssh2_init (0);
if (rc != 0) {
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}
local = fopen(loclfile, "rb");
if (!local) {
printf("Can't local file %s\n", loclfile);
return -1;
}
/*
* The application code is responsible for creating the socket
* and 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;
/* Since we have set non-blocking, tell libssh2 we are 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;
}
/* At this point we havn't yet authenticated. The first thing to do is
* check the hostkey's fingerprint against our known hosts Your app may
* have it hard coded, may go to a file, may present it to the user,
* that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
printf("Fingerprint: ");
for(i = 0; i < 20; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");
if (auth_pw) {
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username, password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
printf("Authentication by password failed.\n");
goto shutdown;
}
} else {
/* Or by public key */
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
"/home/username/.ssh/id_rsa.pub",
"/home/username/.ssh/id_rsa",
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
printf("\tAuthentication by public key failed\n");
goto shutdown;
}
}
fprintf(stderr, "libssh2_sftp_init()!\n");
do {
sftp_session = libssh2_sftp_init(session);
if (!sftp_session &&
(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
fprintf(stderr, "Unable to init SFTP session\n");
goto shutdown;
}
} while (!sftp_session);
fprintf(stderr, "libssh2_sftp_open()!\n");
/* Request a file via SFTP */
do {
sftp_handle =
libssh2_sftp_open(sftp_session, sftppath,
LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
if (!sftp_handle &&
(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
fprintf(stderr, "Unable to open file with SFTP\n");
goto shutdown;
}
} while (!sftp_handle);
fprintf(stderr, "libssh2_sftp_open() is done, now send data!\n");
start = time(NULL);
memuse = 0; /* it starts blank */
do {
nread = fread(&mem[memuse], 1, sizeof(mem)-memuse, local);
if (nread <= 0) {
/* end of file */
break;
}
memuse += nread;
total += nread;
/* write data in a loop until we block */
while ((rc = libssh2_sftp_write(sftp_handle, mem, memuse)) ==
LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
}
if(rc < 0)
break;
if(memuse - rc) {
/* make room for more data at the end of the buffer */
memmove(&mem[0], &mem[rc], memuse - rc);
memuse -= rc;
}
else
/* 'mem' was consumed fully */
memuse = 0;
} while (rc > 0);
duration = (int)(time(NULL)-start);
printf("%ld bytes in %d seconds makes %.1f bytes/sec\n",
total, duration, total/(double)duration);
fclose(local);
libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);
shutdown:
while (libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing")
== LIBSSH2_ERROR_EAGAIN);
libssh2_session_free(session);
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
printf("all done\n");
libssh2_exit();
return 0;
}

View File

@@ -144,7 +144,7 @@ int main(int argc, char *argv[])
username, identity->comment);
break;
}
prev_identity = identity;
prev_identity = identity;
}
if (rc) {
fprintf(stderr, "Couldn't continue authentication\n");

361
example/ssh2_echo.c Normal file
View File

@@ -0,0 +1,361 @@
/*
* $Id: ssh2_exec.c,v 1.4 2009/05/07 20:30:22 bagder Exp $
*
* Run it like this:
*
* $ ./ssh2_echo 127.0.0.1 user password
*
* The code sends a 'cat' command, and then writes a lot of data to it only to
* check that reading the returned data sums up to the same amount.
*
*/
#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;
}
#define BUFSIZE 32000
int main(int argc, char *argv[])
{
const char *hostname = "127.0.0.1";
const char *commandline = "cat";
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 = 0;
char *exitsignal=(char *)"none";
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];
}
rc = libssh2_init (0);
if (rc != 0) {
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}
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_checkp(nh, hostname, 22,
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");
exit(1);
}
}
libssh2_trace(session, LIBSSH2_TRACE_SOCKET);
/* 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, "exec error\n");
exit( 1 );
}
else {
LIBSSH2_POLLFD *fds = NULL;
int running = 1;
int bufsize = BUFSIZE;
char buffer[BUFSIZE];
int totsize = 1500000;
int totwritten = 0;
int totread = 0;
int partials = 0;
int rereads = 0;
int rewrites = 0;
int i;
for (i = 0; i < BUFSIZE; i++)
buffer[i] = 'A';
if ((fds = malloc (sizeof (LIBSSH2_POLLFD))) == NULL) {
fprintf(stderr, "malloc failed\n");
exit(1);
}
fds[0].type = LIBSSH2_POLLFD_CHANNEL;
fds[0].fd.channel = channel;
fds[0].events = LIBSSH2_POLLFD_POLLIN | LIBSSH2_POLLFD_POLLOUT;
do {
int rc = (libssh2_poll(fds, 1, 10));
int act = 0;
if (rc < 1)
continue;
if (fds[0].revents & LIBSSH2_POLLFD_POLLIN) {
int n = libssh2_channel_read(channel, buffer, sizeof(buffer));
act++;
if (n == LIBSSH2_ERROR_EAGAIN) {
rereads++;
fprintf(stderr, "will read again\n");
}
else if (n < 0) {
fprintf(stderr, "read failed\n");
exit(1);
}
else {
totread += n;
fprintf(stderr, "read %d bytes (%d in total)\n",
n, totread);
}
}
if (fds[0].revents & LIBSSH2_POLLFD_POLLOUT) {
act++;
if (totwritten < totsize) {
/* we have not written all data yet */
int left = totsize - totwritten;
int size = (left < bufsize) ? left : bufsize;
int n = libssh2_channel_write_ex(channel, 0, buffer, size);
if (n == LIBSSH2_ERROR_EAGAIN) {
rewrites++;
fprintf(stderr, "will write again\n");
}
else if (n < 0) {
fprintf(stderr, "write failed\n");
exit(1);
}
else {
totwritten += n;
fprintf(stderr, "wrote %d bytes (%d in total)",
n, totwritten);
if (left >= bufsize && n != bufsize) {
partials++;
fprintf(stderr, " PARTIAL");
}
fprintf(stderr, "\n");
}
} else {
/* all data written, send EOF */
rc = libssh2_channel_send_eof(channel);
if (rc == LIBSSH2_ERROR_EAGAIN) {
fprintf(stderr, "will send eof again\n");
}
else if (rc < 0) {
fprintf(stderr, "send eof failed\n");
exit(1);
}
else {
fprintf(stderr, "sent eof\n");
/* we're done writing, stop listening for OUT events */
fds[0].events &= ~LIBSSH2_POLLFD_POLLOUT;
}
}
}
if (fds[0].revents & LIBSSH2_POLLFD_CHANNEL_CLOSED) {
if (!act) /* don't leave loop until we have read all data */
running = 0;
}
} while(running);
exitcode = 127;
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
waitsocket(sock, session);
if( rc == 0 ) {
exitcode = libssh2_channel_get_exit_status( channel );
libssh2_channel_get_exit_signal(channel, &exitsignal,
NULL, NULL, NULL, NULL, NULL);
}
if (exitsignal)
printf("\nGot signal: %s\n", exitsignal);
libssh2_channel_free(channel);
channel = NULL;
fprintf(stderr, "\nrereads: %d rewrites: %d totwritten %d\n",
rereads, rewrites, totwritten);
if (totwritten != totread) {
fprintf(stderr, "\n*** FAIL bytes written: %d bytes "
"read: %d ***\n", totwritten, totread);
exit(1);
}
}
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");
libssh2_exit();
return exitcode;
}

View File

@@ -86,6 +86,7 @@ int main(int argc, char *argv[])
LIBSSH2_CHANNEL *channel;
int rc;
int exitcode;
char *exitsignal=(char *)"none";
int bytecount = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
@@ -286,8 +287,14 @@ int main(int argc, char *argv[])
if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );
libssh2_channel_get_exit_signal(channel, &exitsignal,
NULL, NULL, NULL, NULL, NULL);
}
printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
if (exitsignal)
printf("\nGot signal: %s\n", exitsignal);
else
printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
libssh2_channel_free(channel);
channel = NULL;

76
git2news.pl Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/perl
# git log --pretty=fuller --no-color --date=short --decorate=full
my @mname = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' );
sub nicedate {
my ($date)=$_;
if($date =~ /(\d\d\d\d)-(\d\d)-(\d\d)/) {
return sprintf("%d %s %4d", $3, $mname[$2-1], $1);
}
return $date;
}
print
' Changelog for the libssh2 project. Generated with git2news.pl
';
my $line;
my $tag;
while(<STDIN>) {
my $l = $_;
if($l =~/^commit ([[:xdigit:]]*) ?(.*)/) {
$co = $1;
my $ref = $2;
if ($ref =~ /refs\/tags\/(libssh2-|VERSION\.)([0-9._]*)/) {
$tag = $2;
} else {
$tag = '';
}
}
elsif($l =~ /^Author: *(.*) +</) {
$a = $1;
}
elsif($l =~ /^Commit: *(.*) +</) {
$c = $1;
}
elsif($l =~ /^CommitDate: (.*)/) {
$date = nicedate($1);
}
elsif($l =~ /^( )(.*)/) {
my $extra;
if ($tag) {
# Version entries have a special format
print "\nVersion " . $tag." ($date)\n";
$oldc = "";
$tag = "";
}
if($a ne $c) {
$extra=sprintf("\n- [%s brought this change]\n\n ", $a);
}
else {
$extra="\n- ";
}
if($co ne $oldco) {
if($c ne $oldc) {
print "\n$c ($date)$extra";
}
else {
print "$extra";
}
$line =0;
}
$oldco = $co;
$oldc = $c;
$olddate = $date;
if($line++) {
print " ";
}
print $2."\n";
}
}

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2009-2010 Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
* All rights reserved.
*
@@ -46,13 +46,13 @@
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.2.7_DEV"
#define LIBSSH2_VERSION "1.2.8_DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBSSH2_VERSION_MAJOR 1
#define LIBSSH2_VERSION_MINOR 2
#define LIBSSH2_VERSION_PATCH 7
#define LIBSSH2_VERSION_PATCH 8
/* This is the numeric version of the libssh2 version number, meant for easier
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
@@ -69,7 +69,7 @@
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 0x010207
#define LIBSSH2_VERSION_NUM 0x010208
/*
* This is the date and time when the full source package was created. The
@@ -87,6 +87,10 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
# include <BaseTsd.h>
# include <WinSock2.h>
#endif
#include <stddef.h>
#include <string.h>
@@ -106,8 +110,7 @@ extern "C" {
# endif /* LIBSSH2_WIN32 */
#endif /* LIBSSH2_API */
#if defined(LIBSSH2_DARWIN) || (defined(LIBSSH2_WIN32) && \
!defined(_MSC_VER) && !defined(__MINGW32__))
#if defined(LIBSSH2_DARWIN)
# include <sys/uio.h>
#endif
@@ -122,15 +125,21 @@ typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 libssh2_uint64_t;
typedef __int64 libssh2_int64_t;
# ifndef _SSIZE_T_DEFINED
typedef int ssize_t;
# define _SSIZE_T_DEFINED
#ifndef ssize_t
typedef SSIZE_T ssize_t;
#endif
#else
typedef unsigned long long libssh2_uint64_t;
typedef long long libssh2_int64_t;
#endif
#ifdef WIN32
typedef SOCKET libssh2_socket_t;
#else /* !WIN32 */
typedef int libssh2_socket_t;
#define INVALID_SOCKET -1
#endif /* WIN32 */
/* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
@@ -247,8 +256,9 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
#define LIBSSH2_METHOD_LANG_CS 8
#define LIBSSH2_METHOD_LANG_SC 9
/* session.flags bits */
#define LIBSSH2_FLAG_SIGPIPE 0x00000001
/* flags */
#define LIBSSH2_FLAG_SIGPIPE 1
#define LIBSSH2_FLAG_COMPRESS 2
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
@@ -331,8 +341,15 @@ typedef struct _LIBSSH2_POLLFD {
/* Error Codes (defined by libssh2) */
#define LIBSSH2_ERROR_NONE 0
/* The library once used -1 as a generic error return value on numerous places
through the code, which subsequently was converted to
LIBSSH2_ERROR_SOCKET_NONE uses over time. As this is a generic error code,
the goal is to never ever return this code but instead make sure that a
more accurate and descriptive error code is used. */
#define LIBSSH2_ERROR_SOCKET_NONE -1
#define LIBSSH2_ERROR_BANNER_NONE -2
#define LIBSSH2_ERROR_BANNER_RECV -2
#define LIBSSH2_ERROR_BANNER_SEND -3
#define LIBSSH2_ERROR_INVALID_MAC -4
#define LIBSSH2_ERROR_KEX_FAILURE -5
@@ -374,6 +391,12 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_COMPRESS -40
#define LIBSSH2_ERROR_OUT_OF_BOUNDARY -41
#define LIBSSH2_ERROR_AGENT_PROTOCOL -42
#define LIBSSH2_ERROR_SOCKET_RECV -43
#define LIBSSH2_ERROR_ENCRYPT -44
#define LIBSSH2_ERROR_BAD_SOCKET -45
/* this is a define to provide the old (<= 1.2.7) name */
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
/* Global API */
#define LIBSSH2_INIT_NO_CRYPTO 0x0001
@@ -401,6 +424,13 @@ LIBSSH2_API int libssh2_init(int flags);
*/
LIBSSH2_API void libssh2_exit(void);
/*
* libssh2_free()
*
* Deallocate memory allocated by earlier call to libssh2 functions.
*/
LIBSSH2_API void libssh2_free(LIBSSH2_SESSION *session, void *ptr);
/* Session API */
LIBSSH2_API LIBSSH2_SESSION *
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
@@ -416,6 +446,8 @@ LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session,
const char *banner);
LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int sock);
LIBSSH2_API int libssh2_session_handshake(LIBSSH2_SESSION *session,
libssh2_socket_t sock);
LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session,
int reason,
const char *description,
@@ -702,6 +734,13 @@ LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel,
libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR)
LIBSSH2_API int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL* channel);
LIBSSH2_API int libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL* channel,
char **exitsignal,
size_t *exitsignal_len,
char **errmsg,
size_t *errmsg_len,
char **langtag,
size_t *langtag_len);
LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel);

View File

@@ -63,6 +63,13 @@ else
automake --include-deps Makefile >/dev/null
fi
#######################################################################
#
# Generate the changelog
#
echo "generate NEWS"
git log --pretty=fuller --no-color --date=short --decorate=full -1000 | ./log2changes.pl > NEWS.dist
############################################################################
#
# Now run make dist to generate a tar.gz archive

View File

@@ -19,7 +19,7 @@ endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../openssl-0.9.8o
OPENSSL_PATH = ../../openssl-0.9.8q
endif
# Edit the path below to point to your Distribution folder.

View File

@@ -19,7 +19,7 @@ endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../../openssl-0.9.8o
OPENSSL_PATH = ../../../openssl-0.9.8q
endif
# Edit the var below to enable static linking of libssh2 and libz

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2009 by Daiki Ueno
* Copyright (C) 2010 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -153,15 +154,15 @@ agent_connect_unix(LIBSSH2_AGENT *agent)
agent->fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (agent->fd < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_NONE,
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET,
"failed creating socket");
s_un.sun_family = AF_UNIX;
strncpy (s_un.sun_path, path, sizeof s_un.sun_path);
if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) {
close (agent->fd);
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_NONE,
"failed connecting");
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting with agent");
}
return LIBSSH2_ERROR_NONE;
@@ -176,36 +177,34 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Send the length of the request */
if (transctx->state == agent_NB_state_request_created) {
_libssh2_htonu32(buf, transctx->request_len);
rc = send(agent->fd, buf, sizeof buf, 0);
if (rc < 0) {
if (errno == EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
rc = _libssh2_send(agent->fd, buf, sizeof buf, 0);
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if (rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent send failed");
}
transctx->state = agent_NB_state_request_length_sent;
}
/* Send the request body */
if (transctx->state == agent_NB_state_request_length_sent) {
rc = send(agent->fd, transctx->request,
transctx->request_len, 0);
if (rc < 0) {
if (errno == EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
rc = _libssh2_send(agent->fd, transctx->request,
transctx->request_len, 0);
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if (rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent send failed");
}
transctx->state = agent_NB_state_request_sent;
}
/* Receive the length of a response */
if (transctx->state == agent_NB_state_request_sent) {
rc = recv(agent->fd, buf, sizeof buf, 0);
rc = _libssh2_recv(agent->fd, buf, sizeof buf, 0);
if (rc < 0) {
if (errno == EAGAIN)
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_NONE,
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
"agent recv failed");
}
transctx->response_len = _libssh2_ntohu32(buf);
@@ -219,9 +218,10 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Receive the response body */
if (transctx->state == agent_NB_state_response_length_received) {
rc = recv(agent->fd, transctx->response, transctx->response_len, 0);
rc = _libssh2_recv(agent->fd, transctx->response,
transctx->response_len, 0);
if (rc < 0) {
if (errno == EAGAIN)
if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent recv failed");
@@ -268,7 +268,7 @@ agent_connect_pageant(LIBSSH2_AGENT *agent)
HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_NONE,
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting agent");
agent->fd = 0; /* Mark as the connection has been established */
return LIBSSH2_ERROR_NONE;
@@ -296,7 +296,7 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, PAGEANT_MAX_MSGLEN, mapname);
0, PAGEANT_MAX_MSGLEN, mapname);
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
@@ -312,16 +312,16 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
if (id > 0) {
transctx->response_len = _libssh2_ntohu32(p);
transctx->response_len = _libssh2_ntohu32(p);
if (transctx->response_len > PAGEANT_MAX_MSGLEN) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"agent setup fail");
}
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
if (!transctx->response) {
if (!transctx->response) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC,

View File

@@ -1,6 +1,6 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net>
* Copyright (c) 2008-2010 by Daniel Stenberg
* Copyright (c) 2008-2011 by Daniel Stenberg
*
* All rights reserved.
*
@@ -130,7 +130,8 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
uint32_t channel_type_len,
uint32_t window_size,
uint32_t packet_size,
const char *message, unsigned int message_len)
const unsigned char *message,
size_t message_len)
{
static const unsigned char reply_codes[3] = {
SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
@@ -146,7 +147,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
session->open_data = NULL;
/* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) +
* window_size(4) + packet_size(4) */
session->open_packet_len = channel_type_len + message_len + 17;
session->open_packet_len = channel_type_len + 17;
session->open_local_channel = _libssh2_channel_nextid(session);
/* Zero the whole thing out */
@@ -201,23 +202,23 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
_libssh2_store_u32(&s, window_size);
_libssh2_store_u32(&s, packet_size);
if (message && message_len) {
memcpy(s, message, message_len);
s += message_len;
}
/* Do not copy the message */
session->open_state = libssh2_NB_state_created;
}
if (session->open_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->open_packet,
session->open_packet_len);
rc = _libssh2_transport_send(session,
session->open_packet,
session->open_packet_len,
message, message_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
_libssh2_error(session, rc,
"Would block sending channel-open request");
return NULL;
} else if (rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
}
else if (rc) {
_libssh2_error(session, rc,
"Unable to send channel-open request");
goto channel_error;
}
@@ -303,12 +304,6 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
session->open_data = NULL;
}
/* Free any state variables still holding data */
if (session->open_channel->write_packet) {
LIBSSH2_FREE(session, session->open_channel->write_packet);
session->open_channel->write_packet = NULL;
}
LIBSSH2_FREE(session, session->open_channel);
session->open_channel = NULL;
}
@@ -336,7 +331,8 @@ libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type,
BLOCK_ADJUST_ERRNO(ptr, session,
_libssh2_channel_open(session, type, type_len,
window_size, packet_size,
msg, msg_len));
(unsigned char *)msg,
msg_len));
return ptr;
}
@@ -381,7 +377,7 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
sizeof("direct-tcpip") - 1,
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT,
(char *) session->direct_message,
session->direct_message,
session->direct_message_len);
if (!channel &&
@@ -433,9 +429,11 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
{ SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 };
int rc;
if(!host)
host = "0.0.0.0";
if (session->fwdLstn_state == libssh2_NB_state_idle) {
session->fwdLstn_host_len =
(host ? strlen(host) : (sizeof("0.0.0.0") - 1));
session->fwdLstn_host_len = strlen(host);
/* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4)
+ port(4) */
session->fwdLstn_packet_len =
@@ -461,22 +459,24 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
_libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1);
*(s++) = 0x01; /* want_reply */
_libssh2_store_str(&s, host ? host : "0.0.0.0",
session->fwdLstn_host_len);
_libssh2_store_str(&s, host, session->fwdLstn_host_len);
_libssh2_store_u32(&s, port);
session->fwdLstn_state = libssh2_NB_state_created;
}
if (session->fwdLstn_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->fwdLstn_packet,
session->fwdLstn_packet_len);
rc = _libssh2_transport_send(session,
session->fwdLstn_packet,
session->fwdLstn_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending global-request packet for "
"forward listen request");
return NULL;
} else if (rc) {
}
else if (rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send global-request packet for forward "
"listen request");
@@ -633,8 +633,10 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
}
if (listener->chanFwdCncl_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, packet, packet_len);
rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending forward request");
listener->chanFwdCncl_data = packet;
return rc;
}
@@ -800,9 +802,13 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
}
if (channel->setenv_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, channel->setenv_packet,
channel->setenv_packet_len);
rc = _libssh2_transport_send(session,
channel->setenv_packet,
channel->setenv_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending setenv request");
return rc;
} else if (rc) {
LIBSSH2_FREE(session, channel->setenv_packet);
@@ -888,6 +894,11 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
/* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) +
* want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) +
* height_px(4) + modes_len(4) */
if(term_len + modes_len > 256) {
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"term + mode lengths too large");
}
channel->reqPTY_packet_len = term_len + modes_len + 41;
/* Zero the whole thing out */
@@ -898,12 +909,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
"Allocating tty on channel %lu/%lu", channel->local.id,
channel->remote.id);
s = channel->reqPTY_packet =
LIBSSH2_ALLOC(session, channel->reqPTY_packet_len);
if (!channel->reqPTY_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for pty-request");
}
s = channel->reqPTY_packet;
*(s++) = SSH_MSG_CHANNEL_REQUEST;
_libssh2_store_u32(&s, channel->remote.id);
@@ -922,20 +928,18 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
}
if (channel->reqPTY_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, channel->reqPTY_packet,
channel->reqPTY_packet_len);
rc = _libssh2_transport_send(session, channel->reqPTY_packet,
channel->reqPTY_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending pty request");
return rc;
} else if (rc) {
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
channel->reqPTY_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send pty-request packet");
}
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
_libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
channel->reqPTY_state = libssh2_NB_state_sent;
@@ -952,7 +956,8 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
return rc;
} else if (rc) {
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Failed to require the PTY package");
}
code = data[0];
@@ -997,6 +1002,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
LIBSSH2_SESSION *session = channel->session;
unsigned char *s;
int rc;
int retcode = LIBSSH2_ERROR_PROTO;
if (channel->reqPTY_state == libssh2_NB_state_idle) {
channel->reqPTY_packet_len = 39;
@@ -1010,12 +1016,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
channel->local.id,
channel->remote.id);
s = channel->reqPTY_packet =
LIBSSH2_ALLOC(session, channel->reqPTY_packet_len);
if (!channel->reqPTY_packet)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for pty-request");
s = channel->reqPTY_packet;
*(s++) = SSH_MSG_CHANNEL_REQUEST;
_libssh2_store_u32(&s, channel->remote.id);
@@ -1031,27 +1032,24 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
}
if (channel->reqPTY_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, channel->reqPTY_packet,
channel->reqPTY_packet_len);
rc = _libssh2_transport_send(session, channel->reqPTY_packet,
channel->reqPTY_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending window-change request");
return rc;
} else if (rc) {
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
channel->reqPTY_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send window-change packet");
}
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
_libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
channel->reqPTY_state = libssh2_NB_state_sent;
return 0;
retcode = LIBSSH2_ERROR_NONE;
}
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
return retcode;
}
LIBSSH2_API int
@@ -1149,9 +1147,12 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
}
if (channel->reqX11_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, channel->reqX11_packet,
channel->reqX11_packet_len);
rc = _libssh2_transport_send(session, channel->reqX11_packet,
channel->reqX11_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending X11-req packet");
return rc;
}
if (rc) {
@@ -1225,8 +1226,8 @@ libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection,
*/
int
_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
const char *request, unsigned int request_len,
const char *message, unsigned int message_len)
const char *request, size_t request_len,
const char *message, size_t message_len)
{
LIBSSH2_SESSION *session = channel->session;
unsigned char *s;
@@ -1243,7 +1244,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
sizeof(channel->process_packet_requirev_state));
if (message)
channel->process_packet_len += message_len + 4;
channel->process_packet_len += + 4;
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"starting request(%s) on channel %lu/%lu, message=%s",
@@ -1262,15 +1263,19 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
*(s++) = 0x01;
if (message)
_libssh2_store_str(&s, message, message_len);
_libssh2_store_u32(&s, message_len);
channel->process_state = libssh2_NB_state_created;
}
if (channel->process_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, channel->process_packet,
channel->process_packet_len);
rc = _libssh2_transport_send(session,
channel->process_packet,
channel->process_packet_len,
(unsigned char *)message, message_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending channel request");
return rc;
}
else if (rc) {
@@ -1459,6 +1464,67 @@ libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
return channel->exit_status;
}
/*
* libssh2_channel_get_exit_signal
*
* Get exit signal (without leading "SIG"), error message, and language
* tag into newly allocated buffers of indicated length. Caller can
* use NULL pointers to indicate that the value should not be set. The
* *_len variables are set if they are non-NULL even if the
* corresponding string parameter is NULL. Returns LIBSSH2_ERROR_NONE
* on success, or an API error code.
*/
LIBSSH2_API int
libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
char **exitsignal,
size_t *exitsignal_len,
char **errmsg,
size_t *errmsg_len,
char **langtag,
size_t *langtag_len)
{
LIBSSH2_SESSION *session = channel->session;
size_t namelen = 0;
if (channel) {
if (channel->exit_signal) {
namelen = strlen(channel->exit_signal);
if (exitsignal) {
*exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
if (!*exitsignal) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for signal name");
}
memcpy(*exitsignal, channel->exit_signal, namelen);
(*exitsignal)[namelen] = '\0';
}
if (exitsignal_len)
*exitsignal_len = namelen;
} else {
if (exitsignal)
*exitsignal = NULL;
if (exitsignal_len)
*exitsignal_len = 0;
}
/* TODO: set error message and language tag */
if (errmsg)
*errmsg = NULL;
if (errmsg_len)
*errmsg_len = 0;
if (langtag)
*langtag = NULL;
if (langtag_len)
*langtag_len = 0;
}
return LIBSSH2_ERROR_NONE;
}
/*
* _libssh2_channel_receive_window_adjust
*
@@ -1466,10 +1532,11 @@ libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
* to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
* adjustment amount will be queued for a later packet.
*
* Calls _libssh2_error() !
*/
int
_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
unsigned long adjustment,
uint32_t adjustment,
unsigned char force,
unsigned int *store)
{
@@ -1510,8 +1577,11 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
channel->adjust_state = libssh2_NB_state_created;
}
rc = _libssh2_transport_write(channel->session, channel->adjust_adjust, 9);
rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(channel->session, rc,
"Would block sending window adjust");
return rc;
}
else if (rc) {
@@ -1789,9 +1859,11 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
return code. */
if(channel->remote.eof || channel->remote.close)
return 0;
else
/* if the transport layer said EAGAIN then we say so as well */
return (rc == LIBSSH2_ERROR_EAGAIN)?rc:0;
else if(rc != LIBSSH2_ERROR_EAGAIN)
return 0;
/* if the transport layer said EAGAIN then we say so as well */
return _libssh2_error(session, rc, "would block");
}
else
/* make sure we remain in the created state to focus on emptying the
@@ -1899,160 +1971,132 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
/*
* _libssh2_channel_write
*
* 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.
* Send data to a channel. Note that if this returns EAGAIN, 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)
const unsigned char *buf, size_t buflen)
{
int rc = 0;
LIBSSH2_SESSION *session = channel->session;
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.
/* In theory we could split larger buffers into several smaller packets
* but it turns out to be really hard and nasty to do while still offering
* the API/prototype.
*
* Instead we only deal with the first 32K in this call and for the parent
* function to call it again with the remainder! 32K is a conservative
* limit based on the text in RFC4253 section 6.1.
*/
if(buflen > 32768)
buflen = 32768;
if(buflen > 32700)
buflen = 32700;
if (channel->write_state == libssh2_NB_state_idle) {
channel->write_bufwrote = 0;
unsigned char *s = channel->write_packet;
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
"Writing %d bytes on channel %lu/%lu, stream #%d",
(int) buflen, channel->local.id, channel->remote.id,
stream_id);
if (channel->local.close) {
return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED,
if (channel->local.close)
return _libssh2_error(channel->session,
LIBSSH2_ERROR_CHANNEL_CLOSED,
"We've already closed this channel");
}
if (channel->local.eof) {
return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_EOF_SENT,
else if (channel->local.eof)
return _libssh2_error(channel->session,
LIBSSH2_ERROR_CHANNEL_EOF_SENT,
"EOF has already been received, "
"data might be ignored");
}
/* [13] 9 = packet_type(1) + channelno(4) [ + streamid(4) ] +
buflen(4) */
channel->write_packet_len = buflen + (stream_id ? 13 : 9);
channel->write_packet =
LIBSSH2_ALLOC(session, channel->write_packet_len);
if (!channel->write_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocte space "
"for data transmission packet");
}
/* drain the incoming flow first, mostly to make sure we get all
* pending window adjust packets */
do
rc = _libssh2_transport_read(session);
while (rc > 0);
channel->write_state = libssh2_NB_state_allocated;
}
if(channel->local.window_size <= 0)
/* there's no room for data so we stop */
return 0;
/* Deduct the amount that has already been sent, and set buf accordingly. */
buflen -= channel->write_bufwrote;
buf += channel->write_bufwrote;
channel->write_bufwrite = buflen;
while (buflen > 0) {
if (channel->write_state == libssh2_NB_state_allocated) {
/* drain the incoming flow first */
do
rc = _libssh2_transport_read(session);
while (rc > 0);
if(channel->local.window_size <= 0) {
/* there's no more room for data so we stop sending now */
break;
}
channel->write_bufwrite = buflen;
channel->write_s = channel->write_packet;
*(channel->write_s++) =
stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
SSH_MSG_CHANNEL_DATA;
_libssh2_store_u32(&channel->write_s, channel->remote.id);
if (stream_id)
_libssh2_store_u32(&channel->write_s, stream_id);
/* Don't exceed the remote end's limits */
/* REMEMBER local means local as the SOURCE of the data */
if (channel->write_bufwrite > channel->local.window_size) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Splitting write block due to %lu byte "
"window_size on %lu/%lu/%d",
channel->local.window_size, channel->local.id,
channel->remote.id, stream_id);
channel->write_bufwrite = channel->local.window_size;
}
if (channel->write_bufwrite > channel->local.packet_size) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Splitting write block due to %lu byte "
"packet_size on %lu/%lu/%d",
channel->local.packet_size, channel->local.id,
channel->remote.id, stream_id);
channel->write_bufwrite = channel->local.packet_size;
}
_libssh2_store_str(&channel->write_s, buf, channel->write_bufwrite);
*(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
SSH_MSG_CHANNEL_DATA;
_libssh2_store_u32(&s, channel->remote.id);
if (stream_id)
_libssh2_store_u32(&s, stream_id);
/* Don't exceed the remote end's limits */
/* REMEMBER local means local as the SOURCE of the data */
if (channel->write_bufwrite > channel->local.window_size) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Sending %d bytes on channel %lu/%lu, stream_id=%d",
(int) channel->write_bufwrite, channel->local.id,
"Splitting write block due to %lu byte "
"window_size on %lu/%lu/%d",
channel->local.window_size, channel->local.id,
channel->remote.id, stream_id);
channel->write_state = libssh2_NB_state_created;
channel->write_bufwrite = channel->local.window_size;
}
if (channel->write_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, channel->write_packet,
channel->write_s -
channel->write_packet);
if (rc == LIBSSH2_ERROR_EAGAIN) {
if(wrote) {
/* some pieces of data was sent before the EAGAIN so we
return that amount! As we ignore EAGAIN, we must drain
the outgoing transport buffer. */
_libssh2_transport_drain(session);
goto _channel_write_done;
}
return _libssh2_error(session, rc,
"Unable to send channel data");
}
else if (rc) {
LIBSSH2_FREE(session, channel->write_packet);
channel->write_packet = NULL;
channel->write_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send channel data");
}
/* Shrink local window size */
channel->local.window_size -= channel->write_bufwrite;
/* Adjust buf for next iteration */
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;
if (channel->write_bufwrite > channel->local.packet_size) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Splitting write block due to %lu byte "
"packet_size on %lu/%lu/%d",
channel->local.packet_size, channel->local.id,
channel->remote.id, stream_id);
channel->write_bufwrite = channel->local.packet_size;
}
/* store the size here only, the buffer is passed in as-is to
_libssh2_transport_send() */
_libssh2_store_u32(&s, channel->write_bufwrite);
channel->write_packet_len = s - channel->write_packet;
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Sending %d bytes on channel %lu/%lu, stream_id=%d",
(int) channel->write_bufwrite, channel->local.id,
channel->remote.id, stream_id);
channel->write_state = libssh2_NB_state_created;
}
_channel_write_done:
if (channel->write_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, channel->write_packet,
channel->write_packet_len,
buf, channel->write_bufwrite);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, rc,
"Unable to send channel data");
}
else if (rc) {
channel->write_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send channel data");
}
/* Shrink local window size */
channel->local.window_size -= channel->write_bufwrite;
LIBSSH2_FREE(session, channel->write_packet);
channel->write_packet = NULL;
wrote += channel->write_bufwrite;
channel->write_state = libssh2_NB_state_idle;
/* Since _libssh2_transport_write() succeeded, we must return
now to allow the caller to provide the next chunk of data.
return wrote;
We cannot move on to send the next piece of data that may
already have been provided in this same function call, as we
risk getting EAGAIN for that and we can't return information
both about sent data as well as EAGAIN. So, by returning short
now, the caller will call this function again with new data to
send */
channel->write_state = libssh2_NB_state_idle;
return wrote;
}
return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */
}
/*
@@ -2070,7 +2114,8 @@ libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id,
return LIBSSH2_ERROR_BAD_USE;
BLOCK_ADJUST(rc, channel->session,
_libssh2_channel_write(channel, stream_id, buf, buflen));
_libssh2_channel_write(channel, stream_id,
(unsigned char *)buf, buflen));
return rc;
}
@@ -2089,8 +2134,10 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel)
channel->local.id, channel->remote.id);
packet[0] = SSH_MSG_CHANNEL_EOF;
_libssh2_htonu32(packet + 1, channel->remote.id);
rc = _libssh2_transport_write(session, packet, 5);
rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending EOF");
return rc;
}
else if (rc) {
@@ -2181,7 +2228,8 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
}
else if (rc < 0) {
channel->wait_eof_state = libssh2_NB_state_idle;
return -1;
return _libssh2_error(session, rc,
"_libssh2_transport_read() bailed out!");
}
} while (1);
@@ -2238,8 +2286,11 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
}
if (channel->close_state == libssh2_NB_state_created) {
retcode = _libssh2_transport_write(session, channel->close_packet, 5);
retcode = _libssh2_transport_send(session, channel->close_packet, 5,
NULL, 0);
if (retcode == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending close-channel");
return retcode;
} else if (retcode) {
channel->close_state = libssh2_NB_state_idle;
@@ -2253,9 +2304,9 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
if (channel->close_state == libssh2_NB_state_sent) {
/* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
while (!channel->remote.close && !rc) {
while (!channel->remote.close && !rc &&
(session->socket_state != LIBSSH2_SOCKET_DISCONNECTED))
rc = _libssh2_transport_read(session);
}
}
if(rc != LIBSSH2_ERROR_EAGAIN) {
@@ -2394,6 +2445,10 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
channel->free_state = libssh2_NB_state_idle;
if (channel->exit_signal) {
LIBSSH2_FREE(session, channel->exit_signal);
}
/*
* channel->remote.close *might* not be set yet, Well...
* We've sent the close packet, what more do you want?
@@ -2424,18 +2479,12 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
if (channel->setenv_packet) {
LIBSSH2_FREE(session, channel->setenv_packet);
}
if (channel->reqPTY_packet) {
LIBSSH2_FREE(session, channel->reqPTY_packet);
}
if (channel->reqX11_packet) {
LIBSSH2_FREE(session, channel->reqX11_packet);
}
if (channel->process_packet) {
LIBSSH2_FREE(session, channel->process_packet);
}
if (channel->write_packet) {
LIBSSH2_FREE(session, channel->write_packet);
}
LIBSSH2_FREE(session, channel);

View File

@@ -48,7 +48,7 @@
* Always non-blocking.
*/
int _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
unsigned long adjustment,
uint32_t adjustment,
unsigned char force,
unsigned int *store);
@@ -80,7 +80,7 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
*/
ssize_t
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
const char *buf, size_t buflen);
const unsigned char *buf, size_t buflen);
/*
* _libssh2_channel_open
@@ -92,7 +92,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
uint32_t channel_type_len,
uint32_t window_size,
uint32_t packet_size,
const char *message, unsigned int message_len);
const unsigned char *message, size_t message_len);
/*
@@ -102,9 +102,8 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
*/
int
_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
const char *request, unsigned int request_len,
const char *message, unsigned int message_len);
const char *request, size_t request_len,
const char *message, size_t message_len);
/*
* _libssh2_channel_read

View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -52,24 +53,41 @@
* Minimalist compression: Absolutely none
*/
static int
comp_method_none_comp(LIBSSH2_SESSION * session,
int compress,
unsigned char **dest,
comp_method_none_comp(LIBSSH2_SESSION *session,
unsigned char *dest,
size_t *dest_len,
size_t payload_limit,
int *free_dest,
const unsigned char *src,
size_t src_len, void **abstract)
size_t src_len,
void **abstract)
{
(void) session;
(void) abstract;
(void) dest;
(void) dest_len;
(void) src;
(void) src_len;
return 0;
}
/*
* comp_method_none_decomp
*
* Minimalist decompression: Absolutely none
*/
static int
comp_method_none_decomp(LIBSSH2_SESSION * session,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
const unsigned char *src,
size_t src_len, void **abstract)
{
(void) session;
(void) compress;
(void) payload_limit;
(void) abstract;
*dest = (unsigned char *) src;
*dest_len = src_len;
*free_dest = 0;
return 0;
}
@@ -77,8 +95,10 @@ comp_method_none_comp(LIBSSH2_SESSION * session,
static const LIBSSH2_COMP_METHOD comp_method_none = {
"none",
0, /* not really compressing */
NULL,
comp_method_none_comp,
comp_method_none_decomp,
NULL
};
@@ -114,7 +134,7 @@ comp_method_zlib_free(voidpf opaque, voidpf address)
* All your bandwidth are belong to us (so save some)
*/
static int
comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
comp_method_zlib_init(LIBSSH2_SESSION * session, int compr,
void **abstract)
{
z_stream *strm;
@@ -131,7 +151,7 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
strm->opaque = (voidpf) session;
strm->zalloc = (alloc_func) comp_method_zlib_alloc;
strm->zfree = (free_func) comp_method_zlib_free;
if (compress) {
if (compr) {
/* deflate */
status = deflateInit(strm, Z_DEFAULT_COMPRESSION);
} else {
@@ -141,84 +161,112 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
if (status != Z_OK) {
LIBSSH2_FREE(session, strm);
return -1;
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return LIBSSH2_ERROR_COMPRESS;
}
*abstract = strm;
return LIBSSH2_ERROR_NONE;
}
/*
* libssh2_comp_method_zlib_comp
*
* Compresses source to destination. Without allocation.
*/
static int
comp_method_zlib_comp(LIBSSH2_SESSION *session,
unsigned char *dest,
/* dest_len is a pointer to allow this function to
update it with the final actual size used */
size_t *dest_len,
const unsigned char *src,
size_t src_len,
void **abstract)
{
z_stream *strm = *abstract;
int out_maxlen = *dest_len;
int status;
strm->next_in = (unsigned char *) src;
strm->avail_in = src_len;
strm->next_out = dest;
strm->avail_out = out_maxlen;
status = deflate(strm, Z_PARTIAL_FLUSH);
if (status != Z_OK) {
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib compression error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compression failure");
}
*dest_len = out_maxlen - strm->avail_out;
return 0;
}
/* libssh2_comp_method_zlib_comp
* zlib, a compression standard for all occasions
/*
* libssh2_comp_method_zlib_decomp
*
* Decompresses source to destination. Allocates the output memory.
*/
static int
comp_method_zlib_comp(LIBSSH2_SESSION * session,
int compress,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
int *free_dest,
const unsigned char *src,
size_t src_len, void **abstract)
comp_method_zlib_decomp(LIBSSH2_SESSION * session,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
const unsigned char *src,
size_t src_len, void **abstract)
{
z_stream *strm = *abstract;
/* A short-term alloc of a full data chunk is better than a series of
reallocs */
char *out;
int out_maxlen = compress ? (src_len + 4) : (2 * src_len);
int out_maxlen = 8 * src_len;
int limiter = 0;
/* If strm is null, then we have not yet been initialized. */
if (strm == NULL) {
*dest = (unsigned char *) src;
*dest_len = src_len;
*free_dest = 0;
return 0;
}
if (strm == NULL)
return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS,
"decompression unitilized");;
/* In practice they never come smaller than this */
if (out_maxlen < 25) {
if (out_maxlen < 25)
out_maxlen = 25;
}
if (out_maxlen > (int) payload_limit) {
if (out_maxlen > (int) payload_limit)
out_maxlen = payload_limit;
}
strm->next_in = (unsigned char *) src;
strm->avail_in = src_len;
strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
out = (char *) strm->next_out;
strm->avail_out = out_maxlen;
if (!strm->next_out) {
if (!strm->next_out)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate compression/decompression "
"buffer");
}
"Unable to allocate decompression buffer");
while (strm->avail_in) {
int status;
if (compress) {
status = deflate(strm, Z_PARTIAL_FLUSH);
} else {
status = inflate(strm, Z_PARTIAL_FLUSH);
}
status = inflate(strm, Z_PARTIAL_FLUSH);
if (status != Z_OK) {
LIBSSH2_FREE(session, out);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure");
"decompression failure");
}
if (strm->avail_in) {
size_t out_ofs = out_maxlen - strm->avail_out;
char *newout;
out_maxlen +=
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
out_maxlen += 8 * strm->avail_in;
if ((out_maxlen > (int) payload_limit) && !compress && limiter++) {
if ((out_maxlen > (int) payload_limit) && limiter++) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase");
@@ -228,20 +276,18 @@ comp_method_zlib_comp(LIBSSH2_SESSION * session,
if (!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand compress/"
"decompression buffer");
"Unable to expand decompression buffer");
}
out = newout;
strm->next_out = (unsigned char *) out + out_ofs;
strm->avail_out +=
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
strm->avail_out += 8 * strm->avail_in;
} else
while (!strm->avail_out) {
/* Done with input, might be a byte or two in internal buffer
* during compress. Or potentially many bytes if it's a
* decompress
*/
int grow_size = compress ? 8 : 1024;
int grow_size = 2048;
char *newout;
if (out_maxlen >= (int) payload_limit) {
@@ -262,29 +308,27 @@ comp_method_zlib_comp(LIBSSH2_SESSION * session,
if (!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand final compress/"
"Unable to expand final "
"decompress buffer");
}
out = newout;
strm->next_out = (unsigned char *) out + out_maxlen -
grow_size;
if (compress) {
status = deflate(strm, Z_PARTIAL_FLUSH);
} else {
status = inflate(strm, Z_PARTIAL_FLUSH);
}
status = inflate(strm, Z_PARTIAL_FLUSH);
if (status != Z_OK) {
LIBSSH2_FREE(session, out);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure");
"decompression failure");
}
}
}
*dest = (unsigned char *) out;
*dest_len = out_maxlen - strm->avail_out;
*free_dest = 1;
return 0;
}
@@ -294,50 +338,53 @@ comp_method_zlib_comp(LIBSSH2_SESSION * session,
* All done, no more compression for you
*/
static int
comp_method_zlib_dtor(LIBSSH2_SESSION * session, int compress,
void **abstract)
comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract)
{
z_stream *strm = *abstract;
if (strm) {
if (compress) {
/* deflate */
if (compr)
deflateEnd(strm);
} else {
/* inflate */
else
inflateEnd(strm);
}
LIBSSH2_FREE(session, strm);
}
*abstract = NULL;
return 0;
}
static const LIBSSH2_COMP_METHOD comp_method_zlib = {
"zlib",
1, /* yes, this compresses */
comp_method_zlib_init,
comp_method_zlib_comp,
comp_method_zlib_decomp,
comp_method_zlib_dtor,
};
#endif /* LIBSSH2_HAVE_ZLIB */
/* ***********************
* Compression Methods *
*********************** */
/* If compression is enabled by the API, then this array is used which then
may allow compression if zlib is available at build time */
static const LIBSSH2_COMP_METHOD *comp_methods[] = {
&comp_method_none,
#ifdef LIBSSH2_HAVE_ZLIB
&comp_method_zlib,
#endif /* LIBSSH2_HAVE_ZLIB */
&comp_method_none,
NULL
};
/* If compression is disabled by the API, then this array is used */
static const LIBSSH2_COMP_METHOD *no_comp_methods[] = {
&comp_method_none,
NULL
};
const LIBSSH2_COMP_METHOD **
_libssh2_comp_methods(void)
_libssh2_comp_methods(LIBSSH2_SESSION *session)
{
return comp_methods;
if(session->flag.compress)
return comp_methods;
else
return no_comp_methods;
}

View File

@@ -1,7 +1,7 @@
#ifndef __LIBSSH2_COMP_H
#define __LIBSSH2_COMP_H
/* Copyright (C) 2009 by Daniel Stenberg
/* Copyright (C) 2009-2010 by Daniel Stenberg
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@@ -40,6 +40,6 @@
#include "libssh2_priv.h"
const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(void);
const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session);
#endif /* __LIBSSH2_COMP_H */

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2009 Simon Josefsson <simon@josefsson.org>
/* Copyright (c) 2009, 2010 Simon Josefsson <simon@josefsson.org>
* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
@@ -79,9 +79,9 @@ crypt_init(LIBSSH2_SESSION * session,
{
struct crypt_ctx *ctx = LIBSSH2_ALLOC(session,
sizeof(struct crypt_ctx));
if (!ctx) {
return -1;
}
if (!ctx)
return LIBSSH2_ERROR_ALLOC;
ctx->encrypt = encrypt;
ctx->algo = method->algo;
if (_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
@@ -242,13 +242,13 @@ crypt_init_arcfour128(LIBSSH2_SESSION * session,
int rc;
rc = crypt_init (session, method, iv, free_iv, secret, free_secret,
encrypt, abstract);
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);
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;

116
src/crypto.h Normal file
View File

@@ -0,0 +1,116 @@
/* Copyright (C) 2009, 2010 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
* Copyright (C) 2010 Daniel Stenberg
*
* 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.
*/
#ifndef LIBSSH2_CRYPTO_H
#define LIBSSH2_CRYPTO_H
#ifdef LIBSSH2_LIBGCRYPT
#include "libgcrypt.h"
#else
#include "openssl.h"
#endif
int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
const unsigned char *ndata,
unsigned long nlen,
const unsigned char *ddata,
unsigned long dlen,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *e1data,
unsigned long e1len,
const unsigned char *e2data,
unsigned long e2len,
const unsigned char *coeffdata, unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
const char *filename,
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig,
unsigned long sig_len,
const unsigned char *m, unsigned long m_len);
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
const unsigned char *hash,
size_t hash_len,
unsigned char **signature,
size_t *signature_len);
int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *gdata,
unsigned long glen,
const unsigned char *ydata,
unsigned long ylen,
const unsigned char *x, unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
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);
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash,
unsigned long hash_len, unsigned char *sig);
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),
unsigned char *iv,
unsigned char *secret, int encrypt);
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo),
int encrypt, unsigned char *block);
int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
unsigned char **pubkeydata,
size_t *pubkeydata_len,
const char *privatekey,
const char *passphrase);
#endif

View File

@@ -68,7 +68,8 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session,
now = time (NULL);
if (session->keepalive_last_sent + session->keepalive_interval <= now) {
/* Format is "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */
/* Format is
"SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */
unsigned char keepalive_data[]
= "\x50\x00\x00\x00\x15keepalive@libssh2.orgW";
size_t len = sizeof (keepalive_data) - 1;
@@ -76,9 +77,9 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session,
keepalive_data[len - 1] = session->keepalive_want_reply;
rc = _libssh2_transport_write(session, keepalive_data, len);
/* Silently ignore PACKET_EAGAIN here: if the write buffer is
already full, sending another keepalive is not useful. */
rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0);
/* Silently ignore PACKET_EAGAIN here: if the write buffer is
already full, sending another keepalive is not useful. */
if (rc && rc != LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send keepalive message");

View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -140,8 +141,9 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
if (exchange_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, exchange_state->e_packet,
exchange_state->e_packet_len);
rc = _libssh2_transport_send(session, exchange_state->e_packet,
exchange_state->e_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
@@ -410,7 +412,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
if (exchange_state->state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_write(session, &exchange_state->c, 1);
rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
@@ -843,8 +845,8 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
}
if (key_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, key_state->request,
key_state->request_len);
rc = _libssh2_transport_send(session, key_state->request,
key_state->request_len, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
@@ -1043,10 +1045,10 @@ static int kexinit(LIBSSH2_SESSION * session)
_libssh2_mac_methods());
comp_cs_len =
LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs,
_libssh2_comp_methods());
_libssh2_comp_methods(session));
comp_sc_len =
LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs,
_libssh2_comp_methods());
_libssh2_comp_methods(session));
lang_cs_len =
LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
lang_sc_len =
@@ -1083,9 +1085,9 @@ static int kexinit(LIBSSH2_SESSION * session)
LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs,
_libssh2_mac_methods());
LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs,
_libssh2_comp_methods());
_libssh2_comp_methods(session));
LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs,
_libssh2_comp_methods());
_libssh2_comp_methods(session));
LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs,
NULL);
LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs,
@@ -1133,12 +1135,12 @@ static int kexinit(LIBSSH2_SESSION * session)
} else {
data = session->kexinit_data;
data_len = session->kexinit_data_len;
/* zap the variables to ensure there is NOT a double free later */
/* zap the variables to ensure there is NOT a double free later */
session->kexinit_data = NULL;
session->kexinit_data_len = 0;
}
rc = _libssh2_transport_write(session, data, data_len);
rc = _libssh2_transport_send(session, data, data_len, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
session->kexinit_data = data;
session->kexinit_data_len = data_len;
@@ -1271,7 +1273,7 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
return -1;
}
while (hostkeyp && (*hostkeyp)->name) {
while (hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
s = kex_agree_instr(hostkey, hostkey_len,
(unsigned char *) (*hostkeyp)->name,
strlen((*hostkeyp)->name));
@@ -1487,11 +1489,11 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
/* kex_agree_comp
* Agree on a compression scheme
*/
static int kex_agree_comp(LIBSSH2_SESSION * session,
libssh2_endpoint_data * endpoint, unsigned char *comp,
static int kex_agree_comp(LIBSSH2_SESSION *session,
libssh2_endpoint_data *endpoint, unsigned char *comp,
unsigned long comp_len)
{
const LIBSSH2_COMP_METHOD **compp = _libssh2_comp_methods();
const LIBSSH2_COMP_METHOD **compp = _libssh2_comp_methods(session);
unsigned char *s;
(void) session;
@@ -1827,12 +1829,14 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
case LIBSSH2_METHOD_COMP_CS:
prefvar = &session->local.comp_prefs;
mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods();
mlist = (const LIBSSH2_COMMON_METHOD **)
_libssh2_comp_methods(session);
break;
case LIBSSH2_METHOD_COMP_SC:
prefvar = &session->remote.comp_prefs;
mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods();
mlist = (const LIBSSH2_COMMON_METHOD **)
_libssh2_comp_methods(session);
break;
case LIBSSH2_METHOD_LANG_CS:

View File

@@ -566,6 +566,120 @@ libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts)
LIBSSH2_FREE(hosts->session, hosts);
}
/* old style plain text: [name]([,][name])*
for the sake of simplicity, we add them as separate hosts with the same
key
*/
static int oldstyle_hostline(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, size_t hostlen,
const char *key, size_t keylen, int key_type,
const char *comment, size_t commentlen)
{
int rc = 0;
size_t namelen = 0;
const char *name = host + hostlen;
if(hostlen < 1)
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(no host names)");
while(name > host) {
--name;
++namelen;
/* when we get the the start or see a comma coming up, add the host
name to the collection */
if((name == host) || (*(name-1) == ',')) {
char hostbuf[256];
/* make sure we don't overflow the buffer */
if(namelen >= sizeof(hostbuf)-1)
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(unexpected length)");
/* copy host name to the temp buffer and zero terminate */
memcpy(hostbuf, name, namelen);
hostbuf[namelen]=0;
rc = knownhost_add(hosts, hostbuf, NULL, key, keylen,
comment, commentlen,
key_type | LIBSSH2_KNOWNHOST_TYPE_PLAIN |
LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL);
if(rc)
return rc;
if(name > host) {
namelen = 0;
--name; // skip comma
}
}
}
return rc;
}
/* |1|[salt]|[hash] */
static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, size_t hostlen,
const char *key, size_t keylen, int key_type,
const char *comment, size_t commentlen)
{
const char *p;
char saltbuf[32];
char hostbuf[256];
const char *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)) /* weird length */
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(unexpectedly long salt)");
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 */
/* check that the lengths seem sensible */
if(hostlen >= sizeof(hostbuf)-1)
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(unexpected length)");
memcpy(hostbuf, host, hostlen);
hostbuf[hostlen]=0;
return knownhost_add(hosts, hostbuf, salt, key, keylen, comment,
commentlen,
key_type | LIBSSH2_KNOWNHOST_TYPE_SHA1 |
LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL);
}
else
return 0; /* XXX: This should be an error, shouldn't it? */
}
/*
* hostline()
*
@@ -580,88 +694,21 @@ 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;
const char *comment = NULL;
size_t commentlen = 0;
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)) /* weird length */
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(unexpectedly long salt)");
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;
}
int key_type;
/* make some checks that the lengths seem sensible */
if((keylen < 20) ||
(seplen >= sizeof(hostbuf)-1) ||
(hostlen >= sizeof(hostbuf)-1))
if(keylen < 20)
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(unexpected length)");
"(key too short)");
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;
key_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
@@ -672,9 +719,9 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
case 's': /* ssh-dss or ssh-rsa */
if(!strncmp(key, "ssh-dss", 7))
type |= LIBSSH2_KNOWNHOST_KEY_SSHDSS;
key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
else if(!strncmp(key, "ssh-rsa", 7))
type |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
else
/* unknown key type */
return _libssh2_error(hosts->session,
@@ -721,30 +768,21 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
"Unknown key format");
}
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;
/* Figure out host format */
if((hostlen >2) && memcmp(host, "|1|", 3)) {
/* old style plain text: [name]([,][name])*
rc = knownhost_add(hosts, hostbuf, salt, key, keylen,
comment, commentlen,
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
NULL);
if(rc)
return rc;
for the sake of simplicity, we add them as separate hosts with the
same key
*/
return oldstyle_hostline(hosts, host, hostlen, key, keylen, key_type,
comment, commentlen);
}
else {
/* |1|[salt]|[hash] */
return hashed_hostline(hosts, host, hostlen, key, keylen, key_type,
comment, commentlen);
}
if (!salt)
host = orig;
memcpy(hostbuf, host, hostlen);
hostbuf[hostlen]=0;
rc = knownhost_add(hosts, hostbuf, salt, key, keylen, comment,
commentlen,
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
NULL);
return rc;
}
/*
@@ -764,7 +802,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
* <name> or <hash>
*
* <name> consists of
* [name,address] or just [name] or just [address]
* [name] optionally followed by [,name] one or more times
*
* <hash> consists of
* |1|<salt>|hash

View File

@@ -537,11 +537,11 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
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) {
if (mode == GCRY_CIPHER_MODE_CTR)
ret = gcry_cipher_setctr(*h, iv, blklen);
else
ret = gcry_cipher_setiv(*h, iv, blklen);
if (ret) {
gcry_cipher_close(*h);
return -1;
}
@@ -572,4 +572,17 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
return ret;
}
int
_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
unsigned char **pubkeydata,
size_t *pubkeydata_len,
const char *privatekey,
const char *passphrase)
{
return -1; /* not yet supported; interpreted by userauth.c to call
libssh2_error */
}
#endif /* LIBSSH2_LIBGCRYPT */

View File

@@ -97,62 +97,10 @@
#define libssh2_rsa_ctx struct gcry_sexp
int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
const unsigned char *ndata,
unsigned long nlen,
const unsigned char *ddata,
unsigned long dlen,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *e1data,
unsigned long e1len,
const unsigned char *e2data,
unsigned long e2len,
const unsigned char *coeffdata, unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
const char *filename,
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig,
unsigned long sig_len,
const unsigned char *m, unsigned long m_len);
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
const unsigned char *hash,
size_t hash_len,
unsigned char **signature,
size_t *signature_len);
#define _libssh2_rsa_free(rsactx) gcry_sexp_release (rsactx)
#define libssh2_dsa_ctx struct gcry_sexp
int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *gdata,
unsigned long glen,
const unsigned char *ydata,
unsigned long ylen,
const unsigned char *x, unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
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);
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash,
unsigned long hash_len, unsigned char *sig);
#define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx)
#define _libssh2_cipher_type(name) int name
@@ -162,35 +110,27 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
#define _libssh2_gcry_cipher(c) (c >> 8)
#define _libssh2_gcry_mode(m) (m & 0xFF)
#define _libssh2_cipher_aes256ctr \
#define _libssh2_cipher_aes256ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes192ctr \
#define _libssh2_cipher_aes192ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes128ctr \
#define _libssh2_cipher_aes128ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes256 \
#define _libssh2_cipher_aes256 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_aes192 \
#define _libssh2_cipher_aes192 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_aes128 \
#define _libssh2_cipher_aes128 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_blowfish \
#define _libssh2_cipher_blowfish \
_libssh2_gcry_ciphermode(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_arcfour \
#define _libssh2_cipher_arcfour \
_libssh2_gcry_ciphermode(GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM)
#define _libssh2_cipher_cast5 \
#define _libssh2_cipher_cast5 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_3des \
#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),
unsigned char *iv,
unsigned char *secret, int encrypt);
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo),
int encrypt, unsigned char *block);
#define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx))
@@ -207,3 +147,4 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
#define _libssh2_bn_bytes(bn) (gcry_mpi_get_nbits (bn) / 8 + ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1))
#define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn)
#define _libssh2_bn_free(bn) gcry_mpi_release(bn)

View File

@@ -125,12 +125,7 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
#endif /* WIN32 */
#ifdef LIBSSH2_LIBGCRYPT
#include "libgcrypt.h"
#else
#include "openssl.h"
#endif
#include "crypto.h"
#ifdef HAVE_WINSOCK2_H
@@ -145,13 +140,6 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
#endif
#ifdef WIN32
typedef SOCKET libssh2_socket_t;
#else /* !WIN32 */
typedef int libssh2_socket_t;
#define INVALID_SOCKET -1
#endif /* WIN32 */
/* RFC4253 section 6.1 Maximum Packet Length says:
*
* "All implementations MUST be able to process packets with
@@ -185,7 +173,6 @@ typedef int libssh2_socket_t;
typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD;
typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
typedef struct _LIBSSH2_MAC_METHOD LIBSSH2_MAC_METHOD;
typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD;
@@ -311,18 +298,13 @@ 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) */
/* the raw unencrypted payload */
unsigned char *data;
size_t data_len;
/* Where to start reading data from,
* used for channel data that's been partially consumed */
unsigned long data_head;
/* Can the message be confirmed? */
int mac;
size_t data_head;
};
typedef struct _libssh2_channel_data
@@ -331,7 +313,7 @@ typedef struct _libssh2_channel_data
uint32_t id;
/* Limits and restrictions */
unsigned long window_size_initial, window_size, packet_size;
uint32_t window_size_initial, window_size, packet_size;
/* Set to 1 when CHANNEL_CLOSE / CHANNEL_EOF sent/received */
char close, eof, extended_data_ignore_mode;
@@ -347,9 +329,12 @@ struct _LIBSSH2_CHANNEL
/* channel's program exit status */
int exit_status;
/* channel's program exit signal (without the SIG prefix) */
char *exit_signal;
libssh2_channel_data local, remote;
/* Amount of bytes to be refunded to receive window (but not yet sent) */
unsigned long adjust_queue;
uint32_t adjust_queue;
LIBSSH2_SESSION *session;
@@ -363,9 +348,10 @@ struct _LIBSSH2_CHANNEL
unsigned char setenv_local_channel[4];
packet_requirev_state_t setenv_packet_requirev_state;
/* State variables used in libssh2_channel_request_pty_ex() */
/* State variables used in libssh2_channel_request_pty_ex()
libssh2_channel_request_pty_size_ex() */
libssh2_nonblocking_states reqPTY_state;
unsigned char *reqPTY_packet;
unsigned char reqPTY_packet[41 + 256];
size_t reqPTY_packet_len;
unsigned char reqPTY_local_channel[4];
packet_requirev_state_t reqPTY_packet_requirev_state;
@@ -400,10 +386,8 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_write_ex() */
libssh2_nonblocking_states write_state;
unsigned char *write_packet;
unsigned char *write_s;
unsigned char write_packet[13];
size_t write_packet_len;
size_t write_bufwrote;
size_t write_bufwrite;
/* State variables used in libssh2_channel_close() */
@@ -421,6 +405,7 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_handle_extended_data2() */
libssh2_nonblocking_states extData2_state;
};
struct _LIBSSH2_LISTENER
@@ -454,8 +439,8 @@ typedef struct _libssh2_endpoint_data
const LIBSSH2_CRYPT_METHOD *crypt;
void *crypt_abstract;
const LIBSSH2_MAC_METHOD *mac;
unsigned long seqno;
const struct _LIBSSH2_MAC_METHOD *mac;
uint32_t seqno;
void *mac_abstract;
const LIBSSH2_COMP_METHOD *comp;
@@ -476,17 +461,17 @@ struct transportpacket
unsigned char buf[PACKETBUFSIZE];
unsigned char init[5]; /* first 5 bytes of the incoming data stream,
still encrypted */
int writeidx; /* at what array index we do the next write into
size_t writeidx; /* at what array index we do the next write into
the buffer */
int readidx; /* at what array index we do the next read from
size_t readidx; /* at what array index we do the next read from
the buffer */
uint32_t packet_length; /* the most recent packet_length as read from the
network data */
uint8_t padding_length; /* the most recent padding_length as read from the
network data */
int data_num; /* How much of the total package that has been read
size_t data_num; /* How much of the total package that has been read
so far. */
int total_num; /* How much a total package is supposed to be, in
size_t total_num; /* How much a total package is supposed to be, in
number of bytes. A full package is
packet_length + padding_length + 4 +
mac_length. */
@@ -496,11 +481,10 @@ struct transportpacket
are currently writing decrypted data */
/* ------------- for outgoing data --------------- */
unsigned char *outbuf; /* pointer to a LIBSSH2_ALLOC() area for the
outgoing data */
unsigned char outbuf[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */
int ototal_num; /* size of outbuf in number of bytes */
unsigned char *odata; /* original pointer to the data we stored in
outbuf */
const unsigned char *odata; /* original pointer to the data */
size_t olen; /* original size of the data we stored in
outbuf */
size_t osent; /* number of bytes already sent */
@@ -509,7 +493,7 @@ struct transportpacket
struct _LIBSSH2_PUBLICKEY
{
LIBSSH2_CHANNEL *channel;
unsigned long version;
uint32_t version;
/* State variables used in libssh2_publickey_packet_receive() */
libssh2_nonblocking_states receive_state;
@@ -534,137 +518,13 @@ struct _LIBSSH2_PUBLICKEY
size_t listFetch_data_len;
};
#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
struct _LIBSSH2_SFTP_HANDLE
{
struct list_node node;
LIBSSH2_SFTP *sftp;
/* 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,
write, close and MUST thus be big enough to suit all these. */
unsigned char request_packet[SFTP_HANDLE_MAXLEN + 25];
char handle[SFTP_HANDLE_MAXLEN];
size_t handle_len;
char handle_type;
union _libssh2_sftp_handle_data
{
struct _libssh2_sftp_handle_file_data
{
libssh2_uint64_t offset;
} file;
struct _libssh2_sftp_handle_dir_data
{
unsigned long names_left;
void *names_packet;
char *next_name;
} dir;
} u;
/* State variables used in libssh2_sftp_close_handle() */
libssh2_nonblocking_states close_state;
unsigned long close_request_id;
unsigned char *close_packet;
};
struct _LIBSSH2_SFTP
{
LIBSSH2_CHANNEL *channel;
unsigned long request_id, version;
struct list_head packets;
/* a list of _LIBSSH2_SFTP_HANDLE structs */
struct list_head sftp_handles;
uint32_t last_errno;
/* Holder for partial packet, use in libssh2_sftp_packet_read() */
unsigned char *partial_packet; /* The data */
size_t partial_len; /* Desired number of bytes */
size_t partial_received; /* Bytes received so far */
/* Time that libssh2_sftp_packet_requirev() started reading */
time_t requirev_start;
/* State variables used in libssh2_sftp_open_ex() */
libssh2_nonblocking_states open_state;
unsigned char *open_packet;
size_t open_packet_len;
size_t open_packet_sent;
uint32_t open_request_id;
/* State variables used in libssh2_sftp_read() */
libssh2_nonblocking_states read_state;
unsigned char *read_packet;
uint32_t read_request_id;
size_t read_total_read;
/* State variables used in libssh2_sftp_readdir() */
libssh2_nonblocking_states readdir_state;
unsigned char *readdir_packet;
uint32_t readdir_request_id;
/* State variables used in libssh2_sftp_write() */
libssh2_nonblocking_states write_state;
unsigned char *write_packet;
uint32_t write_request_id;
/* State variables used in libssh2_sftp_fstat_ex() */
libssh2_nonblocking_states fstat_state;
unsigned char *fstat_packet;
uint32_t fstat_request_id;
/* State variables used in libssh2_sftp_unlink_ex() */
libssh2_nonblocking_states unlink_state;
unsigned char *unlink_packet;
uint32_t unlink_request_id;
/* State variables used in libssh2_sftp_rename_ex() */
libssh2_nonblocking_states rename_state;
unsigned char *rename_packet;
unsigned char *rename_s;
uint32_t rename_request_id;
/* State variables used in libssh2_sftp_fstatvfs() */
libssh2_nonblocking_states fstatvfs_state;
unsigned char *fstatvfs_packet;
uint32_t fstatvfs_request_id;
/* State variables used in libssh2_sftp_statvfs() */
libssh2_nonblocking_states statvfs_state;
unsigned char *statvfs_packet;
uint32_t statvfs_request_id;
/* State variables used in libssh2_sftp_mkdir() */
libssh2_nonblocking_states mkdir_state;
unsigned char *mkdir_packet;
uint32_t mkdir_request_id;
/* State variables used in libssh2_sftp_rmdir() */
libssh2_nonblocking_states rmdir_state;
unsigned char *rmdir_packet;
uint32_t rmdir_request_id;
/* State variables used in libssh2_sftp_stat() */
libssh2_nonblocking_states stat_state;
unsigned char *stat_packet;
uint32_t stat_request_id;
/* State variables used in libssh2_sftp_symlink() */
libssh2_nonblocking_states symlink_state;
unsigned char *symlink_packet;
uint32_t symlink_request_id;
};
#define LIBSSH2_SCP_RESPONSE_BUFLEN 256
struct flags {
int sigpipe; /* LIBSSH2_FLAG_SIGPIPE */
int compress; /* LIBSSH2_FLAG_COMPRESS */
};
struct _LIBSSH2_SESSION
{
/* Memory management callbacks */
@@ -685,14 +545,16 @@ struct _LIBSSH2_SESSION
char *hostkey_prefs;
int state;
int flags;
/* Flag options */
struct flags flag;
/* Agreed Key Exchange Method */
const LIBSSH2_KEX_METHOD *kex;
int burn_optimistic_kexinit:1;
unsigned char *session_id;
unsigned long session_id_len;
uint32_t session_id_len;
/* this is set to TRUE if a blocking API behavior is requested */
int api_block_mode;
@@ -705,7 +567,7 @@ struct _LIBSSH2_SESSION
* Or read from server in (eg) KEXDH_INIT (for client mode)
*/
unsigned char *server_hostkey;
unsigned long server_hostkey_len;
uint32_t server_hostkey_len;
#if LIBSSH2_MD5
unsigned char server_hostkey_md5[MD5_DIGEST_LENGTH];
#endif /* ! LIBSSH2_MD5 */
@@ -724,7 +586,7 @@ struct _LIBSSH2_SESSION
/* Active connection channels */
struct list_head channels;
unsigned long next_channel;
uint32_t next_channel;
struct list_head listeners; /* list of LIBSSH2_LISTENER structs */
@@ -771,7 +633,7 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_session_disconnect_ex() */
libssh2_nonblocking_states disconnect_state;
unsigned char *disconnect_data;
unsigned char disconnect_data[256 + 13];
size_t disconnect_data_len;
/* State variables used in libssh2_packet_read() */
@@ -852,8 +714,8 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_channel_forward_listen_ex() */
libssh2_nonblocking_states fwdLstn_state;
unsigned char *fwdLstn_packet;
unsigned long fwdLstn_host_len;
unsigned long fwdLstn_packet_len;
uint32_t fwdLstn_host_len;
uint32_t fwdLstn_packet_len;
packet_requirev_state_t fwdLstn_packet_requirev_state;
/* State variables used in libssh2_publickey_init() */
@@ -868,16 +730,15 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_packet_add() */
libssh2_nonblocking_states packAdd_state;
LIBSSH2_CHANNEL *packAdd_channel;
unsigned long packAdd_data_head;
key_exchange_state_t packAdd_key_state;
LIBSSH2_CHANNEL *packAdd_channelp; /* keeper of the channel during EAGAIN
states */
packet_queue_listener_state_t packAdd_Qlstn_state;
packet_x11_open_state_t packAdd_x11open_state;
/* State variables used in fullpacket() */
libssh2_nonblocking_states fullpacket_state;
int fullpacket_macstate;
int fullpacket_payload_len;
size_t fullpacket_payload_len;
int fullpacket_packet_type;
/* State variables used in libssh2_sftp_init() */
@@ -892,9 +753,9 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_scp_recv() */
libssh2_nonblocking_states scpRecv_state;
unsigned char *scpRecv_command;
unsigned long scpRecv_command_len;
size_t scpRecv_command_len;
unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
unsigned long scpRecv_response_len;
size_t scpRecv_response_len;
long scpRecv_mode;
#if defined(HAVE_LONGLONG) && defined(HAVE_STRTOLL)
/* we have the type and we can parse such numbers */
@@ -906,18 +767,14 @@ struct _LIBSSH2_SESSION
#endif
long scpRecv_mtime;
long scpRecv_atime;
char *scpRecv_err_msg;
long scpRecv_err_len;
LIBSSH2_CHANNEL *scpRecv_channel;
/* State variables used in libssh2_scp_send_ex() */
libssh2_nonblocking_states scpSend_state;
unsigned char *scpSend_command;
unsigned long scpSend_command_len;
size_t scpSend_command_len;
unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
unsigned long scpSend_response_len;
char *scpSend_err_msg;
long scpSend_err_len;
size_t scpSend_response_len;
LIBSSH2_CHANNEL *scpSend_channel;
/* Keepalive variables used by keepalive.c. */
@@ -934,8 +791,8 @@ struct _LIBSSH2_SESSION
/* session.flag helpers */
#ifdef MSG_NOSIGNAL
#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL)
#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL)
#else
/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */
#define LIBSSH2_SOCKET_SEND_FLAGS(session) 0
@@ -1005,33 +862,22 @@ struct _LIBSSH2_CRYPT_METHOD
struct _LIBSSH2_COMP_METHOD
{
const char *name;
int (*init) (LIBSSH2_SESSION * session, int compress, void **abstract);
int (*comp) (LIBSSH2_SESSION * session, int compress, unsigned char **dest,
size_t *dest_len, size_t payload_limit,
int *free_dest, const unsigned char *src,
size_t src_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
};
struct _LIBSSH2_MAC_METHOD
{
const char *name;
/* The length of a given MAC packet */
int mac_len;
/* integrity key length */
int key_len;
/* Message Authentication Code Hashing algo */
int (*init) (LIBSSH2_SESSION * session, unsigned char *key, int *free_key,
int compress; /* 1 if it does compress, 0 if it doesn't */
int (*init) (LIBSSH2_SESSION *session, int compress, void **abstract);
int (*comp) (LIBSSH2_SESSION *session,
unsigned char *dest,
size_t *dest_len,
const unsigned char *src,
size_t src_len,
void **abstract);
int (*hash) (LIBSSH2_SESSION * session, unsigned char *buf,
unsigned long seqno, const unsigned char *packet,
unsigned long packet_len, const unsigned char *addtl,
unsigned long addtl_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
int (*decomp) (LIBSSH2_SESSION *session,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
const unsigned char *src,
size_t src_len,
void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
};
#ifdef LIBSSH2DEBUG
@@ -1115,13 +961,17 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
#define SSH_MSG_CHANNEL_SUCCESS 99
#define SSH_MSG_CHANNEL_FAILURE 100
#if defined( WIN32 ) || defined( __VMS )
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)
#endif
/* Error codes returned in SSH_MSG_CHANNEL_OPEN_FAILURE message
(see RFC4254) */
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
#define SSH_OPEN_CONNECT_FAILED 2
#define SSH_OPEN_UNKNOWN_CHANNELTYPE 3
#define SSH_OPEN_RESOURCE_SHORTAGE 4
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);
#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
waiting for more data to arrive */

View File

@@ -44,9 +44,9 @@
*/
static int
mac_none_MAC(LIBSSH2_SESSION * session, unsigned char *buf,
unsigned long seqno, const unsigned char *packet,
unsigned long packet_len, const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
uint32_t seqno, const unsigned char *packet,
uint32_t packet_len, const unsigned char *addtl,
uint32_t addtl_len, void **abstract)
{
return 0;
}
@@ -101,11 +101,11 @@ mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract)
*/
static int
mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session,
unsigned char *buf, unsigned long seqno,
unsigned char *buf, uint32_t seqno,
const unsigned char *packet,
unsigned long packet_len,
uint32_t packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
uint32_t addtl_len, void **abstract)
{
libssh2_hmac_ctx ctx;
unsigned char seqno_buf[4];
@@ -141,11 +141,11 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1 = {
*/
static int
mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session,
unsigned char *buf, unsigned long seqno,
unsigned char *buf, uint32_t seqno,
const unsigned char *packet,
unsigned long packet_len,
uint32_t packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
uint32_t addtl_len, void **abstract)
{
unsigned char temp[SHA_DIGEST_LENGTH];
@@ -173,11 +173,11 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1_96 = {
*/
static int
mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf,
unsigned long seqno,
uint32_t seqno,
const unsigned char *packet,
unsigned long packet_len,
uint32_t packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
uint32_t addtl_len, void **abstract)
{
libssh2_hmac_ctx ctx;
unsigned char seqno_buf[4];
@@ -213,11 +213,11 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_md5 = {
*/
static int
mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session,
unsigned char *buf, unsigned long seqno,
unsigned char *buf, uint32_t seqno,
const unsigned char *packet,
unsigned long packet_len,
uint32_t packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
uint32_t addtl_len, void **abstract)
{
unsigned char temp[MD5_DIGEST_LENGTH];
mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len,
@@ -244,11 +244,11 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_md5_96 = {
*/
static int
mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session,
unsigned char *buf, unsigned long seqno,
unsigned char *buf, uint32_t seqno,
const unsigned char *packet,
unsigned long packet_len,
uint32_t packet_len,
const unsigned char *addtl,
unsigned long addtl_len,
uint32_t addtl_len,
void **abstract)
{
libssh2_hmac_ctx ctx;

View File

@@ -1,7 +1,7 @@
#ifndef __LIBSSH2_MAC_H
#define __LIBSSH2_MAC_H
/* Copyright (C) 2009 by Daniel Stenberg
/* Copyright (C) 2009-2010 by Daniel Stenberg
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@@ -40,6 +40,28 @@
#include "libssh2_priv.h"
struct _LIBSSH2_MAC_METHOD
{
const char *name;
/* The length of a given MAC packet */
int mac_len;
/* integrity key length */
int key_len;
/* Message Authentication Code Hashing algo */
int (*init) (LIBSSH2_SESSION * session, unsigned char *key, int *free_key,
void **abstract);
int (*hash) (LIBSSH2_SESSION * session, unsigned char *buf,
uint32_t seqno, const unsigned char *packet,
uint32_t packet_len, const unsigned char *addtl,
uint32_t addtl_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
};
typedef struct _LIBSSH2_MAC_METHOD LIBSSH2_MAC_METHOD;
const LIBSSH2_MAC_METHOD **_libssh2_mac_methods(void);
#endif /* __LIBSSH2_MAC_H */

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2009-2010 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -55,6 +56,10 @@ int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
session->err_msg = errmsg;
session->err_code = errcode;
#ifdef LIBSSH2DEBUG
if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode)
/* if this is EAGAIN and we're in non-blocking mode, don't generate
a debug output for this */
return errcode;
_libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
session->err_msg);
#endif
@@ -84,53 +89,56 @@ static int wsa2errno(void)
}
#endif
#ifndef _libssh2_recv
/* _libssh2_recv
*
* Wrapper around standard recv to allow WIN32 systems
* to set errno
* Replacement for the standard recv, return -errno on failure.
*/
ssize_t
_libssh2_recv(libssh2_socket_t socket, void *buffer, size_t length, int flags)
_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags)
{
ssize_t rc = recv(socket, buffer, length, flags);
ssize_t rc = recv(sock, buffer, length, flags);
#ifdef WIN32
if (rc < 0 )
errno = wsa2errno();
#endif
#ifdef __VMS
return -wsa2errno();
#elif defined(__VMS)
if (rc < 0 ){
if ( errno == EWOULDBLOCK ) errno = EAGAIN;
if ( errno == EWOULDBLOCK )
return -EAGAIN;
else
return -errno;
}
#else
if (rc < 0 )
return -errno;
#endif
return rc;
}
#endif /* _libssh2_recv */
#ifndef _libssh2_send
/* _libssh2_send
*
* Wrapper around standard send to allow WIN32 systems
* to set errno
* Replacement for the standard send, return -errno on failure.
*/
ssize_t
_libssh2_send(libssh2_socket_t socket, const void *buffer, size_t length,
_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
int flags)
{
ssize_t rc = send(socket, buffer, length, flags);
ssize_t rc = send(sock, buffer, length, flags);
#ifdef WIN32
if (rc < 0 )
errno = wsa2errno();
#endif
#ifdef VMS
if (rc < 0 ){
if ( errno == EWOULDBLOCK ) errno = EAGAIN;
return -wsa2errno();
#elif defined(__VMS)
if (rc < 0 ) {
if ( errno == EWOULDBLOCK )
return -EAGAIN;
else
return -errno;
}
#else
if (rc < 0 )
return -errno;
#endif
return rc;
}
#endif /* _libssh2_recv */
/* libssh2_ntohu32
*/
@@ -148,8 +156,10 @@ _libssh2_ntohu64(const unsigned char *buf)
{
unsigned long msl, lsl;
msl = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
lsl = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
msl = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16)
| ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3];
lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16)
| ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7];
return ((libssh2_uint64_t)msl <<32) | lsl;
}
@@ -348,6 +358,12 @@ size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
}
/* ---- End of Base64 Encoding ---- */
LIBSSH2_API void
libssh2_free(LIBSSH2_SESSION *session, void *ptr)
{
LIBSSH2_FREE(session, ptr);
}
#ifdef LIBSSH2DEBUG
LIBSSH2_API int
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)

View File

@@ -215,31 +215,31 @@ typedef struct
static int
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) /* init key */
const unsigned char *iv, int enc) /* init key */
{
aes_ctr_ctx *c = malloc(sizeof(*c));
const EVP_CIPHER *aes_cipher;
(void) enc;
if (c == NULL)
return 0;
return 0;
switch (ctx->key_len) {
case 16:
aes_cipher = EVP_aes_128_ecb();
break;
case 24:
aes_cipher = EVP_aes_192_ecb();
break;
case 32:
aes_cipher = EVP_aes_256_ecb();
break;
default:
return 0;
case 16:
aes_cipher = EVP_aes_128_ecb();
break;
case 24:
aes_cipher = EVP_aes_192_ecb();
break;
case 32:
aes_cipher = EVP_aes_256_ecb();
break;
default:
return 0;
}
c->aes_ctx = malloc(sizeof(EVP_CIPHER_CTX));
if (c->aes_ctx == NULL)
return 0;
return 0;
if (EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) {
return 0;
@@ -256,8 +256,8 @@ aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
static int
aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in,
unsigned int inl) /* encrypt/decrypt data */
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];
@@ -265,7 +265,7 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
int outlen = 0;
if (inl != 16) /* libssh2 only ever encrypt one block */
return 0;
return 0;
if (c == NULL) {
return 0;
@@ -283,13 +283,13 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
for (i = 0; i < 16; i++)
*out++ = *in++ ^ b1[i];
*out++ = *in++ ^ b1[i];
i = 15;
while (c->ctr[i]++ == 0xFF) {
if (i == 0)
break;
i--;
if (i == 0)
break;
i--;
}
return 1;
@@ -305,6 +305,7 @@ aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
}
if (c->aes_ctx != NULL) {
_libssh2_cipher_dtor(c->aes_ctx);
free(c->aes_ctx);
}
@@ -514,4 +515,274 @@ libssh2_md5(const unsigned char *message, unsigned long len,
EVP_DigestFinal(&ctx, out, NULL);
}
static unsigned char *
write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes)
{
unsigned char *p = buf;
/* Left space for bn size which will be written below. */
p += 4;
*p = 0;
BN_bn2bin(bn, p + 1);
if (!(*(p + 1) & 0x80)) {
memmove(p, p + 1, --bn_bytes);
}
_libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */
return p + bn_bytes;
}
static unsigned char *
gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa,
size_t *key_len)
{
int e_bytes, n_bytes;
unsigned long len;
unsigned char* key;
unsigned char* p;
e_bytes = BN_num_bytes(rsa->e) + 1;
n_bytes = BN_num_bytes(rsa->n) + 1;
/* Key form is "ssh-rsa" + e + n. */
len = 4 + 7 + 4 + e_bytes + 4 + n_bytes;
key = LIBSSH2_ALLOC(session, len);
if (key == NULL) {
return NULL;
}
/* Process key encoding. */
p = key;
_libssh2_htonu32(p, 7); /* Key type. */
p += 4;
memcpy(p, "ssh-rsa", 7);
p += 7;
p = write_bn(p, rsa->e, e_bytes);
p = write_bn(p, rsa->n, n_bytes);
*key_len = (size_t)(p - key);
return key;
}
static unsigned char *
gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa,
size_t *key_len)
{
int p_bytes, q_bytes, g_bytes, k_bytes;
unsigned long len;
unsigned char* key;
unsigned char* p;
p_bytes = BN_num_bytes(dsa->p) + 1;
q_bytes = BN_num_bytes(dsa->q) + 1;
g_bytes = BN_num_bytes(dsa->g) + 1;
k_bytes = BN_num_bytes(dsa->pub_key) + 1;
/* Key form is "ssh-dss" + p + q + g + pub_key. */
len = 4 + 7 + 4 + p_bytes + 4 + q_bytes + 4 + g_bytes + 4 + k_bytes;
key = LIBSSH2_ALLOC(session, len);
if (key == NULL) {
return NULL;
}
/* Process key encoding. */
p = key;
_libssh2_htonu32(p, 7); /* Key type. */
p += 4;
memcpy(p, "ssh-dss", 7);
p += 7;
p = write_bn(p, dsa->p, p_bytes);
p = write_bn(p, dsa->q, q_bytes);
p = write_bn(p, dsa->g, g_bytes);
p = write_bn(p, dsa->pub_key, k_bytes);
*key_len = (size_t)(p - key);
return key;
}
static int
gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
unsigned char **pubkeydata,
size_t *pubkeydata_len,
EVP_PKEY *pk)
{
RSA* rsa = NULL;
unsigned char* key;
unsigned char* method_buf = NULL;
size_t key_len;
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
"Computing public key from RSA private key envelop");
rsa = EVP_PKEY_get1_RSA(pk);
if (rsa == NULL) {
/* Assume memory allocation error... what else could it be ? */
goto __alloc_error;
}
method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-rsa. */
if (method_buf == NULL) {
goto __alloc_error;
}
key = gen_publickey_from_rsa(session, rsa, &key_len);
if (key == NULL) {
goto __alloc_error;
}
RSA_free(rsa);
memcpy(method_buf, "ssh-rsa", 7);
*method = method_buf;
*method_len = 7;
*pubkeydata = key;
*pubkeydata_len = key_len;
return 0;
__alloc_error:
if (rsa != NULL) {
RSA_free(rsa);
}
if (method_buf != NULL) {
LIBSSH2_FREE(session, method_buf);
}
_libssh2_error(session,
LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for private key data");
return -1;
}
static int
gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
unsigned char **pubkeydata,
size_t *pubkeydata_len,
EVP_PKEY *pk)
{
DSA* dsa = NULL;
unsigned char* key;
unsigned char* method_buf = NULL;
size_t key_len;
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
"Computing public key from DSA private key envelop");
dsa = EVP_PKEY_get1_DSA(pk);
if (dsa == NULL) {
/* Assume memory allocation error... what else could it be ? */
goto __alloc_error;
}
method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-dss. */
if (method_buf == NULL) {
goto __alloc_error;
}
key = gen_publickey_from_dsa(session, dsa, &key_len);
if (key == NULL) {
goto __alloc_error;
}
DSA_free(dsa);
memcpy(method_buf, "ssh-dss", 7);
*method = method_buf;
*method_len = 7;
*pubkeydata = key;
*pubkeydata_len = key_len;
return 0;
__alloc_error:
if (dsa != NULL) {
DSA_free(dsa);
}
if (method_buf != NULL) {
LIBSSH2_FREE(session, method_buf);
}
_libssh2_error(session,
LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for private key data");
return -1;
}
int
_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
unsigned char **pubkeydata,
size_t *pubkeydata_len,
const char *privatekey,
const char *passphrase)
{
int st;
BIO* bp;
EVP_PKEY* pk;
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
"Computing public key from private key file: %s",
privatekey);
bp = BIO_new_file(privatekey, "r");
if (bp == NULL) {
_libssh2_error(session,
LIBSSH2_ERROR_FILE,
"Unable to open private key file");
return -1;
}
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
* ($#&%#$(%$#( Someone buy me an OpenSSL manual and I'll read up on
* it.
*/
OpenSSL_add_all_ciphers();
}
BIO_reset(bp);
pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase);
BIO_free(bp);
if (pk == NULL) {
_libssh2_error(session,
LIBSSH2_ERROR_FILE,
"Wrong passphrase or invalid/unrecognized "
"private key file format");
return -1;
}
switch (pk->type) {
case EVP_PKEY_RSA :
st = gen_publickey_from_rsa_evp(
session, method, method_len, pubkeydata, pubkeydata_len, pk);
break;
case EVP_PKEY_DSA :
st = gen_publickey_from_dsa_evp(
session, method, method_len, pubkeydata, pubkeydata_len, pk);
break;
default :
st = -1;
_libssh2_error(session,
LIBSSH2_ERROR_FILE,
"Unsupported private key file format");
break;
}
EVP_PKEY_free(pk);
return st;
}
#endif /* !LIBSSH2_LIBGCRYPT */

View File

@@ -135,61 +135,10 @@ void libssh2_md5(const unsigned char *message, unsigned long len, unsigned char
#define libssh2_rsa_ctx RSA
int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
const unsigned char *ndata,
unsigned long nlen,
const unsigned char *ddata,
unsigned long dlen,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *e1data,
unsigned long e1len,
const unsigned char *e2data,
unsigned long e2len,
const unsigned char *coeffdata, unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
const char *filename,
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig,
unsigned long sig_len,
const unsigned char *m, unsigned long m_len);
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
const unsigned char *hash,
size_t hash_len,
unsigned char **signature,
size_t *signature_len);
#define _libssh2_rsa_free(rsactx) RSA_free(rsactx)
#define libssh2_dsa_ctx DSA
int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *gdata,
unsigned long glen,
const unsigned char *ydata,
unsigned long ylen,
const unsigned char *x, unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
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);
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash,
unsigned long hash_len, unsigned char *sig);
#define _libssh2_dsa_free(dsactx) DSA_free(dsactx)
@@ -213,15 +162,6 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
#define _libssh2_cipher_cast5 EVP_cast5_cbc
#define _libssh2_cipher_3des EVP_des_ede3_cbc
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),
unsigned char *iv,
unsigned char *secret, int encrypt);
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo),
int encrypt, unsigned char *block);
#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx)
#define _libssh2_bn BIGNUM
@@ -241,3 +181,4 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
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);

File diff suppressed because it is too large Load Diff

View File

@@ -378,7 +378,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
if (session->pkeyInit_state == libssh2_NB_state_sent2) {
rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
(char *)session->pkeyInit_buffer,
session->pkeyInit_buffer,
19 - session->pkeyInit_buffer_sent);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -644,7 +644,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
}
if (pkey->add_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, (char *) pkey->add_packet,
rc = _libssh2_channel_write(channel, 0, pkey->add_packet,
(pkey->add_s - pkey->add_packet));
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
@@ -727,7 +727,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
}
if (pkey->remove_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, (char *) pkey->remove_packet,
rc = _libssh2_channel_write(channel, 0, pkey->remove_packet,
(pkey->remove_s - pkey->remove_packet));
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
@@ -794,7 +794,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
if (pkey->listFetch_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0,
(char *) pkey->listFetch_buffer,
pkey->listFetch_buffer,
(pkey->listFetch_s -
pkey->listFetch_buffer));
if (rc == LIBSSH2_ERROR_EAGAIN) {

215
src/scp.c
View File

@@ -360,7 +360,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
if (session->scpRecv_state == libssh2_NB_state_sent1) {
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->scpRecv_response, 1);
session->scpRecv_response, 1);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending initial wakeup");
@@ -390,56 +390,53 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response");
return NULL;
} else if (rc <= 0) {
/* Timeout, give up */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Timed out waiting for SCP response");
}
else if (rc < 0) {
/* error, give up */
_libssh2_error(session, rc, "Failed reading SCP response");
goto scp_recv_error;
}
else if(rc == 0)
goto scp_recv_empty_channel;
session->scpRecv_response_len++;
if (session->scpRecv_response[0] != 'T') {
/*
* Set this as the default error for here, if
* we are successful it will be replaced
*/
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid data in SCP response, missing Time data");
size_t err_len;
char *err_msg;
session->scpRecv_err_len =
/* there can be
01 for warnings
02 for errors
The following string MUST be newline terminated
*/
err_len =
_libssh2_channel_packet_data_len(session->
scpRecv_channel, 0);
session->scpRecv_err_msg =
LIBSSH2_ALLOC(session, session->scpRecv_err_len + 1);
if (!session->scpRecv_err_msg) {
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
if (!err_msg) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Failed to get memory ");
goto scp_recv_error;
}
memset(session->scpRecv_err_msg, 0,
session->scpRecv_err_len + 1);
/* Read the remote error message */
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
session->scpRecv_err_msg,
session->scpRecv_err_len);
if (rc <= 0) {
/*
* Since we have alread started reading this packet,
* it is already in the systems so it can't return
* LIBSSH2_ERROR_EAGAIN
*/
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unknown error" );
}
else
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"SCP protocol error");
(void)_libssh2_channel_read(session->scpRecv_channel, 0,
err_msg, err_len);
/* If it failed for any reason, we ignore it anyway. */
/* TODO: for debugging purposes, the
session->scpRecv_err_msg should be displayed here
when available */
/* zero terminate the error */
err_msg[err_len]=0;
LIBSSH2_FREE(session, session->scpRecv_err_msg);
session->scpRecv_err_msg = NULL;
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"got %02x %s", session->scpRecv_response[0],
err_msg);
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Failed to recv file");
LIBSSH2_FREE(session, err_msg);
goto scp_recv_error;
}
@@ -513,13 +510,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
*(p++) = '\0';
/* Make sure we don't get fooled by leftover values */
errno = 0;
session->scpRecv_mtime = strtol((char *) s, NULL, 10);
if (errno) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid mtime");
goto scp_recv_error;
}
s = (unsigned char *) strchr((char *) p, ' ');
if (!s || ((s - p) <= 0)) {
/* No spaces or space in the wrong spot */
@@ -540,13 +532,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
*p = '\0';
/* Make sure we don't get fooled by leftover values */
errno = 0;
session->scpRecv_atime = strtol((char *) s, NULL, 10);
if (errno) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid atime");
goto scp_recv_error;
}
/* SCP ACK */
session->scpRecv_response[0] = '\0';
@@ -556,8 +542,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
if (session->scpRecv_state == libssh2_NB_state_sent3) {
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
session->scpRecv_response, 1);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting to send SCP ACK");
@@ -599,12 +584,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response");
return NULL;
} else if (rc <= 0) {
/* Timeout, give up */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Timed out waiting for SCP response");
}
else if (rc < 0) {
/* error, bail out*/
_libssh2_error(session, rc, "Failed reading SCP response");
goto scp_recv_error;
}
else if(rc == 0)
goto scp_recv_empty_channel;
session->scpRecv_response_len++;
if (session->scpRecv_response[0] != 'C') {
@@ -621,11 +609,9 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
scpRecv_response[session->scpRecv_response_len - 1] !=
'\n')
&&
((session->
scpRecv_response[session->scpRecv_response_len - 1] < 32)
|| (session->
scpRecv_response[session->scpRecv_response_len - 1] >
126))) {
(session->
scpRecv_response[session->scpRecv_response_len - 1]
< 32)) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid data in SCP response");
goto scp_recv_error;
@@ -679,9 +665,9 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
*(p++) = '\0';
/* Make sure we don't get fooled by leftover values */
errno = 0;
session->scpRecv_mode = strtol(s, &e, 8);
if ((e && *e) || errno) {
if (e && *e) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid mode");
goto scp_recv_error;
@@ -697,9 +683,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
*s = '\0';
/* Make sure we don't get fooled by leftover values */
errno = 0;
session->scpRecv_size = scpsize_strtol(p, &e, 10);
if ((e && *e) || errno) {
if (e && *e) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid size");
goto scp_recv_error;
@@ -713,8 +698,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
if (session->scpRecv_state == libssh2_NB_state_sent6) {
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
session->scpRecv_response, 1);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending SCP ACK");
@@ -747,8 +731,18 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
session->scpRecv_state = libssh2_NB_state_idle;
return session->scpRecv_channel;
scp_recv_empty_channel:
/* the code only jumps here as a result of a zero read from channel_read()
so we check EOF status to avoid getting stuck in a loop */
if(libssh2_channel_eof(session->scpRecv_channel))
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unexpected channel close");
else
return session->scpRecv_channel;
/* fall-through */
scp_recv_error:
while (libssh2_channel_free(session->scpRecv_channel) == LIBSSH2_ERROR_EAGAIN);
while (libssh2_channel_free(session->scpRecv_channel) ==
LIBSSH2_ERROR_EAGAIN);
session->scpRecv_channel = NULL;
session->scpRecv_state = libssh2_NB_state_idle;
return NULL;
@@ -869,12 +863,19 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from remote");
return NULL;
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
}
else if (rc < 0) {
_libssh2_error(session, rc, "SCP failure");
goto scp_send_error;
}
else if(!rc)
/* remain in the same state */
goto scp_send_empty_channel;
else if (session->scpSend_response[0] != 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
goto scp_send_error;
}
if (mtime || atime) {
/* Send mtime and atime to be used for file */
session->scpSend_response_len =
@@ -892,7 +893,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
if (mtime || atime) {
if (session->scpSend_state == libssh2_NB_state_sent2) {
rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response,
session->scpSend_response_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -915,9 +916,17 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response");
return NULL;
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
}
else if (rc < 0) {
_libssh2_error(session, rc, "SCP failure");
goto scp_send_error;
}
else if(!rc)
/* remain in the same state */
goto scp_send_empty_channel;
else if (session->scpSend_response[0] != 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
"Invalid SCP ACK response");
goto scp_send_error;
}
@@ -950,7 +959,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
if (session->scpSend_state == libssh2_NB_state_sent5) {
rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response,
session->scpSend_response_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -973,51 +982,57 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response");
return NULL;
} else if (rc <= 0) {
}
else if (rc < 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
goto scp_send_error;
} else if (session->scpSend_response[0] != 0) {
/*
* Set this as the default error for here, if
* we are successful it will be replaced
*/
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
}
else if (rc == 0)
goto scp_send_empty_channel;
session->scpSend_err_len =
else if (session->scpSend_response[0] != 0) {
size_t err_len;
char *err_msg;
err_len =
_libssh2_channel_packet_data_len(session->scpSend_channel, 0);
session->scpSend_err_msg =
LIBSSH2_ALLOC(session, session->scpSend_err_len + 1);
if (!session->scpSend_err_msg) {
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
if (!err_msg) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"failed to get memory");
goto scp_send_error;
}
memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
/* Read the remote error message */
rc = _libssh2_channel_read(session->scpSend_channel, 0,
session->scpSend_err_msg,
session->scpSend_err_len);
if (rc <= 0) {
/*
* Since we have alread started reading this packet, it is
* already in the systems so it can't return
* LIBSSH2_ERROR_EAGAIN
*/
LIBSSH2_FREE(session, session->scpSend_err_msg);
session->scpSend_err_msg = NULL;
err_msg, err_len);
if (rc > 0) {
err_msg[err_len]=0;
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"got %02x %s", session->scpSend_response[0],
err_msg);
}
else
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"failed waiting for ACK");
LIBSSH2_FREE(session, err_msg);
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"failed to send file");
goto scp_send_error;
}
}
session->scpSend_state = libssh2_NB_state_idle;
return session->scpSend_channel;
scp_send_empty_channel:
/* the code only jumps here as a result of a zero read from channel_read()
so we check EOF status to avoid getting stuck in a loop */
if(libssh2_channel_eof(session->scpSend_channel)) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unexpected channel close");
}
else
return session->scpSend_channel;
/* fall-through */
scp_send_error:
while (libssh2_channel_free(session->scpSend_channel) ==
LIBSSH2_ERROR_EAGAIN);

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009-2010 by Daniel Stenberg
* Copyright (c) 2009-2011 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
* All rights reserved.
*
@@ -55,6 +55,7 @@
#include "transport.h"
#include "session.h"
#include "channel.h"
#include "mac.h"
/* libssh2_default_alloc
*/
@@ -88,7 +89,8 @@ LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
*
* Wait for a hello from the remote host
* Allocate a buffer and store the banner in session->remote.banner
* Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative on failure
* Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative
* on failure
*/
static int
banner_receive(LIBSSH2_SESSION * session)
@@ -114,15 +116,18 @@ banner_receive(LIBSSH2_SESSION * session)
ret = _libssh2_recv(session->socket_fd, &c, 1,
LIBSSH2_SOCKET_RECV_FLAGS(session));
if (ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error recving %d bytes to %p: %d", 1, &c, errno);
if (ret < 0) {
if(session->api_block_mode || (ret != -EAGAIN))
/* ignore EAGAIN when non-blocking */
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error recving %d bytes: %d", 1, -ret);
}
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Recved %d bytes to %p", ret, &c);
"Recved %d bytes banner", ret);
if (ret < 0) {
if (errno == EAGAIN) {
if (ret == -EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_INBOUND;
session->banner_TxRx_total_send = banner_len;
@@ -132,19 +137,19 @@ banner_receive(LIBSSH2_SESSION * session)
/* Some kinda error */
session->banner_TxRx_state = libssh2_NB_state_idle;
session->banner_TxRx_total_send = 0;
return -1;
return LIBSSH2_ERROR_SOCKET_RECV;
}
if (ret == 0) {
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
return LIBSSH2_ERROR_SOCKET_NONE;
return LIBSSH2_ERROR_SOCKET_RECV;
}
if (c == '\0') {
/* NULLs are not allowed in SSH banners */
session->banner_TxRx_state = libssh2_NB_state_idle;
session->banner_TxRx_total_send = 0;
return -1;
return LIBSSH2_ERROR_BANNER_RECV;
}
session->banner_TxRx_banner[banner_len++] = c;
@@ -161,7 +166,7 @@ banner_receive(LIBSSH2_SESSION * session)
session->banner_TxRx_total_send = 0;
if (!banner_len)
return -1;
return LIBSSH2_ERROR_BANNER_RECV;
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
if (!session->remote.banner) {
@@ -172,7 +177,7 @@ banner_receive(LIBSSH2_SESSION * session)
session->remote.banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
session->remote.banner);
return 0;
return LIBSSH2_ERROR_NONE;
}
/*
@@ -180,9 +185,9 @@ banner_receive(LIBSSH2_SESSION * session)
*
* Send the default banner, or the one set via libssh2_setopt_string
*
* Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you should
* call this function again as soon as it is likely that more data can be
* sent, and this function should then be called with the same argument set
* Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you
* should call this function again as soon as it is likely that more data can
* be sent, and this function should then be called with the same argument set
* (same data pointer and same data_len) until zero or failure is returned.
*/
static int
@@ -228,7 +233,7 @@ banner_send(LIBSSH2_SESSION * session)
if (ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d",
banner_len - session->banner_TxRx_total_send, errno);
banner_len - session->banner_TxRx_total_send, -ret);
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Sent %d/%d bytes at %p+%d", ret,
@@ -236,16 +241,17 @@ banner_send(LIBSSH2_SESSION * session)
banner, session->banner_TxRx_total_send);
if (ret != (banner_len - session->banner_TxRx_total_send)) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
if (ret >= 0 || ret == -EAGAIN) {
/* the whole packet could not be sent, save the what was */
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
session->banner_TxRx_total_send += ret;
if (ret > 0)
session->banner_TxRx_total_send += ret;
return LIBSSH2_ERROR_EAGAIN;
}
session->banner_TxRx_state = libssh2_NB_state_idle;
session->banner_TxRx_total_send = 0;
return LIBSSH2_ERROR_SOCKET_NONE;
return LIBSSH2_ERROR_SOCKET_RECV;
}
/* Set the state back to idle */
@@ -410,16 +416,15 @@ get_socket_nonblocking(int sockfd)
LIBSSH2_API int
libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
{
int banner_len = banner ? strlen(banner) : 0;
size_t banner_len = banner ? strlen(banner) : 0;
if (session->local.banner) {
LIBSSH2_FREE(session, session->local.banner);
session->local.banner = NULL;
}
if (!banner_len) {
if (!banner_len)
return 0;
}
session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
if (!session->local.banner) {
@@ -556,6 +561,14 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session)
/* figure out what to wait for */
dir = libssh2_session_block_directions(session);
if(!dir) {
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Nothing to wait for in wait_socket");
/* To avoid that we hang below just because there's nothing set to
wait for, we timeout on 1 second to also avoid busy-looping
during this condition */
seconds_to_next = 1;
}
{
#ifdef HAVE_POLL
struct pollfd sockets[1];
@@ -621,7 +634,7 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
"session_startup for socket %d", sock);
if (INVALID_SOCKET == sock) {
/* Did we forget something? */
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE,
return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET,
"Bad socket provided");
}
session->socket_fd = sock;
@@ -647,11 +660,14 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
}
if (session->startup_state == libssh2_NB_state_sent) {
rc = banner_receive(session);
if (rc) {
return _libssh2_error(session, rc,
"Failed getting banner");
}
do {
session->banner_TxRx_state = libssh2_NB_state_idle;
rc = banner_receive(session);
if (rc)
return _libssh2_error(session, rc,
"Failed getting banner");
} while(strncmp("SSH-", (char *)session->remote.banner, 4));
session->startup_state = libssh2_NB_state_sent1;
}
@@ -680,8 +696,9 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
}
if (session->startup_state == libssh2_NB_state_sent3) {
rc = _libssh2_transport_write(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1);
rc = _libssh2_transport_send(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1,
NULL, 0);
if (rc) {
return _libssh2_error(session, rc,
"Unable to ask for ssh-userauth service");
@@ -722,16 +739,15 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
}
/*
* proto libssh2_session_startup
* libssh2_session_handshake()
*
* session: LIBSSH2_SESSION struct allocated and owned by the calling program
* sock: *must* be populated with an opened and connected socket.
*
* Returns: 0 on success, or non-zero on failure
* Any memory allocated by libssh2 will use alloc/realloc/free
* callbacks in session.
* The 'sock' socket *must* be populated with an opened and connected socket.
*/
LIBSSH2_API int
libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock)
{
int rc;
@@ -740,6 +756,23 @@ libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
return rc;
}
/*
* libssh2_session_startup()
*
* DEPRECATED. Use libssh2_session_handshake() instead! This function is not
* portable enough.
*
* session: LIBSSH2_SESSION struct allocated and owned by the calling program
* sock: *must* be populated with an opened and connected socket.
*
* Returns: 0 on success, or non-zero on failure
*/
LIBSSH2_API int
libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
{
return libssh2_session_handshake(session, (libssh2_socket_t) sock);
}
/*
* libssh2_session_free
*
@@ -753,7 +786,6 @@ session_free(LIBSSH2_SESSION *session)
LIBSSH2_PACKET *pkg;
LIBSSH2_CHANNEL *ch;
LIBSSH2_LISTENER *l;
struct transportpacket *p = &session->packet;
if (session->free_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource",
@@ -884,9 +916,6 @@ session_free(LIBSSH2_SESSION *session)
if (session->startup_data) {
LIBSSH2_FREE(session, session->startup_data);
}
if (session->disconnect_data) {
LIBSSH2_FREE(session, session->disconnect_data);
}
if (session->userauth_list_data) {
LIBSSH2_FREE(session, session->userauth_list_data);
}
@@ -944,12 +973,6 @@ session_free(LIBSSH2_SESSION *session)
if (session->scpSend_command) {
LIBSSH2_FREE(session, session->scpSend_command);
}
if (session->scpRecv_err_msg) {
LIBSSH2_FREE(session, session->scpRecv_err_msg);
}
if (session->scpSend_err_msg) {
LIBSSH2_FREE(session, session->scpSend_err_msg);
}
/* Cleanup all remaining packets */
while ((pkg = _libssh2_list_first(&session->packets))) {
@@ -961,11 +984,6 @@ session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, pkg);
}
/* Cleanup remaining outgoing packet buffer */
if (p->outbuf) {
LIBSSH2_FREE(session, p->outbuf);
}
if(session->socket_prev_blockstate)
/* if the socket was previously blocking, put it back so */
session_nonblock(session->socket_fd, 0);
@@ -1000,7 +1018,8 @@ libssh2_session_free(LIBSSH2_SESSION * session)
*/
static int
session_disconnect(LIBSSH2_SESSION *session, int reason,
const char *description, const char *lang)
const char *description,
const char *lang)
{
unsigned char *s;
unsigned long descr_len = 0, lang_len = 0;
@@ -1010,40 +1029,36 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Disconnecting: reason=%d, desc=%s, lang=%s", reason,
description, lang);
if (description) {
if (description)
descr_len = strlen(description);
}
if (lang) {
if (lang)
lang_len = strlen(lang);
}
if(descr_len > 256)
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"too long description");
/* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
session->disconnect_data_len = descr_len + lang_len + 13;
s = session->disconnect_data =
LIBSSH2_ALLOC(session, session->disconnect_data_len);
if (!session->disconnect_data) {
session->disconnect_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"disconnect packet");
}
s = session->disconnect_data;
*(s++) = SSH_MSG_DISCONNECT;
_libssh2_store_u32(&s, reason);
_libssh2_store_str(&s, description, descr_len);
_libssh2_store_str(&s, lang, lang_len);
/* store length only, lang is sent separately */
_libssh2_store_u32(&s, lang_len);
session->disconnect_state = libssh2_NB_state_created;
}
rc = _libssh2_transport_write(session, session->disconnect_data,
session->disconnect_data_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
rc = _libssh2_transport_send(session, session->disconnect_data,
session->disconnect_data_len,
(unsigned char *)lang, lang_len);
if (rc == LIBSSH2_ERROR_EAGAIN)
return rc;
}
LIBSSH2_FREE(session, session->disconnect_data);
session->disconnect_data = NULL;
session->disconnect_state = libssh2_NB_state_idle;
return 0;
@@ -1208,19 +1223,24 @@ libssh2_session_last_errno(LIBSSH2_SESSION * session)
*
* Set/Get session flags
*
* Passing flag==0 will avoid changing session->flags while still returning
* its current value
* Return error code.
*/
LIBSSH2_API int
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
{
if (value) {
session->flags |= flag;
} else {
session->flags &= ~flag;
switch(flag) {
case LIBSSH2_FLAG_SIGPIPE:
session->flag.sigpipe = value;
break;
case LIBSSH2_FLAG_COMPRESS:
session->flag.compress = value;
break;
default:
/* unknown flag */
return LIBSSH2_ERROR_INVAL;
}
return session->flags;
return LIBSSH2_ERROR_NONE;
}
/* _libssh2_session_set_blocking
@@ -1338,8 +1358,8 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
struct pollfd sockets[256];
if (nfds > 256)
/* systems without alloca use a fixed-size array, this can be fixed
if we really want to, at least if the compiler is a C99 capable one */
/* systems without alloca use a fixed-size array, this can be fixed if
we really want to, at least if the compiler is a C99 capable one */
return -1;
#endif
/* Setup sockets for polling */

1004
src/sftp.c

File diff suppressed because it is too large Load Diff

219
src/sftp.h Normal file
View File

@@ -0,0 +1,219 @@
#ifndef _LIBSSH2_SFP_H
#define _LIBSSH2_SFTP_H
/*
* Copyright (C) 2010 by Daniel Stenberg
* Author: Daniel Stenberg <daniel@haxx.se>
*
* 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.
*
*/
/*
* MAX_SFTP_OUTGOING_SIZE MUST not be larger than 32500 or so. This is the
* amount of data sent in each FXP_WRITE packet
*/
#define MAX_SFTP_OUTGOING_SIZE 30000
/* MAX_SFTP_READ_SIZE is how much data is asked for at max in each FXP_READ
* packets.
*/
#define MAX_SFTP_READ_SIZE 2000
struct sftp_pipeline_chunk {
struct list_node node;
size_t len; /* WRITE: size of the data to write
READ: how many bytes that was asked for */
size_t sent;
ssize_t lefttosend; /* if 0, the entire packet has been sent off */
uint32_t request_id;
unsigned char packet[1]; /* data */
};
#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#endif
struct _LIBSSH2_SFTP_PACKET
{
struct list_node node; /* linked list header */
uint32_t request_id;
unsigned char *data;
size_t data_len; /* payload size */
};
typedef struct _LIBSSH2_SFTP_PACKET LIBSSH2_SFTP_PACKET;
#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
struct _LIBSSH2_SFTP_HANDLE
{
struct list_node node;
LIBSSH2_SFTP *sftp;
char handle[SFTP_HANDLE_MAXLEN];
size_t handle_len;
enum {
LIBSSH2_SFTP_HANDLE_FILE,
LIBSSH2_SFTP_HANDLE_DIR
} handle_type;
union _libssh2_sftp_handle_data
{
struct _libssh2_sftp_handle_file_data
{
libssh2_uint64_t offset;
libssh2_uint64_t offset_sent;
size_t acked; /* container for acked data that hasn't been
returned to caller yet, used for sftp_write */
/* 'data' is used by sftp_read() and is allocated data that has
been received already from the server but wasn't returned to
the caller yet. It is of size 'data_len' and 'data_left is the
number of bytes not yet returned, counted from the end of the
buffer. */
unsigned char *data;
size_t data_len;
size_t data_left;
char eof; /* we have read to the end */
} file;
struct _libssh2_sftp_handle_dir_data
{
uint32_t names_left;
void *names_packet;
char *next_name;
} dir;
} u;
/* State variables used in libssh2_sftp_close_handle() */
libssh2_nonblocking_states close_state;
uint32_t close_request_id;
unsigned char *close_packet;
/* list of outstanding packets sent to server */
struct list_head packet_list;
};
struct _LIBSSH2_SFTP
{
LIBSSH2_CHANNEL *channel;
uint32_t request_id, version;
struct list_head packets;
/* a list of _LIBSSH2_SFTP_HANDLE structs */
struct list_head sftp_handles;
uint32_t last_errno;
/* Holder for partial packet, use in libssh2_sftp_packet_read() */
unsigned char partial_size[4]; /* buffer for size field */
size_t partial_size_len; /* size field length */
unsigned char *partial_packet; /* The data */
uint32_t partial_len; /* Desired number of bytes */
size_t partial_received; /* Bytes received so far */
/* Time that libssh2_sftp_packet_requirev() started reading */
time_t requirev_start;
/* State variables used in libssh2_sftp_open_ex() */
libssh2_nonblocking_states open_state;
unsigned char *open_packet;
uint32_t open_packet_len; /* 32 bit on the wire */
size_t open_packet_sent;
uint32_t open_request_id;
/* State variables used in libssh2_sftp_read() */
libssh2_nonblocking_states read_state;
unsigned char *read_packet;
uint32_t read_request_id;
size_t read_total_read;
/* State variables used in libssh2_sftp_readdir() */
libssh2_nonblocking_states readdir_state;
unsigned char *readdir_packet;
uint32_t readdir_request_id;
/* State variables used in libssh2_sftp_fstat_ex() */
libssh2_nonblocking_states fstat_state;
unsigned char *fstat_packet;
uint32_t fstat_request_id;
/* State variables used in libssh2_sftp_unlink_ex() */
libssh2_nonblocking_states unlink_state;
unsigned char *unlink_packet;
uint32_t unlink_request_id;
/* State variables used in libssh2_sftp_rename_ex() */
libssh2_nonblocking_states rename_state;
unsigned char *rename_packet;
unsigned char *rename_s;
uint32_t rename_request_id;
/* State variables used in libssh2_sftp_fstatvfs() */
libssh2_nonblocking_states fstatvfs_state;
unsigned char *fstatvfs_packet;
uint32_t fstatvfs_request_id;
/* State variables used in libssh2_sftp_statvfs() */
libssh2_nonblocking_states statvfs_state;
unsigned char *statvfs_packet;
uint32_t statvfs_request_id;
/* State variables used in libssh2_sftp_mkdir() */
libssh2_nonblocking_states mkdir_state;
unsigned char *mkdir_packet;
uint32_t mkdir_request_id;
/* State variables used in libssh2_sftp_rmdir() */
libssh2_nonblocking_states rmdir_state;
unsigned char *rmdir_packet;
uint32_t rmdir_request_id;
/* State variables used in libssh2_sftp_stat() */
libssh2_nonblocking_states stat_state;
unsigned char *stat_packet;
uint32_t stat_request_id;
/* State variables used in libssh2_sftp_symlink() */
libssh2_nonblocking_states symlink_state;
unsigned char *symlink_packet;
uint32_t symlink_request_id;
};
#endif

View File

@@ -42,10 +42,14 @@
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#ifdef LIBSSH2DEBUG
#include <stdio.h>
#endif
#include <assert.h>
#include "transport.h"
#include "mac.h"
#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */
#define MAX_MACSIZE 20 /* MUST fit biggest MAC length we support */
@@ -54,7 +58,7 @@
#define UNPRINTABLE_CHAR '.'
static void
debugdump(LIBSSH2_SESSION * session,
const char *desc, unsigned char *ptr, size_t size)
const char *desc, const unsigned char *ptr, size_t size)
{
size_t i;
size_t c;
@@ -74,7 +78,7 @@ debugdump(LIBSSH2_SESSION * session,
(session->tracehandler)(session, session->tracehandler_context,
buffer, used);
else
write(2 /* stderr */, buffer, used);
fprintf(stderr, "%s", buffer);
for(i = 0; i < size; i += width) {
@@ -110,7 +114,7 @@ debugdump(LIBSSH2_SESSION * session,
(session->tracehandler)(session, session->tracehandler_context,
buffer, used);
else
write(2, buffer, used);
fprintf(stderr, "%s", buffer);
}
}
#else
@@ -138,7 +142,7 @@ decrypt(LIBSSH2_SESSION * session, unsigned char *source,
if (session->remote.crypt->crypt(session, source,
&session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, p->payload);
return LIBSSH2_ERROR_SOCKET_NONE;
return LIBSSH2_ERROR_DECRYPT;
}
/* if the crypt() function would write to a given address it
@@ -196,49 +200,28 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
/* Check for and deal with decompression */
if (session->remote.comp &&
strcmp(session->remote.comp->name, "none")) {
session->remote.comp->compress &&
session->remote.comp_abstract) {
/*
* The buffer for the decompression (remote.comp_abstract) is
* initialised in time when it is needed so as long it is NULL we
* cannot decompress.
*/
unsigned char *data;
size_t data_len;
int free_payload = 1;
rc = session->remote.comp->decomp(session,
&data, &data_len,
LIBSSH2_PACKET_MAXDECOMP,
p->payload,
session->fullpacket_payload_len,
&session->remote.comp_abstract);
LIBSSH2_FREE(session, p->payload);
if(rc)
return rc;
if (session->remote.comp->comp(session, 0,
&data, &data_len,
LIBSSH2_PACKET_MAXDECOMP,
&free_payload,
p->payload,
session->fullpacket_payload_len,
&session->remote.comp_abstract)) {
LIBSSH2_FREE(session, p->payload);
return LIBSSH2_ERROR_SOCKET_NONE;
}
if (free_payload) {
LIBSSH2_FREE(session, p->payload);
p->payload = data;
session->fullpacket_payload_len = data_len;
} else {
if (data == p->payload) {
/* It's not to be freed, because the
* compression layer reused payload, So let's
* do the same!
*/
session->fullpacket_payload_len = data_len;
} else {
/* No comp_method actually lets this happen,
* but let's prepare for the future */
LIBSSH2_FREE(session, p->payload);
/* We need a freeable struct otherwise the
* brigade won't know what to do with it */
p->payload = LIBSSH2_ALLOC(session, data_len);
if (!p->payload)
return LIBSSH2_ERROR_ALLOC;
memcpy(p->payload, data, data_len);
session->fullpacket_payload_len = data_len;
}
}
p->payload = data;
session->fullpacket_payload_len = data_len;
}
session->fullpacket_packet_type = p->payload[0];
@@ -280,7 +263,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
*/
int _libssh2_transport_read(LIBSSH2_SESSION * session)
{
int rc = LIBSSH2_ERROR_SOCKET_NONE;
int rc;
struct transportpacket *p = &session->packet;
int remainbuf;
int remainpack;
@@ -289,6 +272,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
unsigned char block[MAX_BLOCKSIZE];
int blocksize;
int encrypted = 1;
size_t total_num;
/* default clear the bit */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
@@ -376,25 +360,22 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
_libssh2_recv(session->socket_fd, &p->buf[remainbuf],
PACKETBUFSIZE - remainbuf,
LIBSSH2_SOCKET_RECV_FLAGS(session));
if (nread < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error recving %d bytes to %p+%d: %d",
PACKETBUFSIZE - remainbuf, p->buf, remainbuf,
errno);
else
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Recved %d/%d bytes to %p+%d", nread,
PACKETBUFSIZE - remainbuf, p->buf, remainbuf);
if (nread <= 0) {
/* check if this is due to EAGAIN and return the special
return code if so, error out normally otherwise */
if ((nread < 0) && (errno == EAGAIN)) {
if ((nread < 0) && (nread == -EAGAIN)) {
session->socket_block_directions |=
LIBSSH2_SESSION_BLOCK_INBOUND;
return LIBSSH2_ERROR_EAGAIN;
}
return LIBSSH2_ERROR_SOCKET_NONE;
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error recving %d bytes (got %d)",
PACKETBUFSIZE - remainbuf, -nread);
return LIBSSH2_ERROR_SOCKET_RECV;
}
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Recved %d/%d bytes to %p+%d", nread,
PACKETBUFSIZE - remainbuf, p->buf, remainbuf);
debugdump(session, "libssh2_transport_read() raw",
&p->buf[remainbuf], nread);
@@ -445,13 +426,13 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
*/
p->packet_length = _libssh2_ntohu32(block);
if (p->packet_length < 1)
return LIBSSH2_ERROR_SOCKET_NONE;
return LIBSSH2_ERROR_DECRYPT;
p->padding_length = block[4];
/* total_num is the number of bytes following the initial
(5 bytes) packet length and padding length fields */
p->total_num =
total_num =
p->packet_length - 1 +
(encrypted ? session->remote.mac->mac_len : 0);
@@ -463,16 +444,17 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
* or less (including length, padding length, payload,
* padding, and MAC.)."
*/
if (p->total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
if (total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
/* Get a packet handle put data into. We get one to
hold all data, including padding and MAC. */
p->payload = LIBSSH2_ALLOC(session, p->total_num);
p->payload = LIBSSH2_ALLOC(session, total_num);
if (!p->payload) {
return LIBSSH2_ERROR_ALLOC;
}
p->total_num = total_num;
/* init write pointer to start of payload buffer */
p->wptr = p->payload;
@@ -597,32 +579,18 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
}
} while (1); /* loop */
return LIBSSH2_ERROR_SOCKET_NONE; /* we never reach this point */
}
/*
* _libssh2_transport_drain() empties the outgoing send buffer if there
* is any.
*/
void _libssh2_transport_drain(LIBSSH2_SESSION * session)
{
struct transportpacket *p = &session->packet;
if(p->outbuf) {
LIBSSH2_FREE(session, p->outbuf);
p->outbuf = NULL;
p->ototal_num = 0;
}
return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */
}
static int
send_existing(LIBSSH2_SESSION * session, unsigned char *data,
size_t data_len, ssize_t * ret)
send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
size_t data_len, ssize_t *ret)
{
ssize_t rc;
ssize_t length;
struct transportpacket *p = &session->packet;
if (!p->outbuf) {
if (!p->olen) {
*ret = 0;
return LIBSSH2_ERROR_NONE;
}
@@ -646,29 +614,31 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_SOCKET_SEND_FLAGS(session));
if (rc < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d", length, errno);
else
"Error sending %d bytes: %d", length, -rc);
else {
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Sent %d/%d bytes at %p+%d", rc, length, p->outbuf,
p->osent);
if(rc > 0) {
debugdump(session, "libssh2_transport_write send()",
&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;
p->olen = 0;
/* we leave *ret set so that the parent returns as we MUST return back
a send success now, so that we don't risk sending EAGAIN later
which then would confuse the parent function */
return LIBSSH2_ERROR_NONE;
}
else if (rc < 0) {
/* nothing was sent */
if (errno != EAGAIN) {
if (rc != -EAGAIN)
/* send failure! */
return LIBSSH2_ERROR_SOCKET_NONE;
}
return LIBSSH2_ERROR_SOCKET_SEND;
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
return LIBSSH2_ERROR_EAGAIN;
}
@@ -679,48 +649,50 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
}
/*
* libssh2_transport_write
* libssh2_transport_send
*
* Send a packet, encrypting it and adding a MAC code if necessary
* Returns 0 on success, non-zero on failure.
*
* Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you should
* call this function again as soon as it is likely that more data can be
* sent, and this function should then be called with the same argument set
* (same data pointer and same data_len) until zero or failure is returned.
* The data is provided as _two_ data areas that are combined by this
* function. The 'data' part is sent immediately before 'data2'. 'data2' may
* be set to NULL to only use a single part.
*
* 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)
* Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was
* not sent yet. If it does so, the caller should call this function again as
* soon as it is likely that more data can be sent, and this function MUST
* then be called with the same argument set (same data pointer and same
* data_len) until ERROR_NONE or failure is returned.
*
* This function DOES not call _libssh2_error() on any errors.
* This function DOES NOT call _libssh2_error() on any errors.
*/
int
_libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
size_t data_len)
int _libssh2_transport_send(LIBSSH2_SESSION *session,
const unsigned char *data, size_t data_len,
const unsigned char *data2, size_t data2_len)
{
int blocksize =
(session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->
blocksize : 8;
(session->state & LIBSSH2_STATE_NEWKEYS) ?
session->local.crypt->blocksize : 8;
int padding_length;
int packet_length;
size_t packet_length;
int total_length;
int free_data = 0;
#ifdef RANDOM_PADDING
int rand_max;
int seed = data[0]; /* FIXME: make this random */
#endif
struct transportpacket *p = &session->packet;
int encrypted;
int i;
ssize_t ret;
int rc;
unsigned char *orgdata = data;
const unsigned char *orgdata = data;
size_t orgdata_len = data_len;
debugdump(session, "libssh2_transport_write plain", data, data_len);
if(data2)
debugdump(session, "libssh2_transport_write plain2", data2, data2_len);
/* FIRST, check if we have a pending write to complete */
/* FIRST, check if we have a pending write to complete. send_existing
only sanity-check data and data_len and not data2 and data2_len!! */
rc = send_existing(session, data, data_len, &ret);
if (rc)
return rc;
@@ -728,19 +700,56 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
if (ret)
/* set by send_existing if data was sent */
return rc;
encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
/* check if we should compress */
if (encrypted && strcmp(session->local.comp->name, "none")) {
if (session->local.comp->comp(session, 1, &data, &data_len,
LIBSSH2_PACKET_MAXCOMP,
&free_data, data, data_len,
&session->local.comp_abstract)) {
return LIBSSH2_ERROR_COMPRESS; /* compression failure */
if (encrypted && session->local.comp->compress) {
/* the idea here is that these function must fail if the output gets
larger than what fits in the assigned buffer so thus they don't
check the input size as we don't know how much it compresses */
size_t dest_len = MAX_SSH_PACKET_LEN-5-256;
size_t dest2_len = dest_len;
/* compress directly to the target buffer */
rc = session->local.comp->comp(session,
&p->outbuf[5], &dest_len,
data, data_len,
&session->local.comp_abstract);
if(rc)
return rc; /* compression failure */
if(data2 && data2_len) {
/* compress directly to the target buffer right after where the
previous call put data */
dest2_len -= dest_len;
rc = session->local.comp->comp(session,
&p->outbuf[5+dest_len], &dest2_len,
data2, data2_len,
&session->local.comp_abstract);
}
else
dest2_len = 0;
if(rc)
return rc; /* compression failure */
data_len = dest_len + dest2_len; /* use the combined length */
}
else {
if((data_len + data2_len) >= (MAX_SSH_PACKET_LEN-0x100))
/* too large packet, return error for this until we make this
function split it up and send multiple SSH packets */
return LIBSSH2_ERROR_INVAL;
/* copy the payload data */
memcpy(&p->outbuf[5], data, data_len);
if(data2 && data2_len)
memcpy(&p->outbuf[5+data_len], data2, data2_len);
data_len += data2_len; /* use the combined length */
}
/* RFC4253 says: Note that the length of the concatenation of
'packet_length', 'padding_length', 'payload', and 'random padding'
@@ -781,28 +790,18 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
total_length =
packet_length + (encrypted ? session->local.mac->mac_len : 0);
/* allocate memory to store the outgoing packet in, in case we can't
send the whole one and thus need to keep it after this function
returns. */
p->outbuf = LIBSSH2_ALLOC(session, total_length);
if (!p->outbuf) {
return LIBSSH2_ERROR_ALLOC;
}
/* store packet_length, which is the size of the whole packet except
the MAC and the packet_length field itself */
_libssh2_htonu32(p->outbuf, packet_length - 4);
/* store padding_length */
p->outbuf[4] = padding_length;
/* copy the payload data */
memcpy(p->outbuf + 5, data, data_len);
/* fill the padding area with random junk */
_libssh2_random(p->outbuf + 5 + data_len, padding_length);
if (free_data) {
LIBSSH2_FREE(session, data);
}
if (encrypted) {
size_t i;
/* Calculate MAC hash. Put the output at index packet_length,
since that size includes the whole packet. The MAC is
calculated on the entire unencrypted packet, including all
@@ -818,7 +817,7 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
unsigned char *ptr = &p->outbuf[i];
if (session->local.crypt->crypt(session, ptr,
&session->local.crypt_abstract))
return LIBSSH2_ERROR_SOCKET_NONE; /* encryption failure */
return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */
}
}
@@ -828,32 +827,29 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_SOCKET_SEND_FLAGS(session));
if (ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d", total_length, errno);
else
"Error sending %d bytes: %d", total_length, -ret);
else {
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p",
ret, total_length, p->outbuf);
if (ret != -1) {
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
}
if (ret != total_length) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
if (ret >= 0 || ret == -EAGAIN) {
/* the whole packet could not be sent, save the rest */
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
p->odata = orgdata;
p->olen = orgdata_len;
p->osent = (ret == -1) ? 0 : ret;
p->osent = ret <= 0 ? 0 : ret;
p->ototal_num = total_length;
return LIBSSH2_ERROR_EAGAIN;
}
return LIBSSH2_ERROR_SOCKET_NONE;
return LIBSSH2_ERROR_SOCKET_SEND;
}
/* the whole thing got sent away */
p->odata = NULL;
p->olen = 0;
LIBSSH2_FREE(session, p->outbuf);
p->outbuf = NULL;
return LIBSSH2_ERROR_NONE; /* all is good */
}

View File

@@ -44,23 +44,29 @@
#include "libssh2_priv.h"
#include "packet.h"
/*
* libssh2_transport_write
* libssh2_transport_send
*
* Send a packet, encrypting it and adding a MAC code if necessary
* Returns 0 on success, non-zero on failure.
*
* Returns PACKET_EAGAIN if it would block - and if it does so, you should
* call this function again as soon as it is likely that more data can be
* sent, and this function should then be called with the same argument set
* (same data pointer and same data_len) until zero or failure is returned.
* The data is provided as _two_ data areas that are combined by this
* function. The 'data' part is sent immediately before 'data2'. 'data2' can
* be set to NULL (or data2_len to 0) to only use a single part.
*
* 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)
* Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was
* not sent yet. If it does so, the caller should call this function again as
* soon as it is likely that more data can be sent, and this function MUST
* then be called with the same argument set (same data pointer and same
* data_len) until ERROR_NONE or failure is returned.
*
* This function DOES NOT call _libssh2_error() on any errors.
*/
int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
size_t data_len);
int _libssh2_transport_send(LIBSSH2_SESSION *session,
const unsigned char *data, size_t data_len,
const unsigned char *data2, size_t data2_len);
/*
* _libssh2_transport_read
*
@@ -78,10 +84,4 @@ int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
*/
int _libssh2_transport_read(LIBSSH2_SESSION * session);
/*
* _libssh2_transport_drain() empties the outgoing send buffer if there
* is any.
*/
void _libssh2_transport_drain(LIBSSH2_SESSION *session);
#endif /* __LIBSSH2_TRANSPORT_H */

View File

@@ -1,6 +1,6 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net>
* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2009-2010 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -66,7 +66,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
static const unsigned char reply_codes[3] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
/* packet_type(1) + username_len(4) + service_len(4) +
service(14)"ssh-connection" + method_len(4) + method(4)"none" */
service(14)"ssh-connection" + method_len(4) = 27 */
unsigned long methods_len;
unsigned char *s;
int rc;
@@ -76,7 +76,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
memset(&session->userauth_list_packet_requirev_state, 0,
sizeof(session->userauth_list_packet_requirev_state));
session->userauth_list_data_len = username_len + 31;
session->userauth_list_data_len = username_len + 27;
s = session->userauth_list_data =
LIBSSH2_ALLOC(session, session->userauth_list_data_len);
@@ -89,14 +89,15 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
*(s++) = SSH_MSG_USERAUTH_REQUEST;
_libssh2_store_str(&s, username, username_len);
_libssh2_store_str(&s, "ssh-connection", 14);
_libssh2_store_str(&s, "none", 4);
_libssh2_store_u32(&s, 4); /* send "none" separately */
session->userauth_list_state = libssh2_NB_state_created;
}
if (session->userauth_list_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_list_data,
session->userauth_list_data_len);
rc = _libssh2_transport_send(session, session->userauth_list_data,
session->userauth_list_data_len,
(unsigned char *)"none", 4);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting userauth list");
@@ -178,12 +179,12 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user,
* libssh2_userauth_authenticated
*
* Returns: 0 if not yet authenticated
* non-zero is already authenticated
* 1 if already authenticated
*/
LIBSSH2_API int
libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
{
return session->state & LIBSSH2_STATE_AUTHENTICATED;
return (session->state & LIBSSH2_STATE_AUTHENTICATED)?1:0;
}
@@ -192,9 +193,9 @@ libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
* Plain ol' login
*/
static int
userauth_password(LIBSSH2_SESSION *session, const char *username,
unsigned int username_len, const char *password,
unsigned int password_len,
userauth_password(LIBSSH2_SESSION *session,
const char *username, unsigned int username_len,
const unsigned char *password, unsigned int password_len,
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
{
unsigned char *s;
@@ -213,10 +214,12 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
* 40 = acket_type(1) + username_len(4) + service_len(4) +
* service(14)"ssh-connection" + method_len(4) + method(8)"password" +
* chgpwdbool(1) + password_len(4) */
session->userauth_pswd_data_len = username_len + password_len + 40;
session->userauth_pswd_data_len = username_len + 40;
session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;
/* TODO: remove this alloc with a fixed buffer in the session
struct */
s = session->userauth_pswd_data =
LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
if (!session->userauth_pswd_data) {
@@ -230,7 +233,8 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
_libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1);
_libssh2_store_str(&s, "password", sizeof("password") - 1);
*s++ = '\0';
_libssh2_store_str(&s, password, password_len);
_libssh2_store_u32(&s, password_len);
/* 'password' is sent separately */
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Attempting to login using password authentication");
@@ -239,8 +243,9 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
}
if (session->userauth_pswd_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_pswd_data,
session->userauth_pswd_data_len);
rc = _libssh2_transport_send(session, session->userauth_pswd_data,
session->userauth_pswd_data_len,
password, password_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block writing password request");
@@ -335,8 +340,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
/* basic data_len + newpw_len(4) */
session->userauth_pswd_data_len =
username_len + password_len + 44 +
session->userauth_pswd_newpw_len;
username_len + password_len + 44;
s = session->userauth_pswd_data =
LIBSSH2_ALLOC(session,
@@ -358,18 +362,21 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
_libssh2_store_str(&s, "password",
sizeof("password") - 1);
*s++ = 0x01;
_libssh2_store_str(&s, password, password_len);
_libssh2_store_str(&s, session->userauth_pswd_newpw,
_libssh2_store_str(&s, (char *)password, password_len);
_libssh2_store_u32(&s,
session->userauth_pswd_newpw_len);
/* send session->userauth_pswd_newpw separately */
session->userauth_pswd_state = libssh2_NB_state_sent2;
}
if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_write(session,
session->userauth_pswd_data,
session->
userauth_pswd_data_len);
rc = _libssh2_transport_send(session,
session->userauth_pswd_data,
session->userauth_pswd_data_len,
(unsigned char *)
session->userauth_pswd_newpw,
session->userauth_pswd_newpw_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting");
@@ -429,7 +436,7 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
int rc;
BLOCK_ADJUST(rc, session,
userauth_password(session, username, username_len,
password, password_len,
(unsigned char *)password, password_len,
passwd_change_cb));
return rc;
}
@@ -648,13 +655,25 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
memset(&session->userauth_host_packet_requirev_state, 0,
sizeof(session->userauth_host_packet_requirev_state));
rc = file_read_publickey(session, &session->userauth_host_method,
&session->userauth_host_method_len,
&pubkeydata, &pubkeydata_len,
publickey);
if(rc)
/* Note: file_read_publickey() calls _libssh2_error() */
return rc;
if (publickey) {
rc = file_read_publickey(session, &session->userauth_host_method,
&session->userauth_host_method_len,
&pubkeydata, &pubkeydata_len, publickey);
if(rc)
/* Note: file_read_publickey() calls _libssh2_error() */
return rc;
}
else {
/* Compute public key from private key. */
if (_libssh2_pub_priv_keyfile(session,
&session->userauth_host_method,
&session->userauth_host_method_len,
&pubkeydata, &pubkeydata_len,
privatekey, passphrase))
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Unable to extract public key "
"from private key file");
}
/*
* 52 = packet_type(1) + username_len(4) + servicename_len(4) +
@@ -776,9 +795,10 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
}
if (session->userauth_host_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_host_packet,
session->userauth_host_s -
session->userauth_host_packet);
rc = _libssh2_transport_send(session, session->userauth_host_packet,
session->userauth_host_s -
session->userauth_host_packet,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
}
@@ -924,7 +944,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
else if (session->userauth_pblc_method_len !=
_libssh2_ntohu32(pubkeydata))
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Invalid public key");
"Invalid public key");
/*
* 45 = packet_type(1) + username_len(4) + servicename_len(4) +
@@ -937,9 +957,13 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
45;
/*
* Preallocate space for an overall length, method name again, and
* the signature, which won't be any larger than the size of the
* publickeydata itself
* Preallocate space for an overall length, method name again, and the
* signature, which won't be any larger than the size of the
* publickeydata itself.
*
* Note that the 'pubkeydata_len' extra bytes allocated here will not
* be used in this first send, but will be used in the later one where
* this same allocation is re-used.
*/
s = session->userauth_pblc_packet =
LIBSSH2_ALLOC(session,
@@ -965,6 +989,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
_libssh2_store_str(&s, (const char *)session->userauth_pblc_method,
session->userauth_pblc_method_len);
_libssh2_store_str(&s, (const char *)pubkeydata, pubkeydata_len);
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Attempting publickey authentication");
@@ -972,8 +997,9 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
}
if (session->userauth_pblc_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
session->userauth_pblc_packet_len);
rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
session->userauth_pblc_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN)
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
else if (rc) {
@@ -1006,7 +1032,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_method = NULL;
session->userauth_pblc_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Failed waiting");
"Waiting for USERAUTH response");
}
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
@@ -1049,7 +1075,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
}
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
unsigned char *buf, *s;
unsigned char *buf;
unsigned char *sig;
size_t sig_len;
@@ -1130,9 +1156,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
}
if (session->userauth_pblc_state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
session->userauth_pblc_s -
session->userauth_pblc_packet);
rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
session->userauth_pblc_s -
session->userauth_pblc_packet,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
} else if (rc) {
@@ -1161,7 +1188,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
} else if (rc) {
session->userauth_pblc_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Failed waiting");
"Waiting for publickey USERAUTH response");
}
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
@@ -1206,11 +1233,24 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
privkey_file.passphrase = passphrase;
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
rc = file_read_publickey(session, &session->userauth_pblc_method,
&session->userauth_pblc_method_len,
&pubkeydata, &pubkeydata_len, publickey);
if(rc)
return rc;
if (publickey) {
rc = file_read_publickey(session, &session->userauth_pblc_method,
&session->userauth_pblc_method_len,
&pubkeydata, &pubkeydata_len,publickey);
if(rc)
return rc;
}
else {
/* Compute public key from private key. */
if (_libssh2_pub_priv_keyfile(session,
&session->userauth_pblc_method,
&session->userauth_pblc_method_len,
&pubkeydata, &pubkeydata_len,
privatekey, passphrase))
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Unable to extract public key "
"from private key file");
}
}
rc = _libssh2_userauth_publickey(session, username, username_len,
@@ -1348,8 +1388,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
}
if (session->userauth_kybd_state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len);
rc = _libssh2_transport_send(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
} else if (rc) {
@@ -1380,7 +1421,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_state = libssh2_NB_state_idle;
return _libssh2_error(session,
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
"Failed waiting");
"Waiting for keyboard USERAUTH response");
}
if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
@@ -1551,8 +1592,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
}
if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len);
rc = _libssh2_transport_send(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len,
NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block");
@@ -1595,6 +1637,10 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_prompts = NULL;
LIBSSH2_FREE(session, session->userauth_kybd_responses);
session->userauth_kybd_responses = NULL;
LIBSSH2_FREE(session, session->userauth_kybd_auth_name);
session->userauth_kybd_auth_name = NULL;
LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
session->userauth_kybd_auth_instruction = NULL;
if (session->userauth_kybd_auth_failure) {
session->userauth_kybd_state = libssh2_NB_state_idle;
@@ -1622,4 +1668,3 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session,
response_callback));
return rc;
}

View File

@@ -35,12 +35,12 @@ RC = wrc
!endif
!if $(__VERSION__) < 1250
RM = del /q /f >NUL 2>&1
RM = del /q /f 2>NUL
!else
RM = rm -f
!endif
MD = mkdir
RD = rmdir /q /s >NUL 2>&1
RD = rmdir /q /s 2>NUL
CP = copy
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=nul -w2 -fpi -oilrtfm &
@@ -70,7 +70,7 @@ ZLIB_ROOT = ..\..\zlib-1.2.5
!ifdef %openssl_root
OPENSSL_ROOT = $(%openssl_root)
!else
OPENSSL_ROOT = ..\..\openssl-0.9.8o
OPENSSL_ROOT = ..\..\openssl-0.9.8q
!endif
#!ifdef %use_zlib

View File

@@ -16,7 +16,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.8o
OPENSSL_PATH = ../../openssl-0.9.8q
endif
# Edit the path below to point to your Distribution folder.
@@ -65,6 +65,7 @@ else
endif
CP = cp -afv
# RM = rm -f
MD = mkdir
# Here you can find a native Win32 binary of the original awk:
# http://www.gknw.net/development/prgtools/awk-20070501.zip
AWK = awk
@@ -98,7 +99,7 @@ LIBEXT = a
RANLIB = $(CROSSPREFIX)ranlib
#LDLIBS += -lwsock32
LDLIBS += -lws2_32
RCFLAGS = -O coff -i
RCFLAGS = -DLIBSSH2_VERSION_ONLY -I. -I ../include -O coff -i
CFLAGS += -fno-strict-aliasing
CFLAGS += -Wall # -pedantic
endif
@@ -123,7 +124,8 @@ ifeq ($(findstring /sh,$(SHELL)),/sh)
DL = '
DS = /
else
DS = \\
XX =
DS = $(XX)\$(XX)
endif
vpath %.c . ../src
@@ -198,13 +200,13 @@ clean:
-$(RM) -r $(OBJDIR)
$(OBJDIR):
@mkdir $@
@$(MD) $@
$(DISTDIR):
@mkdir $@
@$(MD) $@
$(DEVLDIR):
@mkdir $@
@$(MD) $@
$(TARGET).$(LIBEXT): $(OBJS)
@echo Creating $@
@@ -222,7 +224,7 @@ $(TARGET).dll $(TARGET)dll.a: $(OBJL)
$(OBJDIR)/%.res: %.rc
@echo Creating $@
@$(RC) $(RCFLAGS) -DLIBSSH2_VERSION_ONLY -I. -I ../include $< -o $@
@$(RC) $(RCFLAGS) $< -o $@
$(DISTDIR)/readme.txt: Makefile.win32

View File

@@ -1,7 +1,7 @@
# Tweak these for your system
OPENSSLINC=..\openssl-0.9.8o\inc32
OPENSSLLIB=..\openssl-0.9.8o\out32dll
OPENSSLINC=..\openssl-0.9.8q\inc32
OPENSSLLIB=..\openssl-0.9.8q\out32dll
ZLIBINC=-DLIBSSH2_HAVE_ZLIB=1 /I..\zlib-1.2.5
ZLIBLIB=..\zlib-1.2.5

View File

@@ -14,7 +14,7 @@ endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../../openssl-0.9.8o
OPENSSL_PATH = ../../../openssl-0.9.8q
endif
# Edit the var below to enable static linking of libssh2 and libz