Compare commits

...

306 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
Daniel Stenberg
8d9d3e0d7a release: updated to hold 1.2.7 info 2010-08-17 23:10:54 +02:00
Guenter Knauf
c46abb2663 Use the new libssh2.rc file. 2010-08-17 01:58:39 +02:00
Guenter Knauf
0a34fa79f0 Added resource file for libssh2.dll (shamelessly stolen from libcurl). 2010-08-17 01:54:20 +02:00
Guenter Knauf
43001570d6 Updated Win32 MSVC dependencies versions. 2010-08-17 01:35:55 +02:00
Guenter Knauf
4b878e7cf8 Added include for sys/select.h to get fd.set on some platforms. 2010-08-17 01:34:32 +02:00
Guenter Knauf
ac709e0d4f Added Watcom makefile borrowed from libcurl.
This makefile compiles already all files fine for static lib, but needs
final touch when I have OpenSSL fully working with shared libs and Watcom.
2010-08-16 16:10:07 +02:00
Guenter Knauf
56d0877f07 Added copyright define to libssh2.h and use it for binary builds. 2010-08-15 04:09:01 +02:00
Guenter Knauf
51a8335486 Moved version defines up in order to include from .rc file.
Blocked rest of header with ifndef so its possible to let
the rc compiler only use the version defines.
2010-08-15 03:38:49 +02:00
Guenter Knauf
2bd9418ac7 Some minor makefile tweaks. 2010-08-14 21:56:37 +02:00
Daniel Stenberg
4b8013a8a7 example: treat the libssh2_channel_read() return code properly
A short read is not an error. Only negative values are errors!
2010-08-02 00:20:24 +02:00
Daniel Stenberg
697b4e8ed7 libssh2_wait_socket: reset error code to "leak" EAGAIN less
Since libssh2 often sets LIBSSH2_ERROR_EAGAIN internally before
_libssh2_wait_socket is called, we can decrease some amount of
confusion in user programs by resetting the error code in this function
to reduce the risk of EAGAIN being stored as error when a blocking
function returns.
2010-07-18 19:47:21 +02:00
Daniel Stenberg
2afa5b2dc2 _libssh2_wait_socket: poll needs milliseconds
As reported on the mailing list, the code path using poll() should
multiple seconds with 1000 to get milliseconds, not divide!

Reported by: Jan Van Boghout
2010-07-17 19:20:20 +02:00
Daniel Stenberg
992aff7aca typedef: make ssize_t get typedef without LIBSSH2_WIN32
The condition around the ssize_t typedef depended on both LIBSSH2_WIN32
*and* _MSC_VER being defined when it should be enough to depend on
_MSC_VER only. It also makes it nicer so libssh2-using code builds fine
without having custom defines.
2010-07-06 16:17:59 +02:00
John Little
ef4c8718c2 session_free: free more data to avoid memory leaks 2010-07-01 19:56:06 +02:00
Daniel Stenberg
c375e5e5ad channel_free: ignore problems with channel_close()
As was pointed out in bug #182, we must not return failure from
_libssh2_channel_free() when _libssh2_channel_close() returns an error
that isn't EAGAIN. It can effectively cause the function to never go
through, like it did now in the case where the socket was actually
closed but socket_state still said LIBSSH2_SOCKET_CONNECTED.

I consider this fix the right thing as it now also survives other
errors, even if making sure socket_state isn't lying is also a good
idea.
2010-06-30 22:47:22 +02:00
Daniel Stenberg
46be03f92b publickey_list_free: no return value from a void function
Fixed a compiler warning I introduced previously when checking input
arguments more. I also added a check for the other pointer to avoid NULL
pointer dereferences.
2010-06-30 15:43:31 +02:00
Lars Nordin
1d83b520b4 openssl: make use of the EVP interface
Make use of the EVP interface for the AES-funktion. Using this method
supports the use of different ENGINES in OpenSSL for the AES function
(and the direct call to the AES_encrypt should not be used according to
openssl.org)
2010-06-27 22:23:50 +02:00
Tor Arntsen
f9c0a4a95a Don't overflow MD5 server hostkey
Use SHA_DIGEST_LENGTH and MD5_DIGEST_LENGTH in memcpy instead of hardcoded
values. An incorrect value was used for MD5.
2010-06-23 11:31:04 +02:00
Peter Stuge
7861ae8e4e Fix message length bugs in libssh2_debug()
There was a buffer overflow waiting to happen when a debug message was
longer than 1536 bytes.

Thanks to Daniel who spotted that there was a problem with the message
length passed to a trace handler also after commit
0f0652a309.
2010-06-23 11:16:02 +02:00
Peter Stuge
0f0652a309 Make libssh2_debug() create a correctly terminated string
Also use FILE *stderr rather than fd 2, which can very well be something
completely different.
2010-06-23 10:48:29 +02:00
TJ Saunders
2cc4a629ac handshake: Compression enabled at the wrong time
In KEXINIT messages, the client and server agree on, among other
things, whether to use compression. This method agreement occurs
in src/kex.c's kex_agree_methods() function. However, if
compression is enabled (either client->server, server->client, or
both), then the compression layer is initialized in
kex_agree_methods() -- before NEWKEYS has been received.

Instead, the initialization of the compression layer should
happen after NEWKEYS has been received. This looks to occur
insrc/kex.c's diffie_hellman_sha1(), which even has the comment:

    /* The first key exchange has been performed,

        switch to active crypt/comp/mac mode */

There, after NEWKEYS is received, the cipher and mac algorithms
are initialized, and that is where the compression should be
initialized as well.

The current implementation fails if server->client compression is
enabled because most server implementations follow OpenSSH's
lead, where compression is initialized after NEWKEYS. Since the
server initializes compression after NEWKEYS, but libssh2
initializes compression after KEXINIT (i.e. before NEWKEYS), they
are out of sync.

Reported in bug report #180
2010-06-23 00:03:31 +02:00
TJ Saunders
04f90b2265 userauth_hostbased_fromfile: packet length too short
The packet length calculated in src/userauth.c's
userauth_hostbased_fromfile() function is too short by 4 bytes;
it forgets to add four bytes for the length of the hostname.
This causes hostbased authentication to fail, since the server
will read junk data.

verified against proftpd's mod_sftp module
2010-06-22 23:34:21 +02:00
Daniel Stenberg
7dc2bfac94 _libssh2_userauth_publickey: reject method names longer than the data
This functions get the method length by looking at the first 32
bit of data, and I now made it not accept method lengths that are
longer than the whole data set is, as given in the dedicated
function argument.

This was detected when the function was given bogus public key
data as an ascii string, which caused the first 32bits to create
a HUGE number.
2010-06-20 00:23:28 +02:00
Daniel Stenberg
35cf08e130 NULL resistance: make more public functions survive NULL pointer input
Sending in NULL as the primary pointer is now dealt with by more
public functions. I also narrowed the userauth.c code somewhat to
stay within 80 columns better.
2010-06-18 20:25:03 +02:00
Daniel Stenberg
32bd0df992 agent: make libssh2_agent_userauth() work blocking properly
previously it would always work in a non-blocking manner
2010-06-18 20:13:08 +02:00
Peter Stuge
38940f45d2 Fix underscore typo for 64-bit printf format specifiers on Windows
Commit 49ddf447ff was missing underscores.
2010-06-17 12:23:25 +02:00
Daniel Stenberg
537a00ee4b libssh2_session_callback_set: extended the man page 2010-06-16 00:12:24 +02:00
John
6ddcc493e8 LIBSSH2_DEBUG: macro uses incorrect function variable
The LIBSSH2_DEBUG macro, defined in libssh2_priv.h, incorrectly uses the
function variable ssh_msg_disconnect when it should use ssh_msg_debug.

This shows that the LIBSSH2_CALLBACK_DEBUG callback never has worked...
2010-06-16 00:04:25 +02:00
Daniel Stenberg
3496e1c2a2 warning: fix a compiler warning 'pointer differs in signedness'
As reported in bug #177
2010-06-15 19:51:26 +02:00
Daniel Stenberg
49ddf447ff portability: introduce LIBSSH2_INT64_T_FORMAT for 64bit printf()s
As pointed out in bug #177, some of the Windows compilers use
%I64 to output 64 bit variables with the printf family.
2010-06-15 19:47:31 +02:00
Daniel Stenberg
04d4bbb66b debug: avoid sending NULL to sprintf %s
Via the _libssh2_debug() macro/function. Pointed out by john in bug report
2010-06-15 17:00:02 +02:00
Daniel Stenberg
897f8463d8 sftp docs: show macro on macro page, only function on function page
The individual man pages for macros now show the full convenience
macro as defined, and then the man page for the actual function
only shows the function.
2010-06-14 20:04:29 +02:00
Daniel Stenberg
2fd044fdf5 code police: make the code use less than 80 columns 2010-06-14 17:23:00 +02:00
Daniel Stenberg
20e969d2e0 libssh2_channel_write_ex: remove macros, added wording on buffer size 2010-06-13 17:00:43 +02:00
Daniel Stenberg
33e2bc8785 libssh2_sftp_write: document buffer size and changed some ordering 2010-06-13 17:00:14 +02:00
Daniel Stenberg
d7e6f9cf27 libssh2_channel_write_stderr: show how the macro is defined 2010-06-13 16:59:40 +02:00
Daniel Stenberg
be7cee1b3e libssh2_channel_write: show how the macro is defined 2010-06-13 16:59:18 +02:00
Daniel Stenberg
518d25eba1 SFTP: limit write() to not produce overly large packets
sftp_write() now limits how much data it gets at a time even more
than before. Since this function creates a complete outgoing
packet based on what gets passed to it, it is crucial that it
doesn't create too large packets.

With this method, there's also no longer any problem to use very
large buffers in your application and feed that to libssh2. I've
done numerous tests now with uploading data over SFTP using 100K
buffers and I've had no problems with that.
2010-06-11 16:07:30 +02:00
Daniel Stenberg
1785d0d6f3 scp_write_nonblock: add transfer time info
Using the same timing logic and output format as
sftp_write_nonblock allows us to very easily run benchmarks on
SCP vs SFTP uploads using libssh2.
2010-06-11 16:05:22 +02:00
Daniel Stenberg
31d71a94f2 sftp_write_nonblock: select() on socket, use *BIG* buffer, time transfer
The select() is just to make it nicer so that it doesn't
crazy-loop on EAGAIN. The buffer size thing is mostly to verify
that this really work as supposed.

Transfer timing is just a minor thing, but it can just as well be
there and help us time and work on performance easier using out
of the box examples.
2010-06-11 16:03:33 +02:00
Daniel Stenberg
22a2de7347 agent: use _libssh2_error() when returning errors
As pointed out in bug report #173, this module basically never
used _libssh2_error() which made it work inconstently with other
parts of the libssh2 code base. This is my first take at making
this code more in line with the rest.
2010-06-11 13:32:41 +02:00
Daniel Stenberg
4cf935abab inputchecks: make lots of API functions check for NULL pointers
If an application accidentally provides a NULL handle pointer to
the channel or sftp public functions, they now return an error
instead of segfaulting.
2010-06-11 13:05:55 +02:00
Daniel Stenberg
cce6ebbee7 libssh2_channel_eof: clarify that it returns negative on errors 2010-06-11 13:02:00 +02:00
Daniel Stenberg
18605cb81f SFTP: keep the sftp error code as 32 bit
'last_errno' holds to the error code from the SFTP protocol and
since that is 32 bits on the wire there's no point in using a
long for this internally which is larger on some platforms.
2010-06-11 13:00:31 +02:00
Daniel Stenberg
3490b3fe10 agent: make the code better deal with unexpected code flows
agent->ops gets initialized by the libssh2_agent_connect() call
but we need to make sure that we don't segfault even if a bad
sequence of function calls is used.
2010-06-11 11:13:46 +02:00
Alexander Lamaison
c87a48ae4c Better handling of invalid key files.
Passing an invalid public key to libssh2_userauth_publickey_fromfile_ex
triggered an assertion.  Replaced this with a runtime check that rejects
obviously invalid key data.
2010-06-10 12:25:26 +01:00
Daniel Stenberg
ab8ee8abf3 version: we start working on 1.2.7 now 2010-06-10 10:31:18 +02:00
Daniel Stenberg
6e40af7bea NEWS: add the 1.2.6 release details 2010-06-10 10:19:31 +02:00
Daniel Stenberg
5e46c864dc RELEASE-NOTES: 1.2.6 details added 2010-06-10 10:15:46 +02:00
Guenter Knauf
a4fdf0de01 fixed libssh2.dsw to use the generated libssh2.dsp; removed old *.dsp files. 2010-06-10 02:43:49 +02:00
Guenter Knauf
2c1c751ad1 moved MSVC strdup define to libssh2_config.h which we include already. 2010-06-10 02:31:48 +02:00
Guenter Knauf
f682684fdd added missing source files to src/NMakefile. 2010-06-10 02:28:47 +02:00
Daniel Stenberg
0ad1a52a09 libssh2_poll: refer to poll(3) and select(3) instead 2010-06-08 08:37:37 +02:00
Daniel Stenberg
4e10882e06 example: fix strdup() for MSVC compiles
MSVC has a _strdup() that we better use. This was reported in bug
2010-06-07 13:36:12 +02:00
Daniel Stenberg
eeeebd02e7 SFTP: fail init SFTP if session isn't authenticated
Alexander Lamaison filed bug #172
(http://trac.libssh2.org/ticket/172), and pointed out that SFTP
init would do bad if the session isn't yet authenticated at the
time of the call, so we now check for this situation and returns
an error if detected. Calling sftp_init() at this point is bad
usage to start with.
2010-06-07 13:10:51 +02:00
Daniel Stenberg
f285438022 direct_tcpip: bring back inclusion of libssh2_config.h
In order to increase portability of this example, I'm bringing
the inclusion of libssh2_config.h back, and I also added an
require that header for this example to compile.

I also made all code lines fit within 80 columns.
2010-06-03 13:55:54 +02:00
Guenter Knauf
81912f67e7 cast away a warning. 2010-06-03 05:21:02 +02:00
Guenter Knauf
2996e02482 moved CRT_SECURE_NO_DEPRECATE define up so its defined before the winsock headers are included. 2010-06-03 03:12:20 +02:00
Guenter Knauf
2683fddcca fixed platform detection for MingW32 test makefile. 2010-06-01 21:19:14 +02:00
Guenter Knauf
fa5d6c705d MingW32 has gettimeofday() implemented, so proper ifdef this function here. 2010-06-01 21:09:08 +02:00
Guenter Knauf
b6c6470e7e removed MSVC ifdef since seems we can use __int64 still with latest headers. 2010-06-01 20:24:05 +02:00
Guenter Knauf
dceb3d1452 changed copyright notice for MinW32 and NetWare binaries. 2010-06-01 20:17:05 +02:00
Guenter Knauf
86c935317c cleaned up MSVC ifdefs which where spreaded over 3 places. 2010-06-01 19:32:11 +02:00
Guenter Knauf
aad74b7fa6 added uint8_t typedef for NetWare CLIB platform. 2010-06-01 19:08:19 +02:00
Guenter Knauf
0b593c8a9d if the function declaration gets changed the header should be changed too. 2010-06-01 17:28:46 +02:00
Guenter Knauf
8ff3f62786 this is MSVC specific and doesnt apply for all Win32 compilers;
the uint8_t typedef clashes with MingW32 headers.
2010-06-01 17:15:46 +02:00
Guenter Knauf
4d7b2950d9 updated MingW32 makefiles for latest dependency lib versions. 2010-06-01 16:58:40 +02:00
Guenter Knauf
18569d76de updated NetWare makefiles for latest dependency lib versions. 2010-06-01 16:44:17 +02:00
Dan Fandrich
7a088a8ab7 Fixed compiling with libgcrypt
A change of parameter types from unsigned long to size_t was
missed in the prototype in libgcrypt.h
2010-05-30 22:53:53 -07:00
Daniel Stenberg
d15663477b statvfs: use libssh2_sftp_statvfs only, no "_ex"
As the long-term goal is to get rid of the extensive set of
macros from the API we can just as well start small by not adding
new macros when we add new functions. Therefore we let the
function be libssh2_sftp_statvfs() plainly without using an _ex
suffix.

I also made it use size_t instead of unsigned int for the string
length as that too is a long-term goal for the API.
2010-05-28 17:25:42 +02:00
Grubsky Grigory
8145f9e79c DSP: output lib name typo 2010-05-25 23:28:01 +02:00
Grubsky Grigory
dc747fb221 win32: provide a uint8_t typedef for better building on windows 2010-05-25 23:22:39 +02:00
Daniel Stenberg
76fd96e63e agent: win32: fix bad _libssh2_store_str call
As pointed out by Grubsky Grigory <g.grubsky@securitycode.ru>, I
made a mistake when I added the _libssh2_store_str() call before
and I made a slightly different patch than what he suggested.
Based purely on taste.
2010-05-25 23:19:46 +02:00
Joey Degges
ed526a0e24 Add libssh2_sftp_statvfs() and libssh2_sftp_fstatvfs()
These can be used to get file system statistics from servers that
support the statvfs@openssh.com and fstatvfs@openssh.com extensions.
2010-05-24 07:05:23 +02:00
Jose Baars
667f4acda6 VMS specific: make sure final release can be installed over daily build 2010-05-22 11:06:08 +01:00
Jose Baars
f3208b99ca VMS: small improvement to the man2help utilities 2010-05-22 11:05:29 +01:00
Joey Degges
b702441242 libssh2_exit and libssh2_sftp_readdir man page fixes 2010-05-22 08:30:42 +02:00
Daniel Stenberg
396dcedc56 spelling: s/sue/use 2010-05-21 23:37:43 +02:00
Alexander Lamaison
798a808a2b Change magic port number for generic knownhost check.
libssh2_knownhost_checkp took 0 as a magic port number that indicated
a 'generic' check should be performed.  However, 0 is a valid port
number in its own right so this commit changes the magic value to any
negative int.
2010-05-21 00:01:57 +01:00
Mikhail Gusarov
c8df661129 Add re-discovered copyright holders to COPYING 2010-05-05 15:45:17 +07:00
Mikhail Gusarov
b3ed8e064a Restoring copyright statements from pre-git era
Eli Fant has contributed fragmenting SFTP requests
2010-05-05 15:44:15 +07:00
Mikhail Gusarov
ffb55aa2a3 Restoring my copyright statements from pre-git era
keyboard_interactive, 'exit-status' information packet, non-atomic read/write
under FreeBSD, multi-channel operation bugfixes.
2010-05-05 15:41:19 +07:00
Daniel Stenberg
9251642ef3 pedantic: make the code C90 clean 2010-05-03 22:16:01 +02:00
Peter Stuge
79b97c67c7 Do proper keyboard-interactive user dialog in the sftp.c example 2010-05-03 15:36:16 +02:00
Daniel Stenberg
b23ae2bf22 added to tarball: libssh2_knownhost_checkp.3 2010-05-03 09:45:53 +02:00
Daniel Stenberg
a3f3347c12 knownhost: support [host]:port in knownhost file
OpenSSH has ways to add hosts to the knownhosts file that include
a specific port number which makes the key associated with only
that specific host+port pair. libssh2 previously did not support
this, and I was forced to add a new function to the API to
properly expose this ability to applications:
libssh2_knownhost_checkp()

To *add* such hosts to the knownhosts file, you make sure to pass
on the host name in that manner to the libssh2_knownhost_addc()
function.
2010-05-02 16:56:31 +02:00
Daniel Stenberg
5184aec461 init/exit: mention these were added in 1.2.5 2010-05-01 23:49:45 +02:00
Daniel Stenberg
358aa3e24b libssh2_knownhost_check docs: correct the prototype 2010-05-01 23:35:16 +02:00
Daniel Stenberg
7bbefe0660 examples: avoid use of uninitialized variable 'sock' 2010-04-30 12:30:24 +02:00
Daniel Stenberg
204100e636 KEX: stop pretending we negotiate language
There was some stub-like parts of an implementation for
implementing kex language negotiation that caused clang-analyzer
to warn and as it did nothing I've now removed the dead code.
2010-04-29 23:57:47 +02:00
Daniel Stenberg
6c85370428 Uninitialized argument 2010-04-29 22:01:32 +02:00
Daniel Stenberg
23f02aad11 sftpdir: removed dead assignment 2010-04-29 22:00:05 +02:00
Daniel Stenberg
eb7581e72e Makefile.am: include the VMS-specific config header as well 2010-04-29 20:28:56 +02:00
Jose Baars
a16d67e250 Add VMS specific libssh2_config.h 2010-04-29 20:28:02 +02:00
Daniel Stenberg
ab81b75a8e fix Value stored to 's' is never read warning
and moved variable declaration of s to be more local
2010-04-28 23:28:26 +02:00
Daniel Stenberg
0c918ef72a kexinit: simplify the code and avoid scan-build warning
Previously it would say "Value stored to 's' is never read" due
fourth increment of 's'.
2010-04-28 23:28:26 +02:00
Alexander Lamaison
6c3f2ec815 Removed unecessary brackets. 2010-04-28 17:41:17 +01:00
Alexander Lamaison
f1df0b7fbc Changed sftp_attrsize macro to a static function. 2010-04-28 17:38:00 +01:00
Daniel Stenberg
6f895e3298 release: include the VMS-specific files 2010-04-28 13:28:54 +02:00
Daniel Stenberg
45210d8376 sftp_attrsize: protect the macro argument with proper parentheses 2010-04-28 10:23:40 +02:00
Daniel Stenberg
6a44eff0b5 ssh2_agent: avoid using 'session' uninitialized on failures 2010-04-28 09:13:22 +02:00
Daniel Stenberg
0862a1a39a examples: remove assignments of variable rc that's never used 2010-04-28 09:05:19 +02:00
Daniel Stenberg
514f4d9305 publickey_init: remove useless variable increment 2010-04-28 08:59:17 +02:00
Daniel Stenberg
d5d80d296a hostkey_method_ssh_rsa_init: remove useless variable increment 2010-04-28 08:57:56 +02:00
Daniel Stenberg
568060d266 packet_x11_open: removed useless variable increment
and made the declaration of a variable more local
2010-04-28 08:48:50 +02:00
Daniel Stenberg
6e2a0e603a packet_queue_listener: removed useless variable increment
and made the declaration of a variable more local
2010-04-28 08:47:30 +02:00
Daniel Stenberg
d811478071 sftp_read: move a read_responses array to where its used
I find that this increases readability since the array is used
only in the function call just immediately below and nowhere
else.
2010-04-28 00:39:23 +02:00
Daniel Stenberg
b979af1eee sftp_readdir: turn a small array static const and move it 2010-04-28 00:38:22 +02:00
Daniel Stenberg
37624b61e3 sftp_attrsize: converted function to a macro
This way, the macro can evaluate a static number at compile time
for two out of four uses, and it probably runs faster for the
other two cases too.
2010-04-28 00:23:09 +02:00
Daniel Stenberg
4c26a46362 sftp_open: deal with short channel_write calls
This was an old TODO that just wasn't done before. If
channel_write returns short, that is not an error.
2010-04-28 00:12:47 +02:00
Daniel Stenberg
77efca961d sftp_open: clean up, better check of input data
The clang-analyzer report made it look into this function and
I've went through it to remove a potential use of an
uninitialized variable and I also added some validation of input
data received from the server.

In general, lots of more code in this file need to validate the
input before assuming it is correct: there are servers out there
that have bugs or just have another idea of how to do the SFTP
protocol.
2010-04-27 23:59:55 +02:00
Daniel Stenberg
c28fa65424 bugfix: avoid using the socket if it failed to create one 2010-04-27 15:18:40 +02:00
Daniel Stenberg
03815483be bugfix: potential use of NULL pointer 2010-04-27 15:10:48 +02:00
Daniel Stenberg
67de62d650 libssh2_userauth_password_ex: clarify errors somewhat
The errors mentioned in this man page are possible return codes
but not necessarily the only return codes that this can return.

Also reformatted the typ prototypes somewhat.
2010-04-26 22:28:36 +02:00
Daniel Stenberg
cb42be1a9c examples: fixed and made them more similar
The channel read/write functions can return 0 in legitimate cases
without it being an error, and we need to loop properly if they
return short.
2010-04-26 16:49:30 +02:00
Jose Baars
c511177d39 VMS port of libssh2; changes in the libssh2 common code 2010-04-25 19:57:45 +02:00
Daniel Stenberg
d4edb0b9c3 Makefile: added the two news headers userauth.h and session.h 2010-04-25 19:52:36 +02:00
Daniel Stenberg
71fb9cc93e cleanup: prefer the internal functions
To get the blocking vs non-blocking to work as smooth as possible
and behave better internally, we avoid using the external
interfaces when calling functions internally.

Renamed a few internal functions to use _libssh2 prefix when not
being private within a file, and removed the libssh2_ for one
that was private within the file.
2010-04-25 19:35:43 +02:00
Daniel Stenberg
5163e4ecb8 session_free: remove dead code 2010-04-25 19:35:43 +02:00
Daniel Stenberg
000b0f73d0 libssh2_publickey_init: fixed to work better non-blocking
This was triggered by a clang-analyzer complaint that turned out
to be valid, and it made me dig deeper and fix some generic non-
blocking problems I disovered in the code.

While cleaning this up, I moved session-specific stuff over to a
new session.h header from the libssh2_priv.h header.
2010-04-25 19:35:43 +02:00
Daniel Stenberg
c5602fac58 channel: reduce duplicated free and returns
Simplified the code by trying to free data and return on a single
spot.
2010-04-25 19:35:43 +02:00
Daniel Stenberg
046ff03c3f channel: make variables more local
By making 'data' and 'data_len' more local in several places in
this file it will be easier to spot how they are used and we'll
get less risks to accidentally do bad things with them.
2010-04-25 19:35:43 +02:00
Mikhail Gusarov
d06f983c9c Fix typos in manpages, catched by Lintian 2010-04-24 23:43:07 +07:00
Daniel Stenberg
8620cc03f8 channel_request_pty: simplify the code
clang-analyzer pointed out how 'data' could be accessed as a NULL
pointer if the wrong state was set, and while I don't see that
happen in real-life the code flow is easier to read and follow by
moving the LIBSSH2_FREE() call into the block that is supposed to
deal with the data pointer anyway.
2010-04-24 13:14:12 +02:00
Daniel Stenberg
21f55d0006 libssh2_channel_process_startup: simplify the code
clang-analyzer pointed out how 'data' could be accessed as a NULL
pointer if the wrong state was set, and while I don't see that
happen in real-life the code flow is easier to read and follow by
moving the LIBSSH2_FREE() call into the block that is supposed to
deal with the data pointer anyway.
2010-04-24 13:11:05 +02:00
Daniel Stenberg
88ac2dd43c sftp_close_handle: add precation to not access NULL pointer
clang-analyzer pointed this out as a "Pass-by-value argument in
function call is undefined" but while I can't see exactly how
this can ever happen in reality I think a little check for safety
isn't such a bad thing here.
2010-04-24 13:03:27 +02:00
Daniel Stenberg
26d1698320 scp_write_nonblock: Value stored to 'nread' is never read 2010-04-24 12:58:34 +02:00
Daniel Stenberg
7dfeadef97 scp_write: Value stored to 'ptr' is never read 2010-04-24 12:57:32 +02:00
Daniel Stenberg
5804444936 scp_write_nonblock: Value stored to 'ptr' is never read 2010-04-24 12:56:53 +02:00
Daniel Stenberg
ee5dd3561d sftp_mkdir: less silly output but show failures 2010-04-24 12:56:13 +02:00
Jose Baars
ad1ec1c9e4 VMS port of libssh2 including VMS specific build procedures 2010-04-24 10:11:27 +02:00
Daniel Stenberg
28ef62be20 two variable types changes, made lines less than 80 columns
The two variable type changes are only to match type variable
fields actually read from the binary protocol.
2010-04-20 22:49:32 +02:00
Daniel Stenberg
1acca6e3ee remove check for negative padding_length
It was silly, since it is read as an unsigned char...
2010-04-20 22:48:40 +02:00
Daniel Stenberg
d3a0f2932b hostkey_method_ssh_dss_init: Value stored to 's' is never read 2010-04-18 15:31:46 +02:00
Daniel Stenberg
7adc23a628 libssh2_banner_set: avoid unnecessary increment and explain code 2010-04-18 15:30:03 +02:00
Daniel Stenberg
fca949ea55 agent_transact_unix: remove unused variable 2010-04-18 15:27:47 +02:00
Daniel Stenberg
f8b42cab86 remove two unnecessary increments 2010-04-18 15:26:41 +02:00
Daniel Stenberg
fea133f8d6 more code converted to use _libssh2_store_*() 2010-04-18 15:24:13 +02:00
Daniel Stenberg
9ba30d888e libssh2_publickey_list_fetch: removed unused variables 2010-04-18 15:20:29 +02:00
Daniel Stenberg
5d37cd44aa libssh2_publickey_init: remove unused variables 2010-04-18 15:18:18 +02:00
Daniel Stenberg
be9ee7095e libssh2_scp_send64: added to API to provide large file transfers
The previously existing libssh2_scp_send_ex() function has no way
to send files that are larger than 'size_t' which on 32bit
systems mean 4GB. This new API uses a libssh2_int64_t type and
should thus on most modern systems be able to send enormous
files.
2010-04-17 19:47:50 +02:00
Daniel Stenberg
9209309bc3 sftp_init: remove unused variables and assignments 2010-04-17 19:05:53 +02:00
Daniel Stenberg
2a069503be libssh2_knownhost_check: Value stored to 'keylen' is never read 2010-04-17 19:02:44 +02:00
Daniel Stenberg
182108ac91 hostkey: fix compiler warning 2010-04-17 13:38:20 +02:00
Daniel Stenberg
21a01c96f8 remove unused variable 2010-04-17 13:38:07 +02:00
Daniel Stenberg
100059989f data types: convert more to use size_t and uint32_t 2010-04-17 13:34:44 +02:00
Daniel Stenberg
13caffa00e channel: variable type cleanups 2010-04-17 13:27:17 +02:00
Daniel Stenberg
c3bcdd88a4 cleanups: better binary packet gen, size_t fixes and PACKET_* removal
I'll introduce a new internal function set named

 _libssh2_store_u32
 _libssh2_store_u64
 _libssh2_store_str

That can be used all through the library to build binary outgoing
packets.  Using these instead of the current approach removes
hundreds of lines from the library while at the same time greatly
enhances readability. I've not yet fully converted everything to
use these functions.

I've converted LOTS of 'unsigned long' to 'size_t' where
data/string lengths are dealt with internally. This is The Right
Thing and it will help us make the transition to our
size_t-polished API later on as well.

I'm removing the PACKET_* error codes. They were originally
introduced as a set of separate error codes from the transport
layer, but having its own set of errors turned out to be very
awkward and they were then converted into a set of #defines that
simply maps them to the global libssh2 error codes instead. Now,
I'l take the next logical step and simply replace the PACKET_*
defines with the actual LIBSSH2_ERROR_* defines. It will increase
readability and decrease confusion.

I also separated packet stuff into its own packet.h header file.
2010-04-17 13:18:15 +02:00
Daniel Stenberg
81e63b3657 clarified the return code 2010-04-17 09:55:24 +02:00
Daniel Stenberg
1adcb5234f rename libssh2_error to the correct _libssh2_error
We reserve ^libssh2_ for public symbols and we use _libssh2 as
prefix for internal ones. I fixed the intendation of all these
edits with emacs afterwards, which then changed it slightly more
than just _libssh2_error() expressions but I didn't see any
obvious problems.
2010-04-16 00:18:51 +02:00
Daniel Stenberg
9cc824e27b data type cleanup: made lots of code use size_t etc
A lot of code used 'unsigned long' and the likes when it should
rather just use plain 'int' or use size_t for data lengths.
2010-04-15 20:37:46 +02:00
Daniel Stenberg
2f9c105ec2 wait_socket: make c89 compliant and use two fd_sets for select() 2010-04-15 11:02:41 +02:00
Daniel Stenberg
8ab009c0b0 sftp_readdir: always zero terminate, detail the return code
I also added a description for the 'longentry' field which was
previously undocumented!
2010-04-15 01:16:02 +02:00
Daniel Stenberg
e22cdcea77 sftp_readdir: simplified and bugfixed
This function no longer has any special purpose code for the
single entry case, as it was pointless.

The previous code would overflow the buffers with an off-by-one
in case the file name or longentry data fields received from the
server were exactly as long as the buffer provided to
libssh2_sftp_readdir_ex.

We now make sure that libssh2_sftp_readdir_ex() ALWAYS zero
terminate the buffers it fills in.

The function no longer calls the libssh2_* function again, but
properly uses the internal sftp_* instead.
2010-04-15 01:15:35 +02:00
Daniel Stenberg
7f740368f4 channel/transport: we now drain the outgoing send buffer when we ignore EAGAIN
When we ignore the EAGAIN from the transport layer within channel_write, we
now drain the outgoing transport layer buffer so that remainders in that
won't cause any problems in the next invoke of _libssh2_transport_write()
2010-04-15 01:12:22 +02:00
Daniel Stenberg
8b63dc9e59 channel_write: if data has been sent, don't return EAGAIN
When sending data in a loop, we must not return EAGAIN if we
managed to send data in an earlier round. This was reported in
bug #126 => http://libssh2.stuge.se/ticket/126
2010-04-14 23:35:40 +02:00
Simon Josefsson
77fa740674 Fix OpenSSL AES-128-CTR detection.
Patch from Paul Howarth <paul@city-fan.org>.
2010-04-14 14:04:45 +02:00
Daniel Stenberg
32cf14b512 version in header file now says 1.2.6-DEV 2010-04-13 23:39:39 +02:00
Daniel Stenberg
44cd934fa2 1.2.6: clean the RELEASE-NOTES for next release round 2010-04-13 23:38:21 +02:00
Daniel Stenberg
339ad5ccd3 NEWS: add the stuff from the version 1.2.5 RELEASE-NOTES 2010-04-13 23:37:47 +02:00
126 changed files with 10123 additions and 5936 deletions

View File

@@ -1,5 +1,7 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2005,2006 Mikhail Gusarov <dottedmag@dottedmag.net>
* Copyright (c) 2006-2007 The Written Word, Inc.
* Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
* Copyright (c) 2009 Daniel Stenberg
* Copyright (C) 2008, 2009 Simon Josefsson
* All rights reserved.

View File

@@ -21,13 +21,19 @@ VCPROJ = win32/libssh2.vcproj
DISTCLEANFILES = $(DSP)
VMSFILES = vms/libssh2_make_example.dcl vms/libssh2_make_help.dcl \
vms/libssh2_make_kit.dcl vms/libssh2_make_lib.dcl vms/man2help.c \
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
maketgz NMakefile TODO RELEASE-NOTES libssh2.pc.in $(VMSFILES)
ACLOCAL_AMFLAGS = -I m4

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
comp.h mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h

710
NEWS
View File

@@ -1,709 +1,3 @@
o Use poll instead of select when available. By Paul Querna.
The old NEWS file.
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,33 +1,44 @@
libssh2 1.2.5
libssh2 1.2.8
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
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 fix memory leak in libssh2_session_startup()
o added missing error codes - shown as hangs in blocking mode
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 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 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:
Peter Stuge, Simon Josefsson, Alexander Lamaison, Paul Querna, Suyog Jadhav,
Lars Nordin
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)

