Compare commits
193 Commits
libssh2-1.
...
libssh2-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5633bb4a3b | ||
![]() |
fabf1a45ee | ||
![]() |
2e352d3085 | ||
![]() |
8c9571b7ba | ||
![]() |
527c1b2def | ||
![]() |
ec934f6dab | ||
![]() |
516fa7fdd9 | ||
![]() |
3ce2628140 | ||
![]() |
ad88325b3f | ||
![]() |
2db4863e6e | ||
![]() |
691cabc048 | ||
![]() |
90b4b4073f | ||
![]() |
8ce9a66ccf | ||
![]() |
7015488150 | ||
![]() |
164838c7dd | ||
![]() |
f9b1b95059 | ||
![]() |
59207291fc | ||
![]() |
0da37e0924 | ||
![]() |
4552c73cd5 | ||
![]() |
306929ee80 | ||
![]() |
326f741a52 | ||
![]() |
aa4f861643 | ||
![]() |
fd691deb17 | ||
![]() |
20da09932e | ||
![]() |
3ab7af095a | ||
![]() |
5b1a7ec2f1 | ||
![]() |
5ee38702a0 | ||
![]() |
2165ceacd3 | ||
![]() |
121237ce2f | ||
![]() |
b3e832172b | ||
![]() |
3faa8bc940 | ||
![]() |
2f0c0cef76 | ||
![]() |
75909e05a9 | ||
![]() |
47b4e62780 | ||
![]() |
1b1ff333e4 | ||
![]() |
c1683ae92c | ||
![]() |
1b65c6ae26 | ||
![]() |
92ea3bda60 | ||
![]() |
811cce09b5 | ||
![]() |
6875285b71 | ||
![]() |
0cc14be09d | ||
![]() |
499b989d46 | ||
![]() |
fa07d9fefc | ||
![]() |
b0c32a85fc | ||
![]() |
7ed7dad3b4 | ||
![]() |
b215ec0af5 | ||
![]() |
ac6d0fb706 | ||
![]() |
e87293d480 | ||
![]() |
a3ce1073c4 | ||
![]() |
97a1881749 | ||
![]() |
80f7508d55 | ||
![]() |
e8c44e789f | ||
![]() |
ca2e81eb1f | ||
![]() |
aff9c825c8 | ||
![]() |
7899d28ecb | ||
![]() |
2f5a2ff8e6 | ||
![]() |
160453cee4 | ||
![]() |
82fa5d2167 | ||
![]() |
1c3e1c4d25 | ||
![]() |
1d2a5b8456 | ||
![]() |
1d11d02aa9 | ||
![]() |
f4ad3e0120 | ||
![]() |
772564650d | ||
![]() |
05ba8db8aa | ||
![]() |
1964ccb557 | ||
![]() |
bef0ce5392 | ||
![]() |
fb6afd01a1 | ||
![]() |
a302428335 | ||
![]() |
7ad152a6b2 | ||
![]() |
075ff19574 | ||
![]() |
16f46c1cfc | ||
![]() |
aa2fdb3e7e | ||
![]() |
8f10da89c5 | ||
![]() |
2dfa5d38cb | ||
![]() |
095e9e7b3e | ||
![]() |
588c8946fc | ||
![]() |
a6fc9aeec9 | ||
![]() |
7603c0f854 | ||
![]() |
8974dc05ae | ||
![]() |
6395a738fd | ||
![]() |
73be9fab04 | ||
![]() |
753e55ef23 | ||
![]() |
4760e4d051 | ||
![]() |
57af0da9f7 | ||
![]() |
024b5d29f5 | ||
![]() |
a0dd0c5992 | ||
![]() |
92d308c157 | ||
![]() |
4ae71b4838 | ||
![]() |
ba190d34c6 | ||
![]() |
b84f69c960 | ||
![]() |
a7aee34522 | ||
![]() |
1dc366109d | ||
![]() |
e1ea2eb7c2 | ||
![]() |
610a8ab919 | ||
![]() |
8ec21e0afe | ||
![]() |
8e0983347b | ||
![]() |
95db6cc62c | ||
![]() |
727043074a | ||
![]() |
5b4ed2717b | ||
![]() |
59f74de157 | ||
![]() |
d87562976a | ||
![]() |
a94886f157 | ||
![]() |
dec0ea9e70 | ||
![]() |
030b2d9b60 | ||
![]() |
c48840ba88 | ||
![]() |
d9cdd8c0a7 | ||
![]() |
c49061e708 | ||
![]() |
d674b1a09a | ||
![]() |
5ede32a826 | ||
![]() |
3a391f6cf2 | ||
![]() |
64063d5f0b | ||
![]() |
784db8e987 | ||
![]() |
84efbf788f | ||
![]() |
f805c2db2a | ||
![]() |
08ce6425f6 | ||
![]() |
fac9412a74 | ||
![]() |
4d15e0c9d1 | ||
![]() |
6140ec2de3 | ||
![]() |
70d6bd6c6f | ||
![]() |
98e38c4f3a | ||
![]() |
cd6d41b806 | ||
![]() |
c36f379b88 | ||
![]() |
77a9335515 | ||
![]() |
59636cc11e | ||
![]() |
0d58af6aec | ||
![]() |
c34e1d8735 | ||
![]() |
861fc75fa3 | ||
![]() |
f4d302fdfe | ||
![]() |
4faf67d3e9 | ||
![]() |
76a30f2c6f | ||
![]() |
bcd7eee1d2 | ||
![]() |
046ad88d88 | ||
![]() |
9887c01103 | ||
![]() |
822f9e8689 | ||
![]() |
3ee2aabd7a | ||
![]() |
7c49c8be58 | ||
![]() |
665d9ee885 | ||
![]() |
b3d6c6567d | ||
![]() |
7dd574c353 | ||
![]() |
018602cb34 | ||
![]() |
eec7f2fb63 | ||
![]() |
c32b0d164e | ||
![]() |
835c03e076 | ||
![]() |
6c6c43f92c | ||
![]() |
5af87e8c80 | ||
![]() |
10a65fda01 | ||
![]() |
8d9d3e0d7a | ||
![]() |
c46abb2663 | ||
![]() |
0a34fa79f0 | ||
![]() |
43001570d6 | ||
![]() |
4b878e7cf8 | ||
![]() |
ac709e0d4f | ||
![]() |
56d0877f07 | ||
![]() |
51a8335486 | ||
![]() |
2bd9418ac7 | ||
![]() |
4b8013a8a7 | ||
![]() |
697b4e8ed7 | ||
![]() |
2afa5b2dc2 | ||
![]() |
992aff7aca | ||
![]() |
ef4c8718c2 | ||
![]() |
c375e5e5ad | ||
![]() |
46be03f92b | ||
![]() |
1d83b520b4 | ||
![]() |
f9c0a4a95a | ||
![]() |
7861ae8e4e | ||
![]() |
0f0652a309 | ||
![]() |
2cc4a629ac | ||
![]() |
04f90b2265 | ||
![]() |
7dc2bfac94 | ||
![]() |
35cf08e130 | ||
![]() |
32bd0df992 | ||
![]() |
38940f45d2 | ||
![]() |
537a00ee4b | ||
![]() |
6ddcc493e8 | ||
![]() |
3496e1c2a2 | ||
![]() |
49ddf447ff | ||
![]() |
04d4bbb66b | ||
![]() |
897f8463d8 | ||
![]() |
2fd044fdf5 | ||
![]() |
20e969d2e0 | ||
![]() |
33e2bc8785 | ||
![]() |
d7e6f9cf27 | ||
![]() |
be7cee1b3e | ||
![]() |
518d25eba1 | ||
![]() |
1785d0d6f3 | ||
![]() |
31d71a94f2 | ||
![]() |
22a2de7347 | ||
![]() |
4cf935abab | ||
![]() |
cce6ebbee7 | ||
![]() |
18605cb81f | ||
![]() |
3490b3fe10 | ||
![]() |
c87a48ae4c | ||
![]() |
ab8ee8abf3 |
@@ -29,7 +29,8 @@ vms/readme.vms vms/libssh2_config.h
|
||||
WIN32FILES = win32/Makefile.win32 win32/libssh2.dsw \
|
||||
win32/config.mk win32/Makefile win32/test/Makefile.win32 \
|
||||
win32/libssh2_config.h win32/tests.dsp win32/rules.mk $(DSP) \
|
||||
win32/msvcproj.head win32/msvcproj.foot
|
||||
win32/msvcproj.head win32/msvcproj.foot win32/libssh2.rc \
|
||||
win32/Makefile.Watcom
|
||||
|
||||
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \
|
||||
maketgz NMakefile TODO RELEASE-NOTES libssh2.pc.in $(VMSFILES)
|
||||
|
@@ -4,4 +4,4 @@ CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
|
||||
global.c
|
||||
|
||||
HHEADERS = libssh2_priv.h openssl.h libgcrypt.h transport.h channel.h \
|
||||
comp.h mac.h misc.h packet.h userauth.h session.h
|
||||
comp.h mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h
|
||||
|
760
NEWS
760
NEWS
@@ -1,759 +1,3 @@
|
||||
libssh2 1.2.6 (June 10, 2010)
|
||||
The old NEWS file.
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o Added libssh2_sftp_statvfs() and libssh2_sftp_fstatvfs()
|
||||
o Added libssh2_knownhost_checkp()
|
||||
o Added libssh2_scp_send64()
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o wait_socket: make c89 compliant and use two fd_sets for select()
|
||||
o OpenSSL AES-128-CTR detection
|
||||
o proper keyboard-interactive user dialog in the sftp.c example
|
||||
o build procedure for VMS
|
||||
o fixed libssh2.dsw to use the generated libssh2.dsp
|
||||
o several Windows-related build fixes
|
||||
o fail to init SFTP if session isn't already authenticated
|
||||
o many tiny fixes that address clang-analyzer warnings
|
||||
o sftp_open: deal with short channel_write calls
|
||||
o libssh2_publickey_init: fixed to work better non-blocking
|
||||
o sftp_close_handle: add precation to not access NULL pointer
|
||||
o sftp_readdir: simplified and bugfixed
|
||||
o channel_write: if data has been sent, don't return EAGAIN
|
||||
|
||||
Version 1.2.5 (April 13, 2010)
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o Added Add keep-alive support: libssh2_keepalive_config() and
|
||||
libssh2_keepalive_send()
|
||||
o Added libssh2_knownhost_addc(), libssh2_init() and libssh2_exit()
|
||||
o Added LIBSSH2_SFTP_S_IS***() macros
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o fix memory leak in libssh2_session_startup()
|
||||
o added missing error codes - shown as hangs in blocking mode
|
||||
o fix memory leak in userauth_keyboard_interactive()
|
||||
o libssh2_knownhost_del: fix write to freed memory
|
||||
o Send and receive channel EOF before sending SSH_MSG_CHANNEL_CLOSE
|
||||
o Use AES-CTR from OpenSSL when available
|
||||
o Fixed gettimeofday to compile with Visual C++ 6
|
||||
o NULL dereference when window adjusting a non-existing channel
|
||||
o avoid using poll on interix and mac os x systems
|
||||
o fix scp memory leak
|
||||
o Correctly clear blocking flag after sending multipart packet
|
||||
o Reduce used window sizes by factor 10
|
||||
o libssh2_userauth_publickey_fromfile_ex() handles a NULL password
|
||||
o sftp_init() deal with _libssh2_channel_write() short returns
|
||||
|
||||
o Use poll instead of select when available. By Paul Querna.
|
||||
|
||||
o Add APIs to have libssh2 automatically send keep-alive requests.
|
||||
The APIs are libssh2_keepalive_config, and libssh2_keepalive_send.
|
||||
By Simon Josefsson.
|
||||
|
||||
o Add global init/exit points, to do crypto initialization in one place.
|
||||
The APIs are libssh2_init and libssh2_exit. By Lars Nordin.
|
||||
|
||||
* (February 15 2010) Daniel Stenberg:
|
||||
- Added 46 new man pages for public convenience macros. The man pages are
|
||||
just short redirects to the actual underlying function. The were all
|
||||
initially created by a script.
|
||||
|
||||
- Committed the patch by Yoichi Iwaki in bug #2929647, which fixed a memory
|
||||
leak when an 'outbuf' was still allocated when a session was freed.
|
||||
|
||||
Version 1.2.4 (February 13, 2010)
|
||||
|
||||
o Resolve compile issues on Solaris x64 and UltraSPARC
|
||||
o Allow compiling with OpenSSL when AES isn't available
|
||||
o Fix Tru64 socklen_t compile issue with example/direct_tcpip.c
|
||||
|
||||
Version 1.2.3 (February 3, 2010)
|
||||
|
||||
o Added libssh2_trace_sethandler()
|
||||
o Added the direct_tcpip.c example
|
||||
o Fixed memory leak in userauth_publickey
|
||||
o Added support for authentication via SSH-Agent. By Daiki Ueno.
|
||||
|
||||
o Respond to unknown SSH_MSG_GLOBAL_REQUEST/SSH_MSG_CHANNEL_REQUEST
|
||||
with SSH_MSG_REQUEST_FAILURE/SSH_MSG_CHANNEL_FAILURE in order to
|
||||
make (at least) OpenSSH server keepalive work. Before OpenSSH
|
||||
servers (configured with a positive ClientAliveInterval) would
|
||||
terminate connections against libssh2 clients because libssh2 did
|
||||
not respond properly to the request. By Simon Josefsson.
|
||||
|
||||
Version 1.2.2 (November 16, 2009)
|
||||
|
||||
* This release includes the following changes:
|
||||
|
||||
o Fix crash when server sends an invalid SSH_MSG_IGNORE message.
|
||||
Reported by Bob Alexander <balexander@expressor-software.com> in
|
||||
<http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
|
||||
By Simon Josefsson.
|
||||
|
||||
o Support for the "aes128-ctr", "aes192-ctr", "aes256-ctr" ciphers
|
||||
as per RFC 4344 for libgcrypt and OpenSSL. They are now the
|
||||
preferred ciphers. By Simon Josefsson.
|
||||
|
||||
o Support for the "arcfour128" cipher as per RFC 4345 for libgcrypt
|
||||
and OpenSSL. It is preferred over the normal "arcfour" cipher
|
||||
which is somewhat broken. By Simon Josefsson.
|
||||
|
||||
o Add support for GCC visibility features. By Cristian Rodr<64>guez.
|
||||
|
||||
o Fix libssh2_channel_forward_accept. By Juzna.
|
||||
|
||||
o Generate Win32 files correctly. By Peter Stuge.
|
||||
|
||||
o Fix permission issue in ssh2 self test. By Dan Fandrich.
|
||||
|
||||
o Use memmove instead of memcpy in one place which copies
|
||||
overlapping memory areas.
|
||||
|
||||
o Cleanup hard coding of cipher modes in libgcrypt backend. By Simon.
|
||||
|
||||
o Added man page for libssh2_knownhost_free. By Daniel.
|
||||
|
||||
Version 1.2.1 (September 28, 2009)
|
||||
|
||||
* This release includes the following changes:
|
||||
|
||||
o generate and install libssh2.pc
|
||||
|
||||
... and the following bugfixes:
|
||||
|
||||
o proper return codes returned from several functions
|
||||
o return EAGAIN internal cleanup
|
||||
o added knownhost.c to windows makefiles
|
||||
o pass private-key to OpenSSL as a filename with BIO_new_file().
|
||||
o make libssh2_scp_send/recv do blocking mode correctly
|
||||
o libssh2_channel_wait_closed() could hang
|
||||
o libssh2_channel_read_ex() must return 0 when closed
|
||||
o added gettimeofday() function for win32 for the debug trace outputs
|
||||
o transport layer bug causing invalid -39 (LIBSSH2_ERROR_BAD_USE) errors
|
||||
o scp examples now loop correctly over libssh2_channel_write()
|
||||
|
||||
* (August 29 2009) Daniel Stenberg:
|
||||
|
||||
- I fixed all code to use the recently added dedicated linked list functions
|
||||
instead of doing the same stuff spread out all over.
|
||||
|
||||
- I also fixed a few cases where local variables where used to keep memory
|
||||
but was used to keep state for re-invokes due to non-blocking situations
|
||||
which would lead to segfaults.
|
||||
|
||||
Version 1.2 (August 10, 2009)
|
||||
-----------------------------
|
||||
|
||||
* (August 02 2009) Alexander Lamaison:
|
||||
|
||||
- changed _libssh2_rsa_new_private and _libssh2_rsa_new_private so that they
|
||||
no longer use the OpenSSL functions that take a FILE* argument. Passing
|
||||
CRT-created objects across a DLL boundary causes crashes on Windows of the
|
||||
DLL and the client aren't linked to the exact same verison of the CRT. Now
|
||||
we pass the keys as strings to avoid this issue.
|
||||
|
||||
* (May 29 2009) Daniel Stenberg:
|
||||
|
||||
- Updated the knownhost API and there are now 9 functions, and all of them
|
||||
have man pages. The libssh2.h now defines HAVE_LIBSSH2_KNOWNHOST_API to
|
||||
ease things for applications to check for the correct release before trying
|
||||
to use it.
|
||||
|
||||
* (May 23 2009) Daniel Stenberg:
|
||||
|
||||
- Anonymous bug report #2795816 revealed that doing subsequent
|
||||
libssh2_sftp_init() calls on the same session failed.
|
||||
|
||||
* (May 20 2009) Daniel Stenberg:
|
||||
|
||||
- made libssh2_sftp_write() properly deal with huge/any sized input buffers.
|
||||
|
||||
- fixed libssh2_channel_write_ex() to return the correct return code, and
|
||||
deal with sending off huge buffers better
|
||||
|
||||
* (May 7 2009) Daniel Stenberg:
|
||||
|
||||
- linked list code. I got a bit tired of the fact that we don't have any
|
||||
generic linked-list functions within libssh2 so I wrote up the first embryo
|
||||
for one that I use for this new functionality. The plan would then be to
|
||||
move all existing code that uses linked lists to use this new set.
|
||||
|
||||
- base64 encode. I had to add a base64 encoding function which was missing
|
||||
in the code base so it helps to "bloat" my patch.
|
||||
|
||||
- The knownhost API is currently:
|
||||
|
||||
_init() - init a bundle of known hosts
|
||||
_add() - add a known host
|
||||
_del() - delete a known host
|
||||
_free() - free an entire bundle of known hosts
|
||||
_check() - check if a host+key is present in the bundle
|
||||
|
||||
The convenience function:
|
||||
|
||||
_parsefile() - reads a ~/.ssh/known_hosts file and add all entries to the
|
||||
given bundle
|
||||
|
||||
- there's no docs other than some comments in the code/headers yet
|
||||
|
||||
- the patch includes changes to example/simple/ssh2_exec.c that makes use of
|
||||
a few of these functions. Using that I've verified that the functions in
|
||||
fact can verify my localhost's key agains my ~/.ssh/known_hosts file
|
||||
|
||||
* (Apr 30 2009) Daniel Stenberg:
|
||||
|
||||
Markus posted a bug report about a bad 0-return from libssh2_channel_read:
|
||||
http://libssh2.haxx.se/mail/libssh2-devel-archive-2009-04/0076.shtml
|
||||
|
||||
And it was indeed a bad loop that terminated too early due to a receveived
|
||||
close packet.
|
||||
|
||||
* (Apr 14 2009) Daniel Stenberg:
|
||||
|
||||
libssh2_poll() and libssh2_poll_channel_read() are now considered and
|
||||
documented deprecated and they will be removed at next soname bump. It also
|
||||
saves us from fixing some rather quirky bugs in libssh2_poll()...
|
||||
|
||||
|
||||
Version 1.1 (April 2, 2009)
|
||||
---------------------------
|
||||
|
||||
- (Mar 28 2009) Daniel Stenberg:
|
||||
|
||||
Jean-Louis Charton found a memory leak in
|
||||
libssh2_userauth_hostbased_fromfile_ex()
|
||||
|
||||
- (Mar 25 2009) Daniel Stenberg:
|
||||
|
||||
* Renamed the functions in src/transport.c to be _libssh2_transport_ prefixed
|
||||
and introduced a transport.h header.
|
||||
|
||||
* Fixed the blocking mode to only change behavior not the actual underlying
|
||||
socket mode so we now always work with non-blocking sockets. This also
|
||||
introduces a new rule of thumb in libssh2 code: we don't call the
|
||||
external function calls internally. We use the internal (non-blocking)
|
||||
ones!
|
||||
|
||||
* libssh2_channel_receive_window_adjust2 was added and
|
||||
libssh2_channel_receive_window_adjust is now deprecated
|
||||
|
||||
* Introduced "local" header files with prototypes etc for different parts
|
||||
instead of cramming everything into libssh2_priv.h. channel.h is the
|
||||
first.
|
||||
|
||||
- (Mar 19 2009) Daniel Stenberg: based on a patch by "E L" we now use errno
|
||||
properly after recv() and send() calls (that internally are now known as
|
||||
_libssh2_recv() and _libssh2_send()) so that the API and more works fine on
|
||||
windows too!
|
||||
|
||||
- (Mar 17 2009) Simon Josefsson:
|
||||
|
||||
Added a Libtool -export-symbols-regex flag to reduce the number of
|
||||
exported symbols in shared libraries. Reported by Mikhail Gusarov.
|
||||
|
||||
- (Mar 16 2009) Daniel Stenberg:
|
||||
|
||||
I renamed a few man pages to match the exact name of the functions they
|
||||
describe. I also added template versions for the 13 functions that
|
||||
previously lacked man pages. While these don't contain any docs just yet, it
|
||||
will now be easier to add the info as the foundation is there!
|
||||
|
||||
- (Mar 15 2009) Daniel Stenberg:
|
||||
|
||||
* libssh2_channel_read_ex() was simplified and enhanced. It now adjusts the
|
||||
window less frequent and uses much larger window that now allows MUCH
|
||||
faster transfers.
|
||||
|
||||
* SCP send/recv now allow file names with whitespaces etc, thanks to a patch
|
||||
by Heiner Steven
|
||||
|
||||
- (Mar 13 2009) Daniel Stenberg: Cleanups, that do seem to have boosted SFTP
|
||||
download performance up to 300% in some tests:
|
||||
|
||||
* cut off "_ex" from several internal function names
|
||||
|
||||
* corrected some log outputs
|
||||
|
||||
* simplified libssh2_channel_read_ex() and made it much faster in the process
|
||||
|
||||
* cut out {{{ and }}} comments that were incorrect anyway
|
||||
|
||||
* fixed sftp_packet_ask() to return the correct packet by using memcmp() and
|
||||
not strncmp()
|
||||
|
||||
* fixed mkdir()'s wait for packet to use the correct request_id - it
|
||||
semi-worked previously because strncmp() in sftp_packet_ask() made it
|
||||
match far too easily.
|
||||
|
||||
* took away the polling functionality from sftp_packet_ask() since it wasn't
|
||||
used
|
||||
|
||||
- (Mar 7 2009) Olivier Hervieu pointed out a flaw in the
|
||||
libssh2_channel_x11_req_ex() function that made it produce a crappy random
|
||||
chunk of data. Peter Stuge improved the fix to not do out-of-boundary
|
||||
writes. I (Daniel Stenberg) replaced the snprintf() with a plain sprintf()
|
||||
since the size argument wasn't adding anything anyway.
|
||||
|
||||
- (Feb 23 2009) Added libssh2_version()
|
||||
|
||||
- (Feb 20 2009) libssh2_channel_direct_tcpip_ex() bug #1902169 fixed, which
|
||||
caused it to fail when called a second time.
|
||||
|
||||
- (Feb 12 2009) Romain Bondue extended Markus Moeller fix from Feb 8, based on
|
||||
a previous (uncommitted) patch by Erik Brossler. It improves
|
||||
libssh2_channel_write_ex in blocking situations when the socket is set non-
|
||||
blocking.
|
||||
|
||||
- (Feb 8 2009) Markus Moeller fixed a flaw in libssh2_channel_write_ex() that
|
||||
would occur on EAGAIN situations.
|
||||
|
||||
Version 1.0 (December 26 2008)
|
||||
------------------------------
|
||||
|
||||
- (Dec 20 2008) Based on Alexander Lamaison's patch, there's now a new
|
||||
function called libssh2_sftp_tell64() that returns the 64 bit file offset,
|
||||
as the existing libssh2_sftp_tell() only returns a size_t.
|
||||
|
||||
- (Dec 18 2008) Markus Moeller fixed the issue also reported by Alexander
|
||||
Lamaison which caused SFTP reads with large buffers to fail.
|
||||
|
||||
- Several flaws were fixed that prevented at least SFTP to work reliably
|
||||
|
||||
- Vlad Grachov brought the new function called
|
||||
libssh2_session_block_directions() which returns a bitmask for what
|
||||
directions the connection blocks. It is to be used applications that use
|
||||
non-blocking sockets and when a libssh2 function returns
|
||||
LIBSSH2_ERROR_EAGAIN this function can be used to figure out in which
|
||||
direction the socket would block and thus it can wait for the socket to
|
||||
again be ready for communication in that direction before it calls libssh2
|
||||
again.
|
||||
|
||||
- Vincent Jaulin brought the new libssh2_channel_request_pty_size_ex()
|
||||
function.
|
||||
|
||||
- Carlo Bramini fixed the build for msys+mingw. Bug #1943976.
|
||||
|
||||
- Neil Gierman provided improved Visual Studio 2008 code in bug #1946268
|
||||
|
||||
- Bug #1862727 fixed libssh2_poll() to work on windows (by defining
|
||||
HAVE_SELECT).
|
||||
|
||||
- Based on bug #1815692, we introduce libssh2_sftp_seek64() that allows
|
||||
seeking beyond the 2GB margin even on 32bit machines.
|
||||
|
||||
- Based on a patch in bug #1878059 by Steven Ayre libssh2 now parses >2GB file
|
||||
sizes when downloading SCP files.
|
||||
|
||||
- Bug #2064371 pointed out that the SSH2 banner may not use dash
|
||||
('-'). Reported by Bjorn Stenborg.
|
||||
|
||||
- Sean Peterson fixed a key re-exchange bug:
|
||||
http://daniel.haxx.se/projects/libssh2/mail/libssh2-devel-archive-2008-06/0002.shtml
|
||||
|
||||
- Mike Protts filed the bug report #1908724 that identified and fixed a problem
|
||||
with SFTP stat on files >4GB in size. Previously it used 32bit math only.
|
||||
|
||||
- Removed a stderr debug message that was accidentally left in (bug #1863153)
|
||||
|
||||
- OpenSSL and libz detection changed to make cross-compiling to Mingw
|
||||
work. See README for parameters to use if the auto-detection does
|
||||
not work for you. From Simon Josefsson.
|
||||
|
||||
- Simon Josefsson added a self-test that uses libssh2 to connect to a
|
||||
local sshd (only enabled if if OpenSSH is installed).
|
||||
|
||||
Version 0.18 (November 11 2007)
|
||||
-------------------------------
|
||||
|
||||
- Various changes that improve non-blocking operations and prevent stalls.
|
||||
Especially noticable on Windows since libssh2 just didn't work properly
|
||||
non-blocking on Windows before.
|
||||
|
||||
- Peter O'Gorman reported how a SCP transfer would hang for him, and it was
|
||||
fairly easy reproducable. One bug was in the transport layer, ignoring to
|
||||
read more data while there was data left even though it couldn't decrypt the
|
||||
data that was left due to it being too little... The other bug was in the
|
||||
channel layer, where the libssh2_channel_receive_window_adjust() function
|
||||
missed to set the state variables at times and thus this function would
|
||||
misbehave on repeated invokes.
|
||||
|
||||
- Changed the signature of libssh2_channel_setenv_ex to add const to the
|
||||
"varname" parameter (Dan Fandrich)
|
||||
|
||||
- Satish Mittal and David J Sullivan fixed an infinit recv() loop in
|
||||
libssh2_banner_receive()
|
||||
|
||||
Version 0.17 (August 6 2007)
|
||||
----------------------------
|
||||
Changes since previous version include:
|
||||
|
||||
o Re-indented the source code with this GNU indent setup:
|
||||
|
||||
--braces-on-if-line
|
||||
--braces-after-struct-decl-line
|
||||
--space-after-cast
|
||||
--line-length 79
|
||||
--comment-line-length 79
|
||||
--cuddle-else
|
||||
--no-tabs
|
||||
--tab-size 8
|
||||
--indent-level 4
|
||||
--no-space-after-for
|
||||
--space-after-if
|
||||
--space-after-while
|
||||
--no-space-after-function-call-names
|
||||
|
||||
Version 0.16 (August 6 2007)
|
||||
----------------------------
|
||||
Changes since previous version include:
|
||||
|
||||
o CRLF stripping fix for PEM reading
|
||||
o libssh2_scp_recv() error message fix
|
||||
o added HACKING as an initial attempt to describe our source code format
|
||||
o new public defines in include/libssh2.h to allow applictions to figure out
|
||||
version number etc
|
||||
o new script (maketgz) to build releases with
|
||||
o updated files for building with MSVC and mingw
|
||||
o keyboard-interactive would always fail due to claimed memory problem
|
||||
o a few minor memory leaks fixed
|
||||
o libssh2_poll() no longer relies on C99 features
|
||||
o AIX 4 and 5 now supports non-blocking sockets
|
||||
o large file magic checks in configure
|
||||
o LIBSSH2_APINO was removed from the public header file
|
||||
|
||||
This release would not have been possible without these friendly contributors:
|
||||
|
||||
James Housley, Simon Josefsson, Dan Fandrich, Guenter Knauf and I too did
|
||||
some poking. (Sorry if I forgot anyone I should've mentioned here.)
|
||||
|
||||
Of course we would have nothing without the great work by Sara Golemon that
|
||||
we're extending and building upon.
|
||||
|
||||
Version 0.15 (June 15 2007)
|
||||
---------------------------
|
||||
Added libssh2_sftp_readdir_ex() and updated LIBSSH2_APINO to
|
||||
200706151200 (James Housley)
|
||||
|
||||
Converted all of the libssh2 code to be able to work in non-blocking
|
||||
mode. This included some public API changes, listed below (James Housley)
|
||||
Changed function return values:
|
||||
int libssh2_session_free()
|
||||
int libssh2_publickey_shutdown()
|
||||
ssize_t libssh2_channel_read_ex()
|
||||
ssize_t libssh2_channel_write_ex()
|
||||
|
||||
Added functions:
|
||||
libssh2_session_last_errno(), libssh2_channel_handle_extended_data2(),
|
||||
libssh2_channel_wait_closed(), libssh2_channel_wait_eof(),
|
||||
libssh2_session_set_blocking()
|
||||
|
||||
Removed functions:
|
||||
libssh2_channel_readnb_ex(), libssh2_channel_writenb_ex(),
|
||||
libssh2_sftp_readnb(), libssh2_sftp_writenb(),
|
||||
libssh2_sftp_mkdirnb_ex()
|
||||
|
||||
Added the following functions for non-blocking operations: (Daniel Stenberg)
|
||||
libssh2_channel_readnb_ex()
|
||||
libssh2_channel_writenb_ex()
|
||||
libssh2_sftp_readnb()
|
||||
libssh2_sftp_writenb()
|
||||
|
||||
Size parameter changed from 'int' to 'unsigned int' in several
|
||||
public APIs.
|
||||
|
||||
Added (a few) man pages in docs/. (Daniel Stenberg)
|
||||
|
||||
Maximum SSH packet size is now some 35000 bytes.
|
||||
|
||||
Private include files are now in src/ and only public headers are in
|
||||
include/. (Daniel Stenberg)
|
||||
|
||||
Automake and libtool are being used (increased portability). (Daniel
|
||||
Stenberg)
|
||||
|
||||
Fixed OpenSSL detection using pkg-config. (Daniel Stenberg)
|
||||
|
||||
Simple self test added to tests/. (Simon Josefsson)
|
||||
|
||||
Libgcrypt can now be used instead of OpenSSL if you specify
|
||||
--with-libgcrypt. (Simon Josefsson)
|
||||
|
||||
Fixed a memory leak in the packet handling, and better handle out of
|
||||
memory situations. (Dan Fandrich)
|
||||
|
||||
Made libssh2 build with OpenSSL 0.9.6. (Dan Fandrich)
|
||||
|
||||
Improved portability to Solaris related to -lsocket and
|
||||
-lnsl. (Simon Josefsson)
|
||||
|
||||
Clean up of README, INSTALL, NEWS, added ChangeLog. (Simon
|
||||
Josefsson)
|
||||
|
||||
Improve debugging code. Avoids many #ifdef's.
|
||||
|
||||
Improved session closing to avoid potentially truncated files on
|
||||
OpenSSH servers (Dan Fandrich)
|
||||
|
||||
Made some function parameters in the API const (Dan Fandrich)
|
||||
|
||||
Version 0.14
|
||||
------------
|
||||
|
||||
Plug leaks in EVP cipher init/shutdown. (Selcuk Gueney)
|
||||
|
||||
Allow socket_fd == 0 in libssh2_session_startup(). (puudeli)
|
||||
|
||||
Swap ordering of packet_add/packet-inspection to avoid inspect after
|
||||
free. (Selcuk)
|
||||
|
||||
Swap KEX_INIT ordering, send our KEX_INIT first.
|
||||
|
||||
Add check for oportunistic KEX_INIT packets. Burn bad guess if necessary.
|
||||
|
||||
Fix OpenSSL detection using pkg-config. (Dan Casey)
|
||||
|
||||
Version 0.13
|
||||
------------
|
||||
|
||||
Fixed channel not being marked closed when CHANNEL_CLOSE package cannot be
|
||||
sent. (David Robins)
|
||||
|
||||
Fixed payload packet allocation bug when invalid packet length
|
||||
received. (David Robins)
|
||||
|
||||
Fixed `make install' target for MacOSX.
|
||||
|
||||
Add terminating NULL character to readlink()/realpath() results.
|
||||
|
||||
BugFix#1436593: Apply build options for HPUX targets.
|
||||
|
||||
Version 0.12
|
||||
------------
|
||||
|
||||
Added support for publickey subsytem (not the same as publickey auth).
|
||||
|
||||
Fix x11_req. Multiple packet_len issues and error handling logic.
|
||||
(Thanks Simon Hart)
|
||||
|
||||
Fix generation of 'e' portion of Diffie-Hellman keyset.
|
||||
|
||||
Use appropriate order for BN_rand() rather than fixed group1-specific value.
|
||||
|
||||
Re-fixed libssh2_sftp_rename_ex()
|
||||
|
||||
Transport had right packet_len, but sftp layer still had extra 4 bytes.
|
||||
|
||||
Fixed build with newer OpenSSL headers.
|
||||
|
||||
Added extern "C" declarations to libssh2_sftp.h for C++ compatability.
|
||||
|
||||
Version 0.11
|
||||
------------
|
||||
|
||||
Added libssh2_chnnale_get_exit_status() -- Mikhail
|
||||
|
||||
Added libssh2_channel_wait_closed() -- Mikhail
|
||||
|
||||
Added libssh2_userauth_keyboard_interactive_ex() -- Mikhail
|
||||
|
||||
Added libssh2_channel_receive_window_adjust() to be able to increase the
|
||||
size of the receive window.
|
||||
|
||||
Added queueing for small window_adjust packets to avoid unnecessary packet
|
||||
conversation.
|
||||
|
||||
Fixed libssh2_sftp_rename_ex() to only send flags parameter if version >= 5
|
||||
negotiated (not currently possible, but will be and might as well keep the
|
||||
API consistent).
|
||||
|
||||
Version 0.10
|
||||
------------
|
||||
|
||||
Added developer debugging hooks. See --enable-debug-* options to ./configure
|
||||
|
||||
Ignore extended data in the SFTP layer. With no other mechanism to deal
|
||||
with that data it'd just fill up and get stuck.
|
||||
|
||||
(Re)Fixed channel_write() to provide an opportunity for window space to
|
||||
become available again.
|
||||
|
||||
(Re)Fixed SFTP INIT to send the correct SFTP packet length.
|
||||
|
||||
Fixed segfault when client and host can't agree on a hostkey/crypt/mac/comp
|
||||
method. (Thanks puudeli)
|
||||
|
||||
Fixed major issue with sftp packet buffering mechanism. Using wrong
|
||||
blocking semantics. (No puudeli, YOU the man)
|
||||
|
||||
Reduced busy-looping of libssh2_sftp_packet_requirev.
|
||||
|
||||
Version 0.9
|
||||
-----------
|
||||
|
||||
Changed blocking_read to only block as much as necessary and not an
|
||||
arbitrary length of time. (Thanks Felix)
|
||||
|
||||
Fixed SFTP INIT/VERSION to exclude request_id and send correct maximum
|
||||
version number.
|
||||
|
||||
Fixed SFTP to be properly BC with version 1 and 2 servers.
|
||||
|
||||
Fixed libssh2_poll() to recognized closed sessions/channels.
|
||||
|
||||
Fixed libssh2_channel_write_ex() to fully block when set to blocking mode.
|
||||
Return actual bytes written as well. (Thanks deadem)
|
||||
|
||||
Added tests for -lm and -lsocket and add them when necessary.
|
||||
|
||||
Added libssh2_channel_window_read_ex() and libssh2_channel_window_write_ex()
|
||||
for examining the ssh transport windowing states.
|
||||
|
||||
Version 0.8
|
||||
-----------
|
||||
|
||||
Fix potential segfault in compression/decompression.
|
||||
|
||||
Fix compatability with older versions of OpenSSL
|
||||
|
||||
Swapped order of none,zlib compression modes to prefer no compression by
|
||||
default.
|
||||
|
||||
Added sys/uio.h for platforms (FBSD) which need it in order to define struct
|
||||
iovec.
|
||||
|
||||
Added libssh2_poll() to check status of sockets/channels/listeners.
|
||||
|
||||
Removed unnecessary inclusion of stdio.h (holdover from debugging)
|
||||
|
||||
Version 0.7
|
||||
-----------
|
||||
|
||||
Added libssh2_userauth_hostbased_fromfile_ex() for authenticating from hostkey.
|
||||
|
||||
Added configure recognition for MacOSX (Darwin) (Thanks Gabe)
|
||||
|
||||
Fixed extended data identification in libssh2_channel_read().
|
||||
|
||||
Fixed window adjust code. Hadn't acknowledged adjustments correctly.
|
||||
|
||||
Removed initial_window_size requirement for sending window adjust packet.
|
||||
|
||||
|
||||
Version 0.6
|
||||
-----------
|
||||
|
||||
Added LIBSSH2_FLAG_SIGPIPE to enable/disable SIGPIPE generated by
|
||||
send()/recv() calls. Default off.
|
||||
|
||||
Added libssh2_session_flag() to set optional session flags.
|
||||
|
||||
Collapsed exchanging_keys/newkeys/authenticated flags into single state
|
||||
attribute.
|
||||
|
||||
Fix zlib compression issue when internal buffer state misses partial sync.
|
||||
|
||||
Fix segfault when libssh2_session_methods() is called prior to
|
||||
session_startup().
|
||||
|
||||
Fixed client to server channel windowing. Pervent send queue overruns.
|
||||
|
||||
Swapped banner send/receive order (send first, then wait for response).
|
||||
|
||||
Version 0.5
|
||||
-----------
|
||||
|
||||
*** BC Break ***
|
||||
Reimplemented libssh2_session_methods() to match
|
||||
libssh2_session_method_pref() style
|
||||
|
||||
Fixed libssh2_attr2bin() (effects any setstat style call).
|
||||
|
||||
Fixed authenticating with encrypted private key.
|
||||
|
||||
Fixed authenticating via ssh-dss public key.
|
||||
|
||||
Fixed KEX_INIT cookie and packet padding to use actual random data
|
||||
|
||||
Added DESTDIR support to makefiles (Adam Go<47><6F>biowski -- I hope that
|
||||
character set translates right)
|
||||
|
||||
Added libssh2_channel_forward_listen_ex(), libssh2_channel_forward_cancel(),
|
||||
and libssh2_channel_forward_accept().
|
||||
|
||||
Added ./configure option '--disable-gex-new' to allow using the older
|
||||
group-exchange format
|
||||
|
||||
Added MAC methods hmac-md5 and hmac-md5-96.
|
||||
|
||||
Version 0.4
|
||||
-----------
|
||||
|
||||
Fixed crash when trying to free sftp_dirhandle data from a filehandle struct.
|
||||
|
||||
Fixed leak in sftp_open_ex(), handle->handle not freed in handle_close().
|
||||
|
||||
Fixed leak in sftp_symlink_ex(), result for READLINK and REALPATH not freed unless there was an error.
|
||||
|
||||
Added libssh2_banner_set(), specify an arbitrary banner to send on introduction.
|
||||
|
||||
Version 0.3
|
||||
-----------
|
||||
|
||||
Fixed libssh2_channel_read_ex(). Packet loop initialized BEFORE transport polled for new packets (should have been after).
|
||||
|
||||
Fixed blocking issues in scp_send()/scp_recv().
|
||||
|
||||
Fixed degree of indirection in macerror callback.
|
||||
|
||||
Changed packet read mechanism to use a fixed buffer and avoid unnecessary alloc/free calls. (especially while non-block looping)
|
||||
|
||||
Added channel close callback.
|
||||
|
||||
Added SFTP support (Using its own header file: libssh2_sftp.h)
|
||||
|
||||
Version 0.2
|
||||
-----------
|
||||
|
||||
Changed extended data ignorance mechanism:
|
||||
libssh2_channel_ignore_extended_data() changed to libssh2_channel_handle_extended_data()
|
||||
Macro introduced for backward compatability during beta phase.
|
||||
*** THE LIBSSH2_CHANNEL_IGNORE_EXTENDED_DATA() MACRO WILL BE REMOVED PRIOR TO 1.0 RELEASE ***
|
||||
libssh2_channel_handle_extended_data() may be passed one of three "ignore_mode" constants
|
||||
LIBSSH2_CHANNEL_EXTENDED_DATA_NONE Default behavior, queue ED packets and return them with read_ex
|
||||
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE Equivalent to libssh2_channel_ignore_extended_data()
|
||||
IGNORE will implicitly flush the extended data stream(s)
|
||||
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE Calls to channel_read() will check both the standard data stream
|
||||
and the extended data stream(s) for the first available packet
|
||||
|
||||
Changed libssh2_session_disconnect_ex() to return an error code when alloc fails
|
||||
|
||||
Added libssh2_channel_flush_ex() and basic macros: ..._flush() ..._flush_stderr()
|
||||
flush_ex accepts either the streamid (0 for standard data, 1 for stderr) or one of the two following constants:
|
||||
LIBSSH2_CHANNEL_FLUSH_ALL Flush all streams
|
||||
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA Flush all streams EXCEPT the standard data stream
|
||||
|
||||
Added libssh2_session_callback_set() for setting ignore/debug/disconnect/macerror callbacks
|
||||
|
||||
Added libssh2_session_method_pref() to selectively set methods and method preferences.
|
||||
|
||||
Added libssh2_session_methods() to determine what methods were negotiated.
|
||||
|
||||
Added libssh2_session_abstract() for retreiving &session->abstract
|
||||
|
||||
Added libssh2_session_last_error() for retreiving error codes/messages
|
||||
|
||||
Version 0.1
|
||||
-----------
|
||||
|
||||
Initial Release:
|
||||
KEX methods: diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1
|
||||
Hostkey methods: ssh-rsa, ssh-dss
|
||||
Cipher methods: aes256-cbc, rijndael-cbc@lysator.liu.se, aes192-cbc, aes128-cbc, blowfish-cbc, arcfour, cast128-cbc, 3des-cbc, none*
|
||||
Compression methods: zlib, none
|
||||
MAC methods: hmac-sha1, hmac-sha1-96, hmac-ripemd160, hmac-ripemd160@openssh.com none*
|
||||
*Cipher/MAC "none" is disabled by default for security purposes,
|
||||
Use --enable-crypt-none and/or --enable-mac-none with ./configure to enable
|
||||
NEWS is now generated from git and put into the release tarballs.
|
||||
|
@@ -1,32 +1,44 @@
|
||||
libssh2 1.2.6
|
||||
libssh2 1.2.8
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o Added libssh2_sftp_statvfs() and libssh2_sftp_fstatvfs()
|
||||
o Added libssh2_knownhost_checkp()
|
||||
o Added libssh2_scp_send64()
|
||||
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 wait_socket: make c89 compliant and use two fd_sets for select()
|
||||
o OpenSSL AES-128-CTR detection
|
||||
o proper keyboard-interactive user dialog in the sftp.c example
|
||||
o build procedure for VMS
|
||||
o fixed libssh2.dsw to use the generated libssh2.dsp
|
||||
o several Windows-related build fixes
|
||||
o fail to init SFTP if session isn't already authenticated
|
||||
o many tiny fixes that address clang-analyzer warnings
|
||||
o sftp_open: deal with short channel_write calls
|
||||
o libssh2_publickey_init: fixed to work better non-blocking
|
||||
o sftp_close_handle: add precation to not access NULL pointer
|
||||
o sftp_readdir: simplified and bugfixed
|
||||
o channel_write: if data has been sent, don't return EAGAIN
|
||||
o Support unlimited number of host names in a single line of the
|
||||
known_hosts file.
|
||||
o fix memory leak in userauth_keyboard_interactive()
|
||||
o fix memory leaks (two times cipher_data) for each sftp session
|
||||
o session_startup: manage server data before server identification
|
||||
o SCP: allow file names with bytes > 126
|
||||
o scp_recv: improved treatment of channel_read() returning zero
|
||||
o libssh2_userauth_authenticated: make it work as documented
|
||||
o variable size cleanup: match internal variable sizes better with the sizes
|
||||
of the fields used on the wire
|
||||
o channel_request_pty_size: fix reqPTY_state
|
||||
o sftp_symlink: return error if receive buffer too small
|
||||
o sftp_readdir: return error if buffer is too small
|
||||
o libssh2_knownhost_readfile.3: clarify return value
|
||||
o configure: stop using the deprecated AM_INIT_AUTOMAKE syntax
|
||||
o Fixed Win32 makefile which was now broken at resource build
|
||||
o kex_agree_hostkey: fix NULL pointer derefence
|
||||
o _libssh2_ntohu64: fix conversion from network bytes to uint64
|
||||
o ssize_t: proper typedef with MSVC compilers
|
||||
o zlib: Add debug tracing of zlib errors
|
||||
o decomp: increase decompression buffer sizes
|
||||
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Alexander Lamaison, Guenter Knauf, Dan Fandrich, Grubsky Grigory,
|
||||
Joey Degges, Jose Baars, Mikhail Gusarov, Peter Stuge, Simon Josefsson,
|
||||
Daniel Stenberg
|
||||
Alexander Lamaison, Alfred Gebert, Guenter Knauf, Dan Fandrich,
|
||||
Daniel Stenberg, Jasmeet Bagga, Joey Degges, Mark Smith, Peter Stuge,
|
||||
Pierre Joye, Simon Josefsson, TJ Saunders, Tommy Lindgren
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
127
TODO
127
TODO
@@ -1,6 +1,9 @@
|
||||
Things TODO
|
||||
===========
|
||||
|
||||
* Fix the numerous malloc+copy operations for sending data, see "Buffering
|
||||
Improvements" below for details
|
||||
|
||||
* make sure the windowing code adapts better to slow situations so that it
|
||||
doesn't then use as much memory as today. Possibly by an app-controllable
|
||||
"Window mode"?
|
||||
@@ -11,9 +14,11 @@ Things TODO
|
||||
|
||||
* Add more info to the man pages.
|
||||
|
||||
* Decrease the number of mallocs. Everywhere.
|
||||
* Decrease the number of mallocs. Everywhere. Will get easier once the
|
||||
buffering improvements have been done.
|
||||
|
||||
* Use SO_NOSIGPIPE for Mac OS/BSD systems where MSG_NOSIGNAL doesn't exist/work
|
||||
* Use SO_NOSIGPIPE for Mac OS/BSD systems where MSG_NOSIGNAL doesn't
|
||||
exist/work
|
||||
|
||||
* Extend the test suite to actually test lots of aspects of libssh2
|
||||
|
||||
@@ -21,6 +26,13 @@ Things TODO
|
||||
|
||||
* Expose error messages sent by the server
|
||||
|
||||
* Make SFTP transfers ask for and send several packages at once so that it
|
||||
doesn't have to send-waitforack-send-waitforack as much. This will be
|
||||
easier/smoother if we implement the "New SFTP API" described below.
|
||||
|
||||
* select() is troublesome with libssh2 when using multiple channels over
|
||||
the same session. See "New Transport API" below for more details.
|
||||
|
||||
At next SONAME bump
|
||||
===================
|
||||
|
||||
@@ -38,6 +50,7 @@ At next SONAME bump
|
||||
libssh2_channel_receive_window_adjust()
|
||||
libssh2_poll()
|
||||
libssh2_poll_channel_read()
|
||||
libssh2_session_startup() (libssh2_session_handshake() is the replacement)
|
||||
|
||||
* Rename a few function:
|
||||
|
||||
@@ -58,3 +71,113 @@ At next SONAME bump
|
||||
|
||||
* remove the existing libssh2_knownhost_check() functin and rename
|
||||
libssh2_knownhost_checkp() to become the new libssh2_knownhost_check instead
|
||||
|
||||
Buffering Improvements
|
||||
======================
|
||||
|
||||
transport_write
|
||||
|
||||
- If this function gets called with a total packet size that is larger than
|
||||
32K, it should create more than one SSH packet so that it keeps the largest
|
||||
one below 32K
|
||||
|
||||
sftp_write
|
||||
|
||||
- should not copy/allocate anything for the data, only create a header chunk
|
||||
and pass on the payload data to channel_write "pointed to"
|
||||
|
||||
New Transport API
|
||||
=================
|
||||
|
||||
THE PROBLEM
|
||||
|
||||
The problem in a nutshell is that when an application opens up multiple
|
||||
channels over a single session, those are all using the same socket. If the
|
||||
application is then using select() to wait for traffic (like any sensible app
|
||||
does) and wants to act on the data when select() tells there is something to
|
||||
for example read, what does an application do?
|
||||
|
||||
With our current API, you have to loop over all the channels and read from
|
||||
them to see if they have data. This effectively makes blocking reads
|
||||
impossible. If the app has many channels in a setup like this, it even becomes
|
||||
slow. (The original API had the libssh2_poll_channel_read() and libssh2_poll()
|
||||
to somewhat overcome this hurdle, but they too have pretty much the same
|
||||
problems plus a few others.)
|
||||
|
||||
Traffic in the other direction is similarly limited: the app has to try
|
||||
sending to all channels, even though some of them may very well not accept any
|
||||
data at that point.
|
||||
|
||||
A SOLUTION
|
||||
|
||||
I suggest we introduce two new helper functions:
|
||||
|
||||
libssh2_transport_read()
|
||||
|
||||
- Read "a bunch" of data from the given socket and returns information to the
|
||||
app about what channels that are now readable (ie they will not block when
|
||||
read from). The function can be called over and over and it will repeatedly
|
||||
return info about what channels that are readable at that moment.
|
||||
|
||||
libssh2_transport_write()
|
||||
|
||||
- Returns information about what channels that are writable, in the sense
|
||||
that they have windows set from the remote side that allows data to get
|
||||
sent. Writing to one of those channels will not block. Of course, the
|
||||
underlying socket may only accept a certain amount of data, so at the first
|
||||
short return, nothing more should be attempted to get sent until select()
|
||||
(or equivalent) has been used on the master socket again.
|
||||
|
||||
I haven't yet figured out a sensible API for how these functions should return
|
||||
that info, but if we agree on the general principles I guess we can work that
|
||||
out.
|
||||
|
||||
VOLUNTARY
|
||||
|
||||
I wanted to mention that these two helper functions would not be mandatory
|
||||
in any way. They would just be there for those who want them, and existing
|
||||
programs can remain using the old functions only if they prefer to.
|
||||
|
||||
New SFTP API
|
||||
============
|
||||
|
||||
PURPOSE
|
||||
|
||||
Provide API functions that explicitly tells at once that a (full) SFTP file
|
||||
transfer is wanted, to allow libssh2 to leverage on that knowledge to speed
|
||||
up things internally. It can for example do read ahead, buffer writes (merge
|
||||
small writes into larger chunks), better tune the SSH window and more. This
|
||||
sort of API is already provided for SCP transfers.
|
||||
|
||||
API
|
||||
|
||||
New functions:
|
||||
|
||||
LIBSSH2_SFTP_HANDLE *libssh2_sftp_send(SFTP_SESSION *sftp,
|
||||
uint64_t filesize,
|
||||
char *remote_path,
|
||||
size_t remote_path_len,
|
||||
long mode);
|
||||
|
||||
Tell libssh2 that a local file with a given size is about to get sent to
|
||||
the SFTP server.
|
||||
|
||||
LIBSSH2_SFTP_HANDLE *libssh2_sftp_recv();
|
||||
|
||||
Tell libssh2 that a remote file is requested to get downloaded from the SFTP
|
||||
server.
|
||||
|
||||
Only the setup of the file transfer is different from an application's point
|
||||
of view. Depending on direction of the transfer(s), the following already
|
||||
existing functions should then be used until the transfer is complete:
|
||||
|
||||
libssh2_sftp_read()
|
||||
libssh2_sftp_write()
|
||||
|
||||
HOW TO USE
|
||||
|
||||
1. Setup the transfer using one of the two new functions.
|
||||
|
||||
2. Loop through the reading or writing of data.
|
||||
|
||||
3. Cleanup the transfer
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -26,6 +26,7 @@ dist_man_MANS = \
|
||||
libssh2_channel_forward_listen_ex.3 \
|
||||
libssh2_channel_free.3 \
|
||||
libssh2_channel_get_exit_status.3 \
|
||||
libssh2_channel_get_exit_signal.3 \
|
||||
libssh2_channel_handle_extended_data.3 \
|
||||
libssh2_channel_handle_extended_data2.3 \
|
||||
libssh2_channel_ignore_extended_data.3 \
|
||||
@@ -59,6 +60,7 @@ dist_man_MANS = \
|
||||
libssh2_channel_x11_req.3 \
|
||||
libssh2_channel_x11_req_ex.3 \
|
||||
libssh2_exit.3 \
|
||||
libssh2_free.3 \
|
||||
libssh2_free_host_entry.3 \
|
||||
libssh2_host_entry_match.3 \
|
||||
libssh2_hostkey_hash.3 \
|
||||
@@ -133,6 +135,7 @@ dist_man_MANS = \
|
||||
libssh2_sftp_rmdir.3 \
|
||||
libssh2_sftp_rmdir_ex.3 \
|
||||
libssh2_sftp_seek.3 \
|
||||
libssh2_sftp_seek64.3 \
|
||||
libssh2_sftp_setstat.3 \
|
||||
libssh2_sftp_shutdown.3 \
|
||||
libssh2_sftp_stat.3 \
|
||||
@@ -155,6 +158,7 @@ dist_man_MANS = \
|
||||
libssh2_userauth_list.3 \
|
||||
libssh2_userauth_password.3 \
|
||||
libssh2_userauth_password_ex.3 \
|
||||
libssh2_userauth_publickey.3 \
|
||||
libssh2_userauth_publickey_fromfile.3 \
|
||||
libssh2_userauth_publickey_fromfile_ex.3 \
|
||||
libssh2_version.3
|
||||
|
@@ -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)
|
||||
|
36
docs/libssh2_channel_get_exit_signal.3
Normal file
36
docs/libssh2_channel_get_exit_signal.3
Normal 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.
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
19
docs/libssh2_free.3
Normal file
19
docs/libssh2_free.3
Normal 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)
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
42
docs/libssh2_session_handshake.3
Normal file
42
docs/libssh2_session_handshake.3
Normal 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)
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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).
|
||||
|
@@ -13,9 +13,6 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle,
|
||||
char *buffer, size_t buffer_maxlen,
|
||||
char *longentry, size_t longentry_maxlen,
|
||||
LIBSSH2_SFTP_ATTRIBUTES *attrs);
|
||||
|
||||
#define libssh2_sftp_readdir(h, b, bl, a) \\
|
||||
libssh2_sftp_readdir_ex((h), (b), (bl), NULL, 0, (a))
|
||||
.SH DESCRIPTION
|
||||
Reads a block of data from a LIBSSH2_SFTP_HANDLE and returns file entry
|
||||
information for the next entry, if any.
|
||||
@@ -47,6 +44,10 @@ Number of bytes actually populated into buffer (not counting the terminating
|
||||
zero), or negative on failure. It returns LIBSSH2_ERROR_EAGAIN when it would
|
||||
otherwise block. While LIBSSH2_ERROR_EAGAIN is a negative number, it isn't
|
||||
really a failure per se.
|
||||
.SH BUG
|
||||
Passing in a too small buffer for 'buffer' or 'longentry' when receiving data
|
||||
only results in libssh2 1.2.7 or earlier to not copy the entire data amount,
|
||||
and it is not possible for the application to tell when it happens!
|
||||
.SH ERRORS
|
||||
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
|
||||
|
||||
@@ -57,6 +58,10 @@ really a failure per se.
|
||||
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response was
|
||||
received on the socket, or an SFTP operation caused an errorcode to be
|
||||
returned by the server.
|
||||
|
||||
From 1.2.8, LIBSSH2_ERROR_BUFFER_TOO_SMALL is returned if any of the
|
||||
given 'buffer' or 'longentry' buffers are too small to fit the requested
|
||||
object name.
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_sftp_open_ex(3),
|
||||
.BR libssh2_sftp_close_handle(3)
|
||||
|
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
31
docs/libssh2_sftp_seek64.3
Normal file
31
docs/libssh2_sftp_seek64.3
Normal 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)
|
@@ -4,21 +4,13 @@
|
||||
.SH NAME
|
||||
libssh2_sftp_stat_ex - get status about an SFTP file
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
|
||||
int
|
||||
libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned int path_len, int stat_type, LIBSSH2_SFTP_ATTRIBUTES *attrs);
|
||||
|
||||
int
|
||||
libssh2_sftp_stat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUTES *attrs);
|
||||
|
||||
int
|
||||
libssh2_sftp_lstat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUTES *attrs);
|
||||
|
||||
int
|
||||
libssh2_sftp_setstat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUTES *attrs);
|
||||
|
||||
int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path,
|
||||
unsigned int path_len, int stat_type,
|
||||
LIBSSH2_SFTP_ATTRIBUTES *attrs);
|
||||
.SH DESCRIPTION
|
||||
\fIsftp\fP - SFTP instance as returned by
|
||||
.BR libssh2_sftp_init(3)
|
||||
@@ -29,24 +21,47 @@ libssh2_sftp_setstat(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUT
|
||||
to stat/lstat/setstat.
|
||||
|
||||
\fIstat_type\fP - One of the three constants specifying the type of
|
||||
stat operation to perform.
|
||||
stat operation to perform:
|
||||
|
||||
\fIattrs\fP - Pointer to attribute structure to set file metadata
|
||||
from or into depending on the value of stat_type.
|
||||
.br
|
||||
\fBLIBSSH2_SFTP_STAT\fP: performs stat(2) operation
|
||||
.br
|
||||
\fBLIBSSH2_SFTP_LSTAT\fP: performs lstat(2) operation
|
||||
.br
|
||||
\fBLIBSSH2_SFTP_SETSTAT\fP: performs operation to set stat info on file
|
||||
|
||||
Get or Set statbuf type data on a remote filesystem object. When
|
||||
getting statbuf data,
|
||||
\fIattrs\fP - Pointer to a \fBLIBSSH2_SFTP_ATTRIBUTES\fP structure to set file
|
||||
metadata from or into depending on the value of stat_type.
|
||||
|
||||
Get or Set statbuf type data on a remote filesystem object. When getting
|
||||
statbuf data,
|
||||
.BR libssh2_sftp_stat(3)
|
||||
will follow all symlinks, while
|
||||
.BR libssh2_sftp_lstat(3)
|
||||
will return data about the object encountered, even if that object
|
||||
happens to be a symlink.
|
||||
|
||||
.SH RETURN VALUE
|
||||
Return 0 on success or negative on failure. It returns
|
||||
LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
|
||||
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
The LIBSSH2_SFTP_ATTRIBUTES struct looks like this:
|
||||
|
||||
.nf
|
||||
struct LIBSSH2_SFTP_ATTRIBUTES {
|
||||
/* If flags & ATTR_* bit is set, then the value in this struct will be
|
||||
* meaningful Otherwise it should be ignored
|
||||
*/
|
||||
unsigned long flags;
|
||||
|
||||
libssh2_uint64_t filesize;
|
||||
unsigned long uid;
|
||||
unsigned long gid;
|
||||
unsigned long permissions;
|
||||
unsigned long atime;
|
||||
unsigned long mtime;
|
||||
};
|
||||
.fi
|
||||
.SH RETURN VALUE
|
||||
Returns 0 on success or negative on failure. It returns LIBSSH2_ERROR_EAGAIN
|
||||
when it would otherwise block. While LIBSSH2_ERROR_EAGAIN is a negative
|
||||
number, it isn't really a failure per se.
|
||||
.SH ERRORS
|
||||
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
|
||||
|
||||
@@ -57,6 +72,5 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response was
|
||||
received on the socket, or an SFTP operation caused an errorcode to
|
||||
be returned by the server.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_sftp_init(3)
|
||||
|
@@ -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.
|
||||
|
@@ -12,17 +12,6 @@ int
|
||||
libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path,
|
||||
unsigned int path_len, char *target,
|
||||
unsigned int target_len, int link_type);
|
||||
|
||||
int
|
||||
libssh2_sftp_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);
|
||||
.SH DESCRIPTION
|
||||
Create a symlink or read out symlink information from the remote side.
|
||||
|
||||
@@ -70,6 +59,13 @@ zero) or negative on failure.
|
||||
|
||||
It returns LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
|
||||
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
|
||||
From 1.2.8, LIBSSH2_ERROR_BUFFER_TOO_SMALL is returned if the given 'target'
|
||||
buffer is too small to fit the requested object name.
|
||||
.SH BUG
|
||||
Passing in a too small buffer when receiving data only results in libssh2
|
||||
1.2.7 or earlier to not copy the entire data amount, and it is not possible
|
||||
for the application to tell when it happens!
|
||||
.SH ERRORS
|
||||
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
|
||||
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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)
|
||||
|
29
docs/libssh2_userauth_publickey.3
Normal file
29
docs/libssh2_userauth_publickey.3
Normal 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)
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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[])
|
||||
{
|
||||
@@ -50,10 +81,14 @@ int main(int argc, char *argv[])
|
||||
#if defined(HAVE_IOCTLSOCKET)
|
||||
long flag = 1;
|
||||
#endif
|
||||
char mem[1024];
|
||||
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;
|
||||
@@ -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) {
|
||||
@@ -183,15 +219,25 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
ptr = mem;
|
||||
|
||||
total += nread;
|
||||
|
||||
prev = 0;
|
||||
do {
|
||||
/* write the same data over and over, until error or completion */
|
||||
rc = libssh2_channel_write(channel, ptr, nread);
|
||||
if (LIBSSH2_ERROR_EAGAIN == rc) { /* must loop around */
|
||||
continue;
|
||||
} else if (rc < 0) {
|
||||
fprintf(stderr, "ERROR %d\n", rc);
|
||||
while ((rc = libssh2_channel_write(channel, ptr, nread)) ==
|
||||
LIBSSH2_ERROR_EAGAIN) {
|
||||
waitsocket(sock, session);
|
||||
prev = 0;
|
||||
}
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "ERROR %d total %ld / %d prev %d\n", rc,
|
||||
total, (int)nread, (int)prev);
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
prev = nread;
|
||||
if(rc > nread) {
|
||||
fprintf(stderr, "MOO %d > %d\n", (int)rc, (int)nread);
|
||||
}
|
||||
/* rc indicates how many bytes were written this time */
|
||||
nread -= rc;
|
||||
ptr += rc;
|
||||
@@ -199,6 +245,11 @@ int main(int argc, char *argv[])
|
||||
} 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);
|
||||
|
||||
|
@@ -245,7 +245,8 @@ int main(int argc, char *argv[])
|
||||
libssh2_sftp_open(sftp_session, sftppath, LIBSSH2_FXF_READ, 0);
|
||||
|
||||
if (!sftp_handle) {
|
||||
fprintf(stderr, "Unable to open file with SFTP\n");
|
||||
fprintf(stderr, "Unable to open file with SFTP: %ld\n",
|
||||
libssh2_sftp_last_error(sftp_session));
|
||||
goto shutdown;
|
||||
}
|
||||
fprintf(stderr, "libssh2_sftp_open() is done, now receive data!\n");
|
||||
|
232
example/sftp_append.c
Normal file
232
example/sftp_append.c
Normal 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;
|
||||
}
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
@@ -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,16 +240,28 @@ 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 -= 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);
|
||||
libssh2_sftp_shutdown(sftp_session);
|
||||
|
290
example/sftp_write_sliding.c
Normal file
290
example/sftp_write_sliding.c
Normal 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;
|
||||
}
|
@@ -144,7 +144,7 @@ int main(int argc, char *argv[])
|
||||
username, identity->comment);
|
||||
break;
|
||||
}
|
||||
prev_identity = identity;
|
||||
prev_identity = identity;
|
||||
}
|
||||
if (rc) {
|
||||
fprintf(stderr, "Couldn't continue authentication\n");
|
||||
|
361
example/ssh2_echo.c
Normal file
361
example/ssh2_echo.c
Normal 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;
|
||||
}
|
@@ -86,6 +86,7 @@ int main(int argc, char *argv[])
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
int rc;
|
||||
int exitcode;
|
||||
char *exitsignal=(char *)"none";
|
||||
int bytecount = 0;
|
||||
size_t len;
|
||||
LIBSSH2_KNOWNHOSTS *nh;
|
||||
@@ -286,8 +287,14 @@ int main(int argc, char *argv[])
|
||||
if( rc == 0 )
|
||||
{
|
||||
exitcode = libssh2_channel_get_exit_status( channel );
|
||||
libssh2_channel_get_exit_signal(channel, &exitsignal,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
|
||||
|
||||
if (exitsignal)
|
||||
printf("\nGot signal: %s\n", exitsignal);
|
||||
else
|
||||
printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
|
||||
|
||||
libssh2_channel_free(channel);
|
||||
channel = NULL;
|
||||
|
@@ -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
76
git2news.pl
Executable 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";
|
||||
}
|
||||
}
|
@@ -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,8 +110,7 @@ extern "C" {
|
||||
# endif /* LIBSSH2_WIN32 */
|
||||
#endif /* LIBSSH2_API */
|
||||
|
||||
#if defined(LIBSSH2_DARWIN) || (defined(LIBSSH2_WIN32) && \
|
||||
!defined(_MSC_VER) && !defined(__MINGW32__))
|
||||
#if defined(LIBSSH2_DARWIN)
|
||||
# include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
@@ -73,59 +120,25 @@ typedef unsigned char uint8_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#endif
|
||||
|
||||
#if defined(LIBSSH2_WIN32) && defined(_MSC_VER)
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned __int64 libssh2_uint64_t;
|
||||
typedef __int64 libssh2_int64_t;
|
||||
# ifndef _SSIZE_T_DEFINED
|
||||
typedef int ssize_t;
|
||||
# define _SSIZE_T_DEFINED
|
||||
#ifndef ssize_t
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
#else
|
||||
typedef unsigned long long libssh2_uint64_t;
|
||||
typedef long long libssh2_int64_t;
|
||||
#endif
|
||||
|
||||
/* 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.6_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 6
|
||||
|
||||
/* 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 0x010206
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -243,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;
|
||||
@@ -327,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
|
||||
@@ -370,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
|
||||
@@ -397,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)),
|
||||
@@ -412,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,
|
||||
@@ -698,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);
|
||||
@@ -1108,4 +1151,6 @@ LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session,
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LIBSSH2_VERSION_ONLY */
|
||||
|
||||
#endif /* LIBSSH2_H */
|
||||
|
7
maketgz
7
maketgz
@@ -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
|
||||
|
@@ -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
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
@@ -21,7 +19,7 @@ endif
|
||||
|
||||
# Edit the path below to point to the base of your OpenSSL package.
|
||||
ifndef OPENSSL_PATH
|
||||
OPENSSL_PATH = ../../openssl-0.9.8n
|
||||
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-2010 The libssh2 project and its contributors.
|
||||
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) >> $@
|
||||
|
@@ -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
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
@@ -21,7 +19,7 @@ endif
|
||||
|
||||
# Edit the path below to point to the base of your OpenSSL package.
|
||||
ifndef OPENSSL_PATH
|
||||
OPENSSL_PATH = ../../../openssl-0.9.8n
|
||||
OPENSSL_PATH = ../../../openssl-0.9.8q
|
||||
endif
|
||||
|
||||
# Edit the var below to enable static linking of libssh2 and libz
|
||||
@@ -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
|
||||
|
165
src/agent.c
165
src/agent.c
@@ -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,
|
||||
@@ -48,6 +49,7 @@
|
||||
#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
|
||||
@@ -146,23 +148,24 @@ 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
|
||||
@@ -174,51 +177,54 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||
/* Send the length of the request */
|
||||
if (transctx->state == agent_NB_state_request_created) {
|
||||
_libssh2_htonu32(buf, transctx->request_len);
|
||||
rc = send(agent->fd, buf, sizeof buf, 0);
|
||||
if (rc < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
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);
|
||||
transctx->response = LIBSSH2_ALLOC(agent->session,
|
||||
transctx->response_len);
|
||||
if (!transctx->response) {
|
||||
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;
|
||||
}
|
||||
@@ -229,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 = {
|
||||
@@ -256,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
|
||||
@@ -272,21 +285,26 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||
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;
|
||||
}
|
||||
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, transctx->request, transctx->request_len);
|
||||
_libssh2_store_str(&p2, (const char *)transctx->request,
|
||||
transctx->request_len);
|
||||
|
||||
cds.dwData = PAGEANT_COPYDATA_ID;
|
||||
cds.cbData = 1 + strlen(mapname);
|
||||
@@ -294,18 +312,20 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||
|
||||
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
|
||||
if (id > 0) {
|
||||
transctx->response_len = _libssh2_ntohu32(p);
|
||||
transctx->response_len = _libssh2_ntohu32(p);
|
||||
if (transctx->response_len > PAGEANT_MAX_MSGLEN) {
|
||||
UnmapViewOfFile(p);
|
||||
CloseHandle(filemap);
|
||||
return LIBSSH2_ERROR_AGENT_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);
|
||||
}
|
||||
@@ -357,9 +377,9 @@ 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 */
|
||||
@@ -376,9 +396,14 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
@@ -451,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
|
||||
@@ -471,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) {
|
||||
@@ -568,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
|
||||
@@ -713,17 +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,
|
||||
strlen(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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
593
src/channel.c
593
src/channel.c
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,7 @@
|
||||
* Always non-blocking.
|
||||
*/
|
||||
int _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
|
||||
unsigned long adjustment,
|
||||
uint32_t adjustment,
|
||||
unsigned char force,
|
||||
unsigned int *store);
|
||||
|
||||
@@ -80,7 +80,7 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
|
||||
*/
|
||||
ssize_t
|
||||
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
const char *buf, size_t buflen);
|
||||
const unsigned char *buf, size_t buflen);
|
||||
|
||||
/*
|
||||
* _libssh2_channel_open
|
||||
@@ -92,7 +92,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
|
||||
uint32_t channel_type_len,
|
||||
uint32_t window_size,
|
||||
uint32_t packet_size,
|
||||
const char *message, unsigned int message_len);
|
||||
const unsigned char *message, size_t message_len);
|
||||
|
||||
|
||||
/*
|
||||
@@ -102,9 +102,8 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
|
||||
*/
|
||||
int
|
||||
_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
|
||||
const char *request, unsigned int request_len,
|
||||
const char *message, unsigned int message_len);
|
||||
|
||||
const char *request, size_t request_len,
|
||||
const char *message, size_t message_len);
|
||||
|
||||
/*
|
||||
* _libssh2_channel_read
|
||||
|
204
src/comp.c
204
src/comp.c
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -52,24 +53,41 @@
|
||||
* Minimalist compression: Absolutely none
|
||||
*/
|
||||
static int
|
||||
comp_method_none_comp(LIBSSH2_SESSION * session,
|
||||
int compress,
|
||||
unsigned char **dest,
|
||||
comp_method_none_comp(LIBSSH2_SESSION *session,
|
||||
unsigned char *dest,
|
||||
size_t *dest_len,
|
||||
size_t payload_limit,
|
||||
int *free_dest,
|
||||
const unsigned char *src,
|
||||
size_t src_len, void **abstract)
|
||||
size_t src_len,
|
||||
void **abstract)
|
||||
{
|
||||
(void) session;
|
||||
(void) abstract;
|
||||
(void) dest;
|
||||
(void) dest_len;
|
||||
(void) src;
|
||||
(void) src_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* comp_method_none_decomp
|
||||
*
|
||||
* Minimalist decompression: Absolutely none
|
||||
*/
|
||||
static int
|
||||
comp_method_none_decomp(LIBSSH2_SESSION * session,
|
||||
unsigned char **dest,
|
||||
size_t *dest_len,
|
||||
size_t payload_limit,
|
||||
const unsigned char *src,
|
||||
size_t src_len, void **abstract)
|
||||
{
|
||||
(void) session;
|
||||
(void) compress;
|
||||
(void) payload_limit;
|
||||
(void) abstract;
|
||||
*dest = (unsigned char *) src;
|
||||
*dest_len = src_len;
|
||||
|
||||
*free_dest = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -77,8 +95,10 @@ comp_method_none_comp(LIBSSH2_SESSION * session,
|
||||
|
||||
static const LIBSSH2_COMP_METHOD comp_method_none = {
|
||||
"none",
|
||||
0, /* not really compressing */
|
||||
NULL,
|
||||
comp_method_none_comp,
|
||||
comp_method_none_decomp,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -114,7 +134,7 @@ comp_method_zlib_free(voidpf opaque, voidpf address)
|
||||
* All your bandwidth are belong to us (so save some)
|
||||
*/
|
||||
static int
|
||||
comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
|
||||
comp_method_zlib_init(LIBSSH2_SESSION * session, int compr,
|
||||
void **abstract)
|
||||
{
|
||||
z_stream *strm;
|
||||
@@ -131,7 +151,7 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
|
||||
strm->opaque = (voidpf) session;
|
||||
strm->zalloc = (alloc_func) comp_method_zlib_alloc;
|
||||
strm->zfree = (free_func) comp_method_zlib_free;
|
||||
if (compress) {
|
||||
if (compr) {
|
||||
/* deflate */
|
||||
status = deflateInit(strm, Z_DEFAULT_COMPRESSION);
|
||||
} else {
|
||||
@@ -141,75 +161,112 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
|
||||
|
||||
if (status != Z_OK) {
|
||||
LIBSSH2_FREE(session, strm);
|
||||
return -1;
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"unhandled zlib error %d", status);
|
||||
return LIBSSH2_ERROR_COMPRESS;
|
||||
}
|
||||
*abstract = strm;
|
||||
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_comp_method_zlib_comp
|
||||
*
|
||||
* Compresses source to destination. Without allocation.
|
||||
*/
|
||||
static int
|
||||
comp_method_zlib_comp(LIBSSH2_SESSION *session,
|
||||
unsigned char *dest,
|
||||
|
||||
/* dest_len is a pointer to allow this function to
|
||||
update it with the final actual size used */
|
||||
size_t *dest_len,
|
||||
const unsigned char *src,
|
||||
size_t src_len,
|
||||
void **abstract)
|
||||
{
|
||||
z_stream *strm = *abstract;
|
||||
int out_maxlen = *dest_len;
|
||||
int status;
|
||||
|
||||
strm->next_in = (unsigned char *) src;
|
||||
strm->avail_in = src_len;
|
||||
strm->next_out = dest;
|
||||
strm->avail_out = out_maxlen;
|
||||
|
||||
status = deflate(strm, Z_PARTIAL_FLUSH);
|
||||
|
||||
if (status != Z_OK) {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"unhandled zlib compression error %d", status);
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
||||
"compression failure");
|
||||
}
|
||||
|
||||
*dest_len = out_maxlen - strm->avail_out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* libssh2_comp_method_zlib_comp
|
||||
* zlib, a compression standard for all occasions
|
||||
/*
|
||||
* libssh2_comp_method_zlib_decomp
|
||||
*
|
||||
* Decompresses source to destination. Allocates the output memory.
|
||||
*/
|
||||
static int
|
||||
comp_method_zlib_comp(LIBSSH2_SESSION * session,
|
||||
int compress,
|
||||
unsigned char **dest,
|
||||
size_t *dest_len,
|
||||
size_t payload_limit,
|
||||
int *free_dest,
|
||||
const unsigned char *src,
|
||||
size_t src_len, void **abstract)
|
||||
comp_method_zlib_decomp(LIBSSH2_SESSION * session,
|
||||
unsigned char **dest,
|
||||
size_t *dest_len,
|
||||
size_t payload_limit,
|
||||
const unsigned char *src,
|
||||
size_t src_len, void **abstract)
|
||||
{
|
||||
z_stream *strm = *abstract;
|
||||
/* A short-term alloc of a full data chunk is better than a series of
|
||||
reallocs */
|
||||
char *out;
|
||||
int out_maxlen = compress ? (src_len + 4) : (2 * src_len);
|
||||
int out_maxlen = 8 * src_len;
|
||||
int limiter = 0;
|
||||
|
||||
/* 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) {
|
||||
if (!strm->next_out)
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate compression/decompression "
|
||||
"buffer");
|
||||
}
|
||||
"Unable to allocate decompression buffer");
|
||||
while (strm->avail_in) {
|
||||
int status;
|
||||
|
||||
if (compress) {
|
||||
status = deflate(strm, Z_PARTIAL_FLUSH);
|
||||
} else {
|
||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||
}
|
||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||
|
||||
if (status != Z_OK) {
|
||||
LIBSSH2_FREE(session, out);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"unhandled zlib error %d", status);
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
||||
"compress/decompression failure");
|
||||
"decompression failure");
|
||||
}
|
||||
if (strm->avail_in) {
|
||||
size_t out_ofs = out_maxlen - strm->avail_out;
|
||||
char *newout;
|
||||
|
||||
out_maxlen +=
|
||||
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||
out_maxlen += 8 * strm->avail_in;
|
||||
|
||||
if ((out_maxlen > (int) payload_limit) && !compress && limiter++) {
|
||||
if ((out_maxlen > (int) payload_limit) && limiter++) {
|
||||
LIBSSH2_FREE(session, out);
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
||||
"Excessive growth in decompression phase");
|
||||
@@ -219,20 +276,18 @@ comp_method_zlib_comp(LIBSSH2_SESSION * session,
|
||||
if (!newout) {
|
||||
LIBSSH2_FREE(session, out);
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to expand compress/"
|
||||
"decompression buffer");
|
||||
"Unable to expand decompression buffer");
|
||||
}
|
||||
out = newout;
|
||||
strm->next_out = (unsigned char *) out + out_ofs;
|
||||
strm->avail_out +=
|
||||
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||
strm->avail_out += 8 * strm->avail_in;
|
||||
} else
|
||||
while (!strm->avail_out) {
|
||||
/* Done with input, might be a byte or two in internal buffer
|
||||
* during compress. Or potentially many bytes if it's a
|
||||
* decompress
|
||||
*/
|
||||
int grow_size = compress ? 8 : 1024;
|
||||
int grow_size = 2048;
|
||||
char *newout;
|
||||
|
||||
if (out_maxlen >= (int) payload_limit) {
|
||||
@@ -253,29 +308,27 @@ comp_method_zlib_comp(LIBSSH2_SESSION * session,
|
||||
if (!newout) {
|
||||
LIBSSH2_FREE(session, out);
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to expand final compress/"
|
||||
"Unable to expand final "
|
||||
"decompress buffer");
|
||||
}
|
||||
out = newout;
|
||||
strm->next_out = (unsigned char *) out + out_maxlen -
|
||||
grow_size;
|
||||
|
||||
if (compress) {
|
||||
status = deflate(strm, Z_PARTIAL_FLUSH);
|
||||
} else {
|
||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||
}
|
||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||
|
||||
if (status != Z_OK) {
|
||||
LIBSSH2_FREE(session, out);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"unhandled zlib error %d", status);
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
||||
"compress/decompression failure");
|
||||
"decompression failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*dest = (unsigned char *) out;
|
||||
*dest_len = out_maxlen - strm->avail_out;
|
||||
*free_dest = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
20
src/crypt.c
20
src/crypt.c
@@ -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
116
src/crypto.h
Normal 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
|
@@ -68,7 +68,8 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session,
|
||||
now = time (NULL);
|
||||
|
||||
if (session->keepalive_last_sent + session->keepalive_interval <= now) {
|
||||
/* Format is "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */
|
||||
/* Format is
|
||||
"SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */
|
||||
unsigned char keepalive_data[]
|
||||
= "\x50\x00\x00\x00\x15keepalive@libssh2.orgW";
|
||||
size_t len = sizeof (keepalive_data) - 1;
|
||||
@@ -76,9 +77,9 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session,
|
||||
|
||||
keepalive_data[len - 1] = session->keepalive_want_reply;
|
||||
|
||||
rc = _libssh2_transport_write(session, keepalive_data, len);
|
||||
/* Silently ignore PACKET_EAGAIN here: if the write buffer is
|
||||
already full, sending another keepalive is not useful. */
|
||||
rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0);
|
||||
/* Silently ignore PACKET_EAGAIN here: if the write buffer is
|
||||
already full, sending another keepalive is not useful. */
|
||||
if (rc && rc != LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send keepalive message");
|
||||
|
85
src/kex.c
85
src/kex.c
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -140,8 +141,9 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (exchange_state->state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, exchange_state->e_packet,
|
||||
exchange_state->e_packet_len);
|
||||
rc = _libssh2_transport_send(session, exchange_state->e_packet,
|
||||
exchange_state->e_packet_len,
|
||||
NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
@@ -410,7 +412,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (exchange_state->state == libssh2_NB_state_sent2) {
|
||||
rc = _libssh2_transport_write(session, &exchange_state->c, 1);
|
||||
rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
@@ -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:
|
||||
@@ -809,8 +845,8 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
|
||||
}
|
||||
|
||||
if (key_state->state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, key_state->request,
|
||||
key_state->request_len);
|
||||
rc = _libssh2_transport_send(session, key_state->request,
|
||||
key_state->request_len, NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
@@ -1009,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 =
|
||||
@@ -1049,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,
|
||||
@@ -1099,9 +1135,12 @@ static int kexinit(LIBSSH2_SESSION * session)
|
||||
} else {
|
||||
data = session->kexinit_data;
|
||||
data_len = session->kexinit_data_len;
|
||||
/* zap the variables to ensure there is NOT a double free later */
|
||||
session->kexinit_data = NULL;
|
||||
session->kexinit_data_len = 0;
|
||||
}
|
||||
|
||||
rc = _libssh2_transport_write(session, data, data_len);
|
||||
rc = _libssh2_transport_send(session, data, data_len, NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
session->kexinit_data = data;
|
||||
session->kexinit_data_len = data_len;
|
||||
@@ -1234,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));
|
||||
@@ -1450,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;
|
||||
|
||||
@@ -1609,18 +1648,6 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_SC method: %s",
|
||||
session->remote.comp->name);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -1802,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:
|
||||
|
232
src/knownhost.c
232
src/knownhost.c
@@ -566,6 +566,120 @@ libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts)
|
||||
LIBSSH2_FREE(hosts->session, hosts);
|
||||
}
|
||||
|
||||
|
||||
/* old style plain text: [name]([,][name])*
|
||||
|
||||
for the sake of simplicity, we add them as separate hosts with the same
|
||||
key
|
||||
*/
|
||||
static int oldstyle_hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
const char *host, size_t hostlen,
|
||||
const char *key, size_t keylen, int key_type,
|
||||
const char *comment, size_t commentlen)
|
||||
{
|
||||
int rc = 0;
|
||||
size_t namelen = 0;
|
||||
const char *name = host + hostlen;
|
||||
|
||||
if(hostlen < 1)
|
||||
return _libssh2_error(hosts->session,
|
||||
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Failed to parse known_hosts line "
|
||||
"(no host names)");
|
||||
|
||||
while(name > host) {
|
||||
--name;
|
||||
++namelen;
|
||||
|
||||
/* when we get the the start or see a comma coming up, add the host
|
||||
name to the collection */
|
||||
if((name == host) || (*(name-1) == ',')) {
|
||||
|
||||
char hostbuf[256];
|
||||
|
||||
/* make sure we don't overflow the buffer */
|
||||
if(namelen >= sizeof(hostbuf)-1)
|
||||
return _libssh2_error(hosts->session,
|
||||
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Failed to parse known_hosts line "
|
||||
"(unexpected length)");
|
||||
|
||||
/* copy host name to the temp buffer and zero terminate */
|
||||
memcpy(hostbuf, name, namelen);
|
||||
hostbuf[namelen]=0;
|
||||
|
||||
rc = knownhost_add(hosts, hostbuf, NULL, key, keylen,
|
||||
comment, commentlen,
|
||||
key_type | LIBSSH2_KNOWNHOST_TYPE_PLAIN |
|
||||
LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL);
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
if(name > host) {
|
||||
namelen = 0;
|
||||
--name; // skip comma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* |1|[salt]|[hash] */
|
||||
static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
const char *host, size_t hostlen,
|
||||
const char *key, size_t keylen, int key_type,
|
||||
const char *comment, size_t commentlen)
|
||||
{
|
||||
const char *p;
|
||||
char saltbuf[32];
|
||||
char hostbuf[256];
|
||||
|
||||
const char *salt = &host[3]; /* skip the magic marker */
|
||||
hostlen -= 3; /* deduct the marker */
|
||||
|
||||
/* this is where the salt starts, find the end of it */
|
||||
for(p = salt; *p && (*p != '|'); p++)
|
||||
;
|
||||
|
||||
if(*p=='|') {
|
||||
const char *hash = NULL;
|
||||
size_t saltlen = p - salt;
|
||||
if(saltlen >= (sizeof(saltbuf)-1)) /* weird length */
|
||||
return _libssh2_error(hosts->session,
|
||||
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Failed to parse known_hosts line "
|
||||
"(unexpectedly long salt)");
|
||||
|
||||
memcpy(saltbuf, salt, saltlen);
|
||||
saltbuf[saltlen] = 0; /* zero terminate */
|
||||
salt = saltbuf; /* point to the stack based buffer */
|
||||
|
||||
hash = p+1; /* the host hash is after the separator */
|
||||
|
||||
/* now make the host point to the hash */
|
||||
host = hash;
|
||||
hostlen -= saltlen+1; /* deduct the salt and separator */
|
||||
|
||||
/* check that the lengths seem sensible */
|
||||
if(hostlen >= sizeof(hostbuf)-1)
|
||||
return _libssh2_error(hosts->session,
|
||||
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Failed to parse known_hosts line "
|
||||
"(unexpected length)");
|
||||
|
||||
memcpy(hostbuf, host, hostlen);
|
||||
hostbuf[hostlen]=0;
|
||||
|
||||
return knownhost_add(hosts, hostbuf, salt, key, keylen, comment,
|
||||
commentlen,
|
||||
key_type | LIBSSH2_KNOWNHOST_TYPE_SHA1 |
|
||||
LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL);
|
||||
}
|
||||
else
|
||||
return 0; /* XXX: This should be an error, shouldn't it? */
|
||||
}
|
||||
|
||||
/*
|
||||
* hostline()
|
||||
*
|
||||
@@ -580,88 +694,21 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
const char *host, size_t hostlen,
|
||||
const char *key, size_t keylen)
|
||||
{
|
||||
const char *p;
|
||||
const char *orig = host;
|
||||
const char *salt = NULL;
|
||||
const char *comment = NULL;
|
||||
size_t commentlen = 0;
|
||||
int rc;
|
||||
int type = LIBSSH2_KNOWNHOST_TYPE_PLAIN;
|
||||
const char *sep = NULL;
|
||||
size_t seplen = 0;
|
||||
char saltbuf[32];
|
||||
char hostbuf[256];
|
||||
|
||||
/* Figure out host format */
|
||||
if((hostlen >2) && memcmp(host, "|1|", 3)) {
|
||||
/* old style plain text: [name][,][ip-address]
|
||||
|
||||
for the sake of simplicity, we add them as two hosts with the same
|
||||
key
|
||||
*/
|
||||
size_t scan = hostlen;
|
||||
|
||||
while(scan && (*host != ',')) {
|
||||
host++;
|
||||
scan--;
|
||||
}
|
||||
|
||||
if(scan) {
|
||||
sep = host+1;
|
||||
seplen = scan-1;
|
||||
hostlen -= scan; /* deduct what's left to scan from the first
|
||||
host name */
|
||||
}
|
||||
else
|
||||
host = orig;
|
||||
}
|
||||
else {
|
||||
/* |1|[salt]|[hash] */
|
||||
type = LIBSSH2_KNOWNHOST_TYPE_SHA1;
|
||||
|
||||
salt = &host[3]; /* skip the magic marker */
|
||||
hostlen -= 3; /* deduct the marker */
|
||||
|
||||
/* this is where the salt starts, find the end of it */
|
||||
for(p = salt; *p && (*p != '|'); p++)
|
||||
;
|
||||
|
||||
if(*p=='|') {
|
||||
const char *hash = NULL;
|
||||
size_t saltlen = p - salt;
|
||||
if(saltlen >= (sizeof(saltbuf)-1)) /* weird length */
|
||||
return _libssh2_error(hosts->session,
|
||||
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Failed to parse known_hosts line "
|
||||
"(unexpectedly long salt)");
|
||||
|
||||
memcpy(saltbuf, salt, saltlen);
|
||||
saltbuf[saltlen] = 0; /* zero terminate */
|
||||
salt = saltbuf; /* point to the stack based buffer */
|
||||
|
||||
hash = p+1; /* the host hash is after the separator */
|
||||
|
||||
/* now make the host point to the hash */
|
||||
host = hash;
|
||||
hostlen -= saltlen+1; /* deduct the salt and separator */
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
int key_type;
|
||||
|
||||
/* make some checks that the lengths seem sensible */
|
||||
if((keylen < 20) ||
|
||||
(seplen >= sizeof(hostbuf)-1) ||
|
||||
(hostlen >= sizeof(hostbuf)-1))
|
||||
if(keylen < 20)
|
||||
return _libssh2_error(hosts->session,
|
||||
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Failed to parse known_hosts line "
|
||||
"(unexpected length)");
|
||||
|
||||
"(key too short)");
|
||||
|
||||
switch(key[0]) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
type |= LIBSSH2_KNOWNHOST_KEY_RSA1;
|
||||
key_type = LIBSSH2_KNOWNHOST_KEY_RSA1;
|
||||
|
||||
/* Note that the old-style keys (RSA1) aren't truly base64, but we
|
||||
* claim it is for now since we can get away with strcmp()ing the
|
||||
@@ -672,9 +719,9 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
|
||||
case 's': /* ssh-dss or ssh-rsa */
|
||||
if(!strncmp(key, "ssh-dss", 7))
|
||||
type |= LIBSSH2_KNOWNHOST_KEY_SSHDSS;
|
||||
key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
|
||||
else if(!strncmp(key, "ssh-rsa", 7))
|
||||
type |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
||||
key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
||||
else
|
||||
/* unknown key type */
|
||||
return _libssh2_error(hosts->session,
|
||||
@@ -721,30 +768,21 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
"Unknown key format");
|
||||
}
|
||||
|
||||
if(sep) {
|
||||
/* The second host after the comma, add this first. Copy it to the
|
||||
temp buffer and zero terminate */
|
||||
memcpy(hostbuf, sep, seplen);
|
||||
hostbuf[seplen]=0;
|
||||
/* Figure out host format */
|
||||
if((hostlen >2) && memcmp(host, "|1|", 3)) {
|
||||
/* old style plain text: [name]([,][name])*
|
||||
|
||||
rc = knownhost_add(hosts, hostbuf, salt, key, keylen,
|
||||
comment, commentlen,
|
||||
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
|
||||
NULL);
|
||||
if(rc)
|
||||
return rc;
|
||||
for the sake of simplicity, we add them as separate hosts with the
|
||||
same key
|
||||
*/
|
||||
return oldstyle_hostline(hosts, host, hostlen, key, keylen, key_type,
|
||||
comment, commentlen);
|
||||
}
|
||||
else {
|
||||
/* |1|[salt]|[hash] */
|
||||
return hashed_hostline(hosts, host, hostlen, key, keylen, key_type,
|
||||
comment, commentlen);
|
||||
}
|
||||
|
||||
if (!salt)
|
||||
host = orig;
|
||||
memcpy(hostbuf, host, hostlen);
|
||||
hostbuf[hostlen]=0;
|
||||
|
||||
rc = knownhost_add(hosts, hostbuf, salt, key, keylen, comment,
|
||||
commentlen,
|
||||
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
|
||||
NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -764,7 +802,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
* <name> or <hash>
|
||||
*
|
||||
* <name> consists of
|
||||
* [name,address] or just [name] or just [address]
|
||||
* [name] optionally followed by [,name] one or more times
|
||||
*
|
||||
* <hash> consists of
|
||||
* |1|<salt>|hash
|
||||
|
@@ -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 */
|
||||
|
@@ -63,7 +63,7 @@
|
||||
#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,
|
||||
size_t hash_len,
|
||||
unsigned char **signature,
|
||||
size_t *signature_len);
|
||||
|
||||
#define _libssh2_rsa_free(rsactx) gcry_sexp_release (rsactx)
|
||||
|
||||
#define libssh2_dsa_ctx struct gcry_sexp
|
||||
|
||||
int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
|
||||
const unsigned char *pdata,
|
||||
unsigned long plen,
|
||||
const unsigned char *qdata,
|
||||
unsigned long qlen,
|
||||
const unsigned char *gdata,
|
||||
unsigned long glen,
|
||||
const unsigned char *ydata,
|
||||
unsigned long ylen,
|
||||
const unsigned char *x, unsigned long x_len);
|
||||
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
const char *filename,
|
||||
unsigned const char *passphrase);
|
||||
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsa,
|
||||
const unsigned char *sig,
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len, unsigned char *sig);
|
||||
|
||||
#define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx)
|
||||
|
||||
#define _libssh2_cipher_type(name) int name
|
||||
@@ -162,35 +110,27 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
#define _libssh2_gcry_cipher(c) (c >> 8)
|
||||
#define _libssh2_gcry_mode(m) (m & 0xFF)
|
||||
|
||||
#define _libssh2_cipher_aes256ctr \
|
||||
#define _libssh2_cipher_aes256ctr \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR)
|
||||
#define _libssh2_cipher_aes192ctr \
|
||||
#define _libssh2_cipher_aes192ctr \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR)
|
||||
#define _libssh2_cipher_aes128ctr \
|
||||
#define _libssh2_cipher_aes128ctr \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR)
|
||||
#define _libssh2_cipher_aes256 \
|
||||
#define _libssh2_cipher_aes256 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_aes192 \
|
||||
#define _libssh2_cipher_aes192 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_aes128 \
|
||||
#define _libssh2_cipher_aes128 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_blowfish \
|
||||
#define _libssh2_cipher_blowfish \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_arcfour \
|
||||
#define _libssh2_cipher_arcfour \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM)
|
||||
#define _libssh2_cipher_cast5 \
|
||||
#define _libssh2_cipher_cast5 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_3des \
|
||||
#define _libssh2_cipher_3des \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC)
|
||||
|
||||
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
|
||||
_libssh2_cipher_type(algo),
|
||||
unsigned char *iv,
|
||||
unsigned char *secret, int encrypt);
|
||||
|
||||
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
_libssh2_cipher_type(algo),
|
||||
int encrypt, unsigned char *block);
|
||||
|
||||
#define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx))
|
||||
|
||||
@@ -207,3 +147,4 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
#define _libssh2_bn_bytes(bn) (gcry_mpi_get_nbits (bn) / 8 + ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1))
|
||||
#define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn)
|
||||
#define _libssh2_bn_free(bn) gcry_mpi_release(bn)
|
||||
|
||||
|
@@ -125,12 +125,7 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
|
||||
#ifdef LIBSSH2_LIBGCRYPT
|
||||
#include "libgcrypt.h"
|
||||
#else
|
||||
#include "openssl.h"
|
||||
#endif
|
||||
#include "crypto.h"
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
|
||||
@@ -145,13 +140,6 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
typedef SOCKET libssh2_socket_t;
|
||||
#else /* !WIN32 */
|
||||
typedef int libssh2_socket_t;
|
||||
#define INVALID_SOCKET -1
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* RFC4253 section 6.1 Maximum Packet Length says:
|
||||
*
|
||||
* "All implementations MUST be able to process packets with
|
||||
@@ -172,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)
|
||||
|
||||
@@ -185,7 +173,6 @@ typedef int libssh2_socket_t;
|
||||
|
||||
typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD;
|
||||
typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
|
||||
typedef struct _LIBSSH2_MAC_METHOD LIBSSH2_MAC_METHOD;
|
||||
typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
|
||||
typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD;
|
||||
|
||||
@@ -311,18 +298,13 @@ struct _LIBSSH2_PACKET
|
||||
{
|
||||
struct list_node node; /* linked list header */
|
||||
|
||||
unsigned char type;
|
||||
|
||||
/* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */
|
||||
/* the raw unencrypted payload */
|
||||
unsigned char *data;
|
||||
size_t data_len;
|
||||
|
||||
/* Where to start reading data from,
|
||||
* used for channel data that's been partially consumed */
|
||||
unsigned long data_head;
|
||||
|
||||
/* Can the message be confirmed? */
|
||||
int mac;
|
||||
size_t data_head;
|
||||
};
|
||||
|
||||
typedef struct _libssh2_channel_data
|
||||
@@ -331,7 +313,7 @@ typedef struct _libssh2_channel_data
|
||||
uint32_t id;
|
||||
|
||||
/* Limits and restrictions */
|
||||
unsigned long window_size_initial, window_size, packet_size;
|
||||
uint32_t window_size_initial, window_size, packet_size;
|
||||
|
||||
/* Set to 1 when CHANNEL_CLOSE / CHANNEL_EOF sent/received */
|
||||
char close, eof, extended_data_ignore_mode;
|
||||
@@ -347,9 +329,12 @@ struct _LIBSSH2_CHANNEL
|
||||
/* channel's program exit status */
|
||||
int exit_status;
|
||||
|
||||
/* channel's program exit signal (without the SIG prefix) */
|
||||
char *exit_signal;
|
||||
|
||||
libssh2_channel_data local, remote;
|
||||
/* Amount of bytes to be refunded to receive window (but not yet sent) */
|
||||
unsigned long adjust_queue;
|
||||
uint32_t adjust_queue;
|
||||
|
||||
LIBSSH2_SESSION *session;
|
||||
|
||||
@@ -363,9 +348,10 @@ struct _LIBSSH2_CHANNEL
|
||||
unsigned char setenv_local_channel[4];
|
||||
packet_requirev_state_t setenv_packet_requirev_state;
|
||||
|
||||
/* State variables used in libssh2_channel_request_pty_ex() */
|
||||
/* State variables used in libssh2_channel_request_pty_ex()
|
||||
libssh2_channel_request_pty_size_ex() */
|
||||
libssh2_nonblocking_states reqPTY_state;
|
||||
unsigned char *reqPTY_packet;
|
||||
unsigned char reqPTY_packet[41 + 256];
|
||||
size_t reqPTY_packet_len;
|
||||
unsigned char reqPTY_local_channel[4];
|
||||
packet_requirev_state_t reqPTY_packet_requirev_state;
|
||||
@@ -400,10 +386,8 @@ struct _LIBSSH2_CHANNEL
|
||||
|
||||
/* State variables used in libssh2_channel_write_ex() */
|
||||
libssh2_nonblocking_states write_state;
|
||||
unsigned char *write_packet;
|
||||
unsigned char *write_s;
|
||||
unsigned char write_packet[13];
|
||||
size_t write_packet_len;
|
||||
size_t write_bufwrote;
|
||||
size_t write_bufwrite;
|
||||
|
||||
/* State variables used in libssh2_channel_close() */
|
||||
@@ -421,6 +405,7 @@ struct _LIBSSH2_CHANNEL
|
||||
|
||||
/* State variables used in libssh2_channel_handle_extended_data2() */
|
||||
libssh2_nonblocking_states extData2_state;
|
||||
|
||||
};
|
||||
|
||||
struct _LIBSSH2_LISTENER
|
||||
@@ -454,8 +439,8 @@ typedef struct _libssh2_endpoint_data
|
||||
const LIBSSH2_CRYPT_METHOD *crypt;
|
||||
void *crypt_abstract;
|
||||
|
||||
const LIBSSH2_MAC_METHOD *mac;
|
||||
unsigned long seqno;
|
||||
const struct _LIBSSH2_MAC_METHOD *mac;
|
||||
uint32_t seqno;
|
||||
void *mac_abstract;
|
||||
|
||||
const LIBSSH2_COMP_METHOD *comp;
|
||||
@@ -476,17 +461,17 @@ struct transportpacket
|
||||
unsigned char buf[PACKETBUFSIZE];
|
||||
unsigned char init[5]; /* first 5 bytes of the incoming data stream,
|
||||
still encrypted */
|
||||
int writeidx; /* at what array index we do the next write into
|
||||
size_t writeidx; /* at what array index we do the next write into
|
||||
the buffer */
|
||||
int readidx; /* at what array index we do the next read from
|
||||
size_t readidx; /* at what array index we do the next read from
|
||||
the buffer */
|
||||
uint32_t packet_length; /* the most recent packet_length as read from the
|
||||
network data */
|
||||
uint8_t padding_length; /* the most recent padding_length as read from the
|
||||
network data */
|
||||
int data_num; /* How much of the total package that has been read
|
||||
size_t data_num; /* How much of the total package that has been read
|
||||
so far. */
|
||||
int total_num; /* How much a total package is supposed to be, in
|
||||
size_t total_num; /* How much a total package is supposed to be, in
|
||||
number of bytes. A full package is
|
||||
packet_length + padding_length + 4 +
|
||||
mac_length. */
|
||||
@@ -496,11 +481,10 @@ struct transportpacket
|
||||
are currently writing decrypted data */
|
||||
|
||||
/* ------------- for outgoing data --------------- */
|
||||
unsigned char *outbuf; /* pointer to a LIBSSH2_ALLOC() area for the
|
||||
outgoing data */
|
||||
unsigned char outbuf[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */
|
||||
|
||||
int ototal_num; /* size of outbuf in number of bytes */
|
||||
unsigned char *odata; /* original pointer to the data we stored in
|
||||
outbuf */
|
||||
const unsigned char *odata; /* original pointer to the data */
|
||||
size_t olen; /* original size of the data we stored in
|
||||
outbuf */
|
||||
size_t osent; /* number of bytes already sent */
|
||||
@@ -509,7 +493,7 @@ struct transportpacket
|
||||
struct _LIBSSH2_PUBLICKEY
|
||||
{
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
unsigned long version;
|
||||
uint32_t version;
|
||||
|
||||
/* State variables used in libssh2_publickey_packet_receive() */
|
||||
libssh2_nonblocking_states receive_state;
|
||||
@@ -534,137 +518,13 @@ struct _LIBSSH2_PUBLICKEY
|
||||
size_t listFetch_data_len;
|
||||
};
|
||||
|
||||
#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
|
||||
|
||||
struct _LIBSSH2_SFTP_HANDLE
|
||||
{
|
||||
struct list_node node;
|
||||
|
||||
LIBSSH2_SFTP *sftp;
|
||||
|
||||
/* This is a pre-allocated buffer used for sending SFTP requests as the
|
||||
whole thing might not get sent in one go. This buffer is used for read,
|
||||
write, close and MUST thus be big enough to suit all these. */
|
||||
unsigned char request_packet[SFTP_HANDLE_MAXLEN + 25];
|
||||
|
||||
char handle[SFTP_HANDLE_MAXLEN];
|
||||
size_t handle_len;
|
||||
|
||||
char handle_type;
|
||||
|
||||
union _libssh2_sftp_handle_data
|
||||
{
|
||||
struct _libssh2_sftp_handle_file_data
|
||||
{
|
||||
libssh2_uint64_t offset;
|
||||
} file;
|
||||
struct _libssh2_sftp_handle_dir_data
|
||||
{
|
||||
unsigned long names_left;
|
||||
void *names_packet;
|
||||
char *next_name;
|
||||
} dir;
|
||||
} u;
|
||||
|
||||
/* State variables used in libssh2_sftp_close_handle() */
|
||||
libssh2_nonblocking_states close_state;
|
||||
unsigned long close_request_id;
|
||||
unsigned char *close_packet;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_SFTP
|
||||
{
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
|
||||
unsigned long request_id, version;
|
||||
|
||||
struct list_head packets;
|
||||
|
||||
/* a list of _LIBSSH2_SFTP_HANDLE structs */
|
||||
struct list_head sftp_handles;
|
||||
|
||||
unsigned long last_errno;
|
||||
|
||||
/* Holder for partial packet, use in libssh2_sftp_packet_read() */
|
||||
unsigned char *partial_packet; /* The data */
|
||||
size_t partial_len; /* Desired number of bytes */
|
||||
size_t partial_received; /* Bytes received so far */
|
||||
|
||||
/* Time that libssh2_sftp_packet_requirev() started reading */
|
||||
time_t requirev_start;
|
||||
|
||||
/* State variables used in libssh2_sftp_open_ex() */
|
||||
libssh2_nonblocking_states open_state;
|
||||
unsigned char *open_packet;
|
||||
size_t open_packet_len;
|
||||
size_t open_packet_sent;
|
||||
uint32_t open_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_read() */
|
||||
libssh2_nonblocking_states read_state;
|
||||
unsigned char *read_packet;
|
||||
uint32_t read_request_id;
|
||||
size_t read_total_read;
|
||||
|
||||
/* State variables used in libssh2_sftp_readdir() */
|
||||
libssh2_nonblocking_states readdir_state;
|
||||
unsigned char *readdir_packet;
|
||||
uint32_t readdir_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_write() */
|
||||
libssh2_nonblocking_states write_state;
|
||||
unsigned char *write_packet;
|
||||
uint32_t write_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_fstat_ex() */
|
||||
libssh2_nonblocking_states fstat_state;
|
||||
unsigned char *fstat_packet;
|
||||
uint32_t fstat_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_unlink_ex() */
|
||||
libssh2_nonblocking_states unlink_state;
|
||||
unsigned char *unlink_packet;
|
||||
uint32_t unlink_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_rename_ex() */
|
||||
libssh2_nonblocking_states rename_state;
|
||||
unsigned char *rename_packet;
|
||||
unsigned char *rename_s;
|
||||
uint32_t rename_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_fstatvfs() */
|
||||
libssh2_nonblocking_states fstatvfs_state;
|
||||
unsigned char *fstatvfs_packet;
|
||||
uint32_t fstatvfs_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_statvfs() */
|
||||
libssh2_nonblocking_states statvfs_state;
|
||||
unsigned char *statvfs_packet;
|
||||
uint32_t statvfs_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_mkdir() */
|
||||
libssh2_nonblocking_states mkdir_state;
|
||||
unsigned char *mkdir_packet;
|
||||
uint32_t mkdir_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_rmdir() */
|
||||
libssh2_nonblocking_states rmdir_state;
|
||||
unsigned char *rmdir_packet;
|
||||
uint32_t rmdir_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_stat() */
|
||||
libssh2_nonblocking_states stat_state;
|
||||
unsigned char *stat_packet;
|
||||
uint32_t stat_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_symlink() */
|
||||
libssh2_nonblocking_states symlink_state;
|
||||
unsigned char *symlink_packet;
|
||||
uint32_t symlink_request_id;
|
||||
};
|
||||
|
||||
#define LIBSSH2_SCP_RESPONSE_BUFLEN 256
|
||||
|
||||
struct flags {
|
||||
int sigpipe; /* LIBSSH2_FLAG_SIGPIPE */
|
||||
int compress; /* LIBSSH2_FLAG_COMPRESS */
|
||||
};
|
||||
|
||||
struct _LIBSSH2_SESSION
|
||||
{
|
||||
/* Memory management callbacks */
|
||||
@@ -685,14 +545,16 @@ struct _LIBSSH2_SESSION
|
||||
char *hostkey_prefs;
|
||||
|
||||
int state;
|
||||
int flags;
|
||||
|
||||
/* Flag options */
|
||||
struct flags flag;
|
||||
|
||||
/* Agreed Key Exchange Method */
|
||||
const LIBSSH2_KEX_METHOD *kex;
|
||||
int burn_optimistic_kexinit:1;
|
||||
|
||||
unsigned char *session_id;
|
||||
unsigned long session_id_len;
|
||||
uint32_t session_id_len;
|
||||
|
||||
/* this is set to TRUE if a blocking API behavior is requested */
|
||||
int api_block_mode;
|
||||
@@ -705,7 +567,7 @@ struct _LIBSSH2_SESSION
|
||||
* Or read from server in (eg) KEXDH_INIT (for client mode)
|
||||
*/
|
||||
unsigned char *server_hostkey;
|
||||
unsigned long server_hostkey_len;
|
||||
uint32_t server_hostkey_len;
|
||||
#if LIBSSH2_MD5
|
||||
unsigned char server_hostkey_md5[MD5_DIGEST_LENGTH];
|
||||
#endif /* ! LIBSSH2_MD5 */
|
||||
@@ -724,7 +586,7 @@ struct _LIBSSH2_SESSION
|
||||
/* Active connection channels */
|
||||
struct list_head channels;
|
||||
|
||||
unsigned long next_channel;
|
||||
uint32_t next_channel;
|
||||
|
||||
struct list_head listeners; /* list of LIBSSH2_LISTENER structs */
|
||||
|
||||
@@ -771,7 +633,7 @@ struct _LIBSSH2_SESSION
|
||||
|
||||
/* State variables used in libssh2_session_disconnect_ex() */
|
||||
libssh2_nonblocking_states disconnect_state;
|
||||
unsigned char *disconnect_data;
|
||||
unsigned char disconnect_data[256 + 13];
|
||||
size_t disconnect_data_len;
|
||||
|
||||
/* State variables used in libssh2_packet_read() */
|
||||
@@ -852,8 +714,8 @@ struct _LIBSSH2_SESSION
|
||||
/* State variables used in libssh2_channel_forward_listen_ex() */
|
||||
libssh2_nonblocking_states fwdLstn_state;
|
||||
unsigned char *fwdLstn_packet;
|
||||
unsigned long fwdLstn_host_len;
|
||||
unsigned long fwdLstn_packet_len;
|
||||
uint32_t fwdLstn_host_len;
|
||||
uint32_t fwdLstn_packet_len;
|
||||
packet_requirev_state_t fwdLstn_packet_requirev_state;
|
||||
|
||||
/* State variables used in libssh2_publickey_init() */
|
||||
@@ -868,16 +730,15 @@ struct _LIBSSH2_SESSION
|
||||
|
||||
/* State variables used in libssh2_packet_add() */
|
||||
libssh2_nonblocking_states packAdd_state;
|
||||
LIBSSH2_CHANNEL *packAdd_channel;
|
||||
unsigned long packAdd_data_head;
|
||||
key_exchange_state_t packAdd_key_state;
|
||||
LIBSSH2_CHANNEL *packAdd_channelp; /* keeper of the channel during EAGAIN
|
||||
states */
|
||||
packet_queue_listener_state_t packAdd_Qlstn_state;
|
||||
packet_x11_open_state_t packAdd_x11open_state;
|
||||
|
||||
/* State variables used in fullpacket() */
|
||||
libssh2_nonblocking_states fullpacket_state;
|
||||
int fullpacket_macstate;
|
||||
int fullpacket_payload_len;
|
||||
size_t fullpacket_payload_len;
|
||||
int fullpacket_packet_type;
|
||||
|
||||
/* State variables used in libssh2_sftp_init() */
|
||||
@@ -892,9 +753,9 @@ struct _LIBSSH2_SESSION
|
||||
/* State variables used in libssh2_scp_recv() */
|
||||
libssh2_nonblocking_states scpRecv_state;
|
||||
unsigned char *scpRecv_command;
|
||||
unsigned long scpRecv_command_len;
|
||||
size_t scpRecv_command_len;
|
||||
unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
|
||||
unsigned long scpRecv_response_len;
|
||||
size_t scpRecv_response_len;
|
||||
long scpRecv_mode;
|
||||
#if defined(HAVE_LONGLONG) && defined(HAVE_STRTOLL)
|
||||
/* we have the type and we can parse such numbers */
|
||||
@@ -906,18 +767,14 @@ struct _LIBSSH2_SESSION
|
||||
#endif
|
||||
long scpRecv_mtime;
|
||||
long scpRecv_atime;
|
||||
char *scpRecv_err_msg;
|
||||
long scpRecv_err_len;
|
||||
LIBSSH2_CHANNEL *scpRecv_channel;
|
||||
|
||||
/* State variables used in libssh2_scp_send_ex() */
|
||||
libssh2_nonblocking_states scpSend_state;
|
||||
unsigned char *scpSend_command;
|
||||
unsigned long scpSend_command_len;
|
||||
size_t scpSend_command_len;
|
||||
unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
|
||||
unsigned long scpSend_response_len;
|
||||
char *scpSend_err_msg;
|
||||
long scpSend_err_len;
|
||||
size_t scpSend_response_len;
|
||||
LIBSSH2_CHANNEL *scpSend_channel;
|
||||
|
||||
/* Keepalive variables used by keepalive.c. */
|
||||
@@ -934,8 +791,8 @@ struct _LIBSSH2_SESSION
|
||||
|
||||
/* session.flag helpers */
|
||||
#ifdef MSG_NOSIGNAL
|
||||
#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
|
||||
#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
|
||||
#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL)
|
||||
#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL)
|
||||
#else
|
||||
/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */
|
||||
#define LIBSSH2_SOCKET_SEND_FLAGS(session) 0
|
||||
@@ -1005,33 +862,22 @@ struct _LIBSSH2_CRYPT_METHOD
|
||||
struct _LIBSSH2_COMP_METHOD
|
||||
{
|
||||
const char *name;
|
||||
|
||||
int (*init) (LIBSSH2_SESSION * session, int compress, void **abstract);
|
||||
int (*comp) (LIBSSH2_SESSION * session, int compress, unsigned char **dest,
|
||||
size_t *dest_len, size_t payload_limit,
|
||||
int *free_dest, const unsigned char *src,
|
||||
size_t src_len, void **abstract);
|
||||
int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
|
||||
};
|
||||
|
||||
struct _LIBSSH2_MAC_METHOD
|
||||
{
|
||||
const char *name;
|
||||
|
||||
/* The length of a given MAC packet */
|
||||
int mac_len;
|
||||
|
||||
/* integrity key length */
|
||||
int key_len;
|
||||
|
||||
/* Message Authentication Code Hashing algo */
|
||||
int (*init) (LIBSSH2_SESSION * session, unsigned char *key, int *free_key,
|
||||
int compress; /* 1 if it does compress, 0 if it doesn't */
|
||||
int (*init) (LIBSSH2_SESSION *session, int compress, void **abstract);
|
||||
int (*comp) (LIBSSH2_SESSION *session,
|
||||
unsigned char *dest,
|
||||
size_t *dest_len,
|
||||
const unsigned char *src,
|
||||
size_t src_len,
|
||||
void **abstract);
|
||||
int (*hash) (LIBSSH2_SESSION * session, unsigned char *buf,
|
||||
unsigned long seqno, const unsigned char *packet,
|
||||
unsigned long packet_len, const unsigned char *addtl,
|
||||
unsigned long addtl_len, void **abstract);
|
||||
int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
|
||||
int (*decomp) (LIBSSH2_SESSION *session,
|
||||
unsigned char **dest,
|
||||
size_t *dest_len,
|
||||
size_t payload_limit,
|
||||
const unsigned char *src,
|
||||
size_t src_len,
|
||||
void **abstract);
|
||||
int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
|
||||
};
|
||||
|
||||
#ifdef LIBSSH2DEBUG
|
||||
@@ -1115,13 +961,17 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
#define SSH_MSG_CHANNEL_SUCCESS 99
|
||||
#define SSH_MSG_CHANNEL_FAILURE 100
|
||||
|
||||
#if defined( WIN32 ) || defined( __VMS )
|
||||
ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer, size_t length, int flags);
|
||||
ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer, size_t length, int flags);
|
||||
#else
|
||||
#define _libssh2_recv(a,b,c,d) recv(a,b,c,d)
|
||||
#define _libssh2_send(a,b,c,d) send(a,b,c,d)
|
||||
#endif
|
||||
/* Error codes returned in SSH_MSG_CHANNEL_OPEN_FAILURE message
|
||||
(see RFC4254) */
|
||||
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
|
||||
#define SSH_OPEN_CONNECT_FAILED 2
|
||||
#define SSH_OPEN_UNKNOWN_CHANNELTYPE 3
|
||||
#define SSH_OPEN_RESOURCE_SHORTAGE 4
|
||||
|
||||
ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer,
|
||||
size_t length, int flags);
|
||||
ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer,
|
||||
size_t length, int flags);
|
||||
|
||||
#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
|
||||
waiting for more data to arrive */
|
||||
@@ -1149,4 +999,11 @@ void _libssh2_init_if_needed (void);
|
||||
|
||||
#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 */
|
||||
|
36
src/mac.c
36
src/mac.c
@@ -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;
|
||||
|
24
src/mac.h
24
src/mac.h
@@ -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 */
|
||||
|
108
src/misc.c
108
src/misc.c
@@ -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,6 +48,7 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
|
||||
@@ -54,6 +56,10 @@ int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
|
||||
session->err_msg = errmsg;
|
||||
session->err_code = errcode;
|
||||
#ifdef LIBSSH2DEBUG
|
||||
if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode)
|
||||
/* if this is EAGAIN and we're in non-blocking mode, don't generate
|
||||
a debug output for this */
|
||||
return errcode;
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
|
||||
session->err_msg);
|
||||
#endif
|
||||
@@ -83,52 +89,56 @@ static int wsa2errno(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _libssh2_recv
|
||||
/* _libssh2_recv
|
||||
*
|
||||
* Wrapper around standard recv to allow WIN32 systems
|
||||
* to set errno
|
||||
* Replacement for the standard recv, return -errno on failure.
|
||||
*/
|
||||
ssize_t
|
||||
_libssh2_recv(libssh2_socket_t socket, void *buffer, size_t length, int flags)
|
||||
_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags)
|
||||
{
|
||||
ssize_t rc = recv(socket, buffer, length, flags);
|
||||
ssize_t rc = recv(sock, buffer, length, flags);
|
||||
#ifdef WIN32
|
||||
if (rc < 0 )
|
||||
errno = wsa2errno();
|
||||
#endif
|
||||
#ifdef __VMS
|
||||
return -wsa2errno();
|
||||
#elif defined(__VMS)
|
||||
if (rc < 0 ){
|
||||
if ( errno == EWOULDBLOCK ) errno = EAGAIN;
|
||||
if ( errno == EWOULDBLOCK )
|
||||
return -EAGAIN;
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
#else
|
||||
if (rc < 0 )
|
||||
return -errno;
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
#endif /* _libssh2_recv */
|
||||
|
||||
#ifndef _libssh2_send
|
||||
|
||||
/* _libssh2_send
|
||||
*
|
||||
* Wrapper around standard send to allow WIN32 systems
|
||||
* to set errno
|
||||
* Replacement for the standard send, return -errno on failure.
|
||||
*/
|
||||
ssize_t
|
||||
_libssh2_send(libssh2_socket_t socket, const void *buffer, size_t length, 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();
|
||||
#endif
|
||||
#ifdef VMS
|
||||
if (rc < 0 ){
|
||||
if ( errno == EWOULDBLOCK ) errno = EAGAIN;
|
||||
return -wsa2errno();
|
||||
#elif defined(__VMS)
|
||||
if (rc < 0 ) {
|
||||
if ( errno == EWOULDBLOCK )
|
||||
return -EAGAIN;
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
#else
|
||||
if (rc < 0 )
|
||||
return -errno;
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
#endif /* _libssh2_recv */
|
||||
|
||||
/* libssh2_ntohu32
|
||||
*/
|
||||
@@ -146,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;
|
||||
}
|
||||
@@ -259,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;
|
||||
@@ -347,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)
|
||||
@@ -356,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;
|
||||
@@ -367,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;
|
||||
@@ -392,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;
|
||||
@@ -405,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
|
||||
@@ -430,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;
|
||||
|
340
src/openssl.c
340
src/openssl.c
@@ -204,24 +204,49 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
@@ -135,61 +135,10 @@ void libssh2_md5(const unsigned char *message, unsigned long len, unsigned char
|
||||
|
||||
#define libssh2_rsa_ctx RSA
|
||||
|
||||
int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
|
||||
const unsigned char *edata,
|
||||
unsigned long elen,
|
||||
const unsigned char *ndata,
|
||||
unsigned long nlen,
|
||||
const unsigned char *ddata,
|
||||
unsigned long dlen,
|
||||
const unsigned char *pdata,
|
||||
unsigned long plen,
|
||||
const unsigned char *qdata,
|
||||
unsigned long qlen,
|
||||
const unsigned char *e1data,
|
||||
unsigned long e1len,
|
||||
const unsigned char *e2data,
|
||||
unsigned long e2len,
|
||||
const unsigned char *coeffdata, unsigned long coefflen);
|
||||
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
const char *filename,
|
||||
unsigned const char *passphrase);
|
||||
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
size_t hash_len,
|
||||
unsigned char **signature,
|
||||
size_t *signature_len);
|
||||
|
||||
#define _libssh2_rsa_free(rsactx) RSA_free(rsactx)
|
||||
|
||||
#define libssh2_dsa_ctx DSA
|
||||
|
||||
int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
|
||||
const unsigned char *pdata,
|
||||
unsigned long plen,
|
||||
const unsigned char *qdata,
|
||||
unsigned long qlen,
|
||||
const unsigned char *gdata,
|
||||
unsigned long glen,
|
||||
const unsigned char *ydata,
|
||||
unsigned long ylen,
|
||||
const unsigned char *x, unsigned long x_len);
|
||||
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
const char *filename,
|
||||
unsigned const char *passphrase);
|
||||
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *sig,
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len, unsigned char *sig);
|
||||
|
||||
#define _libssh2_dsa_free(dsactx) DSA_free(dsactx)
|
||||
|
||||
@@ -213,15 +162,6 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
#define _libssh2_cipher_cast5 EVP_cast5_cbc
|
||||
#define _libssh2_cipher_3des EVP_des_ede3_cbc
|
||||
|
||||
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
|
||||
_libssh2_cipher_type(algo),
|
||||
unsigned char *iv,
|
||||
unsigned char *secret, int encrypt);
|
||||
|
||||
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
_libssh2_cipher_type(algo),
|
||||
int encrypt, unsigned char *block);
|
||||
|
||||
#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx)
|
||||
|
||||
#define _libssh2_bn BIGNUM
|
||||
@@ -241,3 +181,4 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);
|
||||
|
||||
|
718
src/packet.c
718
src/packet.c
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@
|
||||
|
||||
#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
|
||||
@@ -259,12 +259,13 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
|
||||
default:
|
||||
LIBSSH2_FREE(session, data);
|
||||
if (response < 0) {
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
|
||||
"Invalid publickey subsystem response code");
|
||||
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, ignoring");
|
||||
"Unexpected publickey subsystem response");
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
@@ -321,7 +322,8 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
|
||||
rc = _libssh2_channel_process_startup(session->pkeyInit_channel,
|
||||
"subsystem",
|
||||
sizeof("subsystem") - 1,
|
||||
"publickey", strlen("publickey"));
|
||||
"publickey",
|
||||
sizeof("publickey") - 1);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block starting publickey subsystem");
|
||||
@@ -368,7 +370,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
|
||||
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;
|
||||
@@ -376,7 +378,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
|
||||
|
||||
if (session->pkeyInit_state == libssh2_NB_state_sent2) {
|
||||
rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
|
||||
(char *)session->pkeyInit_buffer,
|
||||
session->pkeyInit_buffer,
|
||||
19 - session->pkeyInit_buffer_sent);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
@@ -459,7 +461,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
|
||||
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;
|
||||
@@ -529,20 +531,27 @@ libssh2_publickey_init(LIBSSH2_SESSION *session)
|
||||
* 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;
|
||||
|
||||
@@ -627,14 +636,15 @@ 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 == LIBSSH2_ERROR_EAGAIN) {
|
||||
return rc;
|
||||
@@ -661,19 +671,27 @@ 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;
|
||||
|
||||
@@ -701,14 +719,15 @@ 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 == LIBSSH2_ERROR_EAGAIN) {
|
||||
return rc;
|
||||
@@ -742,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;
|
||||
|
||||
@@ -769,7 +794,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
|
||||
|
||||
if (pkey->listFetch_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_channel_write(channel, 0,
|
||||
(char *) pkey->listFetch_buffer,
|
||||
pkey->listFetch_buffer,
|
||||
(pkey->listFetch_s -
|
||||
pkey->listFetch_buffer));
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
@@ -927,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 */
|
||||
@@ -942,7 +970,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
|
||||
default:
|
||||
/* Unknown/Unexpected */
|
||||
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
|
||||
"Unexpected publickey subsystem response, ignoring");
|
||||
"Unexpected publickey subsystem response");
|
||||
LIBSSH2_FREE(session, pkey->listFetch_data);
|
||||
pkey->listFetch_data = NULL;
|
||||
}
|
||||
@@ -968,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);
|
||||
@@ -986,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
|
||||
*/
|
||||
|
218
src/scp.c
218
src/scp.c
@@ -360,7 +360,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
|
||||
if (session->scpRecv_state == libssh2_NB_state_sent1) {
|
||||
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
|
||||
(char *) session->scpRecv_response, 1);
|
||||
session->scpRecv_response, 1);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block sending initial wakeup");
|
||||
@@ -390,56 +390,53 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting for SCP response");
|
||||
return NULL;
|
||||
} else if (rc <= 0) {
|
||||
/* Timeout, give up */
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Timed out waiting for SCP response");
|
||||
}
|
||||
else if (rc < 0) {
|
||||
/* error, give up */
|
||||
_libssh2_error(session, rc, "Failed reading SCP response");
|
||||
goto scp_recv_error;
|
||||
}
|
||||
else if(rc == 0)
|
||||
goto scp_recv_empty_channel;
|
||||
|
||||
session->scpRecv_response_len++;
|
||||
|
||||
if (session->scpRecv_response[0] != 'T') {
|
||||
/*
|
||||
* Set this as the default error for here, if
|
||||
* we are successful it will be replaced
|
||||
*/
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid data in SCP response, missing Time data");
|
||||
size_t err_len;
|
||||
char *err_msg;
|
||||
|
||||
session->scpRecv_err_len =
|
||||
/* there can be
|
||||
01 for warnings
|
||||
02 for errors
|
||||
|
||||
The following string MUST be newline terminated
|
||||
*/
|
||||
err_len =
|
||||
_libssh2_channel_packet_data_len(session->
|
||||
scpRecv_channel, 0);
|
||||
session->scpRecv_err_msg =
|
||||
LIBSSH2_ALLOC(session, session->scpRecv_err_len + 1);
|
||||
if (!session->scpRecv_err_msg) {
|
||||
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
|
||||
if (!err_msg) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Failed to get memory ");
|
||||
goto scp_recv_error;
|
||||
}
|
||||
memset(session->scpRecv_err_msg, 0,
|
||||
session->scpRecv_err_len + 1);
|
||||
|
||||
/* Read the remote error message */
|
||||
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
|
||||
session->scpRecv_err_msg,
|
||||
session->scpRecv_err_len);
|
||||
if (rc <= 0) {
|
||||
/*
|
||||
* Since we have alread started reading this packet,
|
||||
* it is already in the systems so it can't return
|
||||
* LIBSSH2_ERROR_EAGAIN
|
||||
*/
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Unknown error" );
|
||||
}
|
||||
else
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"SCP protocol error");
|
||||
(void)_libssh2_channel_read(session->scpRecv_channel, 0,
|
||||
err_msg, err_len);
|
||||
/* If it failed for any reason, we ignore it anyway. */
|
||||
|
||||
/* TODO: for debugging purposes, the
|
||||
session->scpRecv_err_msg should be displayed here
|
||||
when available */
|
||||
/* zero terminate the error */
|
||||
err_msg[err_len]=0;
|
||||
|
||||
LIBSSH2_FREE(session, session->scpRecv_err_msg);
|
||||
session->scpRecv_err_msg = NULL;
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
|
||||
"got %02x %s", session->scpRecv_response[0],
|
||||
err_msg);
|
||||
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Failed to recv file");
|
||||
|
||||
LIBSSH2_FREE(session, err_msg);
|
||||
goto scp_recv_error;
|
||||
}
|
||||
|
||||
@@ -513,13 +510,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
|
||||
*(p++) = '\0';
|
||||
/* Make sure we don't get fooled by leftover values */
|
||||
errno = 0;
|
||||
session->scpRecv_mtime = strtol((char *) s, NULL, 10);
|
||||
if (errno) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid response from SCP server, invalid mtime");
|
||||
goto scp_recv_error;
|
||||
}
|
||||
|
||||
s = (unsigned char *) strchr((char *) p, ' ');
|
||||
if (!s || ((s - p) <= 0)) {
|
||||
/* No spaces or space in the wrong spot */
|
||||
@@ -540,13 +532,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
|
||||
*p = '\0';
|
||||
/* Make sure we don't get fooled by leftover values */
|
||||
errno = 0;
|
||||
session->scpRecv_atime = strtol((char *) s, NULL, 10);
|
||||
if (errno) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid response from SCP server, invalid atime");
|
||||
goto scp_recv_error;
|
||||
}
|
||||
|
||||
/* SCP ACK */
|
||||
session->scpRecv_response[0] = '\0';
|
||||
@@ -556,8 +542,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
|
||||
if (session->scpRecv_state == libssh2_NB_state_sent3) {
|
||||
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
|
||||
(char *) session->
|
||||
scpRecv_response, 1);
|
||||
session->scpRecv_response, 1);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting to send SCP ACK");
|
||||
@@ -599,12 +584,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting for SCP response");
|
||||
return NULL;
|
||||
} else if (rc <= 0) {
|
||||
/* Timeout, give up */
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Timed out waiting for SCP response");
|
||||
}
|
||||
else if (rc < 0) {
|
||||
/* error, bail out*/
|
||||
_libssh2_error(session, rc, "Failed reading SCP response");
|
||||
goto scp_recv_error;
|
||||
}
|
||||
else if(rc == 0)
|
||||
goto scp_recv_empty_channel;
|
||||
|
||||
session->scpRecv_response_len++;
|
||||
|
||||
if (session->scpRecv_response[0] != 'C') {
|
||||
@@ -621,11 +609,9 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
scpRecv_response[session->scpRecv_response_len - 1] !=
|
||||
'\n')
|
||||
&&
|
||||
((session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1] < 32)
|
||||
|| (session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1] >
|
||||
126))) {
|
||||
(session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1]
|
||||
< 32)) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid data in SCP response");
|
||||
goto scp_recv_error;
|
||||
@@ -679,9 +665,9 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
|
||||
*(p++) = '\0';
|
||||
/* Make sure we don't get fooled by leftover values */
|
||||
errno = 0;
|
||||
|
||||
session->scpRecv_mode = strtol(s, &e, 8);
|
||||
if ((e && *e) || errno) {
|
||||
if (e && *e) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid response from SCP server, invalid mode");
|
||||
goto scp_recv_error;
|
||||
@@ -697,9 +683,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
|
||||
*s = '\0';
|
||||
/* Make sure we don't get fooled by leftover values */
|
||||
errno = 0;
|
||||
session->scpRecv_size = scpsize_strtol(p, &e, 10);
|
||||
if ((e && *e) || errno) {
|
||||
if (e && *e) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid response from SCP server, invalid size");
|
||||
goto scp_recv_error;
|
||||
@@ -713,8 +698,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
|
||||
if (session->scpRecv_state == libssh2_NB_state_sent6) {
|
||||
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
|
||||
(char *) session->
|
||||
scpRecv_response, 1);
|
||||
session->scpRecv_response, 1);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block sending SCP ACK");
|
||||
@@ -747,8 +731,18 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
session->scpRecv_state = libssh2_NB_state_idle;
|
||||
return session->scpRecv_channel;
|
||||
|
||||
scp_recv_empty_channel:
|
||||
/* the code only jumps here as a result of a zero read from channel_read()
|
||||
so we check EOF status to avoid getting stuck in a loop */
|
||||
if(libssh2_channel_eof(session->scpRecv_channel))
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Unexpected channel close");
|
||||
else
|
||||
return session->scpRecv_channel;
|
||||
/* fall-through */
|
||||
scp_recv_error:
|
||||
while (libssh2_channel_free(session->scpRecv_channel) == LIBSSH2_ERROR_EAGAIN);
|
||||
while (libssh2_channel_free(session->scpRecv_channel) ==
|
||||
LIBSSH2_ERROR_EAGAIN);
|
||||
session->scpRecv_channel = NULL;
|
||||
session->scpRecv_state = libssh2_NB_state_idle;
|
||||
return NULL;
|
||||
@@ -869,12 +863,19 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting for response from remote");
|
||||
return NULL;
|
||||
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
|
||||
}
|
||||
else if (rc < 0) {
|
||||
_libssh2_error(session, rc, "SCP failure");
|
||||
goto scp_send_error;
|
||||
}
|
||||
else if(!rc)
|
||||
/* remain in the same state */
|
||||
goto scp_send_empty_channel;
|
||||
else if (session->scpSend_response[0] != 0) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid ACK response from remote");
|
||||
goto scp_send_error;
|
||||
}
|
||||
|
||||
if (mtime || atime) {
|
||||
/* Send mtime and atime to be used for file */
|
||||
session->scpSend_response_len =
|
||||
@@ -892,7 +893,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
if (mtime || atime) {
|
||||
if (session->scpSend_state == libssh2_NB_state_sent2) {
|
||||
rc = _libssh2_channel_write(session->scpSend_channel, 0,
|
||||
(char *) session->scpSend_response,
|
||||
session->scpSend_response,
|
||||
session->scpSend_response_len);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
@@ -915,9 +916,17 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting for response");
|
||||
return NULL;
|
||||
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
|
||||
}
|
||||
else if (rc < 0) {
|
||||
_libssh2_error(session, rc, "SCP failure");
|
||||
goto scp_send_error;
|
||||
}
|
||||
else if(!rc)
|
||||
/* remain in the same state */
|
||||
goto scp_send_empty_channel;
|
||||
else if (session->scpSend_response[0] != 0) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid ACK response from remote");
|
||||
"Invalid SCP ACK response");
|
||||
goto scp_send_error;
|
||||
}
|
||||
|
||||
@@ -939,7 +948,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
|
||||
session->scpSend_response_len =
|
||||
snprintf((char *) session->scpSend_response,
|
||||
LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %llu %s\n", mode,
|
||||
LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %"
|
||||
LIBSSH2_INT64_T_FORMAT "u %s\n", mode,
|
||||
size, base);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
|
||||
session->scpSend_response);
|
||||
@@ -949,7 +959,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
|
||||
if (session->scpSend_state == libssh2_NB_state_sent5) {
|
||||
rc = _libssh2_channel_write(session->scpSend_channel, 0,
|
||||
(char *) session->scpSend_response,
|
||||
session->scpSend_response,
|
||||
session->scpSend_response_len);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
@@ -972,51 +982,57 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting for response");
|
||||
return NULL;
|
||||
} else if (rc <= 0) {
|
||||
}
|
||||
else if (rc < 0) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid ACK response from remote");
|
||||
goto scp_send_error;
|
||||
} else if (session->scpSend_response[0] != 0) {
|
||||
/*
|
||||
* Set this as the default error for here, if
|
||||
* we are successful it will be replaced
|
||||
*/
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid ACK response from remote");
|
||||
}
|
||||
else if (rc == 0)
|
||||
goto scp_send_empty_channel;
|
||||
|
||||
session->scpSend_err_len =
|
||||
else if (session->scpSend_response[0] != 0) {
|
||||
size_t err_len;
|
||||
char *err_msg;
|
||||
|
||||
err_len =
|
||||
_libssh2_channel_packet_data_len(session->scpSend_channel, 0);
|
||||
session->scpSend_err_msg =
|
||||
LIBSSH2_ALLOC(session, session->scpSend_err_len + 1);
|
||||
if (!session->scpSend_err_msg) {
|
||||
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
|
||||
if (!err_msg) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"failed to get memory");
|
||||
goto scp_send_error;
|
||||
}
|
||||
memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
|
||||
|
||||
/* Read the remote error message */
|
||||
rc = _libssh2_channel_read(session->scpSend_channel, 0,
|
||||
session->scpSend_err_msg,
|
||||
session->scpSend_err_len);
|
||||
if (rc <= 0) {
|
||||
/*
|
||||
* Since we have alread started reading this packet, it is
|
||||
* already in the systems so it can't return
|
||||
* LIBSSH2_ERROR_EAGAIN
|
||||
*/
|
||||
LIBSSH2_FREE(session, session->scpSend_err_msg);
|
||||
session->scpSend_err_msg = NULL;
|
||||
err_msg, err_len);
|
||||
if (rc > 0) {
|
||||
err_msg[err_len]=0;
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
|
||||
"got %02x %s", session->scpSend_response[0],
|
||||
err_msg);
|
||||
}
|
||||
else
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"failed waiting for ACK");
|
||||
LIBSSH2_FREE(session, err_msg);
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"failed to send file");
|
||||
goto scp_send_error;
|
||||
}
|
||||
}
|
||||
|
||||
session->scpSend_state = libssh2_NB_state_idle;
|
||||
|
||||
return session->scpSend_channel;
|
||||
|
||||
scp_send_empty_channel:
|
||||
/* the code only jumps here as a result of a zero read from channel_read()
|
||||
so we check EOF status to avoid getting stuck in a loop */
|
||||
if(libssh2_channel_eof(session->scpSend_channel)) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Unexpected channel close");
|
||||
}
|
||||
else
|
||||
return session->scpSend_channel;
|
||||
/* fall-through */
|
||||
scp_send_error:
|
||||
while (libssh2_channel_free(session->scpSend_channel) ==
|
||||
LIBSSH2_ERROR_EAGAIN);
|
||||
|
208
src/session.c
208
src/session.c
@@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2009-2010 by Daniel Stenberg
|
||||
* Copyright (c) 2009-2011 by Daniel Stenberg
|
||||
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "transport.h"
|
||||
#include "session.h"
|
||||
#include "channel.h"
|
||||
#include "mac.h"
|
||||
|
||||
/* libssh2_default_alloc
|
||||
*/
|
||||
@@ -88,7 +89,8 @@ LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
|
||||
*
|
||||
* Wait for a hello from the remote host
|
||||
* Allocate a buffer and store the banner in session->remote.banner
|
||||
* Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative on failure
|
||||
* Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative
|
||||
* on failure
|
||||
*/
|
||||
static int
|
||||
banner_receive(LIBSSH2_SESSION * session)
|
||||
@@ -114,15 +116,18 @@ banner_receive(LIBSSH2_SESSION * session)
|
||||
|
||||
ret = _libssh2_recv(session->socket_fd, &c, 1,
|
||||
LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||
if (ret < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error recving %d bytes to %p: %d", 1, &c, errno);
|
||||
if (ret < 0) {
|
||||
if(session->api_block_mode || (ret != -EAGAIN))
|
||||
/* ignore EAGAIN when non-blocking */
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error recving %d bytes: %d", 1, -ret);
|
||||
}
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Recved %d bytes to %p", ret, &c);
|
||||
"Recved %d bytes banner", ret);
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
if (ret == -EAGAIN) {
|
||||
session->socket_block_directions =
|
||||
LIBSSH2_SESSION_BLOCK_INBOUND;
|
||||
session->banner_TxRx_total_send = banner_len;
|
||||
@@ -132,19 +137,19 @@ banner_receive(LIBSSH2_SESSION * session)
|
||||
/* Some kinda error */
|
||||
session->banner_TxRx_state = libssh2_NB_state_idle;
|
||||
session->banner_TxRx_total_send = 0;
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_SOCKET_RECV;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
return LIBSSH2_ERROR_SOCKET_RECV;
|
||||
}
|
||||
|
||||
if (c == '\0') {
|
||||
/* NULLs are not allowed in SSH banners */
|
||||
session->banner_TxRx_state = libssh2_NB_state_idle;
|
||||
session->banner_TxRx_total_send = 0;
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_BANNER_RECV;
|
||||
}
|
||||
|
||||
session->banner_TxRx_banner[banner_len++] = c;
|
||||
@@ -161,7 +166,7 @@ banner_receive(LIBSSH2_SESSION * session)
|
||||
session->banner_TxRx_total_send = 0;
|
||||
|
||||
if (!banner_len)
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_BANNER_RECV;
|
||||
|
||||
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
|
||||
if (!session->remote.banner) {
|
||||
@@ -172,7 +177,7 @@ banner_receive(LIBSSH2_SESSION * session)
|
||||
session->remote.banner[banner_len] = '\0';
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
|
||||
session->remote.banner);
|
||||
return 0;
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -180,9 +185,9 @@ banner_receive(LIBSSH2_SESSION * session)
|
||||
*
|
||||
* Send the default banner, or the one set via libssh2_setopt_string
|
||||
*
|
||||
* Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you should
|
||||
* call this function again as soon as it is likely that more data can be
|
||||
* sent, and this function should then be called with the same argument set
|
||||
* Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you
|
||||
* should call this function again as soon as it is likely that more data can
|
||||
* be sent, and this function should then be called with the same argument set
|
||||
* (same data pointer and same data_len) until zero or failure is returned.
|
||||
*/
|
||||
static int
|
||||
@@ -228,7 +233,7 @@ banner_send(LIBSSH2_SESSION * session)
|
||||
if (ret < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error sending %d bytes: %d",
|
||||
banner_len - session->banner_TxRx_total_send, errno);
|
||||
banner_len - session->banner_TxRx_total_send, -ret);
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Sent %d/%d bytes at %p+%d", ret,
|
||||
@@ -236,16 +241,17 @@ banner_send(LIBSSH2_SESSION * session)
|
||||
banner, session->banner_TxRx_total_send);
|
||||
|
||||
if (ret != (banner_len - session->banner_TxRx_total_send)) {
|
||||
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
|
||||
if (ret >= 0 || ret == -EAGAIN) {
|
||||
/* the whole packet could not be sent, save the what was */
|
||||
session->socket_block_directions =
|
||||
LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
||||
session->banner_TxRx_total_send += ret;
|
||||
if (ret > 0)
|
||||
session->banner_TxRx_total_send += ret;
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
}
|
||||
session->banner_TxRx_state = libssh2_NB_state_idle;
|
||||
session->banner_TxRx_total_send = 0;
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
return LIBSSH2_ERROR_SOCKET_RECV;
|
||||
}
|
||||
|
||||
/* Set the state back to idle */
|
||||
@@ -410,16 +416,15 @@ get_socket_nonblocking(int sockfd)
|
||||
LIBSSH2_API int
|
||||
libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
|
||||
{
|
||||
int banner_len = banner ? strlen(banner) : 0;
|
||||
size_t banner_len = banner ? strlen(banner) : 0;
|
||||
|
||||
if (session->local.banner) {
|
||||
LIBSSH2_FREE(session, session->local.banner);
|
||||
session->local.banner = NULL;
|
||||
}
|
||||
|
||||
if (!banner_len) {
|
||||
if (!banner_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
|
||||
if (!session->local.banner) {
|
||||
@@ -543,6 +548,12 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session)
|
||||
int seconds_to_next;
|
||||
int dir;
|
||||
|
||||
/* since libssh2 often sets EAGAIN internally before this function 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 has returned */
|
||||
session->err_code = LIBSSH2_ERROR_NONE;
|
||||
|
||||
rc = libssh2_keepalive_send (session, &seconds_to_next);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -550,6 +561,14 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session)
|
||||
/* figure out what to wait for */
|
||||
dir = libssh2_session_block_directions(session);
|
||||
|
||||
if(!dir) {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Nothing to wait for in wait_socket");
|
||||
/* To avoid that we hang below just because there's nothing set to
|
||||
wait for, we timeout on 1 second to also avoid busy-looping
|
||||
during this condition */
|
||||
seconds_to_next = 1;
|
||||
}
|
||||
{
|
||||
#ifdef HAVE_POLL
|
||||
struct pollfd sockets[1];
|
||||
@@ -564,7 +583,8 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session)
|
||||
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
|
||||
sockets[0].events |= POLLOUT;
|
||||
|
||||
rc = poll(sockets, 1, seconds_to_next ? seconds_to_next / 1000 : -1);
|
||||
rc = poll(sockets, 1, seconds_to_next ?
|
||||
seconds_to_next * 1000 : -1);
|
||||
#else
|
||||
fd_set rfd;
|
||||
fd_set wfd;
|
||||
@@ -614,7 +634,7 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
"session_startup for socket %d", sock);
|
||||
if (INVALID_SOCKET == sock) {
|
||||
/* Did we forget something? */
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE,
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET,
|
||||
"Bad socket provided");
|
||||
}
|
||||
session->socket_fd = sock;
|
||||
@@ -640,11 +660,14 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
}
|
||||
|
||||
if (session->startup_state == libssh2_NB_state_sent) {
|
||||
rc = banner_receive(session);
|
||||
if (rc) {
|
||||
return _libssh2_error(session, rc,
|
||||
"Failed getting banner");
|
||||
}
|
||||
do {
|
||||
session->banner_TxRx_state = libssh2_NB_state_idle;
|
||||
|
||||
rc = banner_receive(session);
|
||||
if (rc)
|
||||
return _libssh2_error(session, rc,
|
||||
"Failed getting banner");
|
||||
} while(strncmp("SSH-", (char *)session->remote.banner, 4));
|
||||
|
||||
session->startup_state = libssh2_NB_state_sent1;
|
||||
}
|
||||
@@ -673,8 +696,9 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
}
|
||||
|
||||
if (session->startup_state == libssh2_NB_state_sent3) {
|
||||
rc = _libssh2_transport_write(session, session->startup_service,
|
||||
sizeof("ssh-userauth") + 5 - 1);
|
||||
rc = _libssh2_transport_send(session, session->startup_service,
|
||||
sizeof("ssh-userauth") + 5 - 1,
|
||||
NULL, 0);
|
||||
if (rc) {
|
||||
return _libssh2_error(session, rc,
|
||||
"Unable to ask for ssh-userauth service");
|
||||
@@ -715,16 +739,15 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
}
|
||||
|
||||
/*
|
||||
* proto libssh2_session_startup
|
||||
* libssh2_session_handshake()
|
||||
*
|
||||
* session: LIBSSH2_SESSION struct allocated and owned by the calling program
|
||||
* sock: *must* be populated with an opened and connected socket.
|
||||
*
|
||||
* Returns: 0 on success, or non-zero on failure
|
||||
* Any memory allocated by libssh2 will use alloc/realloc/free
|
||||
* callbacks in session.
|
||||
* The 'sock' socket *must* be populated with an opened and connected socket.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
|
||||
libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -733,6 +756,23 @@ libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_session_startup()
|
||||
*
|
||||
* DEPRECATED. Use libssh2_session_handshake() instead! This function is not
|
||||
* portable enough.
|
||||
*
|
||||
* session: LIBSSH2_SESSION struct allocated and owned by the calling program
|
||||
* sock: *must* be populated with an opened and connected socket.
|
||||
*
|
||||
* Returns: 0 on success, or non-zero on failure
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
|
||||
{
|
||||
return libssh2_session_handshake(session, (libssh2_socket_t) sock);
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_session_free
|
||||
*
|
||||
@@ -746,7 +786,6 @@ session_free(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_PACKET *pkg;
|
||||
LIBSSH2_CHANNEL *ch;
|
||||
LIBSSH2_LISTENER *l;
|
||||
struct transportpacket *p = &session->packet;
|
||||
|
||||
if (session->free_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource",
|
||||
@@ -836,6 +875,9 @@ session_free(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_FREE(session, session->hostkey_prefs);
|
||||
}
|
||||
|
||||
if (session->local.kexinit) {
|
||||
LIBSSH2_FREE(session, session->local.kexinit);
|
||||
}
|
||||
if (session->local.crypt_prefs) {
|
||||
LIBSSH2_FREE(session, session->local.crypt_prefs);
|
||||
}
|
||||
@@ -849,6 +891,9 @@ session_free(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_FREE(session, session->local.lang_prefs);
|
||||
}
|
||||
|
||||
if (session->remote.kexinit) {
|
||||
LIBSSH2_FREE(session, session->remote.kexinit);
|
||||
}
|
||||
if (session->remote.crypt_prefs) {
|
||||
LIBSSH2_FREE(session, session->remote.crypt_prefs);
|
||||
}
|
||||
@@ -865,12 +910,12 @@ session_free(LIBSSH2_SESSION *session)
|
||||
/*
|
||||
* Make sure all memory used in the state variables are free
|
||||
*/
|
||||
if (session->kexinit_data) {
|
||||
LIBSSH2_FREE(session, session->kexinit_data);
|
||||
}
|
||||
if (session->startup_data) {
|
||||
LIBSSH2_FREE(session, session->startup_data);
|
||||
}
|
||||
if (session->disconnect_data) {
|
||||
LIBSSH2_FREE(session, session->disconnect_data);
|
||||
}
|
||||
if (session->userauth_list_data) {
|
||||
LIBSSH2_FREE(session, session->userauth_list_data);
|
||||
}
|
||||
@@ -928,12 +973,6 @@ session_free(LIBSSH2_SESSION *session)
|
||||
if (session->scpSend_command) {
|
||||
LIBSSH2_FREE(session, session->scpSend_command);
|
||||
}
|
||||
if (session->scpRecv_err_msg) {
|
||||
LIBSSH2_FREE(session, session->scpRecv_err_msg);
|
||||
}
|
||||
if (session->scpSend_err_msg) {
|
||||
LIBSSH2_FREE(session, session->scpSend_err_msg);
|
||||
}
|
||||
|
||||
/* Cleanup all remaining packets */
|
||||
while ((pkg = _libssh2_list_first(&session->packets))) {
|
||||
@@ -945,11 +984,6 @@ session_free(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_FREE(session, pkg);
|
||||
}
|
||||
|
||||
/* Cleanup remaining outgoing packet buffer */
|
||||
if (p->outbuf) {
|
||||
LIBSSH2_FREE(session, p->outbuf);
|
||||
}
|
||||
|
||||
if(session->socket_prev_blockstate)
|
||||
/* if the socket was previously blocking, put it back so */
|
||||
session_nonblock(session->socket_fd, 0);
|
||||
@@ -984,7 +1018,8 @@ libssh2_session_free(LIBSSH2_SESSION * session)
|
||||
*/
|
||||
static int
|
||||
session_disconnect(LIBSSH2_SESSION *session, int reason,
|
||||
const char *description, const char *lang)
|
||||
const char *description,
|
||||
const char *lang)
|
||||
{
|
||||
unsigned char *s;
|
||||
unsigned long descr_len = 0, lang_len = 0;
|
||||
@@ -994,40 +1029,36 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Disconnecting: reason=%d, desc=%s, lang=%s", reason,
|
||||
description, lang);
|
||||
if (description) {
|
||||
if (description)
|
||||
descr_len = strlen(description);
|
||||
}
|
||||
if (lang) {
|
||||
|
||||
if (lang)
|
||||
lang_len = strlen(lang);
|
||||
}
|
||||
|
||||
if(descr_len > 256)
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
|
||||
"too long description");
|
||||
|
||||
/* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
|
||||
session->disconnect_data_len = descr_len + lang_len + 13;
|
||||
|
||||
s = session->disconnect_data =
|
||||
LIBSSH2_ALLOC(session, session->disconnect_data_len);
|
||||
if (!session->disconnect_data) {
|
||||
session->disconnect_state = libssh2_NB_state_idle;
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate memory for "
|
||||
"disconnect packet");
|
||||
}
|
||||
s = session->disconnect_data;
|
||||
|
||||
*(s++) = SSH_MSG_DISCONNECT;
|
||||
_libssh2_store_u32(&s, reason);
|
||||
_libssh2_store_str(&s, description, descr_len);
|
||||
_libssh2_store_str(&s, lang, lang_len);
|
||||
/* store length only, lang is sent separately */
|
||||
_libssh2_store_u32(&s, lang_len);
|
||||
|
||||
session->disconnect_state = libssh2_NB_state_created;
|
||||
}
|
||||
|
||||
rc = _libssh2_transport_write(session, session->disconnect_data,
|
||||
session->disconnect_data_len);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
rc = _libssh2_transport_send(session, session->disconnect_data,
|
||||
session->disconnect_data_len,
|
||||
(unsigned char *)lang, lang_len);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN)
|
||||
return rc;
|
||||
}
|
||||
|
||||
LIBSSH2_FREE(session, session->disconnect_data);
|
||||
session->disconnect_data = NULL;
|
||||
session->disconnect_state = libssh2_NB_state_idle;
|
||||
|
||||
return 0;
|
||||
@@ -1192,19 +1223,24 @@ libssh2_session_last_errno(LIBSSH2_SESSION * session)
|
||||
*
|
||||
* Set/Get session flags
|
||||
*
|
||||
* Passing flag==0 will avoid changing session->flags while still returning
|
||||
* its current value
|
||||
* Return error code.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
|
||||
{
|
||||
if (value) {
|
||||
session->flags |= flag;
|
||||
} else {
|
||||
session->flags &= ~flag;
|
||||
switch(flag) {
|
||||
case LIBSSH2_FLAG_SIGPIPE:
|
||||
session->flag.sigpipe = value;
|
||||
break;
|
||||
case LIBSSH2_FLAG_COMPRESS:
|
||||
session->flag.compress = value;
|
||||
break;
|
||||
default:
|
||||
/* unknown flag */
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
}
|
||||
|
||||
return session->flags;
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* _libssh2_session_set_blocking
|
||||
@@ -1252,10 +1288,16 @@ libssh2_session_get_blocking(LIBSSH2_SESSION * session)
|
||||
* non-0 if data is available
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
|
||||
libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended)
|
||||
{
|
||||
LIBSSH2_SESSION *session = channel->session;
|
||||
LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
|
||||
LIBSSH2_SESSION *session;
|
||||
LIBSSH2_PACKET *packet;
|
||||
|
||||
if(!channel)
|
||||
return LIBSSH2_ERROR_BAD_USE;
|
||||
|
||||
session = channel->session;
|
||||
packet = _libssh2_list_first(&session->packets);
|
||||
|
||||
while (packet) {
|
||||
if ( channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
|
||||
@@ -1316,8 +1358,8 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
|
||||
struct pollfd sockets[256];
|
||||
|
||||
if (nfds > 256)
|
||||
/* systems without alloca use a fixed-size array, this can be fixed
|
||||
if we really want to, at least if the compiler is a C99 capable one */
|
||||
/* systems without alloca use a fixed-size array, this can be fixed if
|
||||
we really want to, at least if the compiler is a C99 capable one */
|
||||
return -1;
|
||||
#endif
|
||||
/* Setup sockets for polling */
|
||||
|
1062
src/sftp.c
1062
src/sftp.c
File diff suppressed because it is too large
Load Diff
219
src/sftp.h
Normal file
219
src/sftp.h
Normal file
@@ -0,0 +1,219 @@
|
||||
#ifndef _LIBSSH2_SFP_H
|
||||
#define _LIBSSH2_SFTP_H
|
||||
/*
|
||||
* Copyright (C) 2010 by Daniel Stenberg
|
||||
* Author: Daniel Stenberg <daniel@haxx.se>
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names
|
||||
* of any other contributors may be used to endorse or
|
||||
* promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* MAX_SFTP_OUTGOING_SIZE MUST not be larger than 32500 or so. This is the
|
||||
* amount of data sent in each FXP_WRITE packet
|
||||
*/
|
||||
#define MAX_SFTP_OUTGOING_SIZE 30000
|
||||
|
||||
/* MAX_SFTP_READ_SIZE is how much data is asked for at max in each FXP_READ
|
||||
* packets.
|
||||
*/
|
||||
#define MAX_SFTP_READ_SIZE 2000
|
||||
|
||||
struct sftp_pipeline_chunk {
|
||||
struct list_node node;
|
||||
size_t len; /* WRITE: size of the data to write
|
||||
READ: how many bytes that was asked for */
|
||||
size_t sent;
|
||||
ssize_t lefttosend; /* if 0, the entire packet has been sent off */
|
||||
uint32_t request_id;
|
||||
unsigned char packet[1]; /* data */
|
||||
};
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
struct _LIBSSH2_SFTP_PACKET
|
||||
{
|
||||
struct list_node node; /* linked list header */
|
||||
uint32_t request_id;
|
||||
unsigned char *data;
|
||||
size_t data_len; /* payload size */
|
||||
};
|
||||
|
||||
typedef struct _LIBSSH2_SFTP_PACKET LIBSSH2_SFTP_PACKET;
|
||||
|
||||
#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
|
||||
|
||||
struct _LIBSSH2_SFTP_HANDLE
|
||||
{
|
||||
struct list_node node;
|
||||
|
||||
LIBSSH2_SFTP *sftp;
|
||||
|
||||
char handle[SFTP_HANDLE_MAXLEN];
|
||||
size_t handle_len;
|
||||
|
||||
enum {
|
||||
LIBSSH2_SFTP_HANDLE_FILE,
|
||||
LIBSSH2_SFTP_HANDLE_DIR
|
||||
} handle_type;
|
||||
|
||||
union _libssh2_sftp_handle_data
|
||||
{
|
||||
struct _libssh2_sftp_handle_file_data
|
||||
{
|
||||
libssh2_uint64_t offset;
|
||||
libssh2_uint64_t offset_sent;
|
||||
size_t acked; /* container for acked data that hasn't been
|
||||
returned to caller yet, used for sftp_write */
|
||||
|
||||
/* 'data' is used by sftp_read() and is allocated data that has
|
||||
been received already from the server but wasn't returned to
|
||||
the caller yet. It is of size 'data_len' and 'data_left is the
|
||||
number of bytes not yet returned, counted from the end of the
|
||||
buffer. */
|
||||
unsigned char *data;
|
||||
size_t data_len;
|
||||
size_t data_left;
|
||||
|
||||
char eof; /* we have read to the end */
|
||||
} file;
|
||||
struct _libssh2_sftp_handle_dir_data
|
||||
{
|
||||
uint32_t names_left;
|
||||
void *names_packet;
|
||||
char *next_name;
|
||||
} dir;
|
||||
} u;
|
||||
|
||||
/* State variables used in libssh2_sftp_close_handle() */
|
||||
libssh2_nonblocking_states close_state;
|
||||
uint32_t close_request_id;
|
||||
unsigned char *close_packet;
|
||||
|
||||
/* list of outstanding packets sent to server */
|
||||
struct list_head packet_list;
|
||||
|
||||
};
|
||||
|
||||
struct _LIBSSH2_SFTP
|
||||
{
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
|
||||
uint32_t request_id, version;
|
||||
|
||||
struct list_head packets;
|
||||
|
||||
/* a list of _LIBSSH2_SFTP_HANDLE structs */
|
||||
struct list_head sftp_handles;
|
||||
|
||||
uint32_t last_errno;
|
||||
|
||||
/* Holder for partial packet, use in libssh2_sftp_packet_read() */
|
||||
unsigned char partial_size[4]; /* buffer for size field */
|
||||
size_t partial_size_len; /* size field length */
|
||||
unsigned char *partial_packet; /* The data */
|
||||
uint32_t partial_len; /* Desired number of bytes */
|
||||
size_t partial_received; /* Bytes received so far */
|
||||
|
||||
/* Time that libssh2_sftp_packet_requirev() started reading */
|
||||
time_t requirev_start;
|
||||
|
||||
/* State variables used in libssh2_sftp_open_ex() */
|
||||
libssh2_nonblocking_states open_state;
|
||||
unsigned char *open_packet;
|
||||
uint32_t open_packet_len; /* 32 bit on the wire */
|
||||
size_t open_packet_sent;
|
||||
uint32_t open_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_read() */
|
||||
libssh2_nonblocking_states read_state;
|
||||
unsigned char *read_packet;
|
||||
uint32_t read_request_id;
|
||||
size_t read_total_read;
|
||||
|
||||
/* State variables used in libssh2_sftp_readdir() */
|
||||
libssh2_nonblocking_states readdir_state;
|
||||
unsigned char *readdir_packet;
|
||||
uint32_t readdir_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_fstat_ex() */
|
||||
libssh2_nonblocking_states fstat_state;
|
||||
unsigned char *fstat_packet;
|
||||
uint32_t fstat_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_unlink_ex() */
|
||||
libssh2_nonblocking_states unlink_state;
|
||||
unsigned char *unlink_packet;
|
||||
uint32_t unlink_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_rename_ex() */
|
||||
libssh2_nonblocking_states rename_state;
|
||||
unsigned char *rename_packet;
|
||||
unsigned char *rename_s;
|
||||
uint32_t rename_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_fstatvfs() */
|
||||
libssh2_nonblocking_states fstatvfs_state;
|
||||
unsigned char *fstatvfs_packet;
|
||||
uint32_t fstatvfs_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_statvfs() */
|
||||
libssh2_nonblocking_states statvfs_state;
|
||||
unsigned char *statvfs_packet;
|
||||
uint32_t statvfs_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_mkdir() */
|
||||
libssh2_nonblocking_states mkdir_state;
|
||||
unsigned char *mkdir_packet;
|
||||
uint32_t mkdir_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_rmdir() */
|
||||
libssh2_nonblocking_states rmdir_state;
|
||||
unsigned char *rmdir_packet;
|
||||
uint32_t rmdir_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_stat() */
|
||||
libssh2_nonblocking_states stat_state;
|
||||
unsigned char *stat_packet;
|
||||
uint32_t stat_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_symlink() */
|
||||
libssh2_nonblocking_states symlink_state;
|
||||
unsigned char *symlink_packet;
|
||||
uint32_t symlink_request_id;
|
||||
};
|
||||
|
||||
#endif
|
268
src/transport.c
268
src/transport.c
@@ -42,10 +42,14 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#ifdef LIBSSH2DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "transport.h"
|
||||
#include "mac.h"
|
||||
|
||||
#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */
|
||||
#define MAX_MACSIZE 20 /* MUST fit biggest MAC length we support */
|
||||
@@ -54,7 +58,7 @@
|
||||
#define UNPRINTABLE_CHAR '.'
|
||||
static void
|
||||
debugdump(LIBSSH2_SESSION * session,
|
||||
const char *desc, unsigned char *ptr, size_t size)
|
||||
const char *desc, const unsigned char *ptr, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
size_t c;
|
||||
@@ -74,7 +78,7 @@ debugdump(LIBSSH2_SESSION * session,
|
||||
(session->tracehandler)(session, session->tracehandler_context,
|
||||
buffer, used);
|
||||
else
|
||||
write(2 /* stderr */, buffer, used);
|
||||
fprintf(stderr, "%s", buffer);
|
||||
|
||||
for(i = 0; i < size; i += width) {
|
||||
|
||||
@@ -110,7 +114,7 @@ debugdump(LIBSSH2_SESSION * session,
|
||||
(session->tracehandler)(session, session->tracehandler_context,
|
||||
buffer, used);
|
||||
else
|
||||
write(2, buffer, used);
|
||||
fprintf(stderr, "%s", buffer);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -138,7 +142,7 @@ decrypt(LIBSSH2_SESSION * session, unsigned char *source,
|
||||
if (session->remote.crypt->crypt(session, source,
|
||||
&session->remote.crypt_abstract)) {
|
||||
LIBSSH2_FREE(session, p->payload);
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
return LIBSSH2_ERROR_DECRYPT;
|
||||
}
|
||||
|
||||
/* if the crypt() function would write to a given address it
|
||||
@@ -196,49 +200,28 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
||||
|
||||
/* Check for and deal with decompression */
|
||||
if (session->remote.comp &&
|
||||
strcmp(session->remote.comp->name, "none")) {
|
||||
session->remote.comp->compress &&
|
||||
session->remote.comp_abstract) {
|
||||
/*
|
||||
* The buffer for the decompression (remote.comp_abstract) is
|
||||
* initialised in time when it is needed so as long it is NULL we
|
||||
* cannot decompress.
|
||||
*/
|
||||
|
||||
unsigned char *data;
|
||||
size_t data_len;
|
||||
int free_payload = 1;
|
||||
rc = session->remote.comp->decomp(session,
|
||||
&data, &data_len,
|
||||
LIBSSH2_PACKET_MAXDECOMP,
|
||||
p->payload,
|
||||
session->fullpacket_payload_len,
|
||||
&session->remote.comp_abstract);
|
||||
LIBSSH2_FREE(session, p->payload);
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
if (session->remote.comp->comp(session, 0,
|
||||
&data, &data_len,
|
||||
LIBSSH2_PACKET_MAXDECOMP,
|
||||
&free_payload,
|
||||
p->payload,
|
||||
session->fullpacket_payload_len,
|
||||
&session->remote.comp_abstract)) {
|
||||
LIBSSH2_FREE(session, p->payload);
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
}
|
||||
|
||||
if (free_payload) {
|
||||
LIBSSH2_FREE(session, p->payload);
|
||||
p->payload = data;
|
||||
session->fullpacket_payload_len = data_len;
|
||||
} else {
|
||||
if (data == p->payload) {
|
||||
/* It's not to be freed, because the
|
||||
* compression layer reused payload, So let's
|
||||
* do the same!
|
||||
*/
|
||||
session->fullpacket_payload_len = data_len;
|
||||
} else {
|
||||
/* No comp_method actually lets this happen,
|
||||
* but let's prepare for the future */
|
||||
|
||||
LIBSSH2_FREE(session, p->payload);
|
||||
|
||||
/* We need a freeable struct otherwise the
|
||||
* brigade won't know what to do with it */
|
||||
p->payload = LIBSSH2_ALLOC(session, data_len);
|
||||
if (!p->payload)
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
|
||||
memcpy(p->payload, data, data_len);
|
||||
session->fullpacket_payload_len = data_len;
|
||||
}
|
||||
}
|
||||
p->payload = data;
|
||||
session->fullpacket_payload_len = data_len;
|
||||
}
|
||||
|
||||
session->fullpacket_packet_type = p->payload[0];
|
||||
@@ -280,7 +263,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
||||
*/
|
||||
int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
{
|
||||
int rc = LIBSSH2_ERROR_SOCKET_NONE;
|
||||
int rc;
|
||||
struct transportpacket *p = &session->packet;
|
||||
int remainbuf;
|
||||
int remainpack;
|
||||
@@ -289,6 +272,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
unsigned char block[MAX_BLOCKSIZE];
|
||||
int blocksize;
|
||||
int encrypted = 1;
|
||||
size_t total_num;
|
||||
|
||||
/* default clear the bit */
|
||||
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
|
||||
@@ -376,25 +360,22 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
_libssh2_recv(session->socket_fd, &p->buf[remainbuf],
|
||||
PACKETBUFSIZE - remainbuf,
|
||||
LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||
if (nread < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error recving %d bytes to %p+%d: %d",
|
||||
PACKETBUFSIZE - remainbuf, p->buf, remainbuf,
|
||||
errno);
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Recved %d/%d bytes to %p+%d", nread,
|
||||
PACKETBUFSIZE - remainbuf, p->buf, remainbuf);
|
||||
if (nread <= 0) {
|
||||
/* check if this is due to EAGAIN and return the special
|
||||
return code if so, error out normally otherwise */
|
||||
if ((nread < 0) && (errno == EAGAIN)) {
|
||||
if ((nread < 0) && (nread == -EAGAIN)) {
|
||||
session->socket_block_directions |=
|
||||
LIBSSH2_SESSION_BLOCK_INBOUND;
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
}
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error recving %d bytes (got %d)",
|
||||
PACKETBUFSIZE - remainbuf, -nread);
|
||||
return LIBSSH2_ERROR_SOCKET_RECV;
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Recved %d/%d bytes to %p+%d", nread,
|
||||
PACKETBUFSIZE - remainbuf, p->buf, remainbuf);
|
||||
|
||||
debugdump(session, "libssh2_transport_read() raw",
|
||||
&p->buf[remainbuf], nread);
|
||||
@@ -445,13 +426,13 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
*/
|
||||
p->packet_length = _libssh2_ntohu32(block);
|
||||
if (p->packet_length < 1)
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
return LIBSSH2_ERROR_DECRYPT;
|
||||
|
||||
p->padding_length = block[4];
|
||||
|
||||
/* total_num is the number of bytes following the initial
|
||||
(5 bytes) packet length and padding length fields */
|
||||
p->total_num =
|
||||
total_num =
|
||||
p->packet_length - 1 +
|
||||
(encrypted ? session->remote.mac->mac_len : 0);
|
||||
|
||||
@@ -463,16 +444,17 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
* or less (including length, padding length, payload,
|
||||
* padding, and MAC.)."
|
||||
*/
|
||||
if (p->total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
|
||||
if (total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
|
||||
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
||||
}
|
||||
|
||||
/* Get a packet handle put data into. We get one to
|
||||
hold all data, including padding and MAC. */
|
||||
p->payload = LIBSSH2_ALLOC(session, p->total_num);
|
||||
p->payload = LIBSSH2_ALLOC(session, total_num);
|
||||
if (!p->payload) {
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
}
|
||||
p->total_num = total_num;
|
||||
/* init write pointer to start of payload buffer */
|
||||
p->wptr = p->payload;
|
||||
|
||||
@@ -597,32 +579,18 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
}
|
||||
} while (1); /* loop */
|
||||
|
||||
return LIBSSH2_ERROR_SOCKET_NONE; /* we never reach this point */
|
||||
}
|
||||
|
||||
/*
|
||||
* _libssh2_transport_drain() empties the outgoing send buffer if there
|
||||
* is any.
|
||||
*/
|
||||
void _libssh2_transport_drain(LIBSSH2_SESSION * session)
|
||||
{
|
||||
struct transportpacket *p = &session->packet;
|
||||
if(p->outbuf) {
|
||||
LIBSSH2_FREE(session, p->outbuf);
|
||||
p->outbuf = NULL;
|
||||
p->ototal_num = 0;
|
||||
}
|
||||
return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */
|
||||
}
|
||||
|
||||
static int
|
||||
send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
size_t data_len, ssize_t * ret)
|
||||
send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
|
||||
size_t data_len, ssize_t *ret)
|
||||
{
|
||||
ssize_t rc;
|
||||
ssize_t length;
|
||||
struct transportpacket *p = &session->packet;
|
||||
|
||||
if (!p->outbuf) {
|
||||
if (!p->olen) {
|
||||
*ret = 0;
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
}
|
||||
@@ -646,29 +614,31 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||
if (rc < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error sending %d bytes: %d", length, errno);
|
||||
else
|
||||
"Error sending %d bytes: %d", length, -rc);
|
||||
else {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Sent %d/%d bytes at %p+%d", rc, length, p->outbuf,
|
||||
p->osent);
|
||||
|
||||
if(rc > 0) {
|
||||
debugdump(session, "libssh2_transport_write send()",
|
||||
&p->outbuf[p->osent], rc);
|
||||
}
|
||||
|
||||
if (rc == length) {
|
||||
/* the remainder of the package was sent */
|
||||
LIBSSH2_FREE(session, p->outbuf);
|
||||
p->outbuf = NULL;
|
||||
p->ototal_num = 0;
|
||||
p->olen = 0;
|
||||
/* we leave *ret set so that the parent returns as we MUST return back
|
||||
a send success now, so that we don't risk sending EAGAIN later
|
||||
which then would confuse the parent function */
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
|
||||
}
|
||||
else if (rc < 0) {
|
||||
/* nothing was sent */
|
||||
if (errno != EAGAIN) {
|
||||
if (rc != -EAGAIN)
|
||||
/* send failure! */
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
}
|
||||
return LIBSSH2_ERROR_SOCKET_SEND;
|
||||
|
||||
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
}
|
||||
@@ -679,48 +649,50 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_transport_write
|
||||
* libssh2_transport_send
|
||||
*
|
||||
* Send a packet, encrypting it and adding a MAC code if necessary
|
||||
* Returns 0 on success, non-zero on failure.
|
||||
*
|
||||
* Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you should
|
||||
* call this function again as soon as it is likely that more data can be
|
||||
* sent, and this function should then be called with the same argument set
|
||||
* (same data pointer and same data_len) until zero or failure is returned.
|
||||
* The data is provided as _two_ data areas that are combined by this
|
||||
* function. The 'data' part is sent immediately before 'data2'. 'data2' may
|
||||
* be set to NULL to only use a single part.
|
||||
*
|
||||
* NOTE: this function does not verify that 'data_len' is less than ~35000
|
||||
* which is what all implementations should support at least as packet size.
|
||||
* (RFC4253 section 6.1)
|
||||
* Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was
|
||||
* not sent yet. If it does so, the caller should call this function again as
|
||||
* soon as it is likely that more data can be sent, and this function MUST
|
||||
* then be called with the same argument set (same data pointer and same
|
||||
* data_len) until ERROR_NONE or failure is returned.
|
||||
*
|
||||
* This function DOES not call _libssh2_error() on any errors.
|
||||
* This function DOES NOT call _libssh2_error() on any errors.
|
||||
*/
|
||||
int
|
||||
_libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
size_t data_len)
|
||||
int _libssh2_transport_send(LIBSSH2_SESSION *session,
|
||||
const unsigned char *data, size_t data_len,
|
||||
const unsigned char *data2, size_t data2_len)
|
||||
{
|
||||
int blocksize =
|
||||
(session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->
|
||||
blocksize : 8;
|
||||
(session->state & LIBSSH2_STATE_NEWKEYS) ?
|
||||
session->local.crypt->blocksize : 8;
|
||||
int padding_length;
|
||||
int packet_length;
|
||||
size_t packet_length;
|
||||
int total_length;
|
||||
int free_data = 0;
|
||||
#ifdef RANDOM_PADDING
|
||||
int rand_max;
|
||||
int seed = data[0]; /* FIXME: make this random */
|
||||
#endif
|
||||
struct transportpacket *p = &session->packet;
|
||||
int encrypted;
|
||||
int i;
|
||||
ssize_t ret;
|
||||
int rc;
|
||||
unsigned char *orgdata = data;
|
||||
const unsigned char *orgdata = data;
|
||||
size_t orgdata_len = data_len;
|
||||
|
||||
debugdump(session, "libssh2_transport_write plain", data, data_len);
|
||||
if(data2)
|
||||
debugdump(session, "libssh2_transport_write plain2", data2, data2_len);
|
||||
|
||||
/* FIRST, check if we have a pending write to complete */
|
||||
/* FIRST, check if we have a pending write to complete. send_existing
|
||||
only sanity-check data and data_len and not data2 and data2_len!! */
|
||||
rc = send_existing(session, data, data_len, &ret);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -728,19 +700,56 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
||||
|
||||
if (ret)
|
||||
/* set by send_existing if data was sent */
|
||||
return rc;
|
||||
|
||||
encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
|
||||
|
||||
/* check if we should compress */
|
||||
if (encrypted && strcmp(session->local.comp->name, "none")) {
|
||||
if (session->local.comp->comp(session, 1, &data, &data_len,
|
||||
LIBSSH2_PACKET_MAXCOMP,
|
||||
&free_data, data, data_len,
|
||||
&session->local.comp_abstract)) {
|
||||
return LIBSSH2_ERROR_COMPRESS; /* compression failure */
|
||||
if (encrypted && session->local.comp->compress) {
|
||||
/* the idea here is that these function must fail if the output gets
|
||||
larger than what fits in the assigned buffer so thus they don't
|
||||
check the input size as we don't know how much it compresses */
|
||||
size_t dest_len = MAX_SSH_PACKET_LEN-5-256;
|
||||
size_t dest2_len = dest_len;
|
||||
|
||||
/* compress directly to the target buffer */
|
||||
rc = session->local.comp->comp(session,
|
||||
&p->outbuf[5], &dest_len,
|
||||
data, data_len,
|
||||
&session->local.comp_abstract);
|
||||
if(rc)
|
||||
return rc; /* compression failure */
|
||||
|
||||
if(data2 && data2_len) {
|
||||
/* compress directly to the target buffer right after where the
|
||||
previous call put data */
|
||||
dest2_len -= dest_len;
|
||||
|
||||
rc = session->local.comp->comp(session,
|
||||
&p->outbuf[5+dest_len], &dest2_len,
|
||||
data2, data2_len,
|
||||
&session->local.comp_abstract);
|
||||
}
|
||||
else
|
||||
dest2_len = 0;
|
||||
if(rc)
|
||||
return rc; /* compression failure */
|
||||
|
||||
data_len = dest_len + dest2_len; /* use the combined length */
|
||||
}
|
||||
else {
|
||||
if((data_len + data2_len) >= (MAX_SSH_PACKET_LEN-0x100))
|
||||
/* too large packet, return error for this until we make this
|
||||
function split it up and send multiple SSH packets */
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
|
||||
/* copy the payload data */
|
||||
memcpy(&p->outbuf[5], data, data_len);
|
||||
if(data2 && data2_len)
|
||||
memcpy(&p->outbuf[5+data_len], data2, data2_len);
|
||||
data_len += data2_len; /* use the combined length */
|
||||
}
|
||||
|
||||
|
||||
/* RFC4253 says: Note that the length of the concatenation of
|
||||
'packet_length', 'padding_length', 'payload', and 'random padding'
|
||||
@@ -781,28 +790,18 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
total_length =
|
||||
packet_length + (encrypted ? session->local.mac->mac_len : 0);
|
||||
|
||||
/* allocate memory to store the outgoing packet in, in case we can't
|
||||
send the whole one and thus need to keep it after this function
|
||||
returns. */
|
||||
p->outbuf = LIBSSH2_ALLOC(session, total_length);
|
||||
if (!p->outbuf) {
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
}
|
||||
|
||||
/* store packet_length, which is the size of the whole packet except
|
||||
the MAC and the packet_length field itself */
|
||||
_libssh2_htonu32(p->outbuf, packet_length - 4);
|
||||
/* store padding_length */
|
||||
p->outbuf[4] = padding_length;
|
||||
/* copy the payload data */
|
||||
memcpy(p->outbuf + 5, data, data_len);
|
||||
|
||||
/* fill the padding area with random junk */
|
||||
_libssh2_random(p->outbuf + 5 + data_len, padding_length);
|
||||
if (free_data) {
|
||||
LIBSSH2_FREE(session, data);
|
||||
}
|
||||
|
||||
if (encrypted) {
|
||||
size_t i;
|
||||
|
||||
/* Calculate MAC hash. Put the output at index packet_length,
|
||||
since that size includes the whole packet. The MAC is
|
||||
calculated on the entire unencrypted packet, including all
|
||||
@@ -818,7 +817,7 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
unsigned char *ptr = &p->outbuf[i];
|
||||
if (session->local.crypt->crypt(session, ptr,
|
||||
&session->local.crypt_abstract))
|
||||
return LIBSSH2_ERROR_SOCKET_NONE; /* encryption failure */
|
||||
return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -828,32 +827,29 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||
if (ret < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error sending %d bytes: %d", total_length, errno);
|
||||
else
|
||||
"Error sending %d bytes: %d", total_length, -ret);
|
||||
else {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p",
|
||||
ret, total_length, p->outbuf);
|
||||
|
||||
if (ret != -1) {
|
||||
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
|
||||
}
|
||||
|
||||
if (ret != total_length) {
|
||||
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
|
||||
if (ret >= 0 || ret == -EAGAIN) {
|
||||
/* the whole packet could not be sent, save the rest */
|
||||
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
||||
p->odata = orgdata;
|
||||
p->olen = orgdata_len;
|
||||
p->osent = (ret == -1) ? 0 : ret;
|
||||
p->osent = ret <= 0 ? 0 : ret;
|
||||
p->ototal_num = total_length;
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
}
|
||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||
return LIBSSH2_ERROR_SOCKET_SEND;
|
||||
}
|
||||
|
||||
/* the whole thing got sent away */
|
||||
p->odata = NULL;
|
||||
p->olen = 0;
|
||||
LIBSSH2_FREE(session, p->outbuf);
|
||||
p->outbuf = NULL;
|
||||
|
||||
return LIBSSH2_ERROR_NONE; /* all is good */
|
||||
}
|
||||
|
@@ -44,23 +44,29 @@
|
||||
#include "libssh2_priv.h"
|
||||
#include "packet.h"
|
||||
|
||||
|
||||
/*
|
||||
* libssh2_transport_write
|
||||
* libssh2_transport_send
|
||||
*
|
||||
* Send a packet, encrypting it and adding a MAC code if necessary
|
||||
* Returns 0 on success, non-zero on failure.
|
||||
*
|
||||
* Returns PACKET_EAGAIN if it would block - and if it does so, you should
|
||||
* call this function again as soon as it is likely that more data can be
|
||||
* sent, and this function should then be called with the same argument set
|
||||
* (same data pointer and same data_len) until zero or failure is returned.
|
||||
* The data is provided as _two_ data areas that are combined by this
|
||||
* function. The 'data' part is sent immediately before 'data2'. 'data2' can
|
||||
* be set to NULL (or data2_len to 0) to only use a single part.
|
||||
*
|
||||
* NOTE: this function does not verify that 'data_len' is less than ~35000
|
||||
* which is what all implementations should support at least as packet size.
|
||||
* (RFC4253 section 6.1)
|
||||
* Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was
|
||||
* not sent yet. If it does so, the caller should call this function again as
|
||||
* soon as it is likely that more data can be sent, and this function MUST
|
||||
* then be called with the same argument set (same data pointer and same
|
||||
* data_len) until ERROR_NONE or failure is returned.
|
||||
*
|
||||
* This function DOES NOT call _libssh2_error() on any errors.
|
||||
*/
|
||||
int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
size_t data_len);
|
||||
int _libssh2_transport_send(LIBSSH2_SESSION *session,
|
||||
const unsigned char *data, size_t data_len,
|
||||
const unsigned char *data2, size_t data2_len);
|
||||
|
||||
/*
|
||||
* _libssh2_transport_read
|
||||
*
|
||||
@@ -78,10 +84,4 @@ int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
*/
|
||||
int _libssh2_transport_read(LIBSSH2_SESSION * session);
|
||||
|
||||
/*
|
||||
* _libssh2_transport_drain() empties the outgoing send buffer if there
|
||||
* is any.
|
||||
*/
|
||||
void _libssh2_transport_drain(LIBSSH2_SESSION *session);
|
||||
|
||||
#endif /* __LIBSSH2_TRANSPORT_H */
|
||||
|
200
src/userauth.c
200
src/userauth.c
@@ -1,6 +1,6 @@
|
||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net>
|
||||
* Copyright (c) 2009 by Daniel Stenberg
|
||||
* Copyright (c) 2009-2010 by Daniel Stenberg
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -66,7 +66,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
||||
static const unsigned char reply_codes[3] =
|
||||
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
|
||||
/* packet_type(1) + username_len(4) + service_len(4) +
|
||||
service(14)"ssh-connection" + method_len(4) + method(4)"none" */
|
||||
service(14)"ssh-connection" + method_len(4) = 27 */
|
||||
unsigned long methods_len;
|
||||
unsigned char *s;
|
||||
int rc;
|
||||
@@ -76,7 +76,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
||||
memset(&session->userauth_list_packet_requirev_state, 0,
|
||||
sizeof(session->userauth_list_packet_requirev_state));
|
||||
|
||||
session->userauth_list_data_len = username_len + 31;
|
||||
session->userauth_list_data_len = username_len + 27;
|
||||
|
||||
s = session->userauth_list_data =
|
||||
LIBSSH2_ALLOC(session, session->userauth_list_data_len);
|
||||
@@ -89,14 +89,15 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
||||
*(s++) = SSH_MSG_USERAUTH_REQUEST;
|
||||
_libssh2_store_str(&s, username, username_len);
|
||||
_libssh2_store_str(&s, "ssh-connection", 14);
|
||||
_libssh2_store_str(&s, "none", 4);
|
||||
_libssh2_store_u32(&s, 4); /* send "none" separately */
|
||||
|
||||
session->userauth_list_state = libssh2_NB_state_created;
|
||||
}
|
||||
|
||||
if (session->userauth_list_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_list_data,
|
||||
session->userauth_list_data_len);
|
||||
rc = _libssh2_transport_send(session, session->userauth_list_data,
|
||||
session->userauth_list_data_len,
|
||||
(unsigned char *)"none", 4);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block requesting userauth list");
|
||||
@@ -178,12 +179,12 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user,
|
||||
* libssh2_userauth_authenticated
|
||||
*
|
||||
* Returns: 0 if not yet authenticated
|
||||
* non-zero is already authenticated
|
||||
* 1 if already authenticated
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
|
||||
{
|
||||
return session->state & LIBSSH2_STATE_AUTHENTICATED;
|
||||
return (session->state & LIBSSH2_STATE_AUTHENTICATED)?1:0;
|
||||
}
|
||||
|
||||
|
||||
@@ -192,9 +193,9 @@ libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
|
||||
* Plain ol' login
|
||||
*/
|
||||
static int
|
||||
userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
unsigned int username_len, const char *password,
|
||||
unsigned int password_len,
|
||||
userauth_password(LIBSSH2_SESSION *session,
|
||||
const char *username, unsigned int username_len,
|
||||
const unsigned char *password, unsigned int password_len,
|
||||
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
|
||||
{
|
||||
unsigned char *s;
|
||||
@@ -213,10 +214,12 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
* 40 = acket_type(1) + username_len(4) + service_len(4) +
|
||||
* service(14)"ssh-connection" + method_len(4) + method(8)"password" +
|
||||
* chgpwdbool(1) + password_len(4) */
|
||||
session->userauth_pswd_data_len = username_len + password_len + 40;
|
||||
session->userauth_pswd_data_len = username_len + 40;
|
||||
|
||||
session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;
|
||||
|
||||
/* TODO: remove this alloc with a fixed buffer in the session
|
||||
struct */
|
||||
s = session->userauth_pswd_data =
|
||||
LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
|
||||
if (!session->userauth_pswd_data) {
|
||||
@@ -230,7 +233,8 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
_libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1);
|
||||
_libssh2_store_str(&s, "password", sizeof("password") - 1);
|
||||
*s++ = '\0';
|
||||
_libssh2_store_str(&s, password, password_len);
|
||||
_libssh2_store_u32(&s, password_len);
|
||||
/* 'password' is sent separately */
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Attempting to login using password authentication");
|
||||
@@ -239,8 +243,9 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
}
|
||||
|
||||
if (session->userauth_pswd_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_pswd_data,
|
||||
session->userauth_pswd_data_len);
|
||||
rc = _libssh2_transport_send(session, session->userauth_pswd_data,
|
||||
session->userauth_pswd_data_len,
|
||||
password, password_len);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block writing password request");
|
||||
@@ -335,8 +340,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
|
||||
/* basic data_len + newpw_len(4) */
|
||||
session->userauth_pswd_data_len =
|
||||
username_len + password_len + 44 +
|
||||
session->userauth_pswd_newpw_len;
|
||||
username_len + password_len + 44;
|
||||
|
||||
s = session->userauth_pswd_data =
|
||||
LIBSSH2_ALLOC(session,
|
||||
@@ -358,18 +362,21 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
_libssh2_store_str(&s, "password",
|
||||
sizeof("password") - 1);
|
||||
*s++ = 0x01;
|
||||
_libssh2_store_str(&s, password, password_len);
|
||||
_libssh2_store_str(&s, session->userauth_pswd_newpw,
|
||||
_libssh2_store_str(&s, (char *)password, password_len);
|
||||
_libssh2_store_u32(&s,
|
||||
session->userauth_pswd_newpw_len);
|
||||
/* send session->userauth_pswd_newpw separately */
|
||||
|
||||
session->userauth_pswd_state = libssh2_NB_state_sent2;
|
||||
}
|
||||
|
||||
if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
|
||||
rc = _libssh2_transport_write(session,
|
||||
session->userauth_pswd_data,
|
||||
session->
|
||||
userauth_pswd_data_len);
|
||||
rc = _libssh2_transport_send(session,
|
||||
session->userauth_pswd_data,
|
||||
session->userauth_pswd_data_len,
|
||||
(unsigned char *)
|
||||
session->userauth_pswd_newpw,
|
||||
session->userauth_pswd_newpw_len);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting");
|
||||
@@ -429,7 +436,7 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
|
||||
int rc;
|
||||
BLOCK_ADJUST(rc, session,
|
||||
userauth_password(session, username, username_len,
|
||||
password, password_len,
|
||||
(unsigned char *)password, password_len,
|
||||
passwd_change_cb));
|
||||
return rc;
|
||||
}
|
||||
@@ -439,7 +446,7 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
|
||||
*
|
||||
* Read a public key from an id_???.pub style file
|
||||
*
|
||||
* Returns an allocated string containing the decoded key in *pubkeydata
|
||||
* Returns an allocated string containing the decoded key in *pubkeydata
|
||||
* on success.
|
||||
* Returns an allocated string containing the key method (e.g. "ssh-dss")
|
||||
* in method on success.
|
||||
@@ -648,23 +655,35 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||
memset(&session->userauth_host_packet_requirev_state, 0,
|
||||
sizeof(session->userauth_host_packet_requirev_state));
|
||||
|
||||
rc = file_read_publickey(session, &session->userauth_host_method,
|
||||
&session->userauth_host_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
publickey);
|
||||
if(rc)
|
||||
/* Note: file_read_publickey() calls _libssh2_error() */
|
||||
return rc;
|
||||
if (publickey) {
|
||||
rc = file_read_publickey(session, &session->userauth_host_method,
|
||||
&session->userauth_host_method_len,
|
||||
&pubkeydata, &pubkeydata_len, publickey);
|
||||
if(rc)
|
||||
/* Note: file_read_publickey() calls _libssh2_error() */
|
||||
return rc;
|
||||
}
|
||||
else {
|
||||
/* Compute public key from private key. */
|
||||
if (_libssh2_pub_priv_keyfile(session,
|
||||
&session->userauth_host_method,
|
||||
&session->userauth_host_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
privatekey, passphrase))
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key "
|
||||
"from private key file");
|
||||
}
|
||||
|
||||
/*
|
||||
* 48 = packet_type(1) + username_len(4) + servicename_len(4) +
|
||||
* 52 = packet_type(1) + username_len(4) + servicename_len(4) +
|
||||
* service_name(14)"ssh-connection" + authmethod_len(4) +
|
||||
* authmethod(9)"hostbased" + method_len(4) + pubkeydata_len(4) +
|
||||
* local_username_len(4)
|
||||
* hostname_len(4) + local_username_len(4)
|
||||
*/
|
||||
session->userauth_host_packet_len =
|
||||
username_len + session->userauth_host_method_len + hostname_len +
|
||||
local_username_len + pubkeydata_len + 48;
|
||||
local_username_len + pubkeydata_len + 52;
|
||||
|
||||
/*
|
||||
* Preallocate space for an overall length, method name again,
|
||||
@@ -776,9 +795,10 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_host_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_host_packet,
|
||||
session->userauth_host_s -
|
||||
session->userauth_host_packet);
|
||||
rc = _libssh2_transport_send(session, session->userauth_host_packet,
|
||||
session->userauth_host_s -
|
||||
session->userauth_host_packet,
|
||||
NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
||||
}
|
||||
@@ -876,18 +896,36 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
unsigned char *s;
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
|
||||
|
||||
/*
|
||||
* The call to _libssh2_ntohu32 later relies on pubkeydata having at
|
||||
* least 4 valid bytes containing the length of the method name.
|
||||
*/
|
||||
if (pubkeydata_len < 4)
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||
"Invalid public key, too short");
|
||||
|
||||
/* Zero the whole thing out */
|
||||
memset(&session->userauth_pblc_packet_requirev_state, 0,
|
||||
sizeof(session->userauth_pblc_packet_requirev_state));
|
||||
|
||||
/*
|
||||
* As an optimisation, userauth_publickey_fromfile reuses a
|
||||
* As an optimisation, userauth_publickey_fromfile reuses a
|
||||
* previously allocated copy of the method name to avoid an extra
|
||||
* allocation/free.
|
||||
* For other uses, we allocate and populate it here.
|
||||
*/
|
||||
if (!session->userauth_pblc_method) {
|
||||
session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata);
|
||||
|
||||
if(session->userauth_pblc_method_len > pubkeydata_len)
|
||||
/* the method length simply cannot be longer than the entire
|
||||
passed in data, so we use this to detect crazy input
|
||||
data */
|
||||
return _libssh2_error(session,
|
||||
LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||
"Invalid public key");
|
||||
|
||||
session->userauth_pblc_method =
|
||||
LIBSSH2_ALLOC(session, session->userauth_pblc_method_len);
|
||||
if (!session->userauth_pblc_method) {
|
||||
@@ -898,8 +936,15 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
memcpy(session->userauth_pblc_method, pubkeydata + 4,
|
||||
session->userauth_pblc_method_len);
|
||||
}
|
||||
assert( /* preallocated method len should match what we expect */
|
||||
session->userauth_pblc_method_len == _libssh2_ntohu32(pubkeydata));
|
||||
/*
|
||||
* The length of the method name read from plaintext prefix in the
|
||||
* file must match length embedded in the key.
|
||||
* TODO: The data should match too but we don't check that. Should we?
|
||||
*/
|
||||
else if (session->userauth_pblc_method_len !=
|
||||
_libssh2_ntohu32(pubkeydata))
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||
"Invalid public key");
|
||||
|
||||
/*
|
||||
* 45 = packet_type(1) + username_len(4) + servicename_len(4) +
|
||||
@@ -912,9 +957,13 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
45;
|
||||
|
||||
/*
|
||||
* Preallocate space for an overall length, method name again, and
|
||||
* the signature, which won't be any larger than the size of the
|
||||
* publickeydata itself
|
||||
* Preallocate space for an overall length, method name again, and the
|
||||
* signature, which won't be any larger than the size of the
|
||||
* publickeydata itself.
|
||||
*
|
||||
* Note that the 'pubkeydata_len' extra bytes allocated here will not
|
||||
* be used in this first send, but will be used in the later one where
|
||||
* this same allocation is re-used.
|
||||
*/
|
||||
s = session->userauth_pblc_packet =
|
||||
LIBSSH2_ALLOC(session,
|
||||
@@ -940,6 +989,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
_libssh2_store_str(&s, (const char *)session->userauth_pblc_method,
|
||||
session->userauth_pblc_method_len);
|
||||
_libssh2_store_str(&s, (const char *)pubkeydata, pubkeydata_len);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Attempting publickey authentication");
|
||||
|
||||
@@ -947,8 +997,9 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
|
||||
session->userauth_pblc_packet_len);
|
||||
rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
|
||||
session->userauth_pblc_packet_len,
|
||||
NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN)
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
||||
else if (rc) {
|
||||
@@ -981,7 +1032,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
session->userauth_pblc_method = NULL;
|
||||
session->userauth_pblc_state = libssh2_NB_state_idle;
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||
"Failed waiting");
|
||||
"Waiting for USERAUTH response");
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
@@ -1024,7 +1075,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
|
||||
unsigned char *buf, *s;
|
||||
unsigned char *buf;
|
||||
unsigned char *sig;
|
||||
size_t sig_len;
|
||||
|
||||
@@ -1105,9 +1156,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_sent2) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
|
||||
session->userauth_pblc_s -
|
||||
session->userauth_pblc_packet);
|
||||
rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
|
||||
session->userauth_pblc_s -
|
||||
session->userauth_pblc_packet,
|
||||
NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
||||
} else if (rc) {
|
||||
@@ -1136,7 +1188,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
} else if (rc) {
|
||||
session->userauth_pblc_state = libssh2_NB_state_idle;
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||
"Failed waiting");
|
||||
"Waiting for publickey USERAUTH response");
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
@@ -1181,11 +1233,24 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
privkey_file.passphrase = passphrase;
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
|
||||
rc = file_read_publickey(session, &session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len, publickey);
|
||||
if(rc)
|
||||
return rc;
|
||||
if (publickey) {
|
||||
rc = file_read_publickey(session, &session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len,publickey);
|
||||
if(rc)
|
||||
return rc;
|
||||
}
|
||||
else {
|
||||
/* Compute public key from private key. */
|
||||
if (_libssh2_pub_priv_keyfile(session,
|
||||
&session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
privatekey, passphrase))
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key "
|
||||
"from private key file");
|
||||
}
|
||||
}
|
||||
|
||||
rc = _libssh2_userauth_publickey(session, username, username_len,
|
||||
@@ -1234,6 +1299,10 @@ libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
void **abstract)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if(!session)
|
||||
return LIBSSH2_ERROR_BAD_USE;
|
||||
|
||||
BLOCK_ADJUST(rc, session,
|
||||
_libssh2_userauth_publickey(session, user, strlen(user),
|
||||
pubkeydata, pubkeydata_len,
|
||||
@@ -1319,8 +1388,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
}
|
||||
|
||||
if (session->userauth_kybd_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
|
||||
session->userauth_kybd_packet_len);
|
||||
rc = _libssh2_transport_send(session, session->userauth_kybd_data,
|
||||
session->userauth_kybd_packet_len,
|
||||
NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
||||
} else if (rc) {
|
||||
@@ -1351,7 +1421,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
session->userauth_kybd_state = libssh2_NB_state_idle;
|
||||
return _libssh2_error(session,
|
||||
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
|
||||
"Failed waiting");
|
||||
"Waiting for keyboard USERAUTH response");
|
||||
}
|
||||
|
||||
if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
@@ -1522,8 +1592,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
}
|
||||
|
||||
if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
|
||||
session->userauth_kybd_packet_len);
|
||||
rc = _libssh2_transport_send(session, session->userauth_kybd_data,
|
||||
session->userauth_kybd_packet_len,
|
||||
NULL, 0);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block");
|
||||
@@ -1566,6 +1637,10 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
session->userauth_kybd_prompts = NULL;
|
||||
LIBSSH2_FREE(session, session->userauth_kybd_responses);
|
||||
session->userauth_kybd_responses = NULL;
|
||||
LIBSSH2_FREE(session, session->userauth_kybd_auth_name);
|
||||
session->userauth_kybd_auth_name = NULL;
|
||||
LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
|
||||
session->userauth_kybd_auth_instruction = NULL;
|
||||
|
||||
if (session->userauth_kybd_auth_failure) {
|
||||
session->userauth_kybd_state = libssh2_NB_state_idle;
|
||||
@@ -1593,4 +1668,3 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session,
|
||||
response_callback));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
179
win32/Makefile.Watcom
Normal file
179
win32/Makefile.Watcom
Normal file
@@ -0,0 +1,179 @@
|
||||
#
|
||||
# Watcom / OpenWatcom Win32 makefile for libssh2.
|
||||
#
|
||||
# Comments to: Guenter Knauf http://www.gknw.net/phpbb
|
||||
#
|
||||
|
||||
!ifndef %watcom
|
||||
!error WATCOM environment variable not set!
|
||||
!else
|
||||
SYS_INCL = -I$(%watcom)\h\nt -I$(%watcom)\h
|
||||
SYS_LIBS = $(%watcom)\lib386\nt;$(%watcom)\lib386
|
||||
!endif
|
||||
|
||||
!ifdef %libname
|
||||
LIBNAME = $(%libname)
|
||||
!else
|
||||
LIBNAME = libssh2
|
||||
!endif
|
||||
TARGETS = $(LIBNAME).dll $(LIBNAME)_imp.lib $(LIBNAME).lib
|
||||
|
||||
CC = wcc386
|
||||
LD = wlink
|
||||
AR = wlib
|
||||
RC = wrc
|
||||
|
||||
!ifdef __LOADDLL__
|
||||
! loaddll wcc386 wccd386
|
||||
! loaddll wpp386 wppd386
|
||||
! loaddll wlib wlibd
|
||||
! if $(__VERSION__) > 1270
|
||||
! loaddll wlink wlinkd
|
||||
! else
|
||||
! loaddll wlink wlink
|
||||
! endif
|
||||
!endif
|
||||
|
||||
!if $(__VERSION__) < 1250
|
||||
RM = del /q /f 2>NUL
|
||||
!else
|
||||
RM = rm -f
|
||||
!endif
|
||||
MD = mkdir
|
||||
RD = rmdir /q /s 2>NUL
|
||||
CP = copy
|
||||
|
||||
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=nul -w2 -fpi -oilrtfm &
|
||||
-wcd=201 -bt=nt -d+ -dWIN32 -DLIBSSH2_WIN32 &
|
||||
-I. -I..\include $(SYS_INCL)
|
||||
|
||||
!ifdef %debug
|
||||
DEBUG = -dDEBUG=1 -dDEBUGBUILD
|
||||
CFLAGS += -d3 $(DEBUG)
|
||||
!else
|
||||
CFLAGS += -d0
|
||||
!endif
|
||||
|
||||
!ifdef %use_ipv6
|
||||
CFLAGS += -d_WIN32_WINNT=0x0501 -dENABLE_IPV6
|
||||
!endif
|
||||
|
||||
#
|
||||
# Change to suite.
|
||||
#
|
||||
!ifdef %zlib_root
|
||||
ZLIB_ROOT = $(%zlib_root)
|
||||
!else
|
||||
ZLIB_ROOT = ..\..\zlib-1.2.5
|
||||
!endif
|
||||
|
||||
!ifdef %openssl_root
|
||||
OPENSSL_ROOT = $(%openssl_root)
|
||||
!else
|
||||
OPENSSL_ROOT = ..\..\openssl-0.9.8q
|
||||
!endif
|
||||
|
||||
#!ifdef %use_zlib
|
||||
CFLAGS += -dHAVE_ZLIB_H -dHAVE_LIBZ -I$(ZLIB_ROOT)
|
||||
#!endif
|
||||
|
||||
#!ifdef %use_ssl
|
||||
CFLAGS += -wcd=138 -dUSE_OPENSSL -dUSE_SSLEAY -I$(OPENSSL_ROOT)\inc32
|
||||
#!endif
|
||||
|
||||
!ifdef %use_watt32
|
||||
CFLAGS += -dUSE_WATT32 -I$(%watt_root)\inc
|
||||
!endif
|
||||
|
||||
OBJ_BASE = WC_Win32.obj
|
||||
LINK_ARG = $(OBJ_BASE)\dyn\wlink.arg
|
||||
LIB_ARG = $(OBJ_BASE)\stat\wlib.arg
|
||||
|
||||
# In order to process Makefile.inc wmake must be called with -u switch!
|
||||
!ifndef %MAKEFLAGS
|
||||
!error You MUST call wmake with the -u switch!
|
||||
!else
|
||||
!include ..\Makefile.inc
|
||||
!endif
|
||||
|
||||
OBJS = $(CSOURCES:.c=.obj)
|
||||
OBJS = $OBJ_DIR\$(OBJS: = $OBJ_DIR\)
|
||||
|
||||
#
|
||||
# Use $(OBJS) as a template to generate $(OBJS_STAT) and $(OBJS_DYN).
|
||||
#
|
||||
OBJ_DIR = $(OBJ_BASE)\stat
|
||||
OBJS_STAT = $+ $(OBJS) $-
|
||||
|
||||
OBJ_DIR = $(OBJ_BASE)\dyn
|
||||
OBJS_DYN = $+ $(OBJS) $-
|
||||
|
||||
RESOURCE = $(OBJ_BASE)\dyn\libssh2.res
|
||||
|
||||
.c: ..\src
|
||||
|
||||
|
||||
all: $(OBJ_BASE) $(TARGETS) .SYMBOLIC
|
||||
@echo Welcome to libssh2
|
||||
|
||||
clean: .SYMBOLIC
|
||||
-$(RM) $(OBJS_STAT)
|
||||
-$(RM) $(OBJS_DYN)
|
||||
-$(RM) $(RESOURCE) $(LINK_ARG) $(LIB_ARG)
|
||||
|
||||
vclean realclean: clean .SYMBOLIC
|
||||
-$(RM) $(TARGETS) $(LIBNAME).map $(LIBNAME).sym
|
||||
-$(RD) $(OBJ_BASE)\stat
|
||||
-$(RD) $(OBJ_BASE)\dyn
|
||||
-$(RD) $(OBJ_BASE)
|
||||
|
||||
$(OBJ_BASE):
|
||||
-$(MD) $^@
|
||||
-$(MD) $^@\stat
|
||||
-$(MD) $^@\dyn
|
||||
|
||||
$(LIBNAME).dll: $(OBJS_DYN) $(RESOURCE) $(LINK_ARG)
|
||||
$(LD) name $^@ @$]@
|
||||
|
||||
$(LIBNAME).lib: $(OBJS_STAT) $(LIB_ARG)
|
||||
$(AR) -q -b -c $^@ @$]@
|
||||
|
||||
.ERASE
|
||||
$(RESOURCE): libssh2.rc
|
||||
$(RC) $(DEBUG) -q -r -zm -DLIBSSH2_VERSION_ONLY -I..\include $(SYS_INCL) $[@ -fo=$^@
|
||||
|
||||
.ERASE
|
||||
.c{$(OBJ_BASE)\dyn}.obj:
|
||||
$(CC) $(CFLAGS) -bd -br $[@ -fo=$^@
|
||||
|
||||
.ERASE
|
||||
.c{$(OBJ_BASE)\stat}.obj:
|
||||
$(CC) $(CFLAGS) $[@ -fo=$^@
|
||||
|
||||
$(LINK_ARG): $(__MAKEFILES__)
|
||||
%create $^@
|
||||
@%append $^@ system nt dll
|
||||
@%append $^@ file { $(OBJS_DYN) }
|
||||
!ifdef %debug
|
||||
@%append $^@ debug all
|
||||
@%append $^@ option symfile
|
||||
!endif
|
||||
@%append $^@ option quiet, map, caseexact, eliminate, implib=$(LIBNAME)_imp.lib,
|
||||
@%append $^@ res=$(RESOURCE) libpath $(SYS_LIBS)
|
||||
!ifdef %use_watt32
|
||||
@%append $^@ library $(%watt_root)\lib\wattcpw_imp.lib
|
||||
!else
|
||||
@%append $^@ library ws2_32.lib
|
||||
!endif
|
||||
#!ifdef %use_zlib
|
||||
@%append $^@ library $(ZLIB_ROOT)\zlib.lib
|
||||
#!endif
|
||||
#!ifdef %use_ssl
|
||||
@%append $^@ library $(OPENSSL_ROOT)\out32\libeay32.lib, $(OPENSSL_ROOT)\out32\ssleay32.lib
|
||||
#!endif
|
||||
|
||||
$(LIB_ARG): $(__MAKEFILES__)
|
||||
%create $^@
|
||||
@for %f in ($(OBJS_STAT)) do @%append $^@ +- %f
|
||||
|
||||
|
@@ -3,9 +3,7 @@
|
||||
## Makefile for building libssh2 (Win32 version - gnu make)
|
||||
## Use: make -f Makefile.win32 [help|all|clean|dev|devclean|dist|distclean|dll|objclean]
|
||||
##
|
||||
## Comments to: Guenter Knauf <eflash@gmx.net>
|
||||
##
|
||||
## $Id: Makefile.win32,v 1.11 2009/04/09 03:13:52 gknauf Exp $
|
||||
## Comments to: Guenter Knauf http://www.gknw.net/phpbb
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
@@ -18,7 +16,7 @@ WITH_ZLIB = 1
|
||||
|
||||
# Edit the path below to point to the base of your OpenSSL package.
|
||||
ifndef OPENSSL_PATH
|
||||
OPENSSL_PATH = ../../openssl-0.9.8n
|
||||
OPENSSL_PATH = ../../openssl-0.9.8q
|
||||
endif
|
||||
|
||||
# Edit the path below to point to your Distribution folder.
|
||||
@@ -36,7 +34,7 @@ DEVLARC = $(DEVLDIR).zip
|
||||
# Edit the vars below to change target settings.
|
||||
TARGET = libssh2
|
||||
VERSION = $(LIBSSH2_VERSION)
|
||||
COPYR = (c) 2004-2010 The libssh2 project and its contributors.
|
||||
COPYR = (c) $(LIBSSH2_COPYRIGHT_STR)
|
||||
WWWURL = http://www.libssh2.org/
|
||||
DESCR = libssh2 $(LIBSSH2_VERSION_STR)
|
||||
#STACK = 64000
|
||||
@@ -67,8 +65,9 @@ else
|
||||
endif
|
||||
CP = cp -afv
|
||||
# RM = rm -f
|
||||
MD = mkdir
|
||||
# Here you can find a native Win32 binary of the original awk:
|
||||
# http://www.gknw.net/development/prgtools/awk.zip
|
||||
# http://www.gknw.net/development/prgtools/awk-20070501.zip
|
||||
AWK = awk
|
||||
ZIP = zip -qzr9
|
||||
|
||||
@@ -100,7 +99,7 @@ LIBEXT = a
|
||||
RANLIB = $(CROSSPREFIX)ranlib
|
||||
#LDLIBS += -lwsock32
|
||||
LDLIBS += -lws2_32
|
||||
RCFLAGS = -O coff -i
|
||||
RCFLAGS = -DLIBSSH2_VERSION_ONLY -I. -I ../include -O coff -i
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -Wall # -pedantic
|
||||
endif
|
||||
@@ -125,7 +124,8 @@ ifeq ($(findstring /sh,$(SHELL)),/sh)
|
||||
DL = '
|
||||
DS = /
|
||||
else
|
||||
DS = \\
|
||||
XX =
|
||||
DS = $(XX)\$(XX)
|
||||
endif
|
||||
|
||||
vpath %.c . ../src
|
||||
@@ -200,13 +200,13 @@ clean:
|
||||
-$(RM) -r $(OBJDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
@mkdir $@
|
||||
@$(MD) $@
|
||||
|
||||
$(DISTDIR):
|
||||
@mkdir $@
|
||||
@$(MD) $@
|
||||
|
||||
$(DEVLDIR):
|
||||
@mkdir $@
|
||||
@$(MD) $@
|
||||
|
||||
$(TARGET).$(LIBEXT): $(OBJS)
|
||||
@echo Creating $@
|
||||
@@ -222,46 +222,10 @@ $(TARGET).dll $(TARGET)dll.a: $(OBJL)
|
||||
@$(LD) $(LDFLAGS) $^ -o $@ $(LIBPATH) $(LDLIBS)
|
||||
|
||||
|
||||
$(OBJDIR)/%.res: $(OBJDIR)/%.rc
|
||||
$(OBJDIR)/%.res: %.rc
|
||||
@echo Creating $@
|
||||
@$(RC) $(RCFLAGS) $< -o $@
|
||||
|
||||
$(OBJDIR)/%.rc: Makefile.win32 $(OBJDIR)/version.inc
|
||||
@echo $(DL)1 VERSIONINFO$(DL) > $@
|
||||
@echo $(DL) FILEVERSION $(LIBSSH2_VERSION),0$(DL) >> $@
|
||||
@echo $(DL) PRODUCTVERSION $(LIBSSH2_VERSION),0$(DL) >> $@
|
||||
@echo $(DL) FILEFLAGSMASK 0x3fL$(DL) >> $@
|
||||
@echo $(DL) FILEOS 0x40004L$(DL) >> $@
|
||||
@echo $(DL) FILEFLAGS 0x0L$(DL) >> $@
|
||||
@echo $(DL) FILETYPE 0x1L$(DL) >> $@
|
||||
@echo $(DL) FILESUBTYPE 0x0L$(DL) >> $@
|
||||
@echo $(DL)BEGIN$(DL) >> $@
|
||||
@echo $(DL) BLOCK "StringFileInfo"$(DL) >> $@
|
||||
@echo $(DL) BEGIN$(DL) >> $@
|
||||
@echo $(DL) BLOCK "040904E4"$(DL) >> $@
|
||||
@echo $(DL) BEGIN$(DL) >> $@
|
||||
@echo $(DL) VALUE "LegalCopyright","$(COPYR)\0"$(DL) >> $@
|
||||
ifdef COMPANY
|
||||
@echo $(DL) VALUE "CompanyName","$(COMPANY)\0"$(DL) >> $@
|
||||
endif
|
||||
@echo $(DL) VALUE "ProductName","$(notdir $(@:.rc=.dll))\0"$(DL) >> $@
|
||||
@echo $(DL) VALUE "ProductVersion","$(LIBSSH2_VERSION_STR)\0"$(DL) >> $@
|
||||
@echo $(DL) VALUE "License","Released under the Modified BSD license.\0"$(DL) >> $@
|
||||
@echo $(DL) VALUE "FileDescription","$(DESCR)\0"$(DL) >> $@
|
||||
@echo $(DL) VALUE "FileVersion","$(LIBSSH2_VERSION_STR)\0"$(DL) >> $@
|
||||
@echo $(DL) VALUE "InternalName","$(notdir $(@:.rc=))\0"$(DL) >> $@
|
||||
@echo $(DL) VALUE "OriginalFilename","$(notdir $(@:.rc=.dll))\0"$(DL) >> $@
|
||||
@echo $(DL) VALUE "WWW","$(WWWURL)\0"$(DL) >> $@
|
||||
@echo $(DL) END$(DL) >> $@
|
||||
@echo $(DL) END$(DL) >> $@
|
||||
@echo $(DL) BLOCK "VarFileInfo"$(DL) >> $@
|
||||
@echo $(DL) BEGIN$(DL) >> $@
|
||||
@echo $(DL) VALUE "Translation", 0x409, 1252$(DL) >> $@
|
||||
@echo $(DL) END$(DL) >> $@
|
||||
@echo $(DL)END$(DL) >> $@
|
||||
ifdef ICON
|
||||
@echo $(DL)10 ICON DISCARDABLE "$(ICON)"$(DL) >> $@
|
||||
endif
|
||||
|
||||
$(DISTDIR)/readme.txt: Makefile.win32
|
||||
@echo Creating $@
|
||||
|
@@ -1,10 +1,10 @@
|
||||
|
||||
# Tweak these for your system
|
||||
OPENSSLINC=..\openssl-0.9.8e\inc32
|
||||
OPENSSLLIB=..\openssl-0.9.8e\out32dll
|
||||
OPENSSLINC=..\openssl-0.9.8q\inc32
|
||||
OPENSSLLIB=..\openssl-0.9.8q\out32dll
|
||||
|
||||
ZLIBINC=-DLIBSSH2_HAVE_ZLIB=1 /I..\zlib-1.2.3
|
||||
ZLIBLIB=..\zlib-1.2.3
|
||||
ZLIBINC=-DLIBSSH2_HAVE_ZLIB=1 /I..\zlib-1.2.5
|
||||
ZLIBLIB=..\zlib-1.2.5
|
||||
|
||||
!if "$(TARGET)" == ""
|
||||
TARGET=Release
|
||||
|
45
win32/libssh2.rc
Normal file
45
win32/libssh2.rc
Normal file
@@ -0,0 +1,45 @@
|
||||
/***************************************************************************
|
||||
* libssh2 Win32 resource file *
|
||||
***************************************************************************/
|
||||
#include <winver.h>
|
||||
#include "../include/libssh2.h"
|
||||
|
||||
LANGUAGE 0x09,0x01
|
||||
|
||||
#define RC_VERSION LIBSSH2_VERSION_MAJOR, LIBSSH2_VERSION_MINOR, LIBSSH2_VERSION_PATCH, 0
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION RC_VERSION
|
||||
PRODUCTVERSION RC_VERSION
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#if defined(DEBUGBUILD) || defined(_DEBUG)
|
||||
FILEFLAGS 1
|
||||
#else
|
||||
FILEFLAGS 0
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "The libssh2 library, http://www.libssh2.org/\0"
|
||||
VALUE "FileDescription", "libssh2 Shared Library\0"
|
||||
VALUE "FileVersion", LIBSSH2_VERSION "\0"
|
||||
VALUE "InternalName", "libssh2\0"
|
||||
VALUE "OriginalFilename", "libssh2.dll\0"
|
||||
VALUE "ProductName", "The libssh2 library\0"
|
||||
VALUE "ProductVersion", LIBSSH2_VERSION "\0"
|
||||
VALUE "LegalCopyright", "<22> " LIBSSH2_COPYRIGHT "\0"
|
||||
VALUE "License", "http://www.libssh2.org/license.html\0"
|
||||
END
|
||||
END
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
@@ -3,9 +3,7 @@
|
||||
## Makefile for building libssh2 samples (Win32 version - gnu make)
|
||||
## Use: make -f Makefile.win32 [help]
|
||||
##
|
||||
## Comments to: Guenter Knauf <eflash@gmx.net>
|
||||
##
|
||||
## $Id: Makefile.win32,v 1.8 2009/04/09 03:14:05 gknauf Exp $
|
||||
## Comments to: Guenter Knauf http://www.gknw.net/phpbb
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
@@ -16,7 +14,7 @@ endif
|
||||
|
||||
# Edit the path below to point to the base of your OpenSSL package.
|
||||
ifndef OPENSSL_PATH
|
||||
OPENSSL_PATH = ../../../openssl-0.9.8n
|
||||
OPENSSL_PATH = ../../../openssl-0.9.8q
|
||||
endif
|
||||
|
||||
# Edit the var below to enable static linking of libssh2 and libz
|
||||
@@ -56,7 +54,7 @@ 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
|
||||
ZIP = zip -qzr9
|
||||
|
||||
|
Reference in New Issue
Block a user