135
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"?
@@ -9,13 +12,13 @@ Things TODO
lib, like when libssh2_session_last_error() is asked to return the string
with 'want_buf' set to non-zero.
* Provide a libssh2_scp_send() API for files larger than 4GB (32bit size)
* Add more info to the man pages.
* Decrease the number of mallocs. Everywhere.
* 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
@@ -23,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
===================
@@ -40,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:
@@ -54,3 +65,119 @@ At next SONAME bump
* remove the existing libssh2_knownhost_add() function and rename
libssh2_knownhost_addc to become the new libssh2_knownhost_add instead
* remove the existing libssh2_scp_send_ex() function and rename
libssh2_scp_send64 to become the new libssh2_scp_send instead.
* 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)
@@ -115,7 +115,7 @@ AM_CONDITIONAL(LIBGCRYPT, test "$ac_cv_libgcrypt" = "yes")
if test "$ac_cv_libssl" = "yes"; then
save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $LIBSSL"
AC_CHECK_FUNCS(EVP_aes128_ctr)
AC_CHECK_FUNCS(EVP_aes_128_ctr)
LDFLAGS="$save_LDFLAGS"
fi
@@ -295,7 +295,7 @@ AC_MSG_NOTICE([summary of build options:
Compiler: ${CC}
Compiler flags: ${CFLAGS}
Library types: Shared=${enable_shared}, Static=${enable_static}
Crypto library: openssl: ${ac_cv_libssl:-no} (AES-CTR: ${ac_cv_func_EVP_aes128_ctr:-N/A}) libgcrypt: ${ac_cv_libgcrypt:-no}
Crypto library: openssl: ${ac_cv_libssl:-no} (AES-CTR: ${ac_cv_func_EVP_aes_128_ctr:-N/A}) libgcrypt: ${ac_cv_libgcrypt:-no}
Debug build: $enable_debug
Path to sshd: $ac_cv_path_SSHD (only for self-tests)
libz compression: $ac_cv_libz

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 \
@@ -66,6 +68,7 @@ dist_man_MANS = \
libssh2_knownhost_add.3 \
libssh2_knownhost_addc.3 \
libssh2_knownhost_check.3 \
libssh2_knownhost_checkp.3 \
libssh2_knownhost_del.3 \
libssh2_knownhost_free.3 \
libssh2_knownhost_get.3 \
@@ -88,6 +91,7 @@ dist_man_MANS = \
libssh2_scp_recv.3 \
libssh2_scp_send.3 \
libssh2_scp_send_ex.3 \
libssh2_scp_send64.3 \
libssh2_session_abstract.3 \
libssh2_session_block_directions.3 \
libssh2_session_callback_set.3 \
@@ -111,6 +115,7 @@ dist_man_MANS = \
libssh2_sftp_fsetstat.3 \
libssh2_sftp_fstat.3 \
libssh2_sftp_fstat_ex.3 \
libssh2_sftp_fstatvfs.3 \
libssh2_sftp_init.3 \
libssh2_sftp_last_error.3 \
libssh2_sftp_lstat.3 \
@@ -130,10 +135,12 @@ 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 \
libssh2_sftp_stat_ex.3 \
libssh2_sftp_statvfs.3 \
libssh2_sftp_symlink.3 \
libssh2_sftp_symlink_ex.3 \
libssh2_sftp_tell.3 \
@@ -151,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

@@ -13,6 +13,7 @@ libssh2_channel_eof(LIBSSH2_CHANNEL *channel);
Check if the remote host has sent an EOF status for the selected stream.
.SH RETURN VALUE
Returns 1 if the remote host has sent EOF, otherwise 0.
Returns 1 if the remote host has sent EOF, otherwise 0. Negative on
failure.
.SH SEE ALSO
.BR libssh2_channel_close(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.

View File

@@ -2,12 +2,13 @@
.\"
.TH libssh2_channel_write 3 "20 Feb 2010" "libssh2 1.2.4" "libssh2 manual"
.SH NAME
libssh2_channel_write - convenience macro for \fIlibssh2_channel_write_ex(3)\fP calls
libssh2_channel_write - convenience macro for \fIlibssh2_channel_write_ex(3)\fP
.SH SYNOPSIS
.nf
#include <libssh2.h>
libssh2_channel_write(arguments)
#define libssh2_channel_write(channel, buf, buflen) \\
libssh2_channel_write_ex((channel), 0, (buf), (buflen))
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_channel_write_ex(3)\fP.

View File

@@ -4,16 +4,12 @@
.SH NAME
libssh2_channel_write_ex - write data to a channel stream blocking
.SH SYNOPSIS
.nf
#include <libssh2.h>
ssize_t
libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, size_t buflen);
ssize_t
libssh2_channel_write(LIBSSH2_CHANNEL *channel, char *buf, size_t buflen);
ssize_t
libssh2_channel_write_stderr(LIBSSH2_CHANNEL *channel, char *buf, size_t buflen);
ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel,
int stream_id, char *buf,
size_t buflen);
.SH DESCRIPTION
Write data to a channel stream. All channel streams have one standard I/O
substream (stream_id == 0), and may have up to 2^32 extended data streams as
@@ -29,7 +25,12 @@ defines a stream ID of 1 to be the stderr substream.
\fIbuflen\fP - size of the data to write
\fIlibssh2_channel_write(3)\fP and \fIlibssh2_channel_write_stderr(3)\fP are
macros.
convenience macros for this function.
\fIlibssh2_channel_write_ex(3)\fP will use as much as possible of the buffer
and put it into a single SSH 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 RETURN VALUE
Actual number of bytes written or negative on failure.
LIBSSH2_ERROR_EAGAIN when it would otherwise block. While

View File

@@ -2,12 +2,13 @@
.\"
.TH libssh2_channel_write_stderr 3 "20 Feb 2010" "libssh2 1.2.4" "libssh2 manual"
.SH NAME
libssh2_channel_write_stderr - convenience macro for \fIlibssh2_channel_write_ex(3)\fP calls
libssh2_channel_write_stderr - convenience macro for \fIlibssh2_channel_write_ex(3)\fP
.SH SYNOPSIS
.nf
#include <libssh2.h>
libssh2_channel_write_stderr(arguments)
#define libssh2_channel_write_stderr(channel, buf, buflen) \\
libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen))
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_channel_write_ex(3)\fP.

View File

@@ -4,11 +4,11 @@ libssh2_exit - global library deinitialization
.SH SYNOPSIS
#include <libssh2.h>
int
void
libssh2_exit(void);
.SH DESCRIPTION
Exit the libssh2 functions and free's all memory used internal.
.SH AVAILABILITY
Added in libssh2 1.2.5
.SH SEE ALSO
.BR libssh2_init(3)

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

@@ -8,14 +8,13 @@ libssh2_init - global library initialization
int
libssh2_init(int flags);
.SH DESCRIPTION
Initialize the libssh2 functions. This typically initialize the
crypto library. It uses a global state, and is not thread safe -- you
must make sure this function is not called concurrently.
.SH RETURN VALUE
Returns 0 if succeeded, or a negative value for error.
.SH AVAILABILITY
Added in libssh2 1.2.5
.SH SEE ALSO
.BR libssh2_exit(3)

View File

@@ -1,10 +1,11 @@
.\" Copyright (c) 2009 by Daniel Stenberg
.\" Copyright (c) 2009, 2010 by Daniel Stenberg
.\"
.TH libssh2_knownhost_add 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_add - add a known host
.SH SYNOPSIS
.nf
#include <libssh2.h>
int libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
@@ -14,7 +15,7 @@ int libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_knownhost **store);
.SH DESCRIPTION
We discourage use of this function as of libssh2 1.2.5. Instead we strongly
urge users to sue \fIlibssh2_knownhost_addc(3)\fP instead, which as a more
urge users to use \fIlibssh2_knownhost_addc(3)\fP instead, which as a more
complete API. \fIlibssh2_knownhost_add(3)\fP is subject for removal in a
future release.

View File

@@ -7,12 +7,12 @@ libssh2_knownhost_add - add a known host
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
char *host, char *salt,
char *key, size_t keylen,
const char *comment, size_t commentlen,
int typemask,
struct libssh2_knownhost **store);
int libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts,
char *host, char *salt,
char *key, size_t keylen,
const char *comment, size_t commentlen,
int typemask,
struct libssh2_knownhost **store);
.SH DESCRIPTION
Adds a known host to the collection of known hosts identified by the 'hosts'
handle.
@@ -21,7 +21,12 @@ handle.
must be provided base64 encoded. The host name can be the IP numerical address
of the host or the full name.
\fIsalt\P is a pointer to the salt used for the host hashing, if the host is
If you want to add a key for a specific port number for the given host, you
must provide the host name like '[host]:port' with the actual characters '['
and ']' enclosing the host name and a colon separating the host part from the
port number. For example: \&"[host.example.com]:222".
\fIsalt\fP is a pointer to the salt used for the host hashing, if the host is
provided hashed. If the host is provided in plain text, salt has no meaning.
The salt has to be provided base64 encoded with a trailing zero byte.

View File

@@ -8,7 +8,8 @@ libssh2_knownhost_check - check a host+key against the list of known hosts
#include <libssh2.h>
int libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
char *host, char *key, size_t keylen,
const char *host,
const char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **knownhost);
.SH DESCRIPTION

View File

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

View File

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

@@ -35,7 +35,7 @@ and 0 indicates success.
If the provided buffer is deemed too small to fit the data libssh2 wants to
store in it, LIBSSH2_ERROR_BUFFER_TOO_SMALL will be returned. The application
is then adviced to call the function again with a larger buffer. The
is then advised to call the function again with a larger buffer. The
\fIoutlen\fP size will then hold the requested size.
.SH AVAILABILITY
Added in libssh2 1.2

View File

@@ -8,7 +8,9 @@ libssh2_poll - poll for activity on a socket, channel or listener
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
.SH DESCRIPTION
This function is deprecated. Do note use.
This function is deprecated. Do note use. We encourage users to instead use
the \fIpoll(3)\fP or \fIselect(3)\fP functions to check for socket activity or
when specific sockets are ready to get recevied from or send to.
Poll for activity on a socket, channel, listener, or any combination of these
three types. The calling semantics for this function generally match

49
docs/libssh2_scp_send64.3 Normal file
View File

@@ -0,0 +1,49 @@
.\" $Id: libssh2_scp_send_ex.3,v 1.3 2009/03/17 10:34:27 bagder Exp $
.\"
.TH libssh2_scp_send64 3 "17 Apr 2010" "libssh2 1.2.6" "libssh2 manual"
.SH NAME
libssh2_scp_send64 - Send a file via SCP
.SH SYNOPSIS
.nf
#include <libssh2.h>
LIBSSH2_CHANNEL *
libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode,
libssh2_uint64_t size, time_t mtime, time_t atime);
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
\fIpath\fP - Full path and filename of file to transfer to. That is the remote
file name.
\fImode\fP - File access mode to create file with
\fIsize\fP - Size of file being transmitted (Must be known ahead of
time). Note that this needs to be passed on as variable type
libssh2_uint64_t. This type is 64 bit on modern operating systems and
compilers.
\fImtime\fP - mtime to assign to file being created
\fIatime\fP - atime to assign to file being created (Set this and
mtime to zero to instruct remote host to use current time).
Send a file to the remote host via SCP.
.SH RETURN VALUE
Pointer to a newly allocated LIBSSH2_CHANNEL instance, or NULL on errors.
.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_SCP_PROTOCOL\fP -
\fILIBSSH2_ERROR_EAGAIN\fP - Marked for non-blocking I/O but the call would
block.
.SH AVAILABILITY
This function was added in libssh2 1.2.6 and is meant to replace the former
\fIlibssh2_scp_send_ex(3)\fP function.
.SH SEE ALSO
.BR libssh2_channel_open_ex(3)

View File

@@ -4,11 +4,16 @@
.SH NAME
libssh2_scp_send_ex - Send a file via SCP
.SH SYNOPSIS
.nf
#include <libssh2.h>
LIBSSH2_CHANNEL *
libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime);
libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode,
size_t size, long mtime, long atime);
.SH DESCRIPTION
This function has been deemed deprecated since libssh2 1.2.6. See
\fIlibssh2_scp_send64(3)\fP.
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
@@ -38,6 +43,8 @@ Pointer to a newly allocated LIBSSH2_CHANNEL instance, or NULL on errors.
\fILIBSSH2_ERROR_EAGAIN\fP - Marked for non-blocking I/O but the call would
block.
.SH AVAILABILITY
This function was marked deprecated in libssh2 1.2.6 as
\fIlibssh2_scp_send64(3)\fP has been introduced to replace this function.
.SH SEE ALSO
.BR libssh2_channel_open_ex(3)

View File

@@ -4,12 +4,16 @@
.SH NAME
libssh2_session_callback_set - set a callback function
.SH SYNOPSIS
.nf
#include <libssh2.h>
void *
libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback);
void *libssh2_session_callback_set(LIBSSH2_SESSION *session,
int cbtype, void *callback);
.SH DESCRIPTION
Sets a custom callback handler for a previously initialized session
object. Callbacks are triggered by the receipt of special packets at the
Transport layer. To disable a callback, set it to NULL.
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
@@ -17,14 +21,20 @@ libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callbac
\fIcallback\fP - Pointer to custom callback function. The prototype for
this function must match the associated callback declaration macro.
Sets a custom callback handler for a previously initialized session
object. Callbacks are triggered by the receipt of special packets at
the Transport layer. To disable a callback, set it to NULL.
.SH CALLBACK TYPES
.IP LIBSSH2_CALLBACK_IGNORE
Called when a SSH_MSG_IGNORE message is received
.IP LIBSSH2_CALLBACK_DEBUG
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. 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
Pointer to previous callback handler. Returns NULL if no
prior callback handler was set.
Pointer to previous callback handler. Returns NULL if no prior callback
handler was set or the callback type was unknown.
.SH SEE ALSO
.BR libssh2_session_init_ex(3)

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

@@ -60,7 +60,7 @@ You will find a full set of defines and macros to identify flags and
permissions on the \fBlibssh2_sftp.h\fP header file, but some of the
most common ones are:
To check for specific user permissons, the set of defines are in the
To check for specific user permissions, the set of defines are in the
pattern LIBSSH2_SFTP_S_I<action><who> where <action> is R, W or X for
read, write and excutable and <who> is USR, GRP and OTH for user,
group and other. So, you check for a user readable file, use the bit

View File

@@ -0,0 +1 @@
.so man3/libssh2_sftp_statvfs.3

View File

@@ -17,7 +17,7 @@ libssh2_sftp_last_error(LIBSSH2_SFTP *sftp);
Returns the last error code produced by the SFTP layer. Note that this only
returns a sensible error code if libssh2 returned LIBSSH2_ERROR_SFTP_PROTOCOL
in a previous call. Using \fBlibssh2_sftp_last_error(3)\fP without a
preceeding SFTP protocol error, it will return an unspecified value.
preceding SFTP protocol error, it will return an unspecified value.
.SH RETURN VALUE
Current error code state of the SFTP instance.

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

@@ -2,7 +2,7 @@
.\"
.TH libssh2_sftp_readdir 3 "20 Feb 2010" "libssh2 1.2.4" "libssh2 manual"
.SH NAME
libssh2_sftp_readdir - convenience macro for \fIlibssh2_sftp_readdir_exa(3)\fP calls
libssh2_sftp_readdir - convenience macro for \fIlibssh2_sftp_readdir_ex(3)\fP calls
.SH SYNOPSIS
#include <libssh2.h>
@@ -10,10 +10,10 @@ libssh2_sftp_readdir(arguments)
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_sftp_readdir_exa(3)\fP.
underlying function \fIlibssh2_sftp_readdir_ex(3)\fP.
.SH RETURN VALUE
See \fIlibssh2_sftp_readdir_exa(3)\fP
See \fIlibssh2_sftp_readdir_ex(3)\fP
.SH ERRORS
See \fIlibssh2_sftp_readdir_exa(3)\fP
See \fIlibssh2_sftp_readdir_ex(3)\fP
.SH SEE ALSO
.BR \fIlibssh2_sftp_readdir_exa(3)\fP
.BR \fIlibssh2_sftp_readdir_ex(3)\fP

View File

@@ -4,16 +4,19 @@
.SH NAME
libssh2_sftp_readdir_ex - read directory data from an SFTP handle
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
int
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, char *longentry, size_t longentry_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs);
int
libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs);
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle,
char *buffer, size_t buffer_maxlen,
char *longentry, size_t longentry_maxlen,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
.SH DESCRIPTION
Reads a block of data from a LIBSSH2_SFTP_HANDLE and returns file entry
information for the next entry, if any.
\fIhandle\fP - is the SFTP File Handle as returned by
.BR libssh2_sftp_open_ex(3)
@@ -25,25 +28,26 @@ filename is longer than the space provided by buffer_maxlen it will be
truncated to fit.
\fIlongentry\fP - is a pointer to a pre-allocated buffer of at least
\fIlongentry_maxlen\fP bytes to read data into.
\fIlongentry_maxlen\fP bytes to read data into. The format of the `longname'
field is unspecified by SFTP protocol. It MUST be suitable for use in the
output of a directory listing command (in fact, the recommended operation for
a directory listing command is to simply display this data).
\fIlongentry_maxlen\fP - is the length of longentry in bytes. If the length
of the full directory entry is longer than the space provided by
longentry_maxlen it will be truncated to fit.
\fIlongentry_maxlen\fP - is the length of longentry in bytes. If the length of
the full directory entry is longer than the space provided by
\fIlongentry_maxlen\fP it will be truncated to fit.
\fIattrs\fP - is a pointer to LIBSSH2_SFTP_ATTRIBUTES storage to populate
statbuf style data into.
Read a block of data from a LIBSSH2_SFTP_HANDLE. This method is modeled
after the POSIX
.BR readdir(2)
however, it uses a variable sized directory entry (filename) buffer and
returns statbuf type data in the same call.
.SH RETURN VALUE
Number of bytes actually populated into buffer, 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.
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.
@@ -54,6 +58,10 @@ 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.
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

@@ -2,12 +2,14 @@
.\"
.TH libssh2_sftp_readlink 3 "20 Feb 2010" "libssh2 1.2.4" "libssh2 manual"
.SH NAME
libssh2_sftp_readlink - convenience macro for \fIlibssh2_sftp_symlink_ex(3)\fP calls
libssh2_sftp_readlink - convenience macro for \fIlibssh2_sftp_symlink_ex(3)\fP
.SH SYNOPSIS
.nf
#include <libssh2.h>
libssh2_sftp_readlink(arguments)
#define libssh2_sftp_readlink(sftp, path, target, maxlen) \\
libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \\
LIBSSH2_SFTP_READLINK)
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_sftp_symlink_ex(3)\fP.

View File

@@ -2,12 +2,14 @@
.\"
.TH libssh2_sftp_realpath 3 "20 Feb 2010" "libssh2 1.2.4" "libssh2 manual"
.SH NAME
libssh2_sftp_realpath - convenience macro for \fIlibssh2_sftp_symlink_ex(3)\fP calls
libssh2_sftp_realpath - convenience macro for \fIlibssh2_sftp_symlink_ex(3)\fP
.SH SYNOPSIS
.nf
#include <libssh2.h>
libssh2_sftp_realpath(arguments)
#define libssh2_sftp_realpath(sftp, path, target, maxlen) \\
libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \\
LIBSSH2_SFTP_REALPATH)
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_sftp_symlink_ex(3)\fP.

View File

@@ -2,12 +2,13 @@
.\"
.TH libssh2_sftp_rmdir 3 "20 Feb 2010" "libssh2 1.2.4" "libssh2 manual"
.SH NAME
libssh2_sftp_rmdir - convenience macro for \fIlibssh2_sftp_rmdir_ex(3)\fP calls
libssh2_sftp_rmdir - convenience macro for \fIlibssh2_sftp_rmdir_ex(3)\fP
.SH SYNOPSIS
.nf
#include <libssh2.h>
libssh2_sftp_rmdir(arguments)
#define libssh2_sftp_rmdir(sftp, path) \\
libssh2_sftp_rmdir_ex((sftp), (path), strlen(path))
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_sftp_rmdir_ex(3)\fP.

View File

@@ -4,30 +4,26 @@
.SH NAME
libssh2_sftp_rmdir_ex - remove an SFTP directory
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
int
libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned int path_len);
int
libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path);
int libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path,
unsigned int path_len);
.SH DESCRIPTION
Remove a directory from the remote file system.
\fIsftp\fP - SFTP instance as returned by
.BR libssh2_sftp_init(3)
\fIsourcefile\fP - Full path of the existing directory to remove.
\fIsourcefile_len\fP - Length of the full path of the existing directory to remove.
Remove a directory from the remote file system.
\fIsourcefile_len\fP - Length of the full path of the existing directory to
remove.
.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.
.SH ERRORS
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
@@ -38,6 +34,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

@@ -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,49 +4,64 @@
.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)
\fIpath\fP - Remote filesystem object to stat/lstat/setstat.
\fIpath_len\fP - Lenght of the name of the remote filesystem object
\fIpath_len\fP - Length of the name of the remote filesystem object
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

@@ -0,0 +1,79 @@
.TH libssh2_sftp_statvfs 3 "22 May 2010" "libssh2 1.2.6" "libssh2 manual"
.SH NAME
libssh2_sftp_statvfs, libssh2_sftp_fstatvfs - get file system statistics
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
int
libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
size_t path_len, LIBSSH2_SFTP_STATVFS *st);
int
libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle,
LIBSSH2_SFTP_STATVFS *st)
.fi
.SH DESCRIPTION
These functions provide statvfs(2)-like operations and require
statvfs@openssh.com and fstatvfs@openssh.com extension support on the server.
\fIsftp\fP - SFTP instance as returned by
.BR libssh2_sftp_init(3)
\fIhandle\fP - SFTP File Handle as returned by
.BR libssh2_sftp_open_ex(3)
\fIpath\fP - full path of any file within the mounted file system.
\fIpath_len\fP - length of the full path.
\fIst\fP - Pointer to a LIBSSH2_SFTP_STATVFS structure to place file system
statistics into.
.SH DATA TYPES
LIBSSH2_SFTP_STATVFS is a typedefed struct that is defined as below
.nf
struct _LIBSSH2_SFTP_STATVFS {
libssh2_uint64_t f_bsize; /* file system block size */
libssh2_uint64_t f_frsize; /* fragment size */
libssh2_uint64_t f_blocks; /* size of fs in f_frsize units */
libssh2_uint64_t f_bfree; /* # free blocks */
libssh2_uint64_t f_bavail; /* # free blocks for non-root */
libssh2_uint64_t f_files; /* # inodes */
libssh2_uint64_t f_ffree; /* # free inodes */
libssh2_uint64_t f_favail; /* # free inodes for non-root */
libssh2_uint64_t f_fsid; /* file system ID */
libssh2_uint64_t f_flag; /* mount flags */
libssh2_uint64_t f_namemax; /* maximum filename length */
};
.fi
It is unspecified whether all members of the returned struct have meaningful
values on all file systems.
The field \fIf_flag\fP is a bit mask. Bits are defined as follows:
.IP LIBSSH2_SFTP_ST_RDONLY
Read-only file system.
.IP LIBSSH2_SFTP_ST_NOSUID
Set-user-ID/set-group-ID bits are ignored by \fBexec\fP(3).
.SH RETURN VALUE
Returns 0 on success or negative on failure. If used in non-blocking mode, it
returns LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
.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_SOCKET_TIMEOUT\fP -
\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 AVAILABILITY
Added in libssh2 1.2.6
.SH SEE ALSO
.BR libssh2_sftp_open_ex(3)

View File

@@ -2,12 +2,14 @@
.\"
.TH libssh2_sftp_symlink 3 "20 Feb 2010" "libssh2 1.2.4" "libssh2 manual"
.SH NAME
libssh2_sftp_symlink - convenience macro for \fIlibssh2_sftp_symlink_ex(3)\fP calls
libssh2_sftp_symlink - convenience macro for \fIlibssh2_sftp_symlink_ex(3)\fP
.SH SYNOPSIS
.nf
#include <libssh2.h>
libssh2_sftp_symlink(arguments)
#define libssh2_sftp_symlink(sftp, orig, linkpath) \\
libssh2_sftp_symlink_ex((sftp), (orig), strlen(orig), (linkpath), \\
strlen(linkpath), LIBSSH2_SFTP_SYMLINK)
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_sftp_symlink_ex(3)\fP.

View File

@@ -4,22 +4,17 @@
.SH NAME
libssh2_sftp_symlink_ex - read or set a symbolic link
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
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_symlink(LIBSSH2_SFTP *sftp, const char *path, char *target);
int
libssh2_sftp_readlink(LIBSSH2_SFTP *sftp, const char *path, char *target, unsigned int target_len);
int
libssh2_sftp_realpath(LIBSSH2_SFTP *sftp, const char *path, char *target, unsigned int target_len);
libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path,
unsigned int path_len, char *target,
unsigned int target_len, int link_type);
.SH DESCRIPTION
Create a symlink or read out symlink information from the remote side.
\fIsftp\fP - SFTP instance as returned by
.BR libssh2_sftp_init(3)
@@ -28,19 +23,24 @@ libssh2_sftp_realpath(LIBSSH2_SFTP *sftp, const char *path, char *target, unsign
\fIpath_len\fP - Length of the name of the remote filesystem object to
create a symlink from or resolve.
\fItarget\fP -
\fItarget\fP - a pointer to a buffer. The buffer has different uses depending
what the \fIlink_type\fP argument is set to.
.br
\fBLIBSSH2_SFTP_SYMLINK\fP: Remote filesystem object to link to.
.br
\fBLIBSSH2_SFTP_READLINK\fP: Pre-allocated buffer to resolve symlink target into.
\fBLIBSSH2_SFTP_READLINK\fP: Pre-allocated buffer to resolve symlink target
into.
.br
\fBLIBSSH2_SFTP_REALPATH\fP: Pre-allocated buffer to resolve realpath target into.
\fBLIBSSH2_SFTP_REALPATH\fP: Pre-allocated buffer to resolve realpath target
into.
\fItarget_len\fP - Length of the name of the remote filesystem target object.
\fIlink_type\fP - One of the three previously mentioned constants which
determines the resulting behavior of this function.
These are convenience macros:
.BR libssh2_sftp_symlink(3)
: Create a symbolic link between two filesystem objects.
.br
@@ -49,12 +49,23 @@ determines the resulting behavior of this function.
.br
.BR libssh2_sftp_realpath(3)
: Resolve a complex, relative, or symlinked filepath to its effective target.
.SH RETURN VALUE
Return 0 on success or negative on failure. It returns
LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
When using LIBSSH2_SFTP_SYMLINK, this funtion returns 0 on success or negative
on failure.
When using LIBSSH2_SFTP_READLINK or LIBSSH2_SFTP_REALPATH, it returns the
number of bytes it copied to the target buffer (not including 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.
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

@@ -4,23 +4,51 @@
.SH NAME
libssh2_sftp_write - write SFTP data
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
ssize_t
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count);
ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle,
const char *buffer,
size_t count);
.SH DESCRIPTION
\fBlibssh2_sftp_write(3)\fP writes a block of data to the SFTP server. This
method is modeled after the POSIX write() function and uses the same calling
semantics.
\fIhandle\fP - SFTP file handle as returned by \fIlibssh2_sftp_open_ex(3)\fP.
\fIbuffer\fP - points to the data to send off
\fIbuffer\fP - points to the data to send off.
\fIcount\fP - Number of bytes from 'buffer' to write. Note that it may not be
possible to write all bytes as requested.
\fBlibssh2_sftp_write(3)\fP writes a block of data to the SFTP server. This
method is modeled after the POSIX write() function and uses the same calling
semantics.
\fIlibssh2_sftp_handle(3)\fP will use as much as possible of the buffer and
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

@@ -5,13 +5,18 @@
libssh2_userauth_password_ex - authenticate a session with username and password
.SH SYNOPSIS
#include <libssh2.h>
.nf
int libssh2_userauth_password_ex(LIBSSH2_SESSION *session,
const char *username,
unsigned int username_len,
const char *password,
unsigned int password_len,
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)));
int
libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const char *password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)));
int
libssh2_userauth_password(LIBSSH2_SESSION *session, const char *username, const char *password);
#define libssh2_userauth_password(session, username, password) \\
libssh2_userauth_password_ex((session), (username), \\
strlen(username), \\
(password), strlen(password), NULL)
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
@@ -40,13 +45,15 @@ 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
Some of the errors this function may return include:
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.
\fILIBSSH2_ERROR_PASSWORD_EXPIRED\fP -
\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password or public/private key.
\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password
or public/private key.
.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

@@ -1,3 +1,4 @@
#include "libssh2_config.h"
#include <libssh2.h>
#ifdef WIN32
@@ -18,6 +19,10 @@
#include <unistd.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifndef INADDR_NONE
#define INADDR_NONE (in_addr_t)-1
#endif
@@ -150,7 +155,8 @@ int main(int argc, char *argv[])
goto shutdown;
}
} else if (auth & AUTH_PUBLICKEY) {
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) {
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1,
keyfile2, password)) {
printf("\tAuthentication by public key failed!\n");
goto shutdown;
}
@@ -197,8 +203,9 @@ int main(int argc, char *argv[])
channel = libssh2_channel_direct_tcpip_ex(session, remote_desthost,
remote_destport, shost, sport);
if (!channel) {
fprintf(stderr, "Could not open the direct-tcpip channel!\n");
fprintf(stderr, "(Note that this can be a problem at the server! Please review the server logs.)\n");
fprintf(stderr, "Could not open the direct-tcpip channel!\n"
"(Note that this can be a problem at the server!"
" Please review the server logs.)\n");
goto shutdown;
}

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;
}
@@ -151,10 +152,10 @@ int main(int argc, char *argv[])
}
rc = libssh2_channel_read(channel, mem, amount);
if(rc == amount) {
if(rc > 0) {
write(1, mem, rc);
}
else {
else if(rc < 0) {
fprintf(stderr, "libssh2_channel_read() failed: %d\n", rc);
break;
}

View File

@@ -47,7 +47,7 @@ int main(int argc, char *argv[])
FILE *local;
int rc;
char mem[1024];
size_t nread, sent;
size_t nread;
char *ptr;
struct stat fileinfo;
@@ -84,7 +84,7 @@ int main(int argc, char *argv[])
local = fopen(loclfile, "rb");
if (!local) {
fprintf(stderr, "Can't open local file %s\n", loclfile);
goto shutdown;
return -1;
}
stat(loclfile, &fileinfo);
@@ -94,6 +94,10 @@ int main(int argc, char *argv[])
* connection
*/
sock = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sock) {
fprintf(stderr, "failed to create socket!\n");
return -1;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
@@ -168,20 +172,21 @@ int main(int argc, char *argv[])
break;
}
ptr = mem;
sent = 0;
do {
/* write the same data over and over, until error or completion */
rc = libssh2_channel_write(channel, ptr, nread);
if (rc < 0) {
fprintf(stderr, "ERROR %d\n", rc);
} else {
/* rc indicates how many bytes were written this time */
sent += rc;
break;
}
} while (rc > 0 && sent < nread);
ptr += sent;
nread -= sent;
else {
/* rc indicates how many bytes were written this time */
ptr += rc;
nread -= rc;
}
} while (nread);
} while (1);
fprintf(stderr, "Sending EOF\n");

View File

@@ -32,6 +32,37 @@
#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[])
{
@@ -39,7 +70,7 @@ int main(int argc, char *argv[])
int sock, i, auth_pw = 1;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_SESSION *session = NULL;
LIBSSH2_CHANNEL *channel;
const char *username="username";
const char *password="password";
@@ -50,10 +81,14 @@ int main(int argc, char *argv[])
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
char mem[1024];
size_t nread, sent;
char mem[1024*100];
size_t nread;
char *ptr;
struct stat fileinfo;
time_t start;
long total = 0;
int duration;
size_t prev;
#ifdef WIN32
WSADATA wsadata;
@@ -88,7 +123,7 @@ int main(int argc, char *argv[])
local = fopen(loclfile, "rb");
if (!local) {
fprintf(stderr, "Can't local file %s\n", loclfile);
goto shutdown;
return -1;
}
stat(loclfile, &fileinfo);
@@ -175,6 +210,7 @@ int main(int argc, char *argv[])
} while (!channel);
fprintf(stderr, "SCP session waiting to send file\n");
start = time(NULL);
do {
nread = fread(mem, 1, sizeof(mem), local);
if (nread <= 0) {
@@ -182,23 +218,37 @@ int main(int argc, char *argv[])
break;
}
ptr = mem;
sent = 0;
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);
} else {
/* rc indicates how many bytes were written this time */
sent += rc;
while ((rc = libssh2_channel_write(channel, ptr, nread)) ==
LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
prev = 0;
}
} while (rc > 0 && sent < nread);
ptr += sent;
nread -= sent;
} while (1);
if (rc < 0) {
fprintf(stderr, "ERROR %d total %ld / %d prev %d\n", rc,
total, (int)nread, (int)prev);
break;
}
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;
}
} while (nread);
} while (!nread); /* only continue if nread was drained */
duration = (int)(time(NULL)-start);
printf("%ld bytes in %d seconds makes %.1f bytes/sec\n",
total, duration, total/(double)duration);
fprintf(stderr, "Sending EOF\n");
while (libssh2_channel_send_eof(channel) == LIBSSH2_ERROR_EAGAIN);
@@ -214,8 +264,9 @@ int main(int argc, char *argv[])
shutdown:
while ((rc = libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing")) == LIBSSH2_ERROR_EAGAIN);
while (libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing") ==
LIBSSH2_ERROR_EAGAIN);
libssh2_session_free(session);
#ifdef WIN32

View File

@@ -52,17 +52,45 @@ static void kbd_callback(const char *name, int name_len,
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
void **abstract)
{
(void)name;
(void)name_len;
(void)instruction;
(void)instruction_len;
if (num_prompts == 1) {
responses[0].text = strdup(password);
responses[0].length = strlen(password);
}
(void)prompts;
int i;
size_t n;
char buf[1024];
(void)abstract;
} /* kbd_callback */
printf("Performing keyboard-interactive authentication.\n");
printf("Authentication name: '");
fwrite(name, 1, name_len, stdout);
printf("'\n");
printf("Authentication instruction: '");
fwrite(instruction, 1, instruction_len, stdout);
printf("'\n");
printf("Number of prompts: %d\n\n", num_prompts);
for (i = 0; i < num_prompts; i++) {
printf("Prompt %d from server: '", i);
fwrite(prompts[i].text, 1, prompts[i].length, stdout);
printf("'\n");
printf("Please type response: ");
fgets(buf, sizeof(buf), stdin);
n = strlen(buf);
while (n > 0 && strchr("\r\n", buf[n - 1]))
n--;
buf[n] = 0;
responses[i].text = strdup(buf);
responses[i].length = n;
printf("Response %d from user is '", i);
fwrite(responses[i].text, 1, responses[i].length, stdout);
printf("'\n\n");
}
printf("Done. Sending keyboard-interactive responses to server now.\n");
}
int main(int argc, char *argv[])
@@ -217,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");

View File

@@ -246,7 +246,7 @@ int main(int argc, char *argv[])
nread);
ptr += rc;
nread -= nread;
} while (rc > 0);
} while (rc >= 0);
if(rc != LIBSSH2_ERROR_EAGAIN) {
/* error or end of file */

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

@@ -135,7 +135,6 @@ int main(int argc, char *argv[])
}
}
fprintf(stderr, "libssh2_sftp_init()!\n");
sftp_session = libssh2_sftp_init(session);
if (!sftp_session) {
@@ -146,13 +145,15 @@ int main(int argc, char *argv[])
/* Since we have not set non-blocking, tell libssh2 we are blocking */
libssh2_session_set_blocking(session, 1);
fprintf(stderr, "libssh2_sftp_mkdir()!\n");
/* Make a directory via SFTP */
rc = libssh2_sftp_mkdir(sftp_session, sftppath,
LIBSSH2_SFTP_S_IRWXU|
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IXGRP|
LIBSSH2_SFTP_S_IROTH|LIBSSH2_SFTP_S_IXOTH);
if(rc)
fprintf(stderr, "libssh2_sftp_mkdir failed: %d\n", rc);
libssh2_sftp_shutdown(sftp_session);
shutdown:

View File

@@ -151,13 +151,11 @@ int main(int argc, char *argv[])
fprintf(stderr, "libssh2_sftp_mkdirnb()!\n");
/* Make a directory via SFTP */
while ((rc = libssh2_sftp_mkdir(sftp_session, sftppath,
LIBSSH2_SFTP_S_IRWXU|
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IXGRP|
LIBSSH2_SFTP_S_IROTH|LIBSSH2_SFTP_S_IXOTH))
== LIBSSH2_ERROR_EAGAIN) {
;
}
while (libssh2_sftp_mkdir(sftp_session, sftppath,
LIBSSH2_SFTP_S_IRWXU|
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IXGRP|
LIBSSH2_SFTP_S_IROTH|LIBSSH2_SFTP_S_IXOTH)
== LIBSSH2_ERROR_EAGAIN);
libssh2_sftp_shutdown(sftp_session);

View File

@@ -265,8 +265,8 @@ int main(int argc, char *argv[])
shutdown:
printf("libssh2_session_disconnect\n");
while ((rc = libssh2_session_disconnect(session,
"Normal Shutdown, Thank you")) ==
while (libssh2_session_disconnect(session,
"Normal Shutdown, Thank you") ==
LIBSSH2_ERROR_EAGAIN);
libssh2_session_free(session);

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;
@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
local = fopen(loclfile, "rb");
if (!local) {
printf("Can't local file %s\n", loclfile);
goto shutdown;
return -1;
}
/*
@@ -185,10 +185,13 @@ int main(int argc, char *argv[])
do {
/* write data in a loop until we block */
rc = libssh2_sftp_write(sftp_handle, ptr, nread);
if(rc < 0)
break;
ptr += rc;
nread -= nread;
} while (rc > 0);
} while (1);
nread -= rc;
} while (nread);
} while (rc > 0);
libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);

View File

@@ -22,18 +22,55 @@
#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[])
{
@@ -53,9 +90,12 @@ 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;
time_t start;
long total = 0;
int duration;
#ifdef WIN32
WSADATA wsadata;
@@ -91,7 +131,7 @@ int main(int argc, char *argv[])
local = fopen(loclfile, "rb");
if (!local) {
printf("Can't local file %s\n", loclfile);
goto shutdown;
return -1;
}
/*
@@ -142,17 +182,19 @@ int main(int argc, char *argv[])
if (auth_pw) {
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username, password)) == LIBSSH2_ERROR_EAGAIN);
if (rc) {
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);
"/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;
@@ -163,7 +205,8 @@ int main(int argc, char *argv[])
do {
sftp_session = libssh2_sftp_init(session);
if ((!sftp_session) && (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
if (!sftp_session &&
(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
fprintf(stderr, "Unable to init SFTP session\n");
goto shutdown;
}
@@ -178,13 +221,17 @@ int main(int argc, char *argv[])
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)) {
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);
do {
nread = fread(mem, 1, sizeof(mem), local);
if (nread <= 0) {
@@ -193,15 +240,27 @@ int main(int argc, char *argv[])
}
ptr = mem;
total += nread;
do {
/* write data in a loop until we block */
while ((rc = libssh2_sftp_write(sftp_handle, ptr, nread)) == LIBSSH2_ERROR_EAGAIN) {
;
while ((rc = libssh2_sftp_write(sftp_handle, ptr, nread)) ==
LIBSSH2_ERROR_EAGAIN) {
waitsocket(sock, session);
}
if(rc < 0)
break;
ptr += rc;
nread -= nread;
} while (rc > 0);
} while (1);
nread -= rc;
} while (nread);
} 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);
@@ -209,7 +268,8 @@ int main(int argc, char *argv[])
shutdown:
while ((rc = libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing")) == LIBSSH2_ERROR_EAGAIN);
while (libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing")
== LIBSSH2_ERROR_EAGAIN);
libssh2_session_free(session);
#ifdef WIN32

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

@@ -121,7 +121,7 @@ int main(int argc, char *argv[])
if (auth_pw) {
/* We could authenticate via password */
if ((i = libssh2_userauth_password(session, username, password))) {
if (libssh2_userauth_password(session, username, password)) {
printf("Authentication by password failed.\n");
goto shutdown;
}

View File

@@ -41,11 +41,11 @@ const char *username="username";
int main(int argc, char *argv[])
{
unsigned long hostaddr;
int sock = -1, i, j, rc;
int sock = -1, i, rc;
struct sockaddr_in sin;
const char *fingerprint;
char *userauthlist;
LIBSSH2_SESSION *session;
LIBSSH2_SESSION *session = NULL;
LIBSSH2_CHANNEL *channel;
LIBSSH2_AGENT *agent = NULL;
struct libssh2_agent_publickey *identity, *prev_identity = NULL;
@@ -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");
@@ -218,9 +218,11 @@ int main(int argc, char *argv[])
libssh2_agent_disconnect(agent);
libssh2_agent_free(agent);
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
if(session) {
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
}
if (sock != -1) {
#ifdef WIN32

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;
@@ -167,12 +168,21 @@ int main(int argc, char *argv[])
fingerprint = libssh2_session_hostkey(session, &len, &type);
if(fingerprint) {
struct libssh2_knownhost *host;
int check = libssh2_knownhost_check(nh, (char *)hostname,
(char *)fingerprint, len,
#if LIBSSH2_VERSION_NUM >= 0x010206
/* introduced in 1.2.6 */
int check = libssh2_knownhost_checkp(nh, hostname, 22,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#else
/* 1.2.5 or older */
int check = libssh2_knownhost_check(nh, hostname,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#endif
fprintf(stderr, "Host check: %d, key: %s\n", check,
(check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
host->key:"<none>");
@@ -277,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;

View File

@@ -1,7 +1,10 @@
# fetch libssh2 version number from input file and write them to STDOUT
BEGIN {
while ((getline < ARGV[1]) > 0) {
if (match ($0, /^#define LIBSSH2_VERSION[ |\t]+"[^"]+"/)) {
if (match ($0, /^#define LIBSSH2_COPYRIGHT "[^"]+"$/)) {
my_copyright_str = substr($0, 28, length($0)-28);
}
else if (match ($0, /^#define LIBSSH2_VERSION[ |\t]+"[^"]+"/)) {
my_ver_str = substr($3, 2, length($3) - 2);
split(my_ver_str, v, ".");
if (v[3])
@@ -17,4 +20,5 @@ BEGIN {
}
print "LIBSSH2_VERSION = " my_ver "";
print "LIBSSH2_VERSION_STR = " my_ver_str "";
print "LIBSSH2_COPYRIGHT_STR = " my_copyright_str "";
}

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.
*
@@ -40,9 +40,57 @@
#ifndef LIBSSH2_H
#define LIBSSH2_H 1
#define LIBSSH2_COPYRIGHT "2004-2010 The libssh2 project and its contributors."
/* We use underscore instead of dash when appending DEV in dev versions just
to make the BANNER define (used by src/session.c) be a valid SSH
banner. Release versions have no appended strings and may of course not
have dashes either. */
#define LIBSSH2_VERSION "1.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 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
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal (using 8 bits each). All three numbers are always represented
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
appears as "0x090b07".
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
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 0x010208
/*
* This is the date and time when the full source package was created. The
* timestamp is not stored in the source code repo, as the timestamp is
* properly set in the tarballs by the maketgz script.
*
* The format of the date should follow this template:
*
* "Mon Feb 12 11:35:33 UTC 2007"
*/
#define LIBSSH2_TIMESTAMP "DEV"
#ifndef LIBSSH2_VERSION_ONLY
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
# include <BaseTsd.h>
# include <WinSock2.h>
#endif
#include <stddef.h>
#include <string.h>
@@ -62,68 +110,35 @@ 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
#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
# include <sys/bsdskt.h>
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
#endif
#if defined(LIBSSH2_WIN32) && defined(_MSC_VER) && (_MSC_VER <= 1400)
#ifdef _MSC_VER
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 libssh2_uint64_t;
typedef __int64 libssh2_int64_t;
typedef unsigned int uint32_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
/* We use underscore instead of dash when appending DEV in dev versions just
to make the BANNER define (used by src/session.c) be a valid SSH
banner. Release versions have no appended strings and may of course not
have dashes either. */
#define LIBSSH2_VERSION "1.2.5_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 5
/* This is the numeric version of the libssh2 version number, meant for easier
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal (using 8 bits each). All three numbers are always represented
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
appears as "0x090b07".
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
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 0x010205
/*
* This is the date and time when the full source package was created. The
* timestamp is not stored in the source code repo, as the timestamp is
* properly set in the tarballs by the maketgz script.
*
* The format of the date should follow this template:
*
* "Mon Feb 12 11:35:33 UTC 2007"
*/
#define LIBSSH2_TIMESTAMP "DEV"
#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
@@ -241,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;
@@ -325,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
@@ -368,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
@@ -395,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)),
@@ -410,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,
@@ -696,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);
@@ -710,6 +755,10 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session,
const char *path, int mode,
size_t size, long mtime,
long atime);
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode,
libssh2_int64_t size, time_t mtime, time_t atime);
#define libssh2_scp_send(session, path, mode, size) \
libssh2_scp_send_ex((session), (path), (mode), (size), 0, 0)
@@ -852,6 +901,15 @@ libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
int typemask,
struct libssh2_knownhost **knownhost);
/* this function is identital to the above one, but also takes a port
argument that allows libssh2 to do a better check */
LIBSSH2_API int
libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, int port,
const char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **knownhost);
/*
* libssh2_knownhost_del
*
@@ -1093,4 +1151,6 @@ LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session,
} /* extern "C" */
#endif
#endif /* LIBSSH2_VERSION_ONLY */
#endif /* LIBSSH2_H */

View File

@@ -59,6 +59,7 @@ extern "C" {
typedef struct _LIBSSH2_SFTP LIBSSH2_SFTP;
typedef struct _LIBSSH2_SFTP_HANDLE LIBSSH2_SFTP_HANDLE;
typedef struct _LIBSSH2_SFTP_ATTRIBUTES LIBSSH2_SFTP_ATTRIBUTES;
typedef struct _LIBSSH2_SFTP_STATVFS LIBSSH2_SFTP_STATVFS;
/* Flags for open_ex() */
#define LIBSSH2_SFTP_OPENFILE 0
@@ -86,6 +87,10 @@ typedef struct _LIBSSH2_SFTP_ATTRIBUTES LIBSSH2_SFTP_ATTRIBUTES;
#define LIBSSH2_SFTP_ATTR_ACMODTIME 0x00000008
#define LIBSSH2_SFTP_ATTR_EXTENDED 0x80000000
/* SFTP statvfs flag bits */
#define LIBSSH2_SFTP_ST_RDONLY 0x00000001
#define LIBSSH2_SFTP_ST_NOSUID 0x00000002
struct _LIBSSH2_SFTP_ATTRIBUTES {
/* If flags & ATTR_* bit is set, then the value in this struct will be
* meaningful Otherwise it should be ignored
@@ -98,6 +103,20 @@ struct _LIBSSH2_SFTP_ATTRIBUTES {
unsigned long atime, mtime;
};
struct _LIBSSH2_SFTP_STATVFS {
libssh2_uint64_t f_bsize; /* file system block size */
libssh2_uint64_t f_frsize; /* fragment size */
libssh2_uint64_t f_blocks; /* size of fs in f_frsize units */
libssh2_uint64_t f_bfree; /* # free blocks */
libssh2_uint64_t f_bavail; /* # free blocks for non-root */
libssh2_uint64_t f_files; /* # inodes */
libssh2_uint64_t f_ffree; /* # free inodes */
libssh2_uint64_t f_favail; /* # free inodes for non-root */
libssh2_uint64_t f_fsid; /* file system ID */
libssh2_uint64_t f_flag; /* mount flags */
libssh2_uint64_t f_namemax; /* maximum filename length */
};
/* SFTP filetypes */
#define LIBSSH2_SFTP_TYPE_REGULAR 1
#define LIBSSH2_SFTP_TYPE_DIRECTORY 2
@@ -269,6 +288,14 @@ LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp,
#define libssh2_sftp_unlink(sftp, filename) \
libssh2_sftp_unlink_ex((sftp), (filename), strlen(filename))
LIBSSH2_API int libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle,
LIBSSH2_SFTP_STATVFS *st);
LIBSSH2_API int libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp,
const char *path,
size_t path_len,
LIBSSH2_SFTP_STATVFS *st);
LIBSSH2_API int libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp,
const char *path,
unsigned int path_len, long mode);

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

@@ -3,9 +3,7 @@
## Makefile for building libssh2 (NetWare version - gnu make)
## Use: make -f Makefile.netware [help|all|clean|dev|devclean|dist|distclean|lib|nlm|objclean]
##
## Comments to: Guenter Knauf <eflash@gmx.net>
##
## $Id: Makefile.netware,v 1.14 2009/04/09 03:13:51 gknauf Exp $
## Comments to: Guenter Knauf http://www.gknw.net/phpbb
#
#########################################################################
@@ -16,12 +14,12 @@ endif
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.3
ZLIB_PATH = ../../zlib-1.2.5
endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../openssl-0.9.8k
OPENSSL_PATH = ../../openssl-0.9.8q
endif
# Edit the path below to point to your Distribution folder.
@@ -39,7 +37,7 @@ DEVLARC = $(DEVLDIR).zip
# Edit the vars below to change NLM target settings.
TARGET = libssh2
VERSION = $(LIBSSH2_VERSION)
COPYR = Copyright (c) 2004-2009 Sara Golemon <sarag@libssh2.org>
COPYR = Copyright (c) $(LIBSSH2_COPYRIGHT_STR)
WWWURL = http://www.libssh2.org/
DESCR = libssh2 $(LIBSSH2_VERSION_STR) ($(LIBARCH)) - $(WWWURL)
MTSAFE = YES
@@ -81,9 +79,9 @@ endif
CP = cp -afv
# RM = rm -f
# Here you can find a native Win32 binary of the original awk:
# http://www.gknw.net/development/prgtools/awk.zip
# http://www.gknw.net/development/prgtools/awk-20070501.zip
AWK = awk
# if you want to mark the target as MTSAFE you will need a tool for
# If you want to mark the target as MTSAFE you will need a tool for
# generating the xdc data for the linker; here's a minimal tool:
# http://www.gknw.net/development/prgtools/mkxdc.zip
MPKXDC = mkxdc
@@ -507,6 +505,7 @@ endif
@echo $(DL) libssh2_channel_write_ex,$(DL) >> $@
@echo $(DL) libssh2_hostkey_hash,$(DL) >> $@
@echo $(DL) libssh2_scp_recv,$(DL) >> $@
@echo $(DL) libssh2_scp_send64,$(DL) >> $@
@echo $(DL) libssh2_scp_send_ex,$(DL) >> $@
@echo $(DL) libssh2_knownhost_add,$(DL) >> $@
@echo $(DL) libssh2_knownhost_check,$(DL) >> $@

View File

@@ -3,9 +3,7 @@
## Makefile for building libssh2 (NetWare version - gnu make)
## Use: make -f Makefile.netware
##
## Comments to: Guenter Knauf <eflash@gmx.net>
##
## $Id: Makefile.netware,v 1.10 2009/04/09 03:13:52 gknauf Exp $
## Comments to: Guenter Knauf http://www.gknw.net/phpbb
#
#########################################################################
@@ -16,12 +14,12 @@ endif
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../../zlib-1.2.3
ZLIB_PATH = ../../../zlib-1.2.5
endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../../openssl-0.9.8k
OPENSSL_PATH = ../../../openssl-0.9.8q
endif
# Edit the var below to enable static linking of libssh2 and libz
@@ -31,7 +29,7 @@ LINK_STATIC = 1
SAMPLES = ../../example
TARGETS := $(filter-out x11.nlm,$(patsubst $(SAMPLES)/%.c,%.nlm,$(strip $(wildcard $(SAMPLES)/*.c))))
VERSION = $(LIBSSH2_VERSION)
COPYR = Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
COPYR = Copyright (c) 2004-2010 The libssh2 project and its contributors.
WWWURL = http://www.libssh2.org/
DESCR = libssh2 $(notdir $(@:.def=)) $(LIBSSH2_VERSION_STR) ($(LIBARCH)) - $(WWWURL)
MTSAFE = YES
@@ -75,9 +73,9 @@ endif
CP = cp -afv
# RM = rm -f
# Here you can find a native Win32 binary of the original awk:
# http://www.gknw.net/development/prgtools/awk.zip
# http://www.gknw.net/development/prgtools/awk-20070501.zip
AWK = awk
# if you want to mark the target as MTSAFE you will need a tool for
# If you want to mark the target as MTSAFE you will need a tool for
# generating the xdc data for the linker; here's a minimal tool:
# http://www.gknw.net/development/prgtools/mkxdc.zip
MPKXDC = mkxdc

View File

@@ -6,7 +6,9 @@ OBJECTS = \
$(INTDIR)\channel.obj \
$(INTDIR)\comp.obj \
$(INTDIR)\crypt.obj \
$(INTDIR)\global.obj \
$(INTDIR)\hostkey.obj \
$(INTDIR)\keepalive.obj \
$(INTDIR)\kex.obj \
$(INTDIR)\mac.obj \
$(INTDIR)\misc.obj \

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,
@@ -47,6 +48,8 @@
support them. */
#undef PF_UNIX
#endif
#include "userauth.h"
#include "session.h"
/* Requests from client to agent for protocol 1 key operations */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
@@ -145,79 +148,83 @@ agent_connect_unix(LIBSSH2_AGENT *agent)
struct sockaddr_un s_un;
path = getenv("SSH_AUTH_SOCK");
if (!path) {
return -1;
}
if (!path)
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"no auth sock variable");
agent->fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (agent->fd < 0) {
return -1;
}
if (agent->fd < 0)
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 -1;
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting with agent");
}
return 0;
return LIBSSH2_ERROR_NONE;
}
static int
agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
{
unsigned char buf[4], *s;
unsigned char buf[4];
int rc;
/* Send the length of the request */
if (transctx->state == agent_NB_state_request_created) {
_libssh2_htonu32(buf, transctx->request_len);
rc = send(agent->fd, buf, sizeof buf, 0);
if (rc < 0) {
if (errno == EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return -1;
}
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;
return -1;
}
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 -1;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
"agent recv failed");
}
transctx->response_len = _libssh2_ntohu32(buf);
s = transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
if (!transctx->response) {
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
if (!transctx->response)
return LIBSSH2_ERROR_ALLOC;
}
transctx->state = agent_NB_state_response_length_received;
}
/* Receive the response body */
if (transctx->state == agent_NB_state_response_length_received) {
rc = recv(agent->fd, transctx->response, transctx->response_len, 0);
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 -1;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent recv failed");
}
transctx->state = agent_NB_state_response_received;
}
@@ -228,7 +235,13 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
static int
agent_disconnect_unix(LIBSSH2_AGENT *agent)
{
return close(agent->fd);
int ret;
ret = close(agent->fd);
if(ret == -1)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"failed closing the agent socket");
return LIBSSH2_ERROR_NONE;
}
struct agent_ops agent_ops_unix = {
@@ -255,9 +268,10 @@ agent_connect_pageant(LIBSSH2_AGENT *agent)
HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd)
return -1;
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting agent");
agent->fd = 0; /* Mark as the connection has been established */
return 0;
return LIBSSH2_ERROR_NONE;
}
static int
@@ -267,43 +281,51 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
char mapname[23];
HANDLE filemap;
unsigned char *p;
unsigned char *p2;
int id;
COPYDATASTRUCT cds;
if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) {
return LIBSSH2_ERROR_INVAL;
}
if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN)
return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL,
"illegal input");
hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd) {
return -1;
}
if (!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"found no pageant");
sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, PAGEANT_MAX_MSGLEN, mapname);
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
return -1;
}
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
_libssh2_htonu32(p, transctx->request_len);
memcpy(p + 4, transctx->request, transctx->request_len);
0, PAGEANT_MAX_MSGLEN, mapname);
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed setting up pageant filemap");
p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
_libssh2_store_str(&p2, (const char *)transctx->request,
transctx->request_len);
cds.dwData = PAGEANT_COPYDATA_ID;
cds.cbData = 1 + strlen(mapname);
cds.lpData = mapname;
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
if (id > 0) {
transctx->response_len = _libssh2_ntohu32(p);
transctx->response_len = _libssh2_ntohu32(p);
if (transctx->response_len > PAGEANT_MAX_MSGLEN) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return LIBSSH2_ERROR_AGENT_PROTOCOL;
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_ALLOC;
return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC,
"agent malloc");
}
memcpy(transctx->response, p + 4, transctx->response_len);
}
@@ -355,32 +377,33 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
/* Create a request to sign the data */
if (transctx->state == agent_NB_state_init) {
s = transctx->request = LIBSSH2_ALLOC(session, len);
if (!transctx->request) {
return LIBSSH2_ERROR_ALLOC;
}
if (!transctx->request)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"out of memory");
*s++ = SSH2_AGENTC_SIGN_REQUEST;
/* key blob */
_libssh2_htonu32(s, identity->external.blob_len);
s += 4;
memcpy(s, identity->external.blob, identity->external.blob_len);
s += identity->external.blob_len;
_libssh2_store_str(&s, (const char *)identity->external.blob,
identity->external.blob_len);
/* data */
_libssh2_htonu32(s, data_len);
s += 4;
memcpy(s, data, data_len);
s += data_len;
_libssh2_store_str(&s, (const char *)data, data_len);
/* flags */
_libssh2_htonu32(s, 0);
s += 4;
_libssh2_store_u32(&s, 0);
transctx->request_len = s - transctx->request;
transctx->state = agent_NB_state_request_created;
}
/* Make sure to be re-called as a result of EAGAIN. */
if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST) {
return LIBSSH2_ERROR_BAD_USE;
}
if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST)
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"illegal request");
if (!agent->ops)
/* if no agent has been connected, bail out */
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"agent not connected");
rc = agent->ops->transact(agent, transctx);
if (rc) {
@@ -453,7 +476,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
LIBSSH2_FREE(session, transctx->response);
transctx->response = NULL;
return rc;
return _libssh2_error(session, rc, "agent sign failure");
}
static int
@@ -473,9 +496,14 @@ agent_list_identities(LIBSSH2_AGENT *agent)
}
/* Make sure to be re-called as a result of EAGAIN. */
if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) {
return LIBSSH2_ERROR_BAD_USE;
}
if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES)
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"illegal agent request");
if (!agent->ops)
/* if no agent has been connected, bail out */
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"agent not connected");
rc = agent->ops->transact(agent, transctx);
if (rc) {
@@ -570,7 +598,8 @@ agent_list_identities(LIBSSH2_AGENT *agent)
LIBSSH2_FREE(agent->session, transctx->response);
transctx->response = NULL;
return rc;
return _libssh2_error(agent->session, rc,
"agent list id failed");
}
static void
@@ -618,8 +647,8 @@ libssh2_agent_init(LIBSSH2_SESSION *session)
agent = LIBSSH2_ALLOC(session, sizeof *agent);
if (!agent) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate space for agent connection");
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate space for agent connection");
return NULL;
}
memset(agent, 0, sizeof *agent);
@@ -715,16 +744,21 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent,
struct libssh2_agent_publickey *identity)
{
void *abstract = agent;
int rc;
if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
memset(&agent->transctx, 0, sizeof agent->transctx);
agent->identity = identity->node;
}
return libssh2_userauth_publickey(agent->session, username,
identity->blob,
identity->blob_len,
agent_sign,
&abstract);
BLOCK_ADJUST(rc, agent->session,
_libssh2_userauth_publickey(agent->session, username,
strlen(username),
identity->blob,
identity->blob_len,
agent_sign,
&abstract));
return rc;
}
/*

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#ifndef __LIBSSH2_CHANNEL_H
#define __LIBSSH2_CHANNEL_H
/* Copyright (c) 2008-2009 by Daniel Stenberg
/* Copyright (c) 2008-2010 by Daniel Stenberg
*
* All rights reserved.
*
@@ -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
@@ -89,9 +89,10 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
*/
LIBSSH2_CHANNEL *
_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
unsigned int channel_type_len,
unsigned int window_size, unsigned int packet_size,
const char *message, unsigned int message_len);
uint32_t channel_type_len,
uint32_t window_size,
uint32_t packet_size,
const unsigned char *message, size_t message_len);
/*
@@ -101,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
@@ -116,5 +116,26 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
*/
ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
char *buf, size_t buflen);
uint32_t _libssh2_channel_nextid(LIBSSH2_SESSION * session);
LIBSSH2_CHANNEL *_libssh2_channel_locate(LIBSSH2_SESSION * session,
uint32_t channel_id);
size_t _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,
int stream_id);
int _libssh2_channel_close(LIBSSH2_CHANNEL * channel);
/*
* _libssh2_channel_forward_cancel
*
* Stop listening on a remote port and free the listener
* Toss out any pending (un-accept()ed) connections
*
* Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
*/
int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
#endif /* __LIBSSH2_CHANNEL_H */

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,
@@ -43,8 +44,8 @@
#include "comp.h"
/* ********
* none *
******** */
* none *
******** */
/*
* comp_method_none_comp
@@ -52,24 +53,41 @@
* Minimalist compression: Absolutely none
*/
static int
comp_method_none_comp(LIBSSH2_SESSION * session,
int compress,
unsigned char **dest,
unsigned long *dest_len,
unsigned long payload_limit,
int *free_dest,
comp_method_none_comp(LIBSSH2_SESSION *session,
unsigned char *dest,
size_t *dest_len,
const unsigned char *src,
unsigned long 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,15 +95,17 @@ 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
};
#ifdef LIBSSH2_HAVE_ZLIB
/* ********
* zlib *
******** */
* zlib *
******** */
/* Memory management wrappers
* Yes, I realize we're doing a callback to a callback,
@@ -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;
@@ -122,16 +142,16 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
strm = LIBSSH2_ALLOC(session, sizeof(z_stream));
if (!strm) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"zlib compression/decompression");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"zlib compression/decompression");
}
memset(strm, 0, sizeof(z_stream));
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,105 +161,140 @@ 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,
unsigned long *dest_len,
unsigned long payload_limit,
int *free_dest,
const unsigned char *src,
unsigned long 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;
/* In practice they never come smaller than this */
if (out_maxlen < 25) {
out_maxlen = 25;
}
/* If strm is null, then we have not yet been initialized. */
if (strm == NULL)
return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS,
"decompression unitilized");;
if (out_maxlen > (int) payload_limit) {
/* In practice they never come smaller than this */
if (out_maxlen < 25)
out_maxlen = 25;
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) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate compression/decompression "
"buffer");
}
if (!strm->next_out)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"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);
return libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure");
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"decompression failure");
}
if (strm->avail_in) {
unsigned long out_ofs = out_maxlen - strm->avail_out;
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");
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase");
}
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) {
LIBSSH2_FREE(session, out);
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand compress/"
"decompression buffer");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"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) {
LIBSSH2_FREE(session, out);
return libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression "
"phase");
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression "
"phase");
}
if (grow_size > (int) (payload_limit - out_maxlen)) {
@@ -252,30 +307,28 @@ comp_method_zlib_comp(LIBSSH2_SESSION * session,
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) {
LIBSSH2_FREE(session, out);
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand final compress/"
"decompress buffer");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"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);
return libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure");
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"decompression failure");
}
}
}
*dest = (unsigned char *) out;
*dest_len = out_maxlen - strm->avail_out;
*free_dest = 1;
return 0;
}
@@ -285,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

@@ -46,8 +46,8 @@
#if LIBSSH2_RSA
/* ***********
* ssh-rsa *
*********** */
* ssh-rsa *
*********** */
static int hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session,
void **abstract);
@@ -60,7 +60,7 @@ static int hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session,
static int
hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session,
const unsigned char *hostkey_data,
unsigned long hostkey_data_len,
size_t hostkey_data_len,
void **abstract)
{
libssh2_rsa_ctx *rsactx;
@@ -91,7 +91,6 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session,
n_len = _libssh2_ntohu32(s);
s += 4;
n = s;
s += n_len;
if (_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0,
NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0))
@@ -139,9 +138,9 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
static int
hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session,
const unsigned char *sig,
unsigned long sig_len,
size_t sig_len,
const unsigned char *m,
unsigned long m_len, void **abstract)
size_t m_len, void **abstract)
{
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
(void) session;
@@ -160,14 +159,14 @@ hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session,
static int
hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session,
unsigned char **signature,
unsigned long *signature_len,
unsigned long veccount,
size_t *signature_len,
int veccount,
const struct iovec datavec[],
void **abstract)
{
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
int ret;
unsigned int i;
int i;
unsigned char hash[SHA_DIGEST_LENGTH];
libssh2_sha1_ctx ctx;
@@ -218,8 +217,8 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa = {
#if LIBSSH2_DSA
/* ***********
* ssh-dss *
*********** */
* ssh-dss *
*********** */
static int hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session,
void **abstract);
@@ -232,7 +231,7 @@ static int hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session,
static int
hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session,
const unsigned char *hostkey_data,
unsigned long hostkey_data_len,
size_t hostkey_data_len,
void **abstract)
{
libssh2_dsa_ctx *dsactx;
@@ -268,7 +267,7 @@ hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session,
y_len = _libssh2_ntohu32(s);
s += 4;
y = s;
s += y_len;
/* s += y_len; */
_libssh2_dsa_new(&dsactx, p, p_len, q, q_len, g, g_len, y, y_len, NULL, 0);
@@ -314,9 +313,9 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
static int
hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session,
const unsigned char *sig,
unsigned long sig_len,
size_t sig_len,
const unsigned char *m,
unsigned long m_len, void **abstract)
size_t m_len, void **abstract)
{
libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
@@ -324,8 +323,8 @@ hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session,
sig += 15;
sig_len -= 15;
if (sig_len != 40) {
return libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Invalid DSS signature length");
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Invalid DSS signature length");
}
return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len);
}
@@ -338,15 +337,15 @@ hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session,
static int
hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session,
unsigned char **signature,
unsigned long *signature_len,
unsigned long veccount,
size_t *signature_len,
int veccount,
const struct iovec datavec[],
void **abstract)
{
libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
unsigned char hash[SHA_DIGEST_LENGTH];
libssh2_sha1_ctx ctx;
unsigned int i;
int i;
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
if (!*signature) {

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,12 +77,12 @@ 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. */
if (rc && rc != PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send keepalive message");
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");
return rc;
}
@@ -89,7 +90,7 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session,
if (seconds_to_next)
*seconds_to_next = session->keepalive_interval;
} else if (seconds_to_next) {
*seconds_to_next = session->keepalive_last_sent
*seconds_to_next = (int) session->keepalive_last_sent
+ session->keepalive_interval - now;
}

297
src/kex.c
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,
@@ -44,30 +45,30 @@
/* TODO: Switch this to an inline and handle alloc() failures */
/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */
#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
{ \
libssh2_sha1_ctx hash; \
unsigned long len = 0; \
if (!(value)) { \
value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
} \
if (value) \
while (len < (unsigned long)reqlen) { \
libssh2_sha1_init(&hash); \
libssh2_sha1_update(hash, exchange_state->k_value, \
exchange_state->k_value_len); \
libssh2_sha1_update(hash, exchange_state->h_sig_comp, \
SHA_DIGEST_LENGTH); \
if (len > 0) { \
libssh2_sha1_update(hash, value, len); \
} else { \
libssh2_sha1_update(hash, (version), 1); \
libssh2_sha1_update(hash, session->session_id, \
session->session_id_len); \
} \
libssh2_sha1_final(hash, (value) + len); \
len += SHA_DIGEST_LENGTH; \
} \
}
{ \
libssh2_sha1_ctx hash; \
unsigned long len = 0; \
if (!(value)) { \
value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
} \
if (value) \
while (len < (unsigned long)reqlen) { \
libssh2_sha1_init(&hash); \
libssh2_sha1_update(hash, exchange_state->k_value, \
exchange_state->k_value_len); \
libssh2_sha1_update(hash, exchange_state->h_sig_comp, \
SHA_DIGEST_LENGTH); \
if (len > 0) { \
libssh2_sha1_update(hash, value, len); \
} else { \
libssh2_sha1_update(hash, (version), 1); \
libssh2_sha1_update(hash, session->session_id, \
session->session_id_len); \
} \
libssh2_sha1_final(hash, (value) + len); \
len += SHA_DIGEST_LENGTH; \
} \
}
/*
* diffie_hellman_sha1
@@ -118,13 +119,13 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->e_packet =
LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
if (!exchange_state->e_packet) {
ret = libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Out of memory error");
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Out of memory error");
goto clean_exit;
}
exchange_state->e_packet[0] = packet_type_init;
_libssh2_htonu32(exchange_state->e_packet + 1,
exchange_state->e_packet_len - 5);
exchange_state->e_packet_len - 5);
if (_libssh2_bn_bits(exchange_state->e) % 8) {
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 5);
@@ -140,13 +141,14 @@ 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);
if (rc == PACKET_EAGAIN) {
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) {
ret = libssh2_error(session, rc,
"Unable to send KEX init message");
ret = _libssh2_error(session, rc,
"Unable to send KEX init message");
goto clean_exit;
}
exchange_state->state = libssh2_NB_state_sent;
@@ -163,7 +165,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
"Waiting for badly guessed KEX packet (to be ignored)");
burn_type =
_libssh2_packet_burn(session, &exchange_state->burn_state);
if (burn_type == PACKET_EAGAIN) {
if (burn_type == LIBSSH2_ERROR_EAGAIN) {
return burn_type;
} else if (burn_type <= 0) {
/* Failed to receive a packet */
@@ -186,12 +188,12 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
&exchange_state->s_packet,
&exchange_state->s_packet_len, 0, NULL,
0, &exchange_state->req_state);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
if (rc) {
ret = libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply");
ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply");
goto clean_exit;
}
@@ -203,9 +205,9 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
session->server_hostkey =
LIBSSH2_ALLOC(session, session->server_hostkey_len);
if (!session->server_hostkey) {
ret = libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for a copy "
"of the host key");
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for a copy "
"of the host key");
goto clean_exit;
}
memcpy(session->server_hostkey, exchange_state->s,
@@ -260,8 +262,8 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
if (session->hostkey->init(session, session->server_hostkey,
session->server_hostkey_len,
&session->server_hostkey_abstract)) {
ret = libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
"Unable to initialize hostkey importer");
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
"Unable to initialize hostkey importer");
goto clean_exit;
}
@@ -287,12 +289,12 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->k_value =
LIBSSH2_ALLOC(session, exchange_state->k_value_len);
if (!exchange_state->k_value) {
ret = libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K");
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K");
goto clean_exit;
}
_libssh2_htonu32(exchange_state->k_value,
exchange_state->k_value_len - 4);
exchange_state->k_value_len - 4);
if (_libssh2_bn_bits(exchange_state->k) % 8) {
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
} else {
@@ -303,7 +305,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
libssh2_sha1_init(&exchange_state->exchange_hash);
if (session->local.banner) {
_libssh2_htonu32(exchange_state->h_sig_comp,
strlen((char *) session->local.banner) - 2);
strlen((char *) session->local.banner) - 2);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_state->exchange_hash,
@@ -311,7 +313,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
strlen((char *) session->local.banner) - 2);
} else {
_libssh2_htonu32(exchange_state->h_sig_comp,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_state->exchange_hash,
@@ -320,7 +322,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
_libssh2_htonu32(exchange_state->h_sig_comp,
strlen((char *) session->remote.banner));
strlen((char *) session->remote.banner));
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_state->exchange_hash,
@@ -328,7 +330,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
strlen((char *) session->remote.banner));
_libssh2_htonu32(exchange_state->h_sig_comp,
session->local.kexinit_len);
session->local.kexinit_len);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_state->exchange_hash,
@@ -336,7 +338,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
session->local.kexinit_len);
_libssh2_htonu32(exchange_state->h_sig_comp,
session->remote.kexinit_len);
session->remote.kexinit_len);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_state->exchange_hash,
@@ -344,7 +346,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
session->remote.kexinit_len);
_libssh2_htonu32(exchange_state->h_sig_comp,
session->server_hostkey_len);
session->server_hostkey_len);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_state->exchange_hash,
@@ -355,16 +357,16 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
/* diffie-hellman-group-exchange hashes additional fields */
#ifdef LIBSSH2_DH_GEX_NEW
_libssh2_htonu32(exchange_state->h_sig_comp,
LIBSSH2_DH_GEX_MINGROUP);
LIBSSH2_DH_GEX_MINGROUP);
_libssh2_htonu32(exchange_state->h_sig_comp + 4,
LIBSSH2_DH_GEX_OPTGROUP);
LIBSSH2_DH_GEX_OPTGROUP);
_libssh2_htonu32(exchange_state->h_sig_comp + 8,
LIBSSH2_DH_GEX_MAXGROUP);
LIBSSH2_DH_GEX_MAXGROUP);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 12);
#else
_libssh2_htonu32(exchange_state->h_sig_comp,
LIBSSH2_DH_GEX_OPTGROUP);
LIBSSH2_DH_GEX_OPTGROUP);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
#endif
@@ -380,7 +382,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->e_packet_len - 1);
_libssh2_htonu32(exchange_state->h_sig_comp,
exchange_state->f_value_len);
exchange_state->f_value_len);
libssh2_sha1_update(exchange_state->exchange_hash,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_state->exchange_hash,
@@ -398,8 +400,8 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
sig_verify(session, exchange_state->h_sig,
exchange_state->h_sig_len, exchange_state->h_sig_comp,
20, &session->server_hostkey_abstract)) {
ret = libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
"Unable to verify hostkey signature");
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
"Unable to verify hostkey signature");
goto clean_exit;
}
@@ -410,11 +412,11 @@ 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);
if (rc == PACKET_EAGAIN) {
rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
ret = libssh2_error(session, rc, "Unable to send NEWKEYS message");
ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message");
goto clean_exit;
}
@@ -426,10 +428,10 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
&exchange_state->tmp,
&exchange_state->tmp_len, 0, NULL, 0,
&exchange_state->req_state);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
ret = libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
goto clean_exit;
}
/* The first key exchange has been performed,
@@ -444,8 +446,8 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
if (!session->session_id) {
session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
if (!session->session_id) {
ret = libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for SHA digest");
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for SHA digest");
goto clean_exit;
}
memcpy(session->session_id, exchange_state->h_sig_comp,
@@ -600,6 +602,40 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client HMAC Key calculated");
/* Initialize compression for each direction */
/* Cleanup any existing compression */
if (session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1,
&session->local.comp_abstract);
}
if (session->local.comp && session->local.comp->init) {
if (session->local.comp->init(session, 1,
&session->local.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server compression initialized");
if (session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0,
&session->remote.comp_abstract);
}
if (session->remote.comp && session->remote.comp->init) {
if (session->remote.comp->init(session, 0,
&session->remote.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client compression initialized");
}
clean_exit:
@@ -682,7 +718,7 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128,
SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
if (ret == PACKET_EAGAIN) {
if (ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -758,7 +794,7 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
ret = diffie_hellman_sha1(session, key_state->g, key_state->p,
256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
if (ret == PACKET_EAGAIN) {
if (ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -781,7 +817,6 @@ static int
kex_method_diffie_hellman_group_exchange_sha1_key_exchange
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
{
unsigned char *s;
unsigned long p_len, g_len;
int ret = 0;
int rc;
@@ -810,13 +845,13 @@ 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);
if (rc == PACKET_EAGAIN) {
rc = _libssh2_transport_send(session, key_state->request,
key_state->request_len, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
ret = libssh2_error(session, rc,
"Unable to send Group Exchange Request");
ret = _libssh2_error(session, rc,
"Unable to send Group Exchange Request");
goto dh_gex_clean_exit;
}
@@ -827,11 +862,11 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
&key_state->data, &key_state->data_len,
0, NULL, 0, &key_state->req_state);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
ret = libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply");
ret = _libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply");
goto dh_gex_clean_exit;
}
@@ -839,7 +874,7 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
}
if (key_state->state == libssh2_NB_state_sent1) {
s = key_state->data + 1;
unsigned char *s = key_state->data + 1;
p_len = _libssh2_ntohu32(s);
s += 4;
_libssh2_bn_from_bin(key_state->p, p_len, s);
@@ -848,7 +883,6 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
g_len = _libssh2_ntohu32(s);
s += 4;
_libssh2_bn_from_bin(key_state->g, g_len, s);
s += g_len;
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len,
SSH_MSG_KEX_DH_GEX_INIT,
@@ -856,7 +890,7 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
key_state->data + 1,
key_state->data_len - 1,
&key_state->exchange_state);
if (ret == PACKET_EAGAIN) {
if (ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -891,7 +925,7 @@ static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha1 = {
};
static const LIBSSH2_KEX_METHOD
kex_method_diffie_helman_group_exchange_sha1 = {
kex_method_diffie_helman_group_exchange_sha1 = {
"diffie-hellman-group-exchange-sha1",
kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
@@ -960,13 +994,13 @@ kex_method_list(unsigned char *buf, size_t list_strlen,
#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar) \
((prefvar) ? strlen(prefvar) : \
#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar) \
((prefvar) ? strlen(prefvar) : \
kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar)))
#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \
if (prefvar) { \
_libssh2_htonu32((buf), (prefvarlen)); \
_libssh2_htonu32((buf), (prefvarlen)); \
buf += 4; \
memcpy((buf), (prefvar), (prefvarlen)); \
buf += (prefvarlen); \
@@ -1011,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 =
@@ -1026,13 +1060,13 @@ static int kexinit(LIBSSH2_SESSION * session)
s = data = LIBSSH2_ALLOC(session, data_len);
if (!data) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory");
}
*(s++) = SSH_MSG_KEXINIT;
libssh2_random(s, 16);
_libssh2_random(s, 16);
s += 16;
/* Ennumerating through these lists twice is probably (certainly?)
@@ -1051,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,
@@ -1067,10 +1101,7 @@ static int kexinit(LIBSSH2_SESSION * session)
*(s++) = 0;
/* Reserved == 0 */
*(s++) = 0;
*(s++) = 0;
*(s++) = 0;
*(s++) = 0;
_libssh2_htonu32(s, 0);
#ifdef LIBSSH2DEBUG
{
@@ -1104,10 +1135,13 @@ 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 */
session->kexinit_data = NULL;
session->kexinit_data_len = 0;
}
rc = _libssh2_transport_write(session, data, data_len);
if (rc == PACKET_EAGAIN) {
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;
return rc;
@@ -1115,8 +1149,8 @@ static int kexinit(LIBSSH2_SESSION * session)
else if (rc) {
LIBSSH2_FREE(session, data);
session->kexinit_state = libssh2_NB_state_idle;
return libssh2_error(session, rc,
"Unable to send KEXINIT packet to remote host");
return _libssh2_error(session, rc,
"Unable to send KEXINIT packet to remote host");
}
@@ -1176,7 +1210,7 @@ kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
*/
static const LIBSSH2_COMMON_METHOD *
kex_get_method_by_name(const char *name, size_t name_len,
const LIBSSH2_COMMON_METHOD ** methodlist)
const LIBSSH2_COMMON_METHOD ** methodlist)
{
while (*methodlist) {
if ((strlen((*methodlist)->name) == name_len) &&
@@ -1239,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));
@@ -1455,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;
@@ -1517,9 +1551,9 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
unsigned data_len)
{
unsigned char *kex, *hostkey, *crypt_cs, *crypt_sc, *comp_cs, *comp_sc,
*mac_cs, *mac_sc, *lang_cs, *lang_sc;
*mac_cs, *mac_sc;
size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len;
size_t comp_sc_len, mac_cs_len, mac_sc_len, lang_cs_len, lang_sc_len;
size_t comp_sc_len, mac_cs_len, mac_sc_len;
unsigned char *s = data;
/* Skip packet_type, we know it already */
@@ -1552,6 +1586,7 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
s += 4 + comp_cs_len;
comp_sc_len = _libssh2_ntohu32(s);
comp_sc = s + 4;
#if 0
s += 4 + comp_sc_len;
lang_cs_len = _libssh2_ntohu32(s);
lang_cs = s + 4;
@@ -1559,7 +1594,7 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
lang_sc_len = _libssh2_ntohu32(s);
lang_sc = s + 4;
s += 4 + lang_sc_len;
#endif
/* If the server sent an optimistic packet, assume that it guessed wrong.
* If the guess is determined to be right (by kex_agree_kex_hostkey)
* This flag will be reset to zero so that it's not ignored */
@@ -1588,11 +1623,13 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
return -1;
}
#if 0
if (libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
|| libssh2_kex_agree_lang(session, &session->remote, lang_sc,
lang_sc_len)) {
return -1;
}
#endif
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on KEX method: %s",
session->kex->name);
@@ -1610,34 +1647,20 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
session->local.comp->name);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_SC method: %s",
session->remote.comp->name);
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on LANG_CS method:"); /* None yet */
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on LANG_SC method:"); /* None yet */
/* Initialize compression layer */
if (session->local.comp && session->local.comp->init &&
session->local.comp->init(session, 1, &session->local.comp_abstract)) {
return -1;
}
if (session->remote.comp && session->remote.comp->init &&
session->remote.comp->init(session, 0,
&session->remote.comp_abstract)) {
return -1;
}
return 0;
}
/* libssh2_kex_exchange
/* _libssh2_kex_exchange
* Exchange keys
* Returns 0 on success, non-zero on failure
*
* Returns some errors without libssh2_error()
* Returns some errors without _libssh2_error()
*/
int
libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
_libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_exchange_state_t * key_state)
{
int rc = 0;
@@ -1675,7 +1698,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
if (key_state->state == libssh2_NB_state_sent) {
retcode = kexinit(session);
if (retcode == PACKET_EAGAIN) {
if (retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
} else if (retcode) {
@@ -1696,7 +1719,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
&key_state->data,
&key_state->data_len, 0, NULL, 0,
&key_state->req_state);
if (retcode == PACKET_EAGAIN) {
if (retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
}
@@ -1732,12 +1755,12 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
if (key_state->state == libssh2_NB_state_sent2) {
retcode = session->kex->exchange_keys(session,
&key_state->key_state_low);
if (retcode == PACKET_EAGAIN) {
if (retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
} else if (retcode) {
rc = libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
"Unrecoverable error exchanging keys");
rc = _libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
"Unrecoverable error exchanging keys");
}
}
}
@@ -1806,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:
@@ -1825,14 +1850,14 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
break;
default:
return libssh2_error(session, LIBSSH2_ERROR_INVAL,
"Invalid parameter specified for method_type");
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"Invalid parameter specified for method_type");
}
s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
if (!newprefs) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Error allocated space for method preferences");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Error allocated space for method preferences");
}
memcpy(s, prefs, prefs_len + 1);
@@ -1858,9 +1883,9 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
if (strlen(newprefs) == 0) {
LIBSSH2_FREE(session, newprefs);
return libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"The requested method(s) are not currently "
"supported");
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"The requested method(s) are not currently "
"supported");
}
if (*prefvar) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2009, 2010 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -43,6 +43,8 @@ struct known_host {
struct list_node node;
char *name; /* points to the name or the hash (allocated) */
size_t name_len; /* needed for hashed data */
int port; /* if non-zero, a specific port this key is for on this
host */
int typemask; /* plain, sha1, custom, ... */
char *salt; /* points to binary salt (allocated) */
size_t salt_len; /* size of salt */
@@ -88,9 +90,9 @@ libssh2_knownhost_init(LIBSSH2_SESSION *session)
LIBSSH2_ALLOC(session, sizeof(struct _LIBSSH2_KNOWNHOSTS));
if(!knh) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for known-hosts "
"collection");
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for known-hosts "
"collection");
return NULL;
}
@@ -137,14 +139,14 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
unsigned int ptrlen;
if(!entry)
return libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for known host "
"entry");
return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for known host "
"entry");
/* make sure we have a key type set */
if(!(typemask & LIBSSH2_KNOWNHOST_KEY_MASK)) {
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
"No key type set");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
"No key type set");
goto error;
}
@@ -157,8 +159,8 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
entry->name = LIBSSH2_ALLOC(hosts->session, hostlen+1);
if(!entry->name) {
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for host name");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for host name");
goto error;
}
memcpy(entry->name, host, hostlen+1);
@@ -179,8 +181,8 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
entry->salt_len = ptrlen;
break;
default:
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unknown host name type");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unknown host name type");
goto error;
}
@@ -190,8 +192,8 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
keylen = strlen(key);
entry->key = LIBSSH2_ALLOC(hosts->session, keylen+1);
if(!entry->key) {
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for key");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for key");
goto error;
}
memcpy(entry->key, key, keylen+1);
@@ -202,9 +204,9 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
&ptr);
if(!nlen) {
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"base64-encoded key");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"base64-encoded key");
goto error;
}
@@ -214,8 +216,8 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
if (comment) {
entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen+1);
if(!entry->comment) {
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for comment");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for comment");
goto error;
}
memcpy(entry->comment, comment, commentlen+1);
@@ -308,6 +310,147 @@ libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts,
typemask, store);
}
/*
* knownhost_check
*
* Check a host and its associated key against the collection of known hosts.
*
* The typemask is the type/format of the given host name and key
*
* plain - ascii "hostname.domain.tld"
* sha1 - NOT SUPPORTED AS INPUT
* custom - prehashed base64 encoded. Note that this cannot use any salts.
*
* Returns:
*
* LIBSSH2_KNOWNHOST_CHECK_FAILURE
* LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
* LIBSSH2_KNOWNHOST_CHECK_MATCH
* LIBSSH2_KNOWNHOST_CHECK_MISMATCH
*/
static int
knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
const char *hostp, int port,
const char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **ext)
{
struct known_host *node;
struct known_host *badkey = NULL;
int type = typemask & LIBSSH2_KNOWNHOST_TYPE_MASK;
char *keyalloc = NULL;
int rc = LIBSSH2_KNOWNHOST_CHECK_NOTFOUND;
char hostbuff[270]; /* most host names can't be longer than like 256 */
const char *host;
int numcheck; /* number of host combos to check */
int match = 0;
if(type == LIBSSH2_KNOWNHOST_TYPE_SHA1)
/* we can't work with a sha1 as given input */
return LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
if(!(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64)) {
/* we got a raw key input, convert it to base64 for the checks below */
size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
&keyalloc);
if(!nlen) {
_libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for base64-encoded "
"key");
return LIBSSH2_KNOWNHOST_CHECK_FAILURE;
}
/* make the key point to this */
key = keyalloc;
}
/* if a port number is given, check for a '[host]:port' first before the
plain 'host' */
if(port >= 0) {
snprintf(hostbuff, sizeof(hostbuff), "[%s]:%d", hostp, port);
host = hostbuff;
numcheck = 2; /* check both combos, start with this */
}
else {
host = hostp;
numcheck = 1; /* only check this host version */
}
do {
node = _libssh2_list_first(&hosts->head);
while (node) {
switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN)
match = !strcmp(host, node->name);
break;
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
if(type == LIBSSH2_KNOWNHOST_TYPE_CUSTOM)
match = !strcmp(host, node->name);
break;
case LIBSSH2_KNOWNHOST_TYPE_SHA1:
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) {
/* when we have the sha1 version stored, we can use a
plain input to produce a hash to compare with the
stored hash.
*/
libssh2_hmac_ctx ctx;
unsigned char hash[SHA_DIGEST_LENGTH];
if(SHA_DIGEST_LENGTH != node->name_len) {
/* the name hash length must be the sha1 size or
we can't match it */
break;
}
libssh2_hmac_sha1_init(&ctx, node->salt, node->salt_len);
libssh2_hmac_update(ctx, (unsigned char *)host,
strlen(host));
libssh2_hmac_final(ctx, hash);
libssh2_hmac_cleanup(&ctx);
if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH))
/* this is a node we're interested in */
match = 1;
}
break;
default: /* unsupported type */
break;
}
if(match) {
/* host name match, now compare the keys */
if(!strcmp(key, node->key)) {
/* they match! */
*ext = knownhost_to_external(node);
badkey = NULL;
rc = LIBSSH2_KNOWNHOST_CHECK_MATCH;
break;
}
else {
/* remember the first node that had a host match but a
failed key match since we continue our search from
here */
if(!badkey)
badkey = node;
match = 0; /* don't count this as a match anymore */
}
}
node= _libssh2_list_next(&node->node);
}
host = hostp;
} while(!match && --numcheck);
if(badkey) {
/* key mismatch */
*ext = knownhost_to_external(badkey);
rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
}
if(keyalloc)
LIBSSH2_FREE(hosts->session, keyalloc);
return rc;
}
/*
* libssh2_knownhost_check
*
@@ -328,104 +471,49 @@ libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts,
*/
LIBSSH2_API int
libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
const char *host, const char *key, size_t keylen,
const char *hostp, const char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **ext)
{
struct known_host *node = _libssh2_list_first(&hosts->head);
struct known_host *badkey = NULL;
int type = typemask & LIBSSH2_KNOWNHOST_TYPE_MASK;
char *keyalloc = NULL;
int rc = LIBSSH2_KNOWNHOST_CHECK_NOTFOUND;
if(type == LIBSSH2_KNOWNHOST_TYPE_SHA1)
/* we can't work with a sha1 as given input */
return LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
if(!(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64)) {
/* we got a raw key input, convert it to base64 for the checks below */
size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
&keyalloc);
if(!nlen) {
libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for base64-encoded "
"key");
return LIBSSH2_KNOWNHOST_CHECK_FAILURE;
}
/* make the key point to this */
key = keyalloc;
keylen = nlen;
}
while (node) {
int match = 0;
switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN)
match = !strcmp(host, node->name);
break;
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
if(type == LIBSSH2_KNOWNHOST_TYPE_CUSTOM)
match = !strcmp(host, node->name);
break;
case LIBSSH2_KNOWNHOST_TYPE_SHA1:
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) {
/* when we have the sha1 version stored, we can use a plain
input to produce a hash to compare with the stored hash.
*/
libssh2_hmac_ctx ctx;
unsigned char hash[SHA_DIGEST_LENGTH];
if(SHA_DIGEST_LENGTH != node->name_len) {
/* the name hash length must be the sha1 size or
we can't match it */
break;
}
libssh2_hmac_sha1_init(&ctx, node->salt, node->salt_len);
libssh2_hmac_update(ctx, (unsigned char *)host, strlen(host));
libssh2_hmac_final(ctx, hash);
libssh2_hmac_cleanup(&ctx);
if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH))
/* this is a node we're interested in */
match = 1;
}
break;
default: /* unsupported type */
break;
}
if(match) {
/* host name match, now compare the keys */
if(!strcmp(key, node->key)) {
/* they match! */
*ext = knownhost_to_external(node);
badkey = NULL;
rc = LIBSSH2_KNOWNHOST_CHECK_MATCH;
break;
}
else {
/* remember the first node that had a host match but a failed
key match since we continue our search from here */
if(!badkey)
badkey = node;
}
}
node= _libssh2_list_next(&node->node);
}
if(badkey) {
/* key mismatch */
*ext = knownhost_to_external(badkey);
rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
}
if(keyalloc)
LIBSSH2_FREE(hosts->session, keyalloc);
return rc;
return knownhost_check(hosts, hostp, -1, key, keylen,
typemask, ext);
}
/*
* libssh2_knownhost_checkp
*
* Check a host+port and its associated key against the collection of known
* hosts.
*
* Note that if 'port' is specified as greater than zero, the check function
* will be able to check for a dedicated key for this particular host+port
* combo, and if 'port' is negative it only checks for the generic host key.
*
* The typemask is the type/format of the given host name and key
*
* plain - ascii "hostname.domain.tld"
* sha1 - NOT SUPPORTED AS INPUT
* custom - prehashed base64 encoded. Note that this cannot use any salts.
*
* Returns:
*
* LIBSSH2_KNOWNHOST_CHECK_FAILURE
* LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
* LIBSSH2_KNOWNHOST_CHECK_MATCH
* LIBSSH2_KNOWNHOST_CHECK_MISMATCH
*/
LIBSSH2_API int
libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts,
const char *hostp, int port,
const char *key, size_t keylen,
int typemask,
struct libssh2_knownhost **ext)
{
return knownhost_check(hosts, hostp, port, key, keylen,
typemask, ext);
}
/*
* libssh2_knownhost_del
*
@@ -440,8 +528,8 @@ libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
/* check that this was retrieved the right way or get out */
if(!entry || (entry->magic != KNOWNHOST_MAGIC))
return libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
"Invalid host information");
return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
"Invalid host information");
/* get the internal node pointer */
node = entry->node;
@@ -478,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()
*
@@ -492,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))
return libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(unexpected length)");
if(keylen < 20)
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line "
"(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
@@ -584,14 +719,14 @@ 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,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unknown key type");
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unknown key type");
key += 7;
keylen -= 7;
@@ -628,35 +763,26 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
break;
default: /* unknown key format */
return libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unknown key format");
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"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 = libssh2_knownhost_addc(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 = libssh2_knownhost_addc(hosts, hostbuf, salt, key, keylen, comment,
commentlen,
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
NULL);
return rc;
}
/*
@@ -676,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
@@ -699,10 +825,10 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
int rc;
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
cp = line;
@@ -734,9 +860,9 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
}
if(!*cp || !len) /* illegal line */
return libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line");
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Failed to parse known_hosts line");
keyp = cp; /* the key starts here */
keylen = len;
@@ -777,10 +903,10 @@ libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
char buf[2048];
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
file = fopen(filename, "r");
if(file) {
@@ -792,8 +918,8 @@ libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
fclose(file);
}
else
return libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
"Failed to open file");
return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
"Failed to open file");
return num;
}
@@ -830,10 +956,10 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
/* we only support this single file type for now, bail out on all other
attempts */
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
tindex = (node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) >>
LIBSSH2_KNOWNHOST_KEY_SHIFT;
@@ -852,18 +978,18 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
nlen = _libssh2_base64_encode(hosts->session, node->name,
node->name_len, &namealloc);
if(!nlen)
return libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"base64-encoded host name");
return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"base64-encoded host name");
nlen = _libssh2_base64_encode(hosts->session,
node->salt, node->salt_len,
&saltalloc);
if(!nlen) {
free(namealloc);
return libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"base64-encoded salt");
return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"base64-encoded salt");
}
nlen = strlen(saltalloc) + strlen(namealloc) + strlen(keytype) +
@@ -878,8 +1004,8 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
sprintf(buf, "|1|%s|%s%s %s\n", saltalloc, namealloc,
keytype, node->key);
else
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Known-host write buffer too small");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Known-host write buffer too small");
free(namealloc);
free(saltalloc);
@@ -896,8 +1022,8 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
else
sprintf(buf, "%s%s %s\n", node->name, keytype, node->key);
else
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Known-host write buffer too small");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Known-host write buffer too small");
}
/* we report the full length of the data with the trailing zero excluded */
@@ -924,8 +1050,8 @@ libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
struct known_host *node;
if(known->magic != KNOWNHOST_MAGIC)
return libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
"Invalid host information");
return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
"Invalid host information");
node = known->node;
@@ -939,7 +1065,7 @@ libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
*/
LIBSSH2_API int
libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
const char *filename, int type)
const char *filename, int type)
{
struct known_host *node;
FILE *file;
@@ -949,15 +1075,15 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
/* we only support this single file type for now, bail out on all other
attempts */
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unsupported type of known-host information "
"store");
file = fopen(filename, "w");
if(!file)
return libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
"Failed to open file");
return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
"Failed to open file");
for(node = _libssh2_list_first(&hosts->head);
node;
@@ -972,8 +1098,8 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
nwrote = fwrite(buffer, 1, wrote, file);
if(nwrote != wrote) {
/* failed to write the whole thing, bail out */
rc = libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
"Write failed");
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
"Write failed");
break;
}
}

View File

@@ -344,8 +344,8 @@ int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_dsa_ctx * rsactx,
const unsigned char *hash,
unsigned long hash_len,
unsigned char **signature, unsigned long *signature_len)
size_t hash_len,
unsigned char **signature, size_t *signature_len)
{
gcry_sexp_t sig_sexp;
gcry_sexp_t data;
@@ -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

@@ -56,14 +56,14 @@
#define MD5_DIGEST_LENGTH 16
#define SHA_DIGEST_LENGTH 20
#define libssh2_random(buf, len) \
#define _libssh2_random(buf, len) \
(gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1)
#define libssh2_sha1_ctx gcry_md_hd_t
#define libssh2_sha1_init(ctx) gcry_md_open (ctx, GCRY_MD_SHA1, 0);
#define libssh2_sha1_update(ctx, data, len) gcry_md_write (ctx, data, len)
#define libssh2_sha1_final(ctx, out) \
memcpy (out, gcry_md_read (ctx, 0), 20), gcry_md_close (ctx)
memcpy (out, gcry_md_read (ctx, 0), SHA_DIGEST_LENGTH), gcry_md_close (ctx)
#define libssh2_sha1(message, len, out) \
gcry_md_hash_buffer (GCRY_MD_SHA1, out, message, len)
@@ -71,7 +71,7 @@
#define libssh2_md5_init(ctx) gcry_md_open (ctx, GCRY_MD_MD5, 0);
#define libssh2_md5_update(ctx, data, len) gcry_md_write (ctx, data, len)
#define libssh2_md5_final(ctx, out) \
memcpy (out, gcry_md_read (ctx, 0), 20), gcry_md_close (ctx)
memcpy (out, gcry_md_read (ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close (ctx)
#define libssh2_md5(message, len, out) \
gcry_md_hash_buffer (GCRY_MD_MD5, out, message, len)
@@ -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,
unsigned long hash_len,
unsigned char **signature,
unsigned long *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

@@ -40,12 +40,6 @@
#ifndef LIBSSH2_PRIV_H
#define LIBSSH2_PRIV_H 1
#ifdef _WIN32
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif /* _CRT_SECURE_NO_DEPRECATE */
#endif /* WIN32 */
#define LIBSSH2_LIBRARY
#include "libssh2_config.h"
@@ -83,6 +77,21 @@
# endif
#endif
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include "libssh2.h"
#include "libssh2_publickey.h"
#include "libssh2_sftp.h"
@@ -116,26 +125,7 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
#endif /* WIN32 */
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#ifdef LIBSSH2_LIBGCRYPT
#include "libgcrypt.h"
#else
#include "openssl.h"
#endif
#include "crypto.h"
#ifdef HAVE_WINSOCK2_H
@@ -150,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
@@ -177,9 +160,9 @@ typedef int libssh2_socket_t;
session->ssh_msg_ignore((session), (data), (datalen), &(session)->abstract)
#define LIBSSH2_DEBUG(session, always_display, message, message_len, \
language, language_len) \
session->ssh_msg_disconnect((session), (always_display), (message), \
(message_len), (language), (language_len), \
&(session)->abstract)
session->ssh_msg_debug((session), (always_display), (message), \
(message_len), (language), (language_len), \
&(session)->abstract)
#define LIBSSH2_DISCONNECT(session, reason, message, message_len, language, language_len) \
session->ssh_msg_disconnect((session), (reason), (message), (message_len), (language), (language_len), &(session)->abstract)
@@ -190,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;
@@ -235,9 +217,9 @@ typedef struct kmdhgGPsha1kex_state_t
unsigned char *tmp;
unsigned char h_sig_comp[SHA_DIGEST_LENGTH];
unsigned char c;
unsigned long e_packet_len;
unsigned long s_packet_len;
unsigned long tmp_len;
size_t e_packet_len;
size_t s_packet_len;
size_t tmp_len;
_libssh2_bn_ctx *ctx;
_libssh2_bn *x;
_libssh2_bn *e;
@@ -247,9 +229,9 @@ typedef struct kmdhgGPsha1kex_state_t
unsigned char *f_value;
unsigned char *k_value;
unsigned char *h_sig;
unsigned long f_value_len;
unsigned long k_value_len;
unsigned long h_sig_len;
size_t f_value_len;
size_t k_value_len;
size_t h_sig_len;
libssh2_sha1_ctx exchange_hash;
packet_require_state_t req_state;
libssh2_nonblocking_states burn_state;
@@ -264,8 +246,8 @@ typedef struct key_exchange_state_low_t
_libssh2_bn *g; /* SSH2 defined value (2) */
unsigned char request[13];
unsigned char *data;
unsigned long request_len;
unsigned long data_len;
size_t request_len;
size_t data_len;
} key_exchange_state_low_t;
typedef struct key_exchange_state_t
@@ -274,9 +256,9 @@ typedef struct key_exchange_state_t
packet_require_state_t req_state;
key_exchange_state_low_t key_state_low;
unsigned char *data;
unsigned long data_len;
size_t data_len;
unsigned char *oldlocal;
unsigned long oldlocal_len;
size_t oldlocal_len;
} key_exchange_state_t;
#define FwdNotReq "Forward not requested"
@@ -316,27 +298,22 @@ 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;
unsigned long data_len;
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
{
/* Identifier */
unsigned long id;
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;
@@ -352,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;
@@ -364,35 +344,36 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_setenv_ex() */
libssh2_nonblocking_states setenv_state;
unsigned char *setenv_packet;
unsigned long setenv_packet_len;
size_t setenv_packet_len;
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 long reqPTY_packet_len;
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;
/* State variables used in libssh2_channel_x11_req_ex() */
libssh2_nonblocking_states reqX11_state;
unsigned char *reqX11_packet;
unsigned long reqX11_packet_len;
size_t reqX11_packet_len;
unsigned char reqX11_local_channel[4];
packet_requirev_state_t reqX11_packet_requirev_state;
/* State variables used in libssh2_channel_process_startup() */
libssh2_nonblocking_states process_state;
unsigned char *process_packet;
unsigned long process_packet_len;
size_t process_packet_len;
unsigned char process_local_channel[4];
packet_requirev_state_t process_packet_requirev_state;
/* State variables used in libssh2_channel_flush_ex() */
libssh2_nonblocking_states flush_state;
unsigned long flush_refund_bytes;
unsigned long flush_flush_bytes;
size_t flush_refund_bytes;
size_t flush_flush_bytes;
/* State variables used in libssh2_channel_receive_window_adjust() */
libssh2_nonblocking_states adjust_state;
@@ -405,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 long write_packet_len;
unsigned long write_bufwrote;
unsigned char write_packet[13];
size_t write_packet_len;
size_t write_bufwrite;
/* State variables used in libssh2_channel_close() */
@@ -426,6 +405,7 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_handle_extended_data2() */
libssh2_nonblocking_states extData2_state;
};
struct _LIBSSH2_LISTENER
@@ -454,13 +434,13 @@ typedef struct _libssh2_endpoint_data
unsigned char *banner;
unsigned char *kexinit;
unsigned long kexinit_len;
size_t kexinit_len;
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;
@@ -479,47 +459,46 @@ struct transportpacket
{
/* ------------- for incoming data --------------- */
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
the buffer */
int readidx; /* at what array index we do the next read from
the buffer */
int packet_length; /* the most recent packet_length as read from the
network data */
int 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
so far. */
int 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. */
unsigned char *payload; /* this is a pointer to a LIBSSH2_ALLOC()
area to which we write decrypted data */
unsigned char *wptr; /* write pointer into the payload to where we
are currently writing decrypted data */
unsigned char init[5]; /* first 5 bytes of the incoming data stream,
still encrypted */
size_t writeidx; /* at what array index we do the next write into
the buffer */
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 */
size_t data_num; /* How much of the total package that has been read
so far. */
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. */
unsigned char *payload; /* this is a pointer to a LIBSSH2_ALLOC()
area to which we write decrypted data */
unsigned char *wptr; /* write pointer into the payload to where we
are currently writing decrypted data */
/* ------------- for outgoing data --------------- */
unsigned char *outbuf; /* pointer to a LIBSSH2_ALLOC() 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 */
unsigned long olen; /* original size of the data we stored in
outbuf */
unsigned long osent; /* number of bytes already sent */
unsigned char outbuf[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */
int ototal_num; /* size of outbuf in number of bytes */
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 */
};
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;
unsigned char *receive_packet;
unsigned long receive_packet_len;
size_t receive_packet_len;
/* State variables used in libssh2_publickey_add_ex() */
libssh2_nonblocking_states add_state;
@@ -536,129 +515,16 @@ struct _LIBSSH2_PUBLICKEY
unsigned char *listFetch_s;
unsigned char listFetch_buffer[12];
unsigned char *listFetch_data;
unsigned long 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];
int 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;
unsigned long last_errno;
/* Holder for partial packet, use in libssh2_sftp_packet_read() */
unsigned char *partial_packet; /* The data */
unsigned long partial_len; /* Desired number of bytes */
unsigned long 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;
ssize_t open_packet_len;
unsigned long open_request_id;
/* State variables used in libssh2_sftp_read() */
libssh2_nonblocking_states read_state;
unsigned char *read_packet;
unsigned long read_request_id;
size_t read_total_read;
/* State variables used in libssh2_sftp_readdir() */
libssh2_nonblocking_states readdir_state;
unsigned char *readdir_packet;
unsigned long readdir_request_id;
/* State variables used in libssh2_sftp_write() */
libssh2_nonblocking_states write_state;
unsigned char *write_packet;
unsigned long write_request_id;
/* State variables used in libssh2_sftp_fstat_ex() */
libssh2_nonblocking_states fstat_state;
unsigned char *fstat_packet;
unsigned long fstat_request_id;
/* State variables used in libssh2_sftp_unlink_ex() */
libssh2_nonblocking_states unlink_state;
unsigned char *unlink_packet;
unsigned long unlink_request_id;
/* State variables used in libssh2_sftp_rename_ex() */
libssh2_nonblocking_states rename_state;
unsigned char *rename_packet;
unsigned char *rename_s;
unsigned long rename_request_id;
/* State variables used in libssh2_sftp_mkdir() */
libssh2_nonblocking_states mkdir_state;
unsigned char *mkdir_packet;
unsigned long mkdir_request_id;
/* State variables used in libssh2_sftp_rmdir() */
libssh2_nonblocking_states rmdir_state;
unsigned char *rmdir_packet;
unsigned long rmdir_request_id;
/* State variables used in libssh2_sftp_stat() */
libssh2_nonblocking_states stat_state;
unsigned char *stat_packet;
unsigned long stat_request_id;
/* State variables used in libssh2_sftp_symlink() */
libssh2_nonblocking_states symlink_state;
unsigned char *symlink_packet;
unsigned long symlink_request_id;
size_t listFetch_data_len;
};
#define LIBSSH2_SCP_RESPONSE_BUFLEN 256
struct flags {
int sigpipe; /* LIBSSH2_FLAG_SIGPIPE */
int compress; /* LIBSSH2_FLAG_COMPRESS */
};
struct _LIBSSH2_SESSION
{
/* Memory management callbacks */
@@ -679,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;
@@ -699,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 */
@@ -718,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 */
@@ -754,9 +622,9 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_session_startup() */
libssh2_nonblocking_states startup_state;
unsigned char *startup_data;
unsigned long startup_data_len;
size_t startup_data_len;
unsigned char startup_service[sizeof("ssh-userauth") + 5 - 1];
unsigned long startup_service_length;
size_t startup_service_length;
packet_require_state_t startup_req_state;
key_exchange_state_t startup_key_state;
@@ -765,8 +633,8 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_session_disconnect_ex() */
libssh2_nonblocking_states disconnect_state;
unsigned char *disconnect_data;
unsigned long disconnect_data_len;
unsigned char disconnect_data[256 + 13];
size_t disconnect_data_len;
/* State variables used in libssh2_packet_read() */
libssh2_nonblocking_states readPack_state;
@@ -775,14 +643,14 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_userauth_list() */
libssh2_nonblocking_states userauth_list_state;
unsigned char *userauth_list_data;
unsigned long userauth_list_data_len;
size_t userauth_list_data_len;
packet_requirev_state_t userauth_list_packet_requirev_state;
/* State variables used in libssh2_userauth_password_ex() */
libssh2_nonblocking_states userauth_pswd_state;
unsigned char *userauth_pswd_data;
unsigned char userauth_pswd_data0;
unsigned long userauth_pswd_data_len;
size_t userauth_pswd_data_len;
char *userauth_pswd_newpw;
int userauth_pswd_newpw_len;
packet_requirev_state_t userauth_pswd_packet_requirev_state;
@@ -790,22 +658,22 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_userauth_hostbased_fromfile_ex() */
libssh2_nonblocking_states userauth_host_state;
unsigned char *userauth_host_data;
unsigned long userauth_host_data_len;
size_t userauth_host_data_len;
unsigned char *userauth_host_packet;
unsigned long userauth_host_packet_len;
size_t userauth_host_packet_len;
unsigned char *userauth_host_method;
unsigned long userauth_host_method_len;
size_t userauth_host_method_len;
unsigned char *userauth_host_s;
packet_requirev_state_t userauth_host_packet_requirev_state;
/* State variables used in libssh2_userauth_publickey_fromfile_ex() */
libssh2_nonblocking_states userauth_pblc_state;
unsigned char *userauth_pblc_data;
unsigned long userauth_pblc_data_len;
size_t userauth_pblc_data_len;
unsigned char *userauth_pblc_packet;
unsigned long userauth_pblc_packet_len;
size_t userauth_pblc_packet_len;
unsigned char *userauth_pblc_method;
unsigned long userauth_pblc_method_len;
size_t userauth_pblc_method_len;
unsigned char *userauth_pblc_s;
unsigned char *userauth_pblc_b;
packet_requirev_state_t userauth_pblc_packet_requirev_state;
@@ -813,9 +681,9 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_userauth_keyboard_interactive_ex() */
libssh2_nonblocking_states userauth_kybd_state;
unsigned char *userauth_kybd_data;
unsigned long userauth_kybd_data_len;
size_t userauth_kybd_data_len;
unsigned char *userauth_kybd_packet;
unsigned long userauth_kybd_packet_len;
size_t userauth_kybd_packet_len;
unsigned int userauth_kybd_auth_name_len;
char *userauth_kybd_auth_name;
unsigned userauth_kybd_auth_instruction_len;
@@ -831,23 +699,23 @@ struct _LIBSSH2_SESSION
packet_requirev_state_t open_packet_requirev_state;
LIBSSH2_CHANNEL *open_channel;
unsigned char *open_packet;
unsigned long open_packet_len;
size_t open_packet_len;
unsigned char *open_data;
unsigned long open_data_len;
unsigned long open_local_channel;
size_t open_data_len;
uint32_t open_local_channel;
/* State variables used in libssh2_channel_direct_tcpip_ex() */
libssh2_nonblocking_states direct_state;
unsigned char *direct_message;
unsigned long direct_host_len;
unsigned long direct_shost_len;
unsigned long direct_message_len;
size_t direct_host_len;
size_t direct_shost_len;
size_t direct_message_len;
/* 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() */
@@ -855,20 +723,22 @@ struct _LIBSSH2_SESSION
LIBSSH2_PUBLICKEY *pkeyInit_pkey;
LIBSSH2_CHANNEL *pkeyInit_channel;
unsigned char *pkeyInit_data;
unsigned long pkeyInit_data_len;
size_t pkeyInit_data_len;
/* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */
unsigned char pkeyInit_buffer[19];
size_t pkeyInit_buffer_sent; /* how much of buffer that has been sent */
/* 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() */
@@ -883,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 */
@@ -897,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. */
@@ -925,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
@@ -955,18 +821,18 @@ struct _LIBSSH2_HOSTKEY_METHOD
unsigned long hash_len;
int (*init) (LIBSSH2_SESSION * session, const unsigned char *hostkey_data,
unsigned long hostkey_data_len, void **abstract);
size_t hostkey_data_len, void **abstract);
int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile,
unsigned const char *passphrase, void **abstract);
int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig,
unsigned long sig_len, const unsigned char *m,
unsigned long m_len, void **abstract);
size_t sig_len, const unsigned char *m,
size_t m_len, void **abstract);
int (*signv) (LIBSSH2_SESSION * session, unsigned char **signature,
unsigned long *signature_len, unsigned long veccount,
size_t *signature_len, int veccount,
const struct iovec datavec[], void **abstract);
int (*encrypt) (LIBSSH2_SESSION * session, unsigned char **dst,
unsigned long *dst_len, const unsigned char *src,
unsigned long src_len, void **abstract);
size_t *dst_len, const unsigned char *src,
size_t src_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
};
@@ -996,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,
unsigned long *dest_len, unsigned long payload_limit,
int *free_dest, const unsigned char *src,
unsigned long 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
@@ -1041,8 +896,6 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
#endif
#endif
int libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg);
#define LIBSSH2_SOCKET_UNKNOWN 1
#define LIBSSH2_SOCKET_CONNECTED 0
#define LIBSSH2_SOCKET_DISCONNECTED -1
@@ -1108,91 +961,29 @@ int libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg);
#define SSH_MSG_CHANNEL_SUCCESS 99
#define SSH_MSG_CHANNEL_FAILURE 100
void _libssh2_session_shutdown(LIBSSH2_SESSION * session);
/* 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
unsigned int _libssh2_ntohu32(const unsigned char *buf);
libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf);
void _libssh2_htonu32(unsigned char *buf, unsigned int val);
#ifdef WIN32
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
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 */
int _libssh2_wait_socket(LIBSSH2_SESSION *session);
/* These started out as private return codes for the transport layer, but was
converted to using the library-wide return codes to easy propagation of the
error reasons all over etc without risking mixups. The PACKET_* names are
left only to reduce the impact of changing the code all over.*/
#define PACKET_TIMEOUT LIBSSH2_ERROR_TIMEOUT
#define PACKET_BADUSE LIBSSH2_ERROR_BAD_USE
#define PACKET_COMPRESS LIBSSH2_ERROR_COMPRESS
#define PACKET_TOOBIG LIBSSH2_ERROR_OUT_OF_BOUNDARY
#define PACKET_ENOMEM LIBSSH2_ERROR_ALLOC
#define PACKET_EAGAIN LIBSSH2_ERROR_EAGAIN
#define PACKET_FAIL LIBSSH2_ERROR_SOCKET_NONE
#define PACKET_NONE LIBSSH2_ERROR_NONE
int _libssh2_packet_read(LIBSSH2_SESSION * session);
int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned char **data, unsigned long *data_len,
unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len);
int _libssh2_packet_askv(LIBSSH2_SESSION * session,
const unsigned char *packet_types,
unsigned char **data, unsigned long *data_len,
unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len);
int _libssh2_packet_require(LIBSSH2_SESSION * session,
unsigned char packet_type, unsigned char **data,
unsigned long *data_len, unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len,
packet_require_state_t * state);
int _libssh2_packet_requirev(LIBSSH2_SESSION * session,
const unsigned char *packet_types,
unsigned char **data, unsigned long *data_len,
unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len,
packet_requirev_state_t * state);
int _libssh2_packet_burn(LIBSSH2_SESSION * session,
libssh2_nonblocking_states * state);
int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len);
int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate);
int libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_exchange_state_t * state);
unsigned long _libssh2_channel_nextid(LIBSSH2_SESSION * session);
LIBSSH2_CHANNEL *_libssh2_channel_locate(LIBSSH2_SESSION * session,
unsigned long channel_id);
unsigned long _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,
int stream_id);
/* this is the lib-internal set blocking function */
int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_exchange_state_t * state);
/* Let crypt.c/hostkey.c expose their method structs */
const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void);
const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void);
/* Language API doesn't exist yet. Just act like we've agreed on a language */
#define libssh2_kex_agree_lang(session, endpoint, str, str_len) 0
/* pem.c */
int _libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin,
@@ -1205,50 +996,14 @@ int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
/* global.c */
void _libssh2_init_if_needed (void);
/* Conveniance-macros to allow code like this;
int rc = BLOCK_ADJUST(rc, session, session_startup(session, sock) );
int rc = BLOCK_ADJUST_ERRNO(ptr, session, session_startup(session, sock) );
The point of course being to make sure that while in non-blocking mode
these always return no matter what the return code is, but in blocking mode
it blocks if EAGAIN is the reason for the return from the underlying
function.
*/
#define BLOCK_ADJUST(rc,sess,x) \
do { \
rc = x; \
/* the order of the check below is important to properly deal with the
case when the 'sess' is freed */ \
if((rc != LIBSSH2_ERROR_EAGAIN) || !sess->api_block_mode) \
break; \
rc = _libssh2_wait_socket(sess); \
if(rc) \
break; \
} while(1)
/*
* For functions that returns a pointer, we need to check if the API is
* non-blocking and return immediately. If the pointer is non-NULL we return
* immediately. If the API is blocking and we get a NULL we check the errno
* and *only* if that is EAGAIN we loop and wait for socket action.
*/
#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \
do { \
int rc; \
ptr = x; \
if(!sess->api_block_mode || \
(ptr != NULL) || \
(libssh2_session_last_errno(sess) != LIBSSH2_ERROR_EAGAIN) ) \
break; \
rc = _libssh2_wait_socket(sess); \
if(rc) \
break; \
} while(1)
#define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0]))
/* define to output the libssh2_int64_t type in a *printf() */
#if defined( __BORLANDC__ ) || defined( _MSC_VER ) || defined( __MINGW32__ )
#define LIBSSH2_INT64_T_FORMAT "I64"
#else
#define LIBSSH2_INT64_T_FORMAT "ll"
#endif
#endif /* LIBSSH2_H */

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,
@@ -47,13 +48,18 @@
#include <sys/time.h>
#endif
#include <stdio.h>
#include <errno.h>
int libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
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
@@ -83,42 +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();
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 */
#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, int flags)
_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();
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
*/
@@ -136,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;
}
@@ -145,7 +167,7 @@ _libssh2_ntohu64(const unsigned char *buf)
/* _libssh2_htonu32
*/
void
_libssh2_htonu32(unsigned char *buf, unsigned int value)
_libssh2_htonu32(unsigned char *buf, uint32_t value)
{
buf[0] = (value >> 24) & 0xFF;
buf[1] = (value >> 16) & 0xFF;
@@ -153,6 +175,25 @@ _libssh2_htonu32(unsigned char *buf, unsigned int value)
buf[3] = value & 0xFF;
}
/* _libssh2_store_u32
*/
void _libssh2_store_u32(unsigned char **buf, uint32_t value)
{
_libssh2_htonu32(*buf, value);
*buf += sizeof(uint32_t);
}
/* _libssh2_store_str
*/
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
{
_libssh2_store_u32(buf, (uint32_t)len);
if(len) {
memcpy(*buf, str, len);
*buf += len;
}
}
/* Base64 Conversion */
static const char base64_table[] =
@@ -201,8 +242,8 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
*data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
d = (unsigned char *) *data;
if (!d) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for base64 decoding");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for base64 decoding");
}
for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
@@ -230,8 +271,7 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
/* Invalid -- We have a byte which belongs exclusively to a partial
octet */
LIBSSH2_FREE(session, *data);
return libssh2_error(session, LIBSSH2_ERROR_INVAL,
"Invalid data (byte belonging to partial octet)");
return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
}
*datalen = len;
@@ -318,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)
@@ -327,7 +373,8 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
}
LIBSSH2_API int
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, libssh2_trace_handler_func callback)
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
libssh2_trace_handler_func callback)
{
session->tracehandler = callback;
session->tracehandler_context = handler_context;
@@ -338,7 +385,7 @@ void
_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
{
char buffer[1536];
int len;
int len, msglen, buflen = sizeof(buffer);
va_list vargs;
struct timeval now;
static int firstsec;
@@ -363,7 +410,8 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
}
/* Find the first matching context string for this message */
for (contextindex = 0; contextindex < ARRAY_SIZE(contexts); contextindex++) {
for (contextindex = 0; contextindex < ARRAY_SIZE(contexts);
contextindex++) {
if ((context & (1 << contextindex)) != 0) {
contexttext = contexts[contextindex];
break;
@@ -376,19 +424,25 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
}
now.tv_sec -= firstsec;
len = snprintf(buffer, sizeof(buffer), "[libssh2] %d.%06d %s: ",
len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
(int)now.tv_sec, (int)now.tv_usec, contexttext);
va_start(vargs, format);
len += vsnprintf(buffer + len, 1535 - len, format, vargs);
buffer[len] = '\n';
va_end(vargs);
if (session->tracehandler) {
(session->tracehandler)(session, session->tracehandler_context, buffer, len + 1);
} else {
write(2, buffer, len + 1);
if (len >= buflen)
msglen = buflen - 1;
else {
buflen -= len;
msglen = len;
va_start(vargs, format);
len = vsnprintf(buffer + msglen, buflen, format, vargs);
va_end(vargs);
msglen += len < buflen ? len : buflen - 1;
}
if (session->tracehandler)
(session->tracehandler)(session, session->tracehandler_context, buffer,
msglen);
else
fprintf(stderr, "%s\n", buffer);
}
#else
@@ -401,7 +455,8 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
}
LIBSSH2_API int
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, libssh2_trace_handler_func callback)
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
libssh2_trace_handler_func callback)
{
(void) session;
(void) handler_context;
@@ -504,7 +559,7 @@ void _libssh2_list_insert(struct list_node *after, /* insert before this */
#ifdef WIN32
#if defined(LIBSSH2_WIN32) && !defined(__MINGW32__)
/*
* gettimeofday
* Implementation according to:

View File

@@ -1,6 +1,6 @@
#ifndef __LIBSSH2_MISC_H
#define __LIBSSH2_MISC_H
/* Copyright (c) 2009 by Daniel Stenberg
/* Copyright (c) 2009-2010 by Daniel Stenberg
*
* All rights reserved.
*
@@ -49,6 +49,8 @@ struct list_node {
struct list_head *head;
};
int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg);
void _libssh2_list_init(struct list_head *head);
/* add a node last in the list */
@@ -69,4 +71,11 @@ void _libssh2_list_remove(struct list_node *entry);
size_t _libssh2_base64_encode(struct _LIBSSH2_SESSION *session,
const char *inp, size_t insize, char **outptr);
unsigned int _libssh2_ntohu32(const unsigned char *buf);
libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf);
void _libssh2_htonu32(unsigned char *buf, uint32_t val);
void _libssh2_store_u32(unsigned char **buf, uint32_t value);
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len);
#endif /* _LIBSSH2_MISC_H */

View File

@@ -201,27 +201,52 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
return ret == 1 ? 0 : 1;
}
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES128_CTR)
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
#include <openssl/aes.h>
#include <openssl/evp.h>
typedef struct
{
AES_KEY key;
EVP_CIPHER_CTX *aes_ctx;
unsigned char ctr[AES_BLOCK_SIZE];
} aes_ctr_ctx;
static int
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) /* init key */
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;
}
c->aes_ctx = malloc(sizeof(EVP_CIPHER_CTX));
if (c->aes_ctx == NULL)
return 0;
if (EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) {
return 0;
}
EVP_CIPHER_CTX_set_padding(c->aes_ctx, 0);
AES_set_encrypt_key(key, 8 * ctx->key_len, &c->key);
memcpy(c->ctr, iv, AES_BLOCK_SIZE);
EVP_CIPHER_CTX_set_app_data(ctx, c);
@@ -231,15 +256,20 @@ 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];
size_t i;
size_t i = 0;
int outlen = 0;
if (inl != 16) /* libssh2 only ever encrypt one block */
return 0;
return 0;
if (c == NULL) {
return 0;
}
/*
To encrypt a packet P=P1||P2||...||Pn (where P1, P2, ..., Pn are each
@@ -248,16 +278,18 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
the ciphertext block C1. The counter X is then incremented
*/
AES_encrypt(c->ctr, b1, &c->key);
if (EVP_EncryptUpdate(c->aes_ctx, b1, &outlen, c->ctr, AES_BLOCK_SIZE) != 1) {
return 0;
}
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;
@@ -266,7 +298,19 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int
aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
{
free(EVP_CIPHER_CTX_get_app_data(ctx));
aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
if (c == NULL) {
return 1;
}
if (c->aes_ctx != NULL) {
_libssh2_cipher_dtor(c->aes_ctx);
free(c->aes_ctx);
}
free(c);
return 1;
}
@@ -385,8 +429,8 @@ int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
const unsigned char *hash,
unsigned long hash_len,
unsigned char **signature, unsigned long *signature_len)
size_t hash_len,
unsigned char **signature, size_t *signature_len)
{
int ret;
unsigned char *sig;
@@ -471,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

@@ -104,7 +104,7 @@
# define LIBSSH2_3DES 1
#endif
#define libssh2_random(buf, len) RAND_bytes ((buf), (len))
#define _libssh2_random(buf, len) RAND_bytes ((buf), (len))
#define libssh2_sha1_ctx EVP_MD_CTX
#define libssh2_sha1_init(ctx) EVP_DigestInit(ctx, EVP_get_digestbyname("sha1"))
@@ -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,
unsigned long hash_len,
unsigned char **signature,
unsigned long *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)
@@ -199,7 +148,7 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
#define _libssh2_cipher_aes256 EVP_aes_256_cbc
#define _libssh2_cipher_aes192 EVP_aes_192_cbc
#define _libssh2_cipher_aes128 EVP_aes_128_cbc
#ifdef HAVE_EVP_AES128_CTR
#ifdef HAVE_EVP_AES_128_CTR
#define _libssh2_cipher_aes128ctr EVP_aes_128_ctr
#define _libssh2_cipher_aes192ctr EVP_aes_192_ctr
#define _libssh2_cipher_aes256ctr EVP_aes_256_ctr
@@ -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

76
src/packet.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef LIBSSH2_PACKET_H
#define LIBSSH2_PACKET_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.
*
*/
int _libssh2_packet_read(LIBSSH2_SESSION * session);
int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned char **data, size_t *data_len,
int match_ofs,
const unsigned char *match_buf,
size_t match_len);
int _libssh2_packet_askv(LIBSSH2_SESSION * session,
const unsigned char *packet_types,
unsigned char **data, size_t *data_len,
int match_ofs,
const unsigned char *match_buf,
size_t match_len);
int _libssh2_packet_require(LIBSSH2_SESSION * session,
unsigned char packet_type, unsigned char **data,
size_t *data_len, int match_ofs,
const unsigned char *match_buf,
size_t match_len,
packet_require_state_t * state);
int _libssh2_packet_requirev(LIBSSH2_SESSION *session,
const unsigned char *packet_types,
unsigned char **data, size_t *data_len,
int match_ofs,
const unsigned char *match_buf,
size_t match_len,
packet_requirev_state_t * state);
int _libssh2_packet_burn(LIBSSH2_SESSION * session,
libssh2_nonblocking_states * state);
int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len);
int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate);
#endif /* LIBSSH2_PACKET_H */

View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -38,10 +39,11 @@
#include "libssh2_priv.h"
#include "libssh2_publickey.h"
#include "channel.h"
#include "session.h"
#define LIBSSH2_PUBLICKEY_VERSION 2
/* Numericised response codes -- Not IETF standard, just a local representation */
/* Numericised response codes -- Not IETF, just local representation */
#define LIBSSH2_PUBLICKEY_RESPONSE_STATUS 0
#define LIBSSH2_PUBLICKEY_RESPONSE_VERSION 1
#define LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY 2
@@ -118,7 +120,7 @@ publickey_status_error(const LIBSSH2_PUBLICKEY *pkey,
msg = publickey_status_codes[status].name;
}
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, msg);
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, msg);
}
/*
@@ -128,7 +130,7 @@ publickey_status_error(const LIBSSH2_PUBLICKEY *pkey,
*/
static int
publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
unsigned char **data, unsigned long *data_len)
unsigned char **data, size_t *data_len)
{
LIBSSH2_CHANNEL *channel = pkey->channel;
LIBSSH2_SESSION *session = channel->session;
@@ -137,20 +139,20 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
if (pkey->receive_state == libssh2_NB_state_idle) {
rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc != 4) {
return libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid response from publickey subsystem");
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid response from publickey subsystem");
}
pkey->receive_packet_len = _libssh2_ntohu32(buffer);
pkey->receive_packet =
LIBSSH2_ALLOC(session, pkey->receive_packet_len);
if (!pkey->receive_packet) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate publickey response "
"buffer");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate publickey response "
"buffer");
}
pkey->receive_state = libssh2_NB_state_sent;
@@ -159,15 +161,15 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
if (pkey->receive_state == libssh2_NB_state_sent) {
rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet,
pkey->receive_packet_len);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc != (int)pkey->receive_packet_len) {
LIBSSH2_FREE(session, pkey->receive_packet);
pkey->receive_packet = NULL;
pkey->receive_state = libssh2_NB_state_idle;
return libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for publickey subsystem "
"response packet");
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for publickey subsystem "
"response packet");
}
*data = pkey->receive_packet;
@@ -185,9 +187,9 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
* Data will be incremented by 4 + response_len on success only
*/
static int
publickey_response_id(unsigned char **pdata, int data_len)
publickey_response_id(unsigned char **pdata, size_t data_len)
{
unsigned long response_len;
size_t response_len;
unsigned char *data = *pdata;
const LIBSSH2_PUBLICKEY_CODE_LIST *codes = publickey_response_codes;
@@ -198,7 +200,7 @@ publickey_response_id(unsigned char **pdata, int data_len)
response_len = _libssh2_ntohu32(data);
data += 4;
data_len -= 4;
if (data_len < (int)response_len) {
if (data_len < response_len) {
/* Malformed response */
return -1;
}
@@ -215,7 +217,7 @@ publickey_response_id(unsigned char **pdata, int data_len)
return -1;
}
/* libssh2_publickey_response_success
/* publickey_response_success
*
* Generic helper routine to wait for success response and nothing else
*/
@@ -224,46 +226,46 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
{
LIBSSH2_SESSION *session = pkey->channel->session;
unsigned char *data, *s;
unsigned long data_len;
size_t data_len;
int response;
int rc;
while (1) {
rc = publickey_packet_receive(pkey, &data, &data_len);
if (rc == PACKET_EAGAIN) {
int rc = publickey_packet_receive(pkey, &data, &data_len);
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
return libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
}
s = data;
if ((response = publickey_response_id(&s, data_len)) < 0) {
LIBSSH2_FREE(session, data);
return libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code");
}
response = publickey_response_id(&s, data_len);
switch (response) {
case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
/* Error, or processing complete */
{
unsigned long status = _libssh2_ntohu32(s);
{
unsigned long status = _libssh2_ntohu32(s);
LIBSSH2_FREE(session, data);
if (status == LIBSSH2_PUBLICKEY_SUCCESS)
return 0;
publickey_status_error(pkey, session, status);
return -1;
}
default:
/* Unknown/Unexpected */
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response, ignoring");
LIBSSH2_FREE(session, data);
if (status == LIBSSH2_PUBLICKEY_SUCCESS)
return 0;
publickey_status_error(pkey, session, status);
return -1;
}
default:
LIBSSH2_FREE(session, data);
if (response < 0) {
return _libssh2_error(session,
LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response");
}
/* Unknown/Unexpected */
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response");
data = NULL;
}
}
@@ -272,20 +274,16 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
}
/* *****************
* Publickey API *
***************** */
* Publickey API *
***************** */
/*
* libssh2_publickey_init
* publickey_init
*
* Startup the publickey subsystem
*/
LIBSSH2_API LIBSSH2_PUBLICKEY *
libssh2_publickey_init(LIBSSH2_SESSION * session)
static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
{
/* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */
unsigned char buffer[19];
unsigned char *s;
int response;
int rc;
@@ -301,44 +299,38 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
}
if (session->pkeyInit_state == libssh2_NB_state_allocated) {
do {
session->pkeyInit_channel =
libssh2_channel_open_ex(session, "session",
sizeof("session") - 1,
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
0);
if (!session->pkeyInit_channel
&& (libssh2_session_last_errno(session) ==
LIBSSH2_ERROR_EAGAIN)) {
session->pkeyInit_channel =
_libssh2_channel_open(session, "session",
sizeof("session") - 1,
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
0);
if (!session->pkeyInit_channel) {
if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)
/* The error state is already set, so leave it */
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block to startup channel");
return NULL;
} else if (!session->pkeyInit_channel
&& (libssh2_session_last_errno(session) !=
LIBSSH2_ERROR_EAGAIN)) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Unable to startup channel");
goto err_exit;
}
} while (!session->pkeyInit_channel);
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Unable to startup channel");
goto err_exit;
}
session->pkeyInit_state = libssh2_NB_state_sent;
}
if (session->pkeyInit_state == libssh2_NB_state_sent) {
rc = libssh2_channel_process_startup(session->pkeyInit_channel,
"subsystem",
sizeof("subsystem") - 1,
"publickey", strlen("publickey"));
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickey subsystem");
rc = _libssh2_channel_process_startup(session->pkeyInit_channel,
"subsystem",
sizeof("subsystem") - 1,
"publickey",
sizeof("publickey") - 1);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickey subsystem");
return NULL;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Unable to request publickey subsystem");
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Unable to request publickey subsystem");
goto err_exit;
}
@@ -346,26 +338,27 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
}
if (session->pkeyInit_state == libssh2_NB_state_sent1) {
rc = libssh2_channel_handle_extended_data2(session->pkeyInit_channel,
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickey subsystem");
unsigned char *s;
rc = _libssh2_channel_extended_data(session->pkeyInit_channel,
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickey subsystem");
return NULL;
}
session->pkeyInit_pkey =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PUBLICKEY));
if (!session->pkeyInit_pkey) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a new publickey structure");
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a new publickey structure");
goto err_exit;
}
memset(session->pkeyInit_pkey, 0, sizeof(LIBSSH2_PUBLICKEY));
session->pkeyInit_pkey->channel = session->pkeyInit_channel;
session->pkeyInit_pkey->version = 0;
s = buffer;
s = session->pkeyInit_buffer;
_libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4);
s += 4;
_libssh2_htonu32(s, sizeof("version") - 1);
@@ -373,10 +366,11 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
memcpy(s, "version", sizeof("version") - 1);
s += sizeof("version") - 1;
_libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION);
s += 4;
session->pkeyInit_buffer_sent = 0;
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Sending publickey version packet advertising version %d support",
"Sending publickey advertising version %d support",
(int) LIBSSH2_PUBLICKEY_VERSION);
session->pkeyInit_state = libssh2_NB_state_sent2;
@@ -384,83 +378,90 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
if (session->pkeyInit_state == libssh2_NB_state_sent2) {
rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
(char *) buffer, (s - buffer));
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending publickey version packet");
session->pkeyInit_buffer,
19 - session->pkeyInit_buffer_sent);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending publickey version packet");
return NULL;
} else if ((s - buffer) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey version packet");
} else if (rc) {
_libssh2_error(session, rc,
"Unable to send publickey version packet");
goto err_exit;
}
session->pkeyInit_buffer_sent += rc;
if(session->pkeyInit_buffer_sent < 19) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Need to be called again to complete this");
return NULL;
}
session->pkeyInit_state = libssh2_NB_state_sent3;
}
if (session->pkeyInit_state == libssh2_NB_state_sent3) {
while (1) {
unsigned char *s;
rc = publickey_packet_receive(session->pkeyInit_pkey,
&session->pkeyInit_data,
&session->pkeyInit_data_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from "
"publickey subsystem");
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from "
"publickey subsystem");
return NULL;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
goto err_exit;
}
s = session->pkeyInit_data;
if ((response =
publickey_response_id(&s, session->pkeyInit_data_len)) < 0) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code");
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code");
goto err_exit;
}
switch (response) {
case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
/* Error */
{
unsigned long status, descr_len, lang_len;
unsigned char *descr, *lang;
{
unsigned long status, descr_len, lang_len;
status = _libssh2_ntohu32(s);
s += 4;
descr_len = _libssh2_ntohu32(s);
s += 4;
descr = s;
s += descr_len;
lang_len = _libssh2_ntohu32(s);
s += 4;
lang = s;
s += lang_len;
if (s >
session->pkeyInit_data + session->pkeyInit_data_len) {
libssh2_error(session,
LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet");
goto err_exit;
}
publickey_status_error(NULL, session, status);
status = _libssh2_ntohu32(s);
s += 4;
descr_len = _libssh2_ntohu32(s);
s += 4;
/* description starts here */
s += descr_len;
lang_len = _libssh2_ntohu32(s);
s += 4;
/* lang starts here */
s += lang_len;
if (s >
session->pkeyInit_data + session->pkeyInit_data_len) {
_libssh2_error(session,
LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet");
goto err_exit;
}
publickey_status_error(NULL, session, status);
goto err_exit;
}
case LIBSSH2_PUBLICKEY_RESPONSE_VERSION:
/* What we want */
session->pkeyInit_pkey->version = _libssh2_ntohu32(s);
if (session->pkeyInit_pkey->version >
LIBSSH2_PUBLICKEY_VERSION) {
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Truncating remote publickey version from %lu",
"Truncate remote publickey version from %lu",
session->pkeyInit_pkey->version);
session->pkeyInit_pkey->version =
LIBSSH2_PUBLICKEY_VERSION;
@@ -475,9 +476,9 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
default:
/* Unknown/Unexpected */
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response, "
"ignoring");
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response, "
"ignoring");
LIBSSH2_FREE(session, session->pkeyInit_data);
session->pkeyInit_data = NULL;
}
@@ -488,10 +489,10 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
err_exit:
session->pkeyInit_state = libssh2_NB_state_sent4;
if (session->pkeyInit_channel) {
rc = libssh2_channel_close(session->pkeyInit_channel);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block closing channel");
rc = _libssh2_channel_close(session->pkeyInit_channel);
if (rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block closing channel");
return NULL;
}
}
@@ -507,26 +508,50 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
return NULL;
}
/*
* libssh2_publickey_init
*
* Startup the publickey subsystem
*/
LIBSSH2_API LIBSSH2_PUBLICKEY *
libssh2_publickey_init(LIBSSH2_SESSION *session)
{
LIBSSH2_PUBLICKEY *ptr;
BLOCK_ADJUST_ERRNO(ptr, session,
publickey_init(session));
return ptr;
}
/*
* libssh2_publickey_add_ex
*
* Add a new public key entry
*/
LIBSSH2_API int
libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
unsigned long name_len, const unsigned char *blob,
unsigned long blob_len, char overwrite,
unsigned long num_attrs,
const libssh2_publickey_attribute attrs[])
{
LIBSSH2_CHANNEL *channel = pkey->channel;
LIBSSH2_SESSION *session = channel->session;
/* 19 = packet_len(4) + add_len(4) + "add"(3) + name_len(4) + {name} blob_len(4) + {blob} */
LIBSSH2_CHANNEL *channel;
LIBSSH2_SESSION *session;
/* 19 = packet_len(4) + add_len(4) + "add"(3) + name_len(4) + {name}
blob_len(4) + {blob} */
unsigned long i, packet_len = 19 + name_len + blob_len;
unsigned char *comment = NULL;
unsigned long comment_len = 0;
int rc;
if(!pkey)
return LIBSSH2_ERROR_BAD_USE;
channel = pkey->channel;
session = channel->session;
if (pkey->add_state == libssh2_NB_state_idle) {
pkey->add_packet = NULL;
@@ -555,9 +580,9 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
pkey->add_packet = LIBSSH2_ALLOC(session, packet_len);
if (!pkey->add_packet) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey \"add\" packet");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey \"add\" packet");
}
pkey->add_s = pkey->add_packet;
@@ -611,22 +636,23 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
}
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Sending publickey \"add\" packet: type=%s blob_len=%ld num_attrs=%ld",
"Sending publickey \"add\" packet: "
"type=%s blob_len=%ld num_attrs=%ld",
name, blob_len, num_attrs);
pkey->add_state = libssh2_NB_state_created;
}
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 == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if ((pkey->add_s - pkey->add_packet) != rc) {
LIBSSH2_FREE(session, pkey->add_packet);
pkey->add_packet = NULL;
return libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey add packet");
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey add packet");
}
LIBSSH2_FREE(session, pkey->add_packet);
pkey->add_packet = NULL;
@@ -635,7 +661,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
}
rc = publickey_response_success(pkey);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
@@ -645,27 +671,35 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
}
/* libssh2_publickey_remove_ex
* Remove an existing publickey so that authentication can no longer be performed using it
* Remove an existing publickey so that authentication can no longer be
* performed using it
*/
LIBSSH2_API int
libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
const unsigned char *name, unsigned long name_len,
const unsigned char *blob, unsigned long blob_len)
{
LIBSSH2_CHANNEL *channel = pkey->channel;
LIBSSH2_SESSION *session = channel->session;
/* 22 = packet_len(4) + remove_len(4) + "remove"(6) + name_len(4) + {name} + blob_len(4) + {blob} */
LIBSSH2_CHANNEL *channel;
LIBSSH2_SESSION *session;
/* 22 = packet_len(4) + remove_len(4) + "remove"(6) + name_len(4) + {name}
+ blob_len(4) + {blob} */
unsigned long packet_len = 22 + name_len + blob_len;
int rc;
if(!pkey)
return LIBSSH2_ERROR_BAD_USE;
channel = pkey->channel;
session = channel->session;
if (pkey->remove_state == libssh2_NB_state_idle) {
pkey->remove_packet = NULL;
pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len);
if (!pkey->remove_packet) {
return libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey \"remove\" packet");
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey \"remove\" packet");
}
pkey->remove_s = pkey->remove_packet;
@@ -685,23 +719,24 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
pkey->remove_s += blob_len;
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
"Sending publickey \"remove\" packet: type=%s blob_len=%ld",
"Sending publickey \"remove\" packet: "
"type=%s blob_len=%ld",
name, blob_len);
pkey->remove_state = libssh2_NB_state_created;
}
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 == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if ((pkey->remove_s - pkey->remove_packet) != rc) {
LIBSSH2_FREE(session, pkey->remove_packet);
pkey->remove_packet = NULL;
pkey->remove_state = libssh2_NB_state_idle;
return libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey remove packet");
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey remove packet");
}
LIBSSH2_FREE(session, pkey->remove_packet);
pkey->remove_packet = NULL;
@@ -710,7 +745,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
}
rc = publickey_response_success(pkey);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
@@ -726,14 +761,20 @@ LIBSSH2_API int
libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
libssh2_publickey_list ** pkey_list)
{
LIBSSH2_CHANNEL *channel = pkey->channel;
LIBSSH2_SESSION *session = channel->session;
LIBSSH2_CHANNEL *channel;
LIBSSH2_SESSION *session;
libssh2_publickey_list *list = NULL;
unsigned long buffer_len = 12, keys = 0, max_keys = 0, i;
/* 12 = packet_len(4) + list_len(4) + "list"(4) */
int response;
int rc;
if(!pkey)
return LIBSSH2_ERROR_BAD_USE;
channel = pkey->channel;
session = channel->session;
if (pkey->listFetch_state == libssh2_NB_state_idle) {
pkey->listFetch_data = NULL;
@@ -753,15 +794,15 @@ 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 == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
pkey->listFetch_state = libssh2_NB_state_idle;
return libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey list packet");
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey list packet");
}
pkey->listFetch_state = libssh2_NB_state_sent;
@@ -770,12 +811,12 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
while (1) {
rc = publickey_packet_receive(pkey, &pkey->listFetch_data,
&pkey->listFetch_data_len);
if (rc == PACKET_EAGAIN) {
if (rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
goto err_exit;
}
@@ -783,48 +824,47 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
if ((response =
publickey_response_id(&pkey->listFetch_s,
pkey->listFetch_data_len)) < 0) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code");
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code");
goto err_exit;
}
switch (response) {
case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
/* Error, or processing complete */
{
unsigned long status, descr_len, lang_len;
unsigned char *descr, *lang;
{
unsigned long status, descr_len, lang_len;
status = _libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
descr_len = _libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
descr = pkey->listFetch_s;
pkey->listFetch_s += descr_len;
lang_len = _libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
lang = pkey->listFetch_s;
pkey->listFetch_s += lang_len;
status = _libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
descr_len = _libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
/* description starts at pkey->listFetch_s */
pkey->listFetch_s += descr_len;
lang_len = _libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
/* lang starts at pkey->listFetch_s */
pkey->listFetch_s += lang_len;
if (pkey->listFetch_s >
pkey->listFetch_data + pkey->listFetch_data_len) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet");
goto err_exit;
}
if (status == LIBSSH2_PUBLICKEY_SUCCESS) {
LIBSSH2_FREE(session, pkey->listFetch_data);
pkey->listFetch_data = NULL;
*pkey_list = list;
*num_keys = keys;
pkey->listFetch_state = libssh2_NB_state_idle;
return 0;
}
publickey_status_error(pkey, session, status);
if (pkey->listFetch_s >
pkey->listFetch_data + pkey->listFetch_data_len) {
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet");
goto err_exit;
}
if (status == LIBSSH2_PUBLICKEY_SUCCESS) {
LIBSSH2_FREE(session, pkey->listFetch_data);
pkey->listFetch_data = NULL;
*pkey_list = list;
*num_keys = keys;
pkey->listFetch_state = libssh2_NB_state_idle;
return 0;
}
publickey_status_error(pkey, session, status);
goto err_exit;
}
case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY:
/* What we want */
if (keys >= max_keys) {
@@ -836,9 +876,9 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
(max_keys +
1) * sizeof(libssh2_publickey_list));
if (!newlist) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey list");
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey list");
goto err_exit;
}
list = newlist;
@@ -854,9 +894,9 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
LIBSSH2_ALLOC(session,
sizeof(libssh2_publickey_attribute));
if (!list[keys].attrs) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey attributes");
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey attributes");
goto err_exit;
}
list[keys].attrs[0].name = "comment";
@@ -896,9 +936,9 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
list[keys].num_attrs *
sizeof(libssh2_publickey_attribute));
if (!list[keys].attrs) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey attributes");
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey attributes");
goto err_exit;
}
for(i = 0; i < list[keys].num_attrs; i++) {
@@ -912,13 +952,16 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
pkey->listFetch_s += 4;
list[keys].attrs[i].value = (char *) pkey->listFetch_s;
pkey->listFetch_s += list[keys].attrs[i].value_len;
list[keys].attrs[i].mandatory = 0; /* actually an ignored value */
/* actually an ignored value */
list[keys].attrs[i].mandatory = 0;
}
} else {
list[keys].attrs = NULL;
}
}
list[keys].packet = pkey->listFetch_data; /* To be FREEd in libssh2_publickey_list_free() */
/* To be FREEd in libssh2_publickey_list_free() */
list[keys].packet = pkey->listFetch_data;
keys++;
list[keys].packet = NULL; /* Terminate the list */
@@ -926,8 +969,8 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
break;
default:
/* Unknown/Unexpected */
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response, ignoring");
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response");
LIBSSH2_FREE(session, pkey->listFetch_data);
pkey->listFetch_data = NULL;
}
@@ -953,9 +996,14 @@ LIBSSH2_API void
libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey,
libssh2_publickey_list * pkey_list)
{
LIBSSH2_SESSION *session = pkey->channel->session;
LIBSSH2_SESSION *session;
libssh2_publickey_list *p = pkey_list;
if(!pkey || !p)
return;
session = pkey->channel->session;
while (p->packet) {
if (p->attrs) {
LIBSSH2_FREE(session, p->attrs);
@@ -971,11 +1019,16 @@ libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey,
* Shutdown the publickey subsystem
*/
LIBSSH2_API int
libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey)
{
LIBSSH2_SESSION *session = pkey->channel->session;
LIBSSH2_SESSION *session;
int rc;
if(!pkey)
return LIBSSH2_ERROR_BAD_USE;
session = pkey->channel->session;
/*
* Make sure all memory used in the state variables are free
*/
@@ -996,8 +1049,8 @@ libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
pkey->listFetch_data = NULL;
}
rc = libssh2_channel_free(pkey->channel);
if (rc == PACKET_EAGAIN)
rc = _libssh2_channel_free(pkey->channel);
if (rc == LIBSSH2_ERROR_EAGAIN)
return rc;
LIBSSH2_FREE(session, pkey);

Some files were not shown because too many files have changed in this diff Show More