Compare commits

..

88 Commits

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

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

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

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

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

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

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

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

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

View File

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

View File

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

2
.gitattribute Normal file
View File

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

1
.gitignore vendored
View File

@@ -30,3 +30,4 @@ install-sh
*.lo *.lo
*.la *.la
mkinstalldirs mkinstalldirs
tags

View File

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

View File

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

11
HACKING
View File

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

View File

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

View File

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

45
NEWS
View File

@@ -1,3 +1,48 @@
Version 1.2.2 (unreleased)
* This release includes the following changes:
o Fix crash when server sends an invalid SSH_MSG_IGNORE message.
Reported by Bob Alexander <balexander@expressor-software.com> in
<http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
By Simon Josefsson.
o Support for the "aes128-ctr", "aes192-ctr", "aes256-ctr" ciphers
as per RFC 4344 for libgcrypt and OpenSSL. They are now the
preferred ciphers. By Simon Josefsson.
o Support for the "arcfour128" cipher as per RFC 4345 for libgcrypt
and OpenSSL. It is preferred over the normal "arcfour" cipher
which is somewhat broken. By Simon Josefsson.
Version 1.2.1 (September 28, 2009)
* This release includes the following changes:
o generate and install libssh2.pc
... and the following bugfixes:
o proper return codes returned from several functions
o return EAGAIN internal cleanup
o added knownhost.c to windows makefiles
o pass private-key to OpenSSL as a filename with BIO_new_file().
o make libssh2_scp_send/recv do blocking mode correctly
o libssh2_channel_wait_closed() could hang
o libssh2_channel_read_ex() must return 0 when closed
o added gettimeofday() function for win32 for the debug trace outputs
o transport layer bug causing invalid -39 (LIBSSH2_ERROR_BAD_USE) errors
o scp examples now loop correctly over libssh2_channel_write()
* (August 29 2009) Daniel Stenberg:
- I fixed all code to use the recently added dedicated linked list functions
instead of doing the same stuff spread out all over.
- I also fixed a few cases where local variables where used to keep memory
but was used to keep state for re-invokes due to non-blocking situations
which would lead to segfaults.
Version 1.2 (August 10, 2009) Version 1.2 (August 10, 2009)
----------------------------- -----------------------------

View File

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

3
TODO
View File

@@ -8,9 +8,6 @@ Things TODO
* Provide a libssh2_scp_send() API for files larger than 4GB (32bit size) * Provide a libssh2_scp_send() API for files larger than 4GB (32bit size)
* Convert the linked list code used all over to use the (new) generic linked
list code. See the _libssh2_list_*() functions in src/misc.c
* Add more info to the man pages. * Add more info to the man pages.
* Decrease the number of mallocs. Everywhere. * Decrease the number of mallocs. Everywhere.

View File

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

View File

@@ -162,6 +162,45 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
) )
dnl ************************************************************
dnl Enable hiding of internal symbols in library to reduce its size and
dnl speed dynamic linking of applications. This currently is only supported
dnl on gcc >= 4.0 and SunPro C.
dnl
AC_MSG_CHECKING([whether to enable hidden symbols in the library])
AC_ARG_ENABLE(hidden-symbols,
AC_HELP_STRING([--enable-hidden-symbols],[Hide internal symbols in library])
AC_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibility in library]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_CHECKING([whether $CC supports it])
if test "$GCC" = yes ; then
if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then
AC_MSG_RESULT(yes)
AC_DEFINE(LIBSSH2_API, [__attribute__ ((visibility ("default")))], [to make a symbol visible])
CFLAGS="$CFLAGS -fvisibility=hidden"
else
AC_MSG_RESULT(no)
fi
else
dnl Test for SunPro cc
if $CC 2>&1 | grep flags >/dev/null && $CC -flags | grep xldscope= >/dev/null ; then
AC_MSG_RESULT(yes)
AC_DEFINE(LIBSSH2_API, [__global], [to make a symbol visible])
CFLAGS="$CFLAGS -xldscope=hidden"
else
AC_MSG_RESULT(no)
fi
fi
;;
esac ],
AC_MSG_RESULT(no)
)
# Checks for header files. # Checks for header files.
# AC_HEADER_STDC # AC_HEADER_STDC
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h]) AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
@@ -214,5 +253,6 @@ AC_CONFIG_FILES([Makefile
tests/Makefile tests/Makefile
example/Makefile example/Makefile
example/simple/Makefile example/simple/Makefile
docs/Makefile]) docs/Makefile
libssh2.pc])
AC_OUTPUT AC_OUTPUT

View File

View File

@@ -40,6 +40,7 @@ dist_man_MANS = \
libssh2_knownhost_del.3 \ libssh2_knownhost_del.3 \
libssh2_knownhost_get.3 \ libssh2_knownhost_get.3 \
libssh2_knownhost_init.3 \ libssh2_knownhost_init.3 \
libssh2_knownhost_free.3 \
libssh2_knownhost_readfile.3 \ libssh2_knownhost_readfile.3 \
libssh2_knownhost_readline.3 \ libssh2_knownhost_readline.3 \
libssh2_knownhost_writefile.3 \ libssh2_knownhost_writefile.3 \

View File

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

View File

@@ -0,0 +1,21 @@
.\"
.\" Copyright (c) 2009 by Daniel Stenberg
.\"
.TH libssh2_knownhost_free 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
.SH NAME
libssh2_knownhost_free - free a collection of known hosts
.SH SYNOPSIS
#include <libssh2.h>
void libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
.SH DESCRIPTION
Free a collection of known hosts.
.SH RETURN VALUE
Returns a handle pointer or NULL if something went wrong. The returned handle
is used as input to all other known host related functions libssh2 provides.
.SH AVAILABILITY
Added in libssh2 1.2
.SH SEE ALSO
.BR libssh2_knownhost_init(3)
.BR libssh2_knownhost_add(3)
.BR libssh2_knownhost_check(3)

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,12 +10,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

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

View File

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

View File

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

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

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

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

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

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

@@ -16,12 +16,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

@@ -19,12 +19,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

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

View File

@@ -84,17 +84,17 @@ typedef unsigned long long libssh2_uint64_t;
typedef long long libssh2_int64_t; typedef long long libssh2_int64_t;
#endif #endif
/* We use underscore instead of dash when appending CVS in dev versions just /* We use underscore instead of dash when appending DEV in dev versions just
to make the BANNER define (used by src/session.c) be a valid SSH 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 banner. Release versions have no appended strings and may of course not
have dashes either. */ have dashes either. */
#define LIBSSH2_VERSION "1.1.1_CVS" #define LIBSSH2_VERSION "1.2.2_DEV"
/* The numeric version number is also available "in parts" by using these /* The numeric version number is also available "in parts" by using these
defines: */ defines: */
#define LIBSSH2_VERSION_MAJOR 1 #define LIBSSH2_VERSION_MAJOR 1
#define LIBSSH2_VERSION_MINOR 1 #define LIBSSH2_VERSION_MINOR 2
#define LIBSSH2_VERSION_PATCH 1 #define LIBSSH2_VERSION_PATCH 2
/* This is the numeric version of the libssh2 version number, meant for easier /* This is the numeric version of the libssh2 version number, meant for easier
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
@@ -111,18 +111,18 @@ typedef long long libssh2_int64_t;
and it is always a greater number in a more recent release. It makes and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work. comparisons with greater than and less than work.
*/ */
#define LIBSSH2_VERSION_NUM 0x010101 #define LIBSSH2_VERSION_NUM 0x010202
/* /*
* This is the date and time when the full source package was created. The * This is the date and time when the full source package was created. The
* timestamp is not stored in CVS, as the timestamp is properly set in the * timestamp is not stored in the source code repo, as the timestamp is
* tarballs by the maketgz script. * properly set in the tarballs by the maketgz script.
* *
* The format of the date should follow this template: * The format of the date should follow this template:
* *
* "Mon Feb 12 11:35:33 UTC 2007" * "Mon Feb 12 11:35:33 UTC 2007"
*/ */
#define LIBSSH2_TIMESTAMP "CVS" #define LIBSSH2_TIMESTAMP "DEV"
/* Part of every banner, user specified or not */ /* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION #define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
@@ -356,6 +356,9 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_PUBLICKEY_PROTOCOL -36 #define LIBSSH2_ERROR_PUBLICKEY_PROTOCOL -36
#define LIBSSH2_ERROR_EAGAIN -37 #define LIBSSH2_ERROR_EAGAIN -37
#define LIBSSH2_ERROR_BUFFER_TOO_SMALL -38 #define LIBSSH2_ERROR_BUFFER_TOO_SMALL -38
#define LIBSSH2_ERROR_BAD_USE -39
#define LIBSSH2_ERROR_COMPRESS -40
#define LIBSSH2_ERROR_OUT_OF_BOUNDARY -41
/* Session API */ /* Session API */
LIBSSH2_API LIBSSH2_SESSION * LIBSSH2_API LIBSSH2_SESSION *
@@ -675,6 +678,7 @@ LIBSSH2_API
const char *libssh2_version(int req_version_num); const char *libssh2_version(int req_version_num);
#define HAVE_LIBSSH2_KNOWNHOST_API 0x010101 /* since 1.1.1 */ #define HAVE_LIBSSH2_KNOWNHOST_API 0x010101 /* since 1.1.1 */
#define HAVE_LIBSSH2_VERSION_API 0x010100 /* libssh2_version since 1.1 */
struct libssh2_knownhost { struct libssh2_knownhost {
unsigned int magic; /* magic stored by the library */ unsigned int magic; /* magic stored by the library */

16
libssh2.pc.in Normal file
View File

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

View File

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

View File

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

View File

@@ -61,13 +61,13 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session)
unsigned long id = session->next_channel; unsigned long id = session->next_channel;
LIBSSH2_CHANNEL *channel; LIBSSH2_CHANNEL *channel;
channel = session->channels.head; channel = _libssh2_list_first(&session->channels);
while (channel) { while (channel) {
if (channel->local.id > id) { if (channel->local.id > id) {
id = channel->local.id; id = channel->local.id;
} }
channel = channel->next; channel = _libssh2_list_next(&channel->node);
} }
/* This is a shortcut to avoid waiting for close packets on channels we've /* This is a shortcut to avoid waiting for close packets on channels we've
@@ -92,17 +92,23 @@ LIBSSH2_CHANNEL *
_libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id) _libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id)
{ {
LIBSSH2_CHANNEL *channel; LIBSSH2_CHANNEL *channel;
LIBSSH2_LISTENER *listener; LIBSSH2_LISTENER *l;
for(channel = session->channels.head; channel; channel = channel->next) { for(channel = _libssh2_list_first(&session->channels);
channel;
channel = _libssh2_list_next(&channel->node)) {
if (channel->local.id == channel_id) if (channel->local.id == channel_id)
return channel; return channel;
} }
/* We didn't find the channel in the session, let's then check its /* We didn't find the channel in the session, let's then check its
listeners... */ listeners since each listener may have its own set of pending channels
for(listener = session->listeners; listener; listener = listener->next) { */
for(channel = listener->queue; channel; channel = channel->next) { for(l = _libssh2_list_first(&session->listeners); l;
l = _libssh2_list_next(&l->node)) {
for(channel = _libssh2_list_first(&l->queue);
channel;
channel = _libssh2_list_next(&channel->node)) {
if (channel->local.id == channel_id) if (channel->local.id == channel_id)
return channel; return channel;
} }
@@ -111,20 +117,6 @@ _libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id)
return NULL; return NULL;
} }
#define CHANNEL_ADD(session, channel) \
{ \
if ((session)->channels.tail) { \
(session)->channels.tail->next = (channel); \
(channel)->prev = (session)->channels.tail; \
} else { \
(session)->channels.head = (channel); \
(channel)->prev = NULL; \
} \
(channel)->next = NULL; \
(session)->channels.tail = (channel); \
(channel)->session = (session); \
}
/* /*
* _libssh2_channel_open * _libssh2_channel_open
* *
@@ -187,8 +179,10 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
session->open_channel->remote.window_size = window_size; session->open_channel->remote.window_size = window_size;
session->open_channel->remote.window_size_initial = window_size; session->open_channel->remote.window_size_initial = window_size;
session->open_channel->remote.packet_size = packet_size; session->open_channel->remote.packet_size = packet_size;
session->open_channel->session = session;
CHANNEL_ADD(session, session->open_channel); _libssh2_list_add(&session->channels,
&session->open_channel->node);
s = session->open_packet = s = session->open_packet =
LIBSSH2_ALLOC(session, session->open_packet_len); LIBSSH2_ALLOC(session, session->open_packet_len);
@@ -298,18 +292,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
unsigned char channel_id[4]; unsigned char channel_id[4];
LIBSSH2_FREE(session, session->open_channel->channel_type); LIBSSH2_FREE(session, session->open_channel->channel_type);
if (session->open_channel->next) { _libssh2_list_remove(&session->open_channel->node);
session->open_channel->next->prev = session->open_channel->prev;
}
if (session->open_channel->prev) {
session->open_channel->prev->next = session->open_channel->next;
}
if (session->channels.head == session->open_channel) {
session->channels.head = session->open_channel->next;
}
if (session->channels.tail == session->open_channel) {
session->channels.tail = session->open_channel->prev;
}
/* Clear out packets meant for this channel */ /* Clear out packets meant for this channel */
_libssh2_htonu32(channel_id, session->open_channel->local.id); _libssh2_htonu32(channel_id, session->open_channel->local.id);
@@ -416,18 +399,12 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
/* by default we set (keep?) idle state... */ /* by default we set (keep?) idle state... */
session->direct_state = libssh2_NB_state_idle; session->direct_state = libssh2_NB_state_idle;
if (!channel) { if (!channel &&
if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
/* The error code is still set to LIBSSH2_ERROR_EAGAIN, /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state
set our state to created to avoid re-creating the package to created to avoid re-creating the package on next invoke */
on next invoke */
session->direct_state = libssh2_NB_state_created; session->direct_state = libssh2_NB_state_created;
return NULL; return NULL;
} else {
LIBSSH2_FREE(session, session->direct_message);
session->direct_message = NULL;
return NULL;
}
} }
LIBSSH2_FREE(session, session->direct_message); LIBSSH2_FREE(session, session->direct_message);
@@ -585,12 +562,8 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
listener->queue_size = 0; listener->queue_size = 0;
listener->queue_maxsize = queue_maxsize; listener->queue_maxsize = queue_maxsize;
listener->next = session->listeners; /* append this to the parent's list of listeners */
listener->prev = NULL; _libssh2_list_add(&session->listeners, &listener->node);
if (session->listeners) {
session->listeners->prev = listener;
}
session->listeners = listener;
if (bound_port) { if (bound_port) {
*bound_port = listener->port; *bound_port = listener->port;
@@ -642,7 +615,7 @@ libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host,
static int channel_forward_cancel(LIBSSH2_LISTENER *listener) static int channel_forward_cancel(LIBSSH2_LISTENER *listener)
{ {
LIBSSH2_SESSION *session = listener->session; LIBSSH2_SESSION *session = listener->session;
LIBSSH2_CHANNEL *queued = listener->queue; LIBSSH2_CHANNEL *queued;
unsigned char *packet, *s; unsigned char *packet, *s;
unsigned long host_len = strlen(listener->host); unsigned long host_len = strlen(listener->host);
/* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) +
@@ -660,7 +633,7 @@ static int channel_forward_cancel(LIBSSH2_LISTENER *listener)
if (!packet) { if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memeory for setenv packet", 0); "Unable to allocate memeory for setenv packet", 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
*(s++) = SSH_MSG_GLOBAL_REQUEST; *(s++) = SSH_MSG_GLOBAL_REQUEST;
@@ -695,32 +668,27 @@ static int channel_forward_cancel(LIBSSH2_LISTENER *listener)
0); 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
listener->chanFwdCncl_state = libssh2_NB_state_idle; listener->chanFwdCncl_state = libssh2_NB_state_idle;
return -1; return LIBSSH2_ERROR_SOCKET_SEND;
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
listener->chanFwdCncl_state = libssh2_NB_state_sent; listener->chanFwdCncl_state = libssh2_NB_state_sent;
} }
queued = _libssh2_list_first(&listener->queue);
while (queued) { while (queued) {
LIBSSH2_CHANNEL *next = queued->next; LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node);
rc = libssh2_channel_free(queued); rc = libssh2_channel_free(queued);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
queued = next; queued = next;
} }
LIBSSH2_FREE(session, listener->host); LIBSSH2_FREE(session, listener->host);
if (listener->next) { /* remove this entry from the parent's list of listeners */
listener->next->prev = listener->prev; _libssh2_list_remove(&listener->node);
}
if (listener->prev) {
listener->prev->next = listener->next;
} else {
session->listeners = listener->next;
}
LIBSSH2_FREE(session, listener); LIBSSH2_FREE(session, listener);
@@ -753,42 +721,31 @@ libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
static LIBSSH2_CHANNEL * static LIBSSH2_CHANNEL *
channel_forward_accept(LIBSSH2_LISTENER *listener) channel_forward_accept(LIBSSH2_LISTENER *listener)
{ {
libssh2pack_t rc; int rc;
do { do {
rc = _libssh2_transport_read(listener->session); rc = _libssh2_transport_read(listener->session);
if (rc == PACKET_EAGAIN) {
libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for packet", 0);
return NULL;
}
} while (rc > 0); } while (rc > 0);
if (listener->queue) { if (_libssh2_list_first(&listener->queue)) {
LIBSSH2_SESSION *session = listener->session; LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue);
LIBSSH2_CHANNEL *channel;
channel = listener->queue; /* detach channel from listener's queue */
_libssh2_list_remove(&channel->node);
listener->queue = listener->queue->next;
if (listener->queue) {
listener->queue->prev = NULL;
}
channel->prev = NULL;
channel->next = session->channels.head;
session->channels.head = channel;
if (channel->next) {
channel->next->prev = channel;
} else {
session->channels.tail = channel;
}
listener->queue_size--; listener->queue_size--;
/* add channel to session's channel list */
_libssh2_list_add(&channel->session->channels, &channel->node);
return channel; return channel;
} }
if (rc == PACKET_EAGAIN) {
libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for packet", 0);
}
else
libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
"Channel not found", 0); "Channel not found", 0);
return NULL; return NULL;
@@ -844,7 +801,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
if (!channel->setenv_packet) { if (!channel->setenv_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memeory for setenv packet", 0); "Unable to allocate memeory for setenv packet", 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
*(s++) = SSH_MSG_CHANNEL_REQUEST; *(s++) = SSH_MSG_CHANNEL_REQUEST;
@@ -874,7 +831,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
rc = _libssh2_transport_write(session, channel->setenv_packet, rc = _libssh2_transport_write(session, channel->setenv_packet,
channel->setenv_packet_len); channel->setenv_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel-request packet for " "Unable to send channel-request packet for "
@@ -883,7 +840,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
LIBSSH2_FREE(session, channel->setenv_packet); LIBSSH2_FREE(session, channel->setenv_packet);
channel->setenv_packet = NULL; channel->setenv_packet = NULL;
channel->setenv_state = libssh2_NB_state_idle; channel->setenv_state = libssh2_NB_state_idle;
return -1; return LIBSSH2_ERROR_SOCKET_SEND;
} }
LIBSSH2_FREE(session, channel->setenv_packet); LIBSSH2_FREE(session, channel->setenv_packet);
channel->setenv_packet = NULL; channel->setenv_packet = NULL;
@@ -899,11 +856,11 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
&channel-> &channel->
setenv_packet_requirev_state); setenv_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
if (rc) { if (rc) {
channel->setenv_state = libssh2_NB_state_idle; channel->setenv_state = libssh2_NB_state_idle;
return -1; return rc;
} }
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) { if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
@@ -918,7 +875,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
"Unable to complete request for channel-setenv", 0); "Unable to complete request for channel-setenv", 0);
channel->setenv_state = libssh2_NB_state_idle; channel->setenv_state = libssh2_NB_state_idle;
return -1; return LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED;
} }
/* /*
@@ -1017,14 +974,14 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
rc = _libssh2_transport_write(session, channel->reqPTY_packet, rc = _libssh2_transport_write(session, channel->reqPTY_packet,
channel->reqPTY_packet_len); channel->reqPTY_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send pty-request packet", 0); "Unable to send pty-request packet", 0);
LIBSSH2_FREE(session, channel->reqPTY_packet); LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL; channel->reqPTY_packet = NULL;
channel->reqPTY_state = libssh2_NB_state_idle; channel->reqPTY_state = libssh2_NB_state_idle;
return -1; return rc;
} }
LIBSSH2_FREE(session, channel->reqPTY_packet); LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL; channel->reqPTY_packet = NULL;
@@ -1039,7 +996,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
1, channel->reqPTY_local_channel, 4, 1, channel->reqPTY_local_channel, 4,
&channel->reqPTY_packet_requirev_state); &channel->reqPTY_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
channel->reqPTY_state = libssh2_NB_state_idle; channel->reqPTY_state = libssh2_NB_state_idle;
return -1; return -1;
@@ -1056,7 +1013,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
"Unable to complete request for channel request-pty", 0); "Unable to complete request for channel request-pty", 0);
channel->reqPTY_state = libssh2_NB_state_idle; channel->reqPTY_state = libssh2_NB_state_idle;
return -1; return LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED;
} }
/* /*
@@ -1131,14 +1088,14 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
rc = _libssh2_transport_write(session, channel->reqPTY_packet, rc = _libssh2_transport_write(session, channel->reqPTY_packet,
channel->reqPTY_packet_len); channel->reqPTY_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send window-change packet", 0); "Unable to send window-change packet", 0);
LIBSSH2_FREE(session, channel->reqPTY_packet); LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL; channel->reqPTY_packet = NULL;
channel->reqPTY_state = libssh2_NB_state_idle; channel->reqPTY_state = libssh2_NB_state_idle;
return -1; return rc;
} }
LIBSSH2_FREE(session, channel->reqPTY_packet); LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL; channel->reqPTY_packet = NULL;
@@ -1257,15 +1214,15 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
rc = _libssh2_transport_write(session, channel->reqX11_packet, rc = _libssh2_transport_write(session, channel->reqX11_packet,
channel->reqX11_packet_len); channel->reqX11_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
if (rc) { if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send x11-req packet", 0); "Unable to send x11-req packet", 0);
LIBSSH2_FREE(session, channel->reqX11_packet); LIBSSH2_FREE(session, channel->reqX11_packet);
channel->reqX11_packet = NULL; channel->reqX11_packet = NULL;
channel->reqX11_state = libssh2_NB_state_idle; channel->reqX11_state = libssh2_NB_state_idle;
return -1; return rc;
} }
LIBSSH2_FREE(session, channel->reqX11_packet); LIBSSH2_FREE(session, channel->reqX11_packet);
channel->reqX11_packet = NULL; channel->reqX11_packet = NULL;
@@ -1280,10 +1237,11 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
1, channel->reqX11_local_channel, 4, 1, channel->reqX11_local_channel, 4,
&channel->reqX11_packet_requirev_state); &channel->reqX11_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
/* TODO: call libssh2_error() here! */
channel->reqX11_state = libssh2_NB_state_idle; channel->reqX11_state = libssh2_NB_state_idle;
return -1; return rc;
} }
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) { if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
@@ -1331,7 +1289,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
static const unsigned char reply_codes[3] = static const unsigned char reply_codes[3] =
{ SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
unsigned long data_len; unsigned long data_len;
libssh2pack_t rc; int rc;
if (channel->process_state == libssh2_NB_state_idle) { if (channel->process_state == libssh2_NB_state_idle) {
/* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */ /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
@@ -1355,7 +1313,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for channel-process request", "Unable to allocate memory for channel-process request",
0); 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
*(s++) = SSH_MSG_CHANNEL_REQUEST; *(s++) = SSH_MSG_CHANNEL_REQUEST;
@@ -1382,15 +1340,15 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
rc = _libssh2_transport_write(session, channel->process_packet, rc = _libssh2_transport_write(session, channel->process_packet,
channel->process_packet_len); channel->process_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send channel request", 0); "Unable to send channel request", 0);
LIBSSH2_FREE(session, channel->process_packet); LIBSSH2_FREE(session, channel->process_packet);
channel->process_packet = NULL; channel->process_packet = NULL;
channel->process_state = libssh2_NB_state_idle; channel->process_state = libssh2_NB_state_idle;
return -1; return rc;
} }
LIBSSH2_FREE(session, channel->process_packet); LIBSSH2_FREE(session, channel->process_packet);
channel->process_packet = NULL; channel->process_packet = NULL;
@@ -1405,10 +1363,12 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1, channel->process_local_channel, 4, 1, channel->process_local_channel, 4,
&channel->process_packet_requirev_state); &channel->process_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
channel->process_state = libssh2_NB_state_idle; channel->process_state = libssh2_NB_state_idle;
return -1; libssh2_error(session, rc,
"Failed waiting for channel success", 0);
return rc;
} }
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) { if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
@@ -1422,7 +1382,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
"Unable to complete request for channel-process-startup", 0); "Unable to complete request for channel-process-startup", 0);
channel->process_state = libssh2_NB_state_idle; channel->process_state = libssh2_NB_state_idle;
return -1; return LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED;
} }
/* /*
@@ -1464,14 +1424,14 @@ libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
int int
_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid) _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
{ {
LIBSSH2_PACKET *packet = channel->session->packets.head;
if (channel->flush_state == libssh2_NB_state_idle) { if (channel->flush_state == libssh2_NB_state_idle) {
LIBSSH2_PACKET *packet =
_libssh2_list_first(&channel->session->packets);
channel->flush_refund_bytes = 0; channel->flush_refund_bytes = 0;
channel->flush_flush_bytes = 0; channel->flush_flush_bytes = 0;
while (packet) { while (packet) {
LIBSSH2_PACKET *next = packet->next; LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
unsigned char packet_type = packet->data[0]; unsigned char packet_type = packet->data[0];
if (((packet_type == SSH_MSG_CHANNEL_DATA) if (((packet_type == SSH_MSG_CHANNEL_DATA)
@@ -1479,9 +1439,8 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
&& (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) { && (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) {
/* It's our channel at least */ /* It's our channel at least */
long packet_stream_id = long packet_stream_id =
(packet_type == (packet_type == SSH_MSG_CHANNEL_DATA) ? 0 :
SSH_MSG_CHANNEL_DATA) ? 0 : _libssh2_ntohu32(packet->data + _libssh2_ntohu32(packet->data + 5);
5);
if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL) if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
|| ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA) || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
&& ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
@@ -1501,16 +1460,9 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
channel->flush_flush_bytes += bytes_to_flush; channel->flush_flush_bytes += bytes_to_flush;
LIBSSH2_FREE(channel->session, packet->data); LIBSSH2_FREE(channel->session, packet->data);
if (packet->prev) {
packet->prev->next = packet->next; /* remove this packet from the parent's list */
} else { _libssh2_list_remove(&packet->node);
channel->session->packets.head = packet->next;
}
if (packet->next) {
packet->next->prev = packet->prev;
} else {
channel->session->packets.tail = packet->prev;
}
LIBSSH2_FREE(channel->session, packet); LIBSSH2_FREE(channel->session, packet);
} }
} }
@@ -1526,9 +1478,8 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
rc = _libssh2_channel_receive_window_adjust(channel, rc = _libssh2_channel_receive_window_adjust(channel,
channel->flush_refund_bytes, channel->flush_refund_bytes,
0, NULL); 0, NULL);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
return PACKET_EAGAIN; return rc;
}
} }
channel->flush_state = libssh2_NB_state_idle; channel->flush_state = libssh2_NB_state_idle;
@@ -1615,7 +1566,7 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
rc = _libssh2_transport_write(channel->session, channel->adjust_adjust, 9); rc = _libssh2_transport_write(channel->session, channel->adjust_adjust, 9);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
else if (rc) { else if (rc) {
libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -1638,6 +1589,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
/* /*
* libssh2_channel_receive_window_adjust * libssh2_channel_receive_window_adjust
* *
* DEPRECATED
*
* Adjust the receive window for a channel by adjustment bytes. If the amount * Adjust the receive window for a channel by adjustment bytes. If the amount
* to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
* adjustment amount will be queued for a later packet. * adjustment amount will be queued for a later packet.
@@ -1701,11 +1654,11 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
if (channel->extData2_state == libssh2_NB_state_idle) { if (channel->extData2_state == libssh2_NB_state_idle) {
if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) { if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
if (_libssh2_channel_flush(channel, int rc =
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) == _libssh2_channel_flush(channel,
PACKET_EAGAIN) { LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
return PACKET_EAGAIN; if(PACKET_EAGAIN == rc)
} return rc;
} }
} }
@@ -1747,7 +1700,7 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
/* /*
* channel_read * _libssh2_channel_read
* *
* Read data from a channel * Read data from a channel
* *
@@ -1755,14 +1708,16 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
* complete. If we read stuff from the wire but it was no payload data to fill * complete. If we read stuff from the wire but it was no payload data to fill
* in the buffer with, we MUST make sure to return PACKET_EAGAIN. * in the buffer with, we MUST make sure to return PACKET_EAGAIN.
*/ */
static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id, ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
char *buf, size_t buflen) char *buf, size_t buflen)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
libssh2pack_t rc; int rc;
int bytes_read = 0; int bytes_read = 0;
int bytes_want; int bytes_want;
int unlink_packet; int unlink_packet;
LIBSSH2_PACKET *read_packet;
LIBSSH2_PACKET *read_next;
if (channel->read_state == libssh2_NB_state_idle) { if (channel->read_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
@@ -1780,8 +1735,10 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
while (rc > 0) while (rc > 0)
rc = _libssh2_transport_read(session); rc = _libssh2_transport_read(session);
if ((rc < 0) && (rc != PACKET_EAGAIN)) if ((rc < 0) && (rc != PACKET_EAGAIN)) {
return -1; libssh2_error(session, rc, "tranport read", 0);
return rc;
}
/* /*
* =============================== NOTE =============================== * =============================== NOTE ===============================
@@ -1792,11 +1749,8 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
goto channel_read_ex_point1; goto channel_read_ex_point1;
} }
rc = 0; read_packet = _libssh2_list_first(&session->packets);
while (read_packet && (bytes_read < (int) buflen)) {
channel->read_packet = session->packets.head;
while (channel->read_packet &&
(bytes_read < (int) buflen)) {
/* previously this loop condition also checked for /* previously this loop condition also checked for
!channel->remote.close but we cannot let it do this: !channel->remote.close but we cannot let it do this:
@@ -1805,10 +1759,10 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
makes us flush buffers prematurely and loose data. makes us flush buffers prematurely and loose data.
*/ */
LIBSSH2_PACKET *readpkt = channel->read_packet; LIBSSH2_PACKET *readpkt = read_packet;
/* In case packet gets destroyed during this iteration */ /* In case packet gets destroyed during this iteration */
channel->read_next = readpkt->next; read_next = _libssh2_list_next(&readpkt->node);
channel->read_local_id = channel->read_local_id =
_libssh2_ntohu32(readpkt->data + 1); _libssh2_ntohu32(readpkt->data + 1);
@@ -1859,42 +1813,30 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
/* if drained, remove from list */ /* if drained, remove from list */
if (unlink_packet) { if (unlink_packet) {
if (readpkt->prev) { /* detach readpkt from session->packets list */
readpkt->prev->next = readpkt->next; _libssh2_list_remove(&readpkt->node);
} else {
session->packets.head = readpkt->next;
}
if (readpkt->next) {
readpkt->next->prev = readpkt->prev;
} else {
session->packets.tail = readpkt->prev;
}
LIBSSH2_FREE(session, readpkt->data); LIBSSH2_FREE(session, readpkt->data);
LIBSSH2_FREE(session, readpkt); LIBSSH2_FREE(session, readpkt);
} }
} }
/* check the next struct in the chain */ /* check the next struct in the chain */
channel->read_packet = channel->read_next; read_packet = read_next;
} }
if (bytes_read == 0) { if (!bytes_read) {
channel->read_state = libssh2_NB_state_idle; channel->read_state = libssh2_NB_state_idle;
if (channel->remote.close) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED, /* If the channel is already at EOF or even closed, we need to signal
"Remote end has closed this channel", 0); that back. We may have gotten that info while draining the incoming
transport layer until EAGAIN so we must not be fooled by that
return code. */
if(channel->remote.eof || channel->remote.close)
return 0; return 0;
} else
else { /* if the transport layer said EAGAIN then we say so as well */
/* return (rc == PACKET_EAGAIN)?rc:0;
* when non-blocking, we must return PACKET_EAGAIN if we haven't
* completed reading the channel
*/
if (!libssh2_channel_eof(channel)) {
return PACKET_EAGAIN;
}
return 0;
}
} }
else else
/* make sure we remain in the created state to focus on emptying the /* make sure we remain in the created state to focus on emptying the
@@ -1911,9 +1853,9 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
this special state here */ this special state here */
rc = _libssh2_channel_receive_window_adjust(channel, rc = _libssh2_channel_receive_window_adjust(channel,
(LIBSSH2_CHANNEL_WINDOW_DEFAULT*600), 0, NULL); (LIBSSH2_CHANNEL_WINDOW_DEFAULT*600), 0, NULL);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
return PACKET_EAGAIN; return rc;
}
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"channel_read() filled %d adjusted %d", "channel_read() filled %d adjusted %d",
bytes_read, buflen); bytes_read, buflen);
@@ -1940,8 +1882,8 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
size_t buflen) size_t buflen)
{ {
int rc; int rc;
BLOCK_ADJUST(rc, channel->session, channel_read(channel, stream_id, BLOCK_ADJUST(rc, channel->session,
buf, buflen)); _libssh2_channel_read(channel, stream_id, buf, buflen));
return rc; return rc;
} }
@@ -1958,9 +1900,9 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
LIBSSH2_PACKET *read_packet; LIBSSH2_PACKET *read_packet;
uint32_t read_local_id; uint32_t read_local_id;
if ((read_packet = session->packets.head) == NULL) { read_packet = _libssh2_list_first(&session->packets);
if (read_packet == NULL)
return 0; return 0;
}
while (read_packet) { while (read_packet) {
read_local_id = _libssh2_ntohu32(read_packet->data + 1); read_local_id = _libssh2_ntohu32(read_packet->data + 1);
@@ -1989,7 +1931,7 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
{ {
return (read_packet->data_len - read_packet->data_head); return (read_packet->data_len - read_packet->data_head);
} }
read_packet = read_packet->next; read_packet = _libssh2_list_next(&read_packet->node);
} }
return 0; return 0;
@@ -2001,15 +1943,26 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
* Send data to a channel. Note that if this returns EAGAIN or simply didn't * Send data to a channel. Note that if this returns EAGAIN or simply didn't
* send the entire packet, the caller must call this function again with the * send the entire packet, the caller must call this function again with the
* SAME input arguments. * SAME input arguments.
*
* Returns: number of bytes sent, or if it returns a negative number, that is
* the error code!
*/ */
ssize_t ssize_t
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
const char *buf, size_t buflen) const char *buf, size_t buflen)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
libssh2pack_t rc; int rc;
ssize_t wrote = 0; /* counter for this specific this call */ ssize_t wrote = 0; /* counter for this specific this call */
/* In theory we could split larger buffers into several smaller packets,
* but for now we instead only deal with the first 32K in this call and
* assume the app will call it again with the rest! The 32K is a
* conservative limit based on the text in RFC4253 section 6.1.
*/
if(buflen > 32768)
buflen = 32768;
if (channel->write_state == libssh2_NB_state_idle) { if (channel->write_state == libssh2_NB_state_idle) {
channel->write_bufwrote = 0; channel->write_bufwrote = 0;
@@ -2021,7 +1974,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
if (channel->local.close) { if (channel->local.close) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED,
"We've already closed this channel", 0); "We've already closed this channel", 0);
return -1; return LIBSSH2_ERROR_CHANNEL_CLOSED;
} }
if (channel->local.eof) { if (channel->local.eof) {
@@ -2039,7 +1992,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocte space for data transmission packet", "Unable to allocte space for data transmission packet",
0); 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
channel->write_state = libssh2_NB_state_allocated; channel->write_state = libssh2_NB_state_allocated;
@@ -2071,11 +2024,6 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
if(channel->local.window_size <= 0) { if(channel->local.window_size <= 0) {
/* there's no more room for data so we stop sending now */ /* there's no more room for data so we stop sending now */
if(!wrote) {
/* if nothing has been written at this point we're at an
EAGAIN point */
return PACKET_EAGAIN;
}
break; break;
} }
@@ -2115,17 +2063,17 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->write_s - channel->write_s -
channel->write_packet); channel->write_packet);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
_libssh2_debug(session, LIBSSH2_DBG_CONN, libssh2_error(session, rc,
"libssh2_transport_write returned EAGAIN"); "Unable to send channel data", 0);
return PACKET_EAGAIN; return rc;
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send channel data", 0); "Unable to send channel data", 0);
LIBSSH2_FREE(session, channel->write_packet); LIBSSH2_FREE(session, channel->write_packet);
channel->write_packet = NULL; channel->write_packet = NULL;
channel->write_state = libssh2_NB_state_idle; channel->write_state = libssh2_NB_state_idle;
return -1; return rc;
} }
/* Shrink local window size */ /* Shrink local window size */
channel->local.window_size -= channel->write_bufwrite; channel->local.window_size -= channel->write_bufwrite;
@@ -2180,12 +2128,12 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel)
_libssh2_htonu32(packet + 1, channel->remote.id); _libssh2_htonu32(packet + 1, channel->remote.id);
rc = _libssh2_transport_write(session, packet, 5); rc = _libssh2_transport_write(session, packet, 5);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send EOF on channel", 0); "Unable to send EOF on channel", 0);
return -1; return LIBSSH2_ERROR_SOCKET_SEND;
} }
channel->local.eof = 1; channel->local.eof = 1;
@@ -2214,7 +2162,7 @@ LIBSSH2_API int
libssh2_channel_eof(LIBSSH2_CHANNEL * channel) libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
while (packet) { while (packet) {
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) if (((packet->data[0] == SSH_MSG_CHANNEL_DATA)
@@ -2223,7 +2171,7 @@ libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
/* There's data waiting to be read yet, mask the EOF status */ /* There's data waiting to be read yet, mask the EOF status */
return 0; return 0;
} }
packet = packet->next; packet = _libssh2_list_next(&packet->node);
} }
return channel->remote.eof; return channel->remote.eof;
@@ -2257,7 +2205,7 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
} }
rc = _libssh2_transport_read(session); rc = _libssh2_transport_read(session);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
else if (rc < 0) { else if (rc < 0) {
channel->wait_eof_state = libssh2_NB_state_idle; channel->wait_eof_state = libssh2_NB_state_idle;
@@ -2310,12 +2258,12 @@ channel_close(LIBSSH2_CHANNEL * channel)
if (channel->close_state == libssh2_NB_state_created) { if (channel->close_state == libssh2_NB_state_created) {
retcode = _libssh2_transport_write(session, channel->close_packet, 5); retcode = _libssh2_transport_write(session, channel->close_packet, 5);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN; return retcode;
} else if (retcode) { } else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, retcode,
"Unable to send close-channel request", 0); "Unable to send close-channel request", 0);
channel->close_state = libssh2_NB_state_idle; channel->close_state = libssh2_NB_state_idle;
return -1; return retcode;
} }
channel->close_state = libssh2_NB_state_sent; channel->close_state = libssh2_NB_state_sent;
@@ -2326,16 +2274,10 @@ channel_close(LIBSSH2_CHANNEL * channel)
while (!channel->remote.close && !rc) { while (!channel->remote.close && !rc) {
rc = _libssh2_transport_read(session); rc = _libssh2_transport_read(session);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
else if (rc < 0)
rc = -1;
else
rc = 0;
} }
} }
if(rc != LIBSSH2_ERROR_EAGAIN) {
/* set the local close state first when we're perfectly confirmed to not /* set the local close state first when we're perfectly confirmed to not
do any more EAGAINs */ do any more EAGAINs */
channel->local.close = 1; channel->local.close = 1;
@@ -2347,8 +2289,10 @@ channel_close(LIBSSH2_CHANNEL * channel)
} }
channel->close_state = libssh2_NB_state_idle; channel->close_state = libssh2_NB_state_idle;
}
return rc; /* return 0 or an error */
return rc>=0?0:rc;
} }
/* /*
@@ -2397,6 +2341,9 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
if (!channel->remote.close) { if (!channel->remote.close) {
do { do {
rc = _libssh2_transport_read(session); rc = _libssh2_transport_read(session);
if (channel->remote.close)
/* it is now closed, move on! */
break;
} while (rc > 0); } while (rc > 0);
if(rc < 0) if(rc < 0)
return rc; return rc;
@@ -2450,12 +2397,12 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
if (!channel->local.close if (!channel->local.close
&& (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) { && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
rc = channel_close(channel); rc = channel_close(channel);
if(rc == PACKET_EAGAIN) if(rc == PACKET_EAGAIN)
return rc; return rc;
else if (rc < 0) {
if (rc) {
channel->free_state = libssh2_NB_state_idle; channel->free_state = libssh2_NB_state_idle;
return -1; return rc;
} }
} }
@@ -2482,17 +2429,8 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
LIBSSH2_FREE(session, channel->channel_type); LIBSSH2_FREE(session, channel->channel_type);
} }
/* Unlink from channel brigade */ /* Unlink from channel list */
if (channel->prev) { _libssh2_list_remove(&channel->node);
channel->prev->next = channel->next;
} else {
session->channels.head = channel->next;
}
if (channel->next) {
channel->next->prev = channel->prev;
} else {
session->channels.tail = channel->prev;
}
/* /*
* Make sure all memory used in the state variables are free * Make sure all memory used in the state variables are free
@@ -2553,7 +2491,8 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
if (read_avail) { if (read_avail) {
unsigned long bytes_queued = 0; unsigned long bytes_queued = 0;
LIBSSH2_PACKET *packet = channel->session->packets.head; LIBSSH2_PACKET *packet =
_libssh2_list_first(&channel->session->packets);
while (packet) { while (packet) {
unsigned char packet_type = packet->data[0]; unsigned char packet_type = packet->data[0];
@@ -2564,7 +2503,7 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
bytes_queued += packet->data_len - packet->data_head; bytes_queued += packet->data_len - packet->data_head;
} }
packet = packet->next; packet = _libssh2_list_next(&packet->node);
} }
*read_avail = bytes_queued; *read_avail = bytes_queued;

View File

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

View File

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

View File

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

158
src/kex.c
View File

@@ -69,22 +69,20 @@
} \ } \
} }
/* kex_method_diffie_hellman_groupGP_sha1_key_exchange /*
* diffie_hellman_sha1
*
* Diffie Hellman Key Exchange, Group Agnostic * Diffie Hellman Key Exchange, Group Agnostic
*/ */
static int static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session, _libssh2_bn *g,
_libssh2_bn * g, _libssh2_bn *p,
_libssh2_bn * p,
int group_order, int group_order,
unsigned char unsigned char packet_type_init,
packet_type_init, unsigned char packet_type_reply,
unsigned char
packet_type_reply,
unsigned char *midhash, unsigned char *midhash,
unsigned long midhash_len, unsigned long midhash_len,
kmdhgGPsha1kex_state_t kmdhgGPsha1kex_state_t *exchange_state)
* exchange_state)
{ {
int ret = 0; int ret = 0;
int rc; int rc;
@@ -122,7 +120,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (!exchange_state->e_packet) { if (!exchange_state->e_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Out of memory error", libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Out of memory error",
0); 0);
ret = -1; ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit; goto clean_exit;
} }
exchange_state->e_packet[0] = packet_type_init; exchange_state->e_packet[0] = packet_type_init;
@@ -146,11 +144,11 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
rc = _libssh2_transport_write(session, exchange_state->e_packet, rc = _libssh2_transport_write(session, exchange_state->e_packet,
exchange_state->e_packet_len); exchange_state->e_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send KEX init message", 0); "Unable to send KEX init message", 0);
ret = -1; ret = rc;
goto clean_exit; goto clean_exit;
} }
exchange_state->state = libssh2_NB_state_sent; exchange_state->state = libssh2_NB_state_sent;
@@ -168,10 +166,10 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
burn_type = burn_type =
_libssh2_packet_burn(session, &exchange_state->burn_state); _libssh2_packet_burn(session, &exchange_state->burn_state);
if (burn_type == PACKET_EAGAIN) { if (burn_type == PACKET_EAGAIN) {
return PACKET_EAGAIN; return burn_type;
} else if (burn_type <= 0) { } else if (burn_type <= 0) {
/* Failed to receive a packet */ /* Failed to receive a packet */
ret = -1; ret = burn_type;
goto clean_exit; goto clean_exit;
} }
session->burn_optimistic_kexinit = 0; session->burn_optimistic_kexinit = 0;
@@ -191,12 +189,12 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&exchange_state->s_packet_len, 0, NULL, &exchange_state->s_packet_len, 0, NULL,
0, &exchange_state->req_state); 0, &exchange_state->req_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
if (rc) { if (rc) {
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply", 0); "Timed out waiting for KEX reply", 0);
ret = -1; ret = rc;
goto clean_exit; goto clean_exit;
} }
@@ -211,7 +209,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for a copy of the host key", "Unable to allocate memory for a copy of the host key",
0); 0);
ret = -1; ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit; goto clean_exit;
} }
memcpy(session->server_hostkey, exchange_state->s, memcpy(session->server_hostkey, exchange_state->s,
@@ -263,12 +261,12 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
} }
#endif /* LIBSSH2DEBUG */ #endif /* LIBSSH2DEBUG */
if (session->hostkey-> if (session->hostkey->init(session, session->server_hostkey,
init(session, session->server_hostkey, session->server_hostkey_len, session->server_hostkey_len,
&session->server_hostkey_abstract)) { &session->server_hostkey_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
"Unable to initialize hostkey importer", 0); "Unable to initialize hostkey importer", 0);
ret = -1; ret = LIBSSH2_ERROR_HOSTKEY_INIT;
goto clean_exit; goto clean_exit;
} }
@@ -296,7 +294,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (!exchange_state->k_value) { if (!exchange_state->k_value) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K", 0); "Unable to allocate buffer for K", 0);
ret = -1; ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit; goto clean_exit;
} }
_libssh2_htonu32(exchange_state->k_value, _libssh2_htonu32(exchange_state->k_value,
@@ -421,11 +419,10 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (exchange_state->state == libssh2_NB_state_sent2) { if (exchange_state->state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_write(session, &exchange_state->c, 1); rc = _libssh2_transport_write(session, &exchange_state->c, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc, "Unable to send NEWKEYS message", 0);
"Unable to send NEWKEYS message", 0); ret = rc;
ret = -1;
goto clean_exit; goto clean_exit;
} }
@@ -438,11 +435,10 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&exchange_state->tmp_len, 0, NULL, 0, &exchange_state->tmp_len, 0, NULL, 0,
&exchange_state->req_state); &exchange_state->req_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, libssh2_error(session, rc, "Timed out waiting for NEWKEYS", 0);
"Timed out waiting for NEWKEYS", 0); ret = rc;
ret = -1;
goto clean_exit; goto clean_exit;
} }
/* The first key exchange has been performed, /* The first key exchange has been performed,
@@ -457,7 +453,9 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
if (!session->session_id) { if (!session->session_id) {
session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH); session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
if (!session->session_id) { if (!session->session_id) {
ret = -1; libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for SHA digest", 0);
ret = LIBSSH2_ERROR_ALLOC;
goto clean_exit; goto clean_exit;
} }
memcpy(session->session_id, exchange_state->h_sig_comp, memcpy(session->session_id, exchange_state->h_sig_comp,
@@ -489,7 +487,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
secret_len, "C"); secret_len, "C");
if (!secret) { if (!secret) {
LIBSSH2_FREE(session, iv); LIBSSH2_FREE(session, iv);
ret = -1; ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit; goto clean_exit;
} }
if (session->local.crypt-> if (session->local.crypt->
@@ -497,7 +495,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&free_secret, 1, &session->local.crypt_abstract)) { &free_secret, 1, &session->local.crypt_abstract)) {
LIBSSH2_FREE(session, iv); LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret); LIBSSH2_FREE(session, secret);
ret = -1; ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit; goto clean_exit;
} }
@@ -528,7 +526,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
session->remote.crypt-> session->remote.crypt->
iv_len, "B"); iv_len, "B");
if (!iv) { if (!iv) {
ret = -1; ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit; goto clean_exit;
} }
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
@@ -536,7 +534,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
secret_len, "D"); secret_len, "D");
if (!secret) { if (!secret) {
LIBSSH2_FREE(session, iv); LIBSSH2_FREE(session, iv);
ret = -1; ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit; goto clean_exit;
} }
if (session->remote.crypt-> if (session->remote.crypt->
@@ -544,7 +542,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
&free_secret, 0, &session->remote.crypt_abstract)) { &free_secret, 0, &session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, iv); LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret); LIBSSH2_FREE(session, secret);
ret = -1; ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit; goto clean_exit;
} }
@@ -573,7 +571,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
session->local.mac-> session->local.mac->
key_len, "E"); key_len, "E");
if (!key) { if (!key) {
ret = -1; ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit; goto clean_exit;
} }
session->local.mac->init(session, key, &free_key, session->local.mac->init(session, key, &free_key,
@@ -599,7 +597,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
session->remote.mac-> session->remote.mac->
key_len, "F"); key_len, "F");
if (!key) { if (!key) {
ret = -1; ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit; goto clean_exit;
} }
session->remote.mac->init(session, key, &free_key, session->remote.mac->init(session, key, &free_key,
@@ -691,18 +689,11 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
key_state->state = libssh2_NB_state_created; key_state->state = libssh2_NB_state_created;
} }
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128,
ret = SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
kex_method_diffie_hellman_groupGP_sha1_key_exchange(session, NULL, 0, &key_state->exchange_state);
key_state->g,
key_state->p, 128,
SSH_MSG_KEXDH_INIT,
SSH_MSG_KEXDH_REPLY,
NULL, 0,
&key_state->
exchange_state);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return ret;
} }
_libssh2_bn_free(key_state->p); _libssh2_bn_free(key_state->p);
@@ -774,18 +765,11 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
key_state->state = libssh2_NB_state_created; key_state->state = libssh2_NB_state_created;
} }
ret = ret = diffie_hellman_sha1(session, key_state->g, key_state->p,
kex_method_diffie_hellman_groupGP_sha1_key_exchange(session, 256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
key_state->g, NULL, 0, &key_state->exchange_state);
key_state->p,
256,
SSH_MSG_KEXDH_INIT,
SSH_MSG_KEXDH_REPLY,
NULL, 0,
&key_state->
exchange_state);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return ret;
} }
key_state->state = libssh2_NB_state_idle; key_state->state = libssh2_NB_state_idle;
@@ -839,11 +823,11 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
rc = _libssh2_transport_write(session, key_state->request, rc = _libssh2_transport_write(session, key_state->request,
key_state->request_len); key_state->request_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send Group Exchange Request", 0); "Unable to send Group Exchange Request", 0);
ret = -1; ret = rc;
goto dh_gex_clean_exit; goto dh_gex_clean_exit;
} }
@@ -855,11 +839,11 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
&key_state->data, &key_state->data_len, &key_state->data, &key_state->data_len,
0, NULL, 0, &key_state->req_state); 0, NULL, 0, &key_state->req_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply", 0); "Timeout waiting for GEX_GROUP reply", 0);
ret = -1; ret = rc;
goto dh_gex_clean_exit; goto dh_gex_clean_exit;
} }
@@ -878,14 +862,14 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
_libssh2_bn_from_bin(key_state->g, g_len, s); _libssh2_bn_from_bin(key_state->g, g_len, s);
s += g_len; s += g_len;
ret = ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len,
kex_method_diffie_hellman_groupGP_sha1_key_exchange SSH_MSG_KEX_DH_GEX_INIT,
(session, key_state->g, key_state->p, p_len, SSH_MSG_KEX_DH_GEX_REPLY,
SSH_MSG_KEX_DH_GEX_INIT, SSH_MSG_KEX_DH_GEX_REPLY, key_state->data + 1,
key_state->data + 1, key_state->data_len - 1, key_state->data_len - 1,
&key_state->exchange_state); &key_state->exchange_state);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return ret;
} }
LIBSSH2_FREE(session, key_state->data); LIBSSH2_FREE(session, key_state->data);
@@ -1056,7 +1040,7 @@ static int kexinit(LIBSSH2_SESSION * session)
if (!data) { if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory", 0); "Unable to allocate memory", 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
*(s++) = SSH_MSG_KEXINIT; *(s++) = SSH_MSG_KEXINIT;
@@ -1139,14 +1123,14 @@ static int kexinit(LIBSSH2_SESSION * session)
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
session->kexinit_data = data; session->kexinit_data = data;
session->kexinit_data_len = data_len; session->kexinit_data_len = data_len;
return PACKET_EAGAIN; return rc;
} }
else if (rc) { else if (rc) {
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send KEXINIT packet to remote host", 0); "Unable to send KEXINIT packet to remote host", 0);
session->kexinit_state = libssh2_NB_state_idle; session->kexinit_state = libssh2_NB_state_idle;
return -1; return rc;
} }
if (session->local.kexinit) { if (session->local.kexinit) {
@@ -1662,6 +1646,8 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
/* libssh2_kex_exchange /* libssh2_kex_exchange
* Exchange keys * Exchange keys
* Returns 0 on success, non-zero on failure * Returns 0 on success, non-zero on failure
*
* Returns some errors without libssh2_error()
*/ */
int int
libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
@@ -1704,7 +1690,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
retcode = kexinit(session); retcode = kexinit(session);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN; return retcode;
} else if (retcode) { } else if (retcode) {
session->local.kexinit = key_state->oldlocal; session->local.kexinit = key_state->oldlocal;
session->local.kexinit_len = key_state->oldlocal_len; session->local.kexinit_len = key_state->oldlocal_len;
@@ -1725,7 +1711,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
&key_state->req_state); &key_state->req_state);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN; return retcode;
} }
else if (retcode) { else if (retcode) {
if (session->local.kexinit) { if (session->local.kexinit) {
@@ -1746,9 +1732,8 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
session->remote.kexinit_len = key_state->data_len; session->remote.kexinit_len = key_state->data_len;
if (kex_agree_methods(session, key_state->data, if (kex_agree_methods(session, key_state->data,
key_state->data_len)) { key_state->data_len))
rc = -1; rc = LIBSSH2_ERROR_KEX_FAILURE;
}
key_state->state = libssh2_NB_state_sent2; key_state->state = libssh2_NB_state_sent2;
} }
@@ -1758,16 +1743,15 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
if (rc == 0) { if (rc == 0) {
if (key_state->state == libssh2_NB_state_sent2) { if (key_state->state == libssh2_NB_state_sent2) {
retcode = retcode = session->kex->exchange_keys(session,
session->kex->exchange_keys(session,
&key_state->key_state_low); &key_state->key_state_low);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN; return retcode;
} else if (retcode) { } else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
"Unrecoverable error exchanging keys", 0); "Unrecoverable error exchanging keys", 0);
rc = -1; rc = retcode;
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2006, 2007, The Written Word, Inc. /* Copyright (C) 2008, 2009, Simon Josefsson
* Copyright (C) 2008, Simon Josefsson * Copyright (C) 2006, 2007, The Written Word, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -37,6 +37,9 @@
*/ */
#include "libssh2_priv.h" #include "libssh2_priv.h"
#ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */
#include <string.h> #include <string.h>
int int
@@ -149,8 +152,9 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
int int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase) const char *filename, unsigned const char *passphrase)
{ {
FILE *fp;
unsigned char *data, *save_data; unsigned char *data, *save_data;
unsigned int datalen; unsigned int datalen;
int ret; int ret;
@@ -159,10 +163,16 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
(void) passphrase; (void) passphrase;
fp = fopen(filename, "r");
if (!fp) {
return -1;
}
ret = _libssh2_pem_parse(session, ret = _libssh2_pem_parse(session,
"-----BEGIN RSA PRIVATE KEY-----", "-----BEGIN RSA PRIVATE KEY-----",
"-----END RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----",
fp, &data, &datalen); fp, &data, &datalen);
fclose(fp);
if (ret) { if (ret) {
return -1; return -1;
} }
@@ -244,8 +254,9 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
int int
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase) const char *filename, unsigned const char *passphrase)
{ {
FILE *fp;
unsigned char *data, *save_data; unsigned char *data, *save_data;
unsigned int datalen; unsigned int datalen;
int ret; int ret;
@@ -254,10 +265,16 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
(void) passphrase; (void) passphrase;
fp = fopen(filename, "r");
if (!fp) {
return -1;
}
ret = _libssh2_pem_parse(session, ret = _libssh2_pem_parse(session,
"-----BEGIN DSA PRIVATE KEY-----", "-----BEGIN DSA PRIVATE KEY-----",
"-----END DSA PRIVATE KEY-----", "-----END DSA PRIVATE KEY-----",
fp, &data, &datalen); fp, &data, &datalen);
fclose(fp);
if (ret) { if (ret) {
return -1; return -1;
} }
@@ -507,16 +524,14 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
unsigned char *iv, unsigned char *secret, int encrypt) unsigned char *iv, unsigned char *secret, int encrypt)
{ {
int mode = 0, ret; int ret;
int keylen = gcry_cipher_get_algo_keylen(algo); int cipher = _libssh2_gcry_cipher (algo);
int mode = _libssh2_gcry_mode (algo);
int keylen = gcry_cipher_get_algo_keylen(cipher);
(void) encrypt; (void) encrypt;
if (algo != GCRY_CIPHER_ARCFOUR) { ret = gcry_cipher_open(h, cipher, mode, 0);
mode = GCRY_CIPHER_MODE_CBC;
}
ret = gcry_cipher_open(h, algo, mode, 0);
if (ret) { if (ret) {
return -1; return -1;
} }
@@ -527,8 +542,11 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
return -1; return -1;
} }
if (algo != GCRY_CIPHER_ARCFOUR) { if (mode != GCRY_CIPHER_MODE_STREAM) {
int blklen = gcry_cipher_get_algo_blklen(algo); 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); ret = gcry_cipher_setiv(*h, iv, blklen);
if (ret) { if (ret) {
gcry_cipher_close(*h); gcry_cipher_close(*h);
@@ -544,8 +562,10 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
int encrypt, unsigned char *block) int encrypt, unsigned char *block)
{ {
size_t blklen = gcry_cipher_get_algo_blklen(algo); int cipher = _libssh2_gcry_cipher (algo);
size_t blklen = gcry_cipher_get_algo_blklen(cipher);
int ret; int ret;
if (blklen == 1) { if (blklen == 1) {
/* Hack for arcfour. */ /* Hack for arcfour. */
blklen = 8; blklen = 8;
@@ -558,3 +578,5 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
} }
return ret; return ret;
} }
#endif /* LIBSSH2_LIBGCRYPT */

View File

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

View File

@@ -85,6 +85,7 @@
#include "libssh2.h" #include "libssh2.h"
#include "libssh2_publickey.h" #include "libssh2_publickey.h"
#include "libssh2_sftp.h" #include "libssh2_sftp.h"
#include "misc.h" /* for the linked list stuff */
#ifndef FALSE #ifndef FALSE
#define FALSE 0 #define FALSE 0
@@ -96,10 +97,9 @@
/* Provide iovec / writev on WIN32 platform. */ /* Provide iovec / writev on WIN32 platform. */
#ifdef WIN32 #ifdef WIN32
/* same as WSABUF */
struct iovec { struct iovec {
u_long iov_len; size_t iov_len;
char *iov_base; void * iov_base;
}; };
#define inline __inline #define inline __inline
@@ -149,6 +149,12 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
#endif #endif
#ifdef WIN32
typedef SOCKET libssh2_socket_t;
#else /* !WIN32 */
typedef int libssh2_socket_t;
#endif /* WIN32 */
/* RFC4253 section 6.1 Maximum Packet Length says: /* RFC4253 section 6.1 Maximum Packet Length says:
* *
* "All implementations MUST be able to process packets with * "All implementations MUST be able to process packets with
@@ -187,10 +193,6 @@ typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD; typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD;
typedef struct _LIBSSH2_PACKET LIBSSH2_PACKET; typedef struct _LIBSSH2_PACKET LIBSSH2_PACKET;
typedef struct _LIBSSH2_PACKET_BRIGADE LIBSSH2_PACKET_BRIGADE;
typedef struct _LIBSSH2_CHANNEL_BRIGADE LIBSSH2_CHANNEL_BRIGADE;
typedef int libssh2pack_t;
typedef enum typedef enum
{ {
@@ -288,6 +290,7 @@ typedef struct packet_queue_listener_state_t
uint32_t sport; uint32_t sport;
uint32_t host_len; uint32_t host_len;
uint32_t shost_len; uint32_t shost_len;
LIBSSH2_CHANNEL *channel;
} packet_queue_listener_state_t; } packet_queue_listener_state_t;
#define X11FwdUnAvil "X11 Forward Unavailable" #define X11FwdUnAvil "X11 Forward Unavailable"
@@ -302,10 +305,13 @@ typedef struct packet_x11_open_state_t
uint32_t packet_size; uint32_t packet_size;
uint32_t sport; uint32_t sport;
uint32_t shost_len; uint32_t shost_len;
LIBSSH2_CHANNEL *channel;
} packet_x11_open_state_t; } packet_x11_open_state_t;
struct _LIBSSH2_PACKET struct _LIBSSH2_PACKET
{ {
struct list_node node; /* linked list header */
unsigned char type; unsigned char type;
/* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */ /* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */
@@ -318,15 +324,6 @@ struct _LIBSSH2_PACKET
/* Can the message be confirmed? */ /* Can the message be confirmed? */
int mac; int mac;
LIBSSH2_PACKET_BRIGADE *brigade;
LIBSSH2_PACKET *next, *prev;
};
struct _LIBSSH2_PACKET_BRIGADE
{
LIBSSH2_PACKET *head, *tail;
}; };
typedef struct _libssh2_channel_data typedef struct _libssh2_channel_data
@@ -343,6 +340,8 @@ typedef struct _libssh2_channel_data
struct _LIBSSH2_CHANNEL struct _LIBSSH2_CHANNEL
{ {
struct list_node node;
unsigned char *channel_type; unsigned char *channel_type;
unsigned channel_type_len; unsigned channel_type_len;
@@ -355,8 +354,6 @@ struct _LIBSSH2_CHANNEL
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *next, *prev;
void *abstract; void *abstract;
LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb)); LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb));
@@ -399,8 +396,6 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_read_ex() */ /* State variables used in libssh2_channel_read_ex() */
libssh2_nonblocking_states read_state; libssh2_nonblocking_states read_state;
LIBSSH2_PACKET *read_packet;
LIBSSH2_PACKET *read_next;
uint32_t read_local_id; uint32_t read_local_id;
@@ -429,24 +424,21 @@ struct _LIBSSH2_CHANNEL
libssh2_nonblocking_states extData2_state; libssh2_nonblocking_states extData2_state;
}; };
struct _LIBSSH2_CHANNEL_BRIGADE
{
LIBSSH2_CHANNEL *head, *tail;
};
struct _LIBSSH2_LISTENER struct _LIBSSH2_LISTENER
{ {
struct list_node node; /* linked list header */
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
char *host; char *host;
int port; int port;
LIBSSH2_CHANNEL *queue; /* a list of CHANNELs for this listener */
struct list_head queue;
int queue_size; int queue_size;
int queue_maxsize; int queue_maxsize;
LIBSSH2_LISTENER *prev, *next;
/* State variables used in libssh2_channel_forward_cancel() */ /* State variables used in libssh2_channel_forward_cancel() */
libssh2_nonblocking_states chanFwdCncl_state; libssh2_nonblocking_states chanFwdCncl_state;
unsigned char *chanFwdCncl_data; unsigned char *chanFwdCncl_data;
@@ -547,8 +539,9 @@ struct _LIBSSH2_PUBLICKEY
struct _LIBSSH2_SFTP_HANDLE struct _LIBSSH2_SFTP_HANDLE
{ {
struct list_node node;
LIBSSH2_SFTP *sftp; LIBSSH2_SFTP *sftp;
LIBSSH2_SFTP_HANDLE *prev, *next;
/* This is a pre-allocated buffer used for sending SFTP requests as the /* 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, whole thing might not get sent in one go. This buffer is used for read,
@@ -586,9 +579,10 @@ struct _LIBSSH2_SFTP
unsigned long request_id, version; unsigned long request_id, version;
LIBSSH2_PACKET_BRIGADE packets; struct list_head packets;
LIBSSH2_SFTP_HANDLE *handles; /* a list of _LIBSSH2_SFTP_HANDLE structs */
struct list_head sftp_handles;
unsigned long last_errno; unsigned long last_errno;
@@ -713,18 +707,19 @@ struct _LIBSSH2_SESSION
/* (local as source of data -- packet_write ) */ /* (local as source of data -- packet_write ) */
libssh2_endpoint_data local; libssh2_endpoint_data local;
/* Inbound Data buffer -- Sometimes the packet that comes in isn't the /* Inbound Data linked list -- Sometimes the packet that comes in isn't the
packet we're ready for */ packet we're ready for */
LIBSSH2_PACKET_BRIGADE packets; struct list_head packets;
/* Active connection channels */ /* Active connection channels */
LIBSSH2_CHANNEL_BRIGADE channels; struct list_head channels;
unsigned long next_channel; unsigned long next_channel;
LIBSSH2_LISTENER *listeners; struct list_head listeners; /* list of LIBSSH2_LISTENER structs */
/* Actual I/O socket */ /* Actual I/O socket */
int socket_fd; libssh2_socket_t socket_fd;
int socket_state; int socket_state;
int socket_block_directions; int socket_block_directions;
int socket_prev_blockstate; /* stores the state of the socket blockiness int socket_prev_blockstate; /* stores the state of the socket blockiness
@@ -811,7 +806,7 @@ struct _LIBSSH2_SESSION
unsigned char *userauth_pblc_b; unsigned char *userauth_pblc_b;
packet_requirev_state_t userauth_pblc_packet_requirev_state; packet_requirev_state_t userauth_pblc_packet_requirev_state;
/* State variables used in llibssh2_userauth_keyboard_interactive_ex() */ /* State variables used in libssh2_userauth_keyboard_interactive_ex() */
libssh2_nonblocking_states userauth_kybd_state; libssh2_nonblocking_states userauth_kybd_state;
unsigned char *userauth_kybd_data; unsigned char *userauth_kybd_data;
unsigned long userauth_kybd_data_len; unsigned long userauth_kybd_data_len;
@@ -860,7 +855,6 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_packet_add() */ /* State variables used in libssh2_packet_add() */
libssh2_nonblocking_states packAdd_state; libssh2_nonblocking_states packAdd_state;
LIBSSH2_PACKET *packAdd_packet;
LIBSSH2_CHANNEL *packAdd_channel; LIBSSH2_CHANNEL *packAdd_channel;
unsigned long packAdd_data_head; unsigned long packAdd_data_head;
key_exchange_state_t packAdd_key_state; key_exchange_state_t packAdd_key_state;
@@ -871,7 +865,7 @@ struct _LIBSSH2_SESSION
libssh2_nonblocking_states fullpacket_state; libssh2_nonblocking_states fullpacket_state;
int fullpacket_macstate; int fullpacket_macstate;
int fullpacket_payload_len; int fullpacket_payload_len;
libssh2pack_t fullpacket_packet_type; int fullpacket_packet_type;
/* State variables used in libssh2_sftp_init() */ /* State variables used in libssh2_sftp_init() */
libssh2_nonblocking_states sftpInit_state; libssh2_nonblocking_states sftpInit_state;
@@ -928,22 +922,6 @@ struct _LIBSSH2_SESSION
#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0 #define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
#endif #endif
/* -------- */
/* First take towards a generic linked list handling code for libssh2
internals */
struct list_head {
struct list_node *last;
struct list_node *first;
};
struct list_node {
struct list_node *next;
struct list_node *prev;
struct list_head *head;
};
/* --------- */ /* --------- */
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional /* libssh2 extensible ssh api, ultimately I'd like to allow loading additional
@@ -1161,8 +1139,8 @@ libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf);
void _libssh2_htonu32(unsigned char *buf, unsigned int val); void _libssh2_htonu32(unsigned char *buf, unsigned int val);
#ifdef WIN32 #ifdef WIN32
ssize_t _libssh2_recv(int socket, void *buffer, size_t length, int flags); ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer, size_t length, int flags);
ssize_t _libssh2_send(int socket, const void *buffer, size_t length, int flags); ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer, size_t length, int flags);
#else #else
#define _libssh2_recv(a,b,c,d) recv(a,b,c,d) #define _libssh2_recv(a,b,c,d) recv(a,b,c,d)
#define _libssh2_send(a,b,c,d) send(a,b,c,d) #define _libssh2_send(a,b,c,d) send(a,b,c,d)
@@ -1174,20 +1152,21 @@ ssize_t _libssh2_send(int socket, const void *buffer, size_t length, int flags);
int _libssh2_wait_socket(LIBSSH2_SESSION *session); int _libssh2_wait_socket(LIBSSH2_SESSION *session);
/* CAUTION: some of these error codes are returned in the public API and is /* These started out as private return codes for the transport layer, but was
there known with other #defined names from the public header file. They converted to using the library-wide return codes to easy propagation of the
should not be changed. */ error reasons all over etc without risking mixups. The PACKET_* names are
left only to reduce the impact of changing the code all over.*/
#define PACKET_TIMEOUT -7 #define PACKET_TIMEOUT LIBSSH2_ERROR_TIMEOUT
#define PACKET_BADUSE -6 #define PACKET_BADUSE LIBSSH2_ERROR_BAD_USE
#define PACKET_COMPRESS -5 #define PACKET_COMPRESS LIBSSH2_ERROR_COMPRESS
#define PACKET_TOOBIG -4 #define PACKET_TOOBIG LIBSSH2_ERROR_OUT_OF_BOUNDARY
#define PACKET_ENOMEM -3 #define PACKET_ENOMEM LIBSSH2_ERROR_ALLOC
#define PACKET_EAGAIN LIBSSH2_ERROR_EAGAIN #define PACKET_EAGAIN LIBSSH2_ERROR_EAGAIN
#define PACKET_FAIL -1 #define PACKET_FAIL LIBSSH2_ERROR_SOCKET_NONE
#define PACKET_NONE 0 #define PACKET_NONE LIBSSH2_ERROR_NONE
libssh2pack_t _libssh2_packet_read(LIBSSH2_SESSION * session); int _libssh2_packet_read(LIBSSH2_SESSION * session);
int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned char **data, unsigned long *data_len, unsigned char **data, unsigned long *data_len,

View File

@@ -78,7 +78,7 @@ static int wsa2errno(void)
* to set errno * to set errno
*/ */
ssize_t ssize_t
_libssh2_recv(int socket, void *buffer, size_t length, int flags) _libssh2_recv(libssh2_socket_t socket, void *buffer, size_t length, int flags)
{ {
ssize_t rc = recv(socket, buffer, length, flags); ssize_t rc = recv(socket, buffer, length, flags);
#ifdef WIN32 #ifdef WIN32
@@ -97,7 +97,7 @@ _libssh2_recv(int socket, void *buffer, size_t length, int flags)
* to set errno * to set errno
*/ */
ssize_t ssize_t
_libssh2_send(int socket, const void *buffer, size_t length, int flags) _libssh2_send(libssh2_socket_t socket, const void *buffer, size_t length, int flags)
{ {
ssize_t rc = send(socket, buffer, length, flags); ssize_t rc = send(socket, buffer, length, flags);
#ifdef WIN32 #ifdef WIN32
@@ -426,3 +426,81 @@ void _libssh2_list_remove(struct list_node *entry)
else else
entry->head->last = entry->prev; entry->head->last = entry->prev;
} }
#if 0
/* insert a node before the given 'after' entry */
void _libssh2_list_insert(struct list_node *after, /* insert before this */
struct list_node *entry)
{
/* 'after' is next to 'entry' */
bentry->next = after;
/* entry's prev is then made to be the prev after current has */
entry->prev = after->prev;
/* the node that is now before 'entry' was previously before 'after'
and must be made to point to 'entry' correctly */
if(entry->prev)
entry->prev->next = entry;
/* after's prev entry points back to entry */
after->prev = entry;
/* after's next entry is still the same as before */
/* entry's head is the same as after's */
entry->head = after->head;
}
#endif
#ifdef WIN32
/*
* gettimeofday
* Implementation according to:
* The Open Group Base Specifications Issue 6
* IEEE Std 1003.1, 2004 Edition
*/
/*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Contributed by:
* Danny Smith <dannysmith@users.sourceforge.net>
*/
/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
#define _W32_FT_OFFSET (116444736000000000ULL)
int __cdecl gettimeofday(struct timeval *tp,
void *tzp)
{
union {
unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} _now;
if(tp)
{
GetSystemTimeAsFileTime (&_now.ft);
tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
}
/* Always return 0 as per Open Group Base Specifications Issue 6.
Do not set errno on error. */
return 0;
}
#endif

View File

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

View File

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

View File

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

View File

@@ -60,6 +60,7 @@
#include <sys/types.h> #include <sys/types.h>
#include "transport.h" #include "transport.h"
#include "channel.h"
/* /*
* libssh2_packet_queue_listener * libssh2_packet_queue_listener
@@ -69,7 +70,7 @@
static inline int static inline int
packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long datalen, unsigned long datalen,
packet_queue_listener_state_t * listen_state) packet_queue_listener_state_t *listen_state)
{ {
/* /*
* Look for a matching listener * Look for a matching listener
@@ -78,7 +79,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
/* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1); unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1);
unsigned char *p; unsigned char *p;
LIBSSH2_LISTENER *listen = session->listeners; LIBSSH2_LISTENER *listen = _libssh2_list_first(&session->listeners);
char failure_code = 1; /* SSH_OPEN_ADMINISTRATIVELY_PROHIBITED */ char failure_code = 1; /* SSH_OPEN_ADMINISTRATIVELY_PROHIBITED */
int rc; int rc;
@@ -119,13 +120,12 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
while (listen) { while (listen) {
if ((listen->port == (int) listen_state->port) && if ((listen->port == (int) listen_state->port) &&
(strlen(listen->host) == listen_state->host_len) && (strlen(listen->host) == listen_state->host_len) &&
(memcmp (memcmp (listen->host, listen_state->host,
(listen->host, listen_state->host,
listen_state->host_len) == 0)) { listen_state->host_len) == 0)) {
/* This is our listener */ /* This is our listener */
LIBSSH2_CHANNEL *channel = NULL, *last_queued = listen->queue; LIBSSH2_CHANNEL *channel = NULL;
listen_state->channel = NULL;
last_queued = listen->queue;
if (listen_state->state == libssh2_NB_state_allocated) { if (listen_state->state == libssh2_NB_state_allocated) {
if (listen->queue_maxsize && if (listen->queue_maxsize &&
(listen->queue_maxsize <= listen->queue_size)) { (listen->queue_maxsize <= listen->queue_size)) {
@@ -146,6 +146,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
listen_state->state = libssh2_NB_state_sent; listen_state->state = libssh2_NB_state_sent;
break; break;
} }
listen_state->channel = channel;
memset(channel, 0, sizeof(LIBSSH2_CHANNEL)); memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
channel->session = session; channel->session = session;
@@ -206,31 +208,19 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
if (listen_state->state == libssh2_NB_state_created) { if (listen_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, listen_state->packet, rc = _libssh2_transport_write(session, listen_state->packet,
17); 17);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
return PACKET_EAGAIN; return rc;
} else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc,
"Unable to send channel open confirmation", "Unable to send channel "
0); "open confirmation", 0);
listen_state->state = libssh2_NB_state_idle; listen_state->state = libssh2_NB_state_idle;
return -1; return rc;
} }
/* Link the channel into the end of the queue list */ /* Link the channel into the end of the queue list */
_libssh2_list_add(&listen->queue,
if (!last_queued) { &listen_state->channel->node);
listen->queue = channel;
listen_state->state = libssh2_NB_state_idle;
return 0;
}
while (last_queued->next) {
last_queued = last_queued->next;
}
last_queued->next = channel;
channel->prev = last_queued;
listen->queue_size++; listen->queue_size++;
listen_state->state = libssh2_NB_state_idle; listen_state->state = libssh2_NB_state_idle;
@@ -238,14 +228,13 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
} }
} }
listen = listen->next; listen = _libssh2_list_next(&listen->node);
} }
listen_state->state = libssh2_NB_state_sent; listen_state->state = libssh2_NB_state_sent;
} }
/* We're not listening to you */ /* We're not listening to you */
{
p = listen_state->packet; p = listen_state->packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
_libssh2_htonu32(p, listen_state->sender_channel); _libssh2_htonu32(p, listen_state->sender_channel);
@@ -261,16 +250,14 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
rc = _libssh2_transport_write(session, listen_state->packet, rc = _libssh2_transport_write(session, listen_state->packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc, "Unable to send open failure", 0);
"Unable to send open failure", 0);
listen_state->state = libssh2_NB_state_idle; listen_state->state = libssh2_NB_state_idle;
return -1; return rc;
} }
listen_state->state = libssh2_NB_state_idle; listen_state->state = libssh2_NB_state_idle;
return 0; return 0;
}
} }
/* /*
@@ -281,14 +268,14 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
static inline int static inline int
packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long datalen, unsigned long datalen,
packet_x11_open_state_t * x11open_state) packet_x11_open_state_t *x11open_state)
{ {
int failure_code = 2; /* SSH_OPEN_CONNECT_FAILED */ int failure_code = 2; /* SSH_OPEN_CONNECT_FAILED */
unsigned char *s = data + (sizeof("x11") - 1) + 5; unsigned char *s = data + (sizeof("x11") - 1) + 5;
/* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1);
unsigned char *p; unsigned char *p;
LIBSSH2_CHANNEL *channel = NULL; LIBSSH2_CHANNEL *channel = x11open_state->channel;
int rc; int rc;
(void) datalen; (void) datalen;
@@ -379,7 +366,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
if (x11open_state->state == libssh2_NB_state_created) { if (x11open_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_write(session, x11open_state->packet, 17); rc = _libssh2_transport_write(session, x11open_state->packet, 17);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel open confirmation", 0); "Unable to send channel open confirmation", 0);
@@ -388,21 +375,13 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
} }
/* Link the channel into the session */ /* Link the channel into the session */
if (session->channels.tail) { _libssh2_list_add(&session->channels, &channel->node);
session->channels.tail->next = channel;
channel->prev = session->channels.tail;
} else {
session->channels.head = channel;
channel->prev = NULL;
}
channel->next = NULL;
session->channels.tail = channel;
/* /*
* Pass control to the callback, they may turn right around and * Pass control to the callback, they may turn right around and
* free the channel, or actually use it * free the channel, or actually use it
*/ */
LIBSSH2_X11_OPEN(channel, (char *) x11open_state->shost, LIBSSH2_X11_OPEN(channel, (char *)x11open_state->shost,
x11open_state->sport); x11open_state->sport);
x11open_state->state = libssh2_NB_state_idle; x11open_state->state = libssh2_NB_state_idle;
@@ -427,12 +406,11 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
rc = _libssh2_transport_write(session, x11open_state->packet, packet_len); rc = _libssh2_transport_write(session, x11open_state->packet, packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, rc, "Unable to send open failure", 0);
"Unable to send open failure", 0);
x11open_state->state = libssh2_NB_state_idle; x11open_state->state = libssh2_NB_state_idle;
return -1; return rc;
} }
x11open_state->state = libssh2_NB_state_idle; x11open_state->state = libssh2_NB_state_idle;
return 0; return 0;
@@ -443,6 +421,9 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
* *
* Create a new packet and attach it to the brigade. Called from the transport * Create a new packet and attach it to the brigade. Called from the transport
* layer when it as received a packet. * layer when it as received a packet.
*
* The input pointer 'data' is pointing to allocated data that this function
* is asked to deal with so on failure OR success, it must be freed fine.
*/ */
int int
_libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
@@ -469,8 +450,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"Packet type %d received, length=%d", "Packet type %d received, length=%d",
(int) data[0], (int) datalen); (int) data[0], (int) datalen);
if (macstate == LIBSSH2_MAC_INVALID) { if (macstate == LIBSSH2_MAC_INVALID) {
if (session->macerror) { if (session->macerror &&
if (LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) { LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) {
/* Calling app has given the OK, Process it anyway */ /* Calling app has given the OK, Process it anyway */
macstate = LIBSSH2_MAC_CONFIRMED; macstate = LIBSSH2_MAC_CONFIRMED;
} else { } else {
@@ -484,20 +465,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"", 0); "", 0);
} }
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return -1; return LIBSSH2_ERROR_INVALID_MAC;
}
} else {
libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
"Invalid Message Authentication Code received",
0);
if (session->ssh_msg_disconnect) {
LIBSSH2_DISCONNECT(session, SSH_DISCONNECT_MAC_ERROR,
"Invalid MAC received",
sizeof("Invalid MAC received") - 1,
"", 0);
}
LIBSSH2_FREE(session, data);
return -1;
} }
} }
@@ -544,7 +512,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
message[message_len] = '\0'; message[message_len] = '\0';
language = (char *) data + 9 + message_len + 3; language = (char *) data + 9 + message_len + 3;
if (language_len) { if (language_len) {
memcpy(language, language + 1, language_len); memmove(language, language + 1, language_len);
} }
language[language_len] = '\0'; language[language_len] = '\0';
@@ -558,21 +526,26 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return -1; libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"socket disconnect", 0);
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
} }
break; break;
case SSH_MSG_IGNORE: case SSH_MSG_IGNORE:
/* As with disconnect, back it up one and add a trailing NULL */ if (datalen >= 5) {
memcpy(data + 4, data + 5, datalen - 5); /* Back it up one and add a trailing NULL */
memmove(data, data + 1, datalen - 1);
data[datalen] = '\0'; data[datalen] = '\0';
if (session->ssh_msg_ignore) { if (session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, (char *) data + 4, datalen - 5); LIBSSH2_IGNORE(session, (char *) data + 4, datalen - 1);
}
} else if (session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, "", 0);
} }
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
break;
case SSH_MSG_DEBUG: case SSH_MSG_DEBUG:
{ {
@@ -598,7 +571,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
message[message_len] = '\0'; message[message_len] = '\0';
language = (char *) data + 6 + message_len + 3; language = (char *) data + 6 + message_len + 3;
if (language_len) { if (language_len) {
memcpy(language, language + 1, language_len); memmove(language, language + 1, language_len);
} }
language[language_len] = '\0'; language[language_len] = '\0';
@@ -663,15 +636,13 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
/* Adjust the window based on the block we just freed */ /* Adjust the window based on the block we just freed */
libssh2_packet_add_jump_point1: libssh2_packet_add_jump_point1:
session->packAdd_state = libssh2_NB_state_jump1; session->packAdd_state = libssh2_NB_state_jump1;
rc = libssh2_channel_receive_window_adjust(session-> rc = _libssh2_channel_receive_window_adjust(session->
packAdd_channel, packAdd_channel,
datalen - 13, datalen - 13,
0); 0, NULL);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
session->socket_block_directions = return rc;
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
} }
@@ -731,7 +702,6 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
break; break;
case SSH_MSG_CHANNEL_EOF: case SSH_MSG_CHANNEL_EOF:
{
session->packAdd_channel = session->packAdd_channel =
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1));
@@ -752,11 +722,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
}
break;
case SSH_MSG_CHANNEL_REQUEST: case SSH_MSG_CHANNEL_REQUEST:
{
if (_libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1 if (_libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1
&& !memcmp("exit-status", data + 9, && !memcmp("exit-status", data + 9,
sizeof("exit-status") - 1)) { sizeof("exit-status") - 1)) {
@@ -780,11 +747,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
} }
}
break; break;
case SSH_MSG_CHANNEL_CLOSE: case SSH_MSG_CHANNEL_CLOSE:
{
session->packAdd_channel = session->packAdd_channel =
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1));
@@ -801,31 +766,24 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
session->packAdd_channel->remote.close = 1; session->packAdd_channel->remote.close = 1;
session->packAdd_channel->remote.eof = 1; session->packAdd_channel->remote.eof = 1;
/* TODO: Add a callback for this */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
}
break;
case SSH_MSG_CHANNEL_OPEN: case SSH_MSG_CHANNEL_OPEN:
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip") - 1) == _libssh2_ntohu32(data + 1)) ((sizeof("forwarded-tcpip") - 1) == _libssh2_ntohu32(data + 1))
&& &&
(memcmp (memcmp(data + 5, "forwarded-tcpip",
(data + 5, "forwarded-tcpip",
sizeof("forwarded-tcpip") - 1) == 0)) { sizeof("forwarded-tcpip") - 1) == 0)) {
libssh2_packet_add_jump_point2: libssh2_packet_add_jump_point2:
session->packAdd_state = libssh2_NB_state_jump2; session->packAdd_state = libssh2_NB_state_jump2;
rc = packet_queue_listener(session, data, datalen, rc = packet_queue_listener(session, data, datalen,
&session->packAdd_Qlstn_state); &session->packAdd_Qlstn_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
session->socket_block_directions = return rc;
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
@@ -839,11 +797,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
session->packAdd_state = libssh2_NB_state_jump3; session->packAdd_state = libssh2_NB_state_jump3;
rc = packet_x11_open(session, data, datalen, rc = packet_x11_open(session, data, datalen,
&session->packAdd_x11open_state); &session->packAdd_x11open_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
session->socket_block_directions = return rc;
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
@@ -879,33 +834,23 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
} }
if (session->packAdd_state == libssh2_NB_state_sent) { if (session->packAdd_state == libssh2_NB_state_sent) {
session->packAdd_packet = LIBSSH2_PACKET *packAdd_packet;
packAdd_packet =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!session->packAdd_packet) { if (!packAdd_packet) {
_libssh2_debug(session, LIBSSH2_ERROR_ALLOC, _libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for LIBSSH2_PACKET"); "Unable to allocate memory for LIBSSH2_PACKET");
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return -1; return -1;
} }
memset(session->packAdd_packet, 0, sizeof(LIBSSH2_PACKET)); memset(packAdd_packet, 0, sizeof(LIBSSH2_PACKET));
session->packAdd_packet->data = data; packAdd_packet->data = data;
session->packAdd_packet->data_len = datalen; packAdd_packet->data_len = datalen;
session->packAdd_packet->data_head = session->packAdd_data_head; packAdd_packet->data_head = session->packAdd_data_head;
session->packAdd_packet->mac = macstate; packAdd_packet->mac = macstate;
session->packAdd_packet->brigade = &session->packets;
session->packAdd_packet->next = NULL;
if (session->packets.tail) { _libssh2_list_add(&session->packets, &packAdd_packet->node);
session->packAdd_packet->prev = session->packets.tail;
session->packAdd_packet->prev->next = session->packAdd_packet;
session->packets.tail = session->packAdd_packet;
} else {
session->packets.head = session->packAdd_packet;
session->packets.tail = session->packAdd_packet;
session->packAdd_packet->prev = NULL;
}
session->packAdd_state = libssh2_NB_state_sent1; session->packAdd_state = libssh2_NB_state_sent1;
} }
@@ -948,7 +893,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
*/ */
rc = libssh2_kex_exchange(session, 1, &session->startup_key_state); rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
} }
@@ -968,7 +913,7 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_ofs, const unsigned char *match_buf,
unsigned long match_len) unsigned long match_len)
{ {
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
_libssh2_debug(session, LIBSSH2_DBG_TRANS, _libssh2_debug(session, LIBSSH2_DBG_TRANS,
"Looking for packet of type: %d", (int) packet_type); "Looking for packet of type: %d", (int) packet_type);
@@ -982,24 +927,14 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
*data = packet->data; *data = packet->data;
*data_len = packet->data_len; *data_len = packet->data_len;
/* unlink struct */ /* unlink struct from session->packets */
if (packet->prev) { _libssh2_list_remove(&packet->node);
packet->prev->next = packet->next;
} else {
session->packets.head = packet->next;
}
if (packet->next) {
packet->next->prev = packet->prev;
} else {
session->packets.tail = packet->prev;
}
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
return 0; return 0;
} }
packet = packet->next; packet = _libssh2_list_next(&packet->node);
} }
return -1; return -1;
} }
@@ -1060,13 +995,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
} }
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
libssh2pack_t ret = _libssh2_transport_read(session); int ret = _libssh2_transport_read(session);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN)
return PACKET_EAGAIN; return ret;
} else if (ret == 0) { else if (ret < 0) {
/* There is no data, return that. TODO: is this really correct? */
return PACKET_EAGAIN;
} else if (ret < 0) {
state->start = 0; state->start = 0;
/* an error which is not just because of blocking */ /* an error which is not just because of blocking */
return ret; return ret;
@@ -1084,11 +1016,12 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
state->start = 0; state->start = 0;
return PACKET_TIMEOUT; return PACKET_TIMEOUT;
} }
return -1; /* no packet available yet */
} }
} }
/* Only reached if the socket died */ /* Only reached if the socket died */
return -1; return LIBSSH2_ERROR_SOCKET_DISCONNECT;
} }
/* /*
@@ -1127,8 +1060,9 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
} }
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
if ((ret = _libssh2_transport_read(session)) == PACKET_EAGAIN) { ret = _libssh2_transport_read(session);
return PACKET_EAGAIN; if (ret == PACKET_EAGAIN) {
return ret;
} else if (ret < 0) { } else if (ret < 0) {
*state = libssh2_NB_state_idle; *state = libssh2_NB_state_idle;
return ret; return ret;
@@ -1148,7 +1082,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
} }
/* Only reached if the socket died */ /* Only reached if the socket died */
return -1; return LIBSSH2_ERROR_SOCKET_DISCONNECT;
} }
/* /*
@@ -1194,7 +1128,7 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
return PACKET_TIMEOUT; return PACKET_TIMEOUT;
} }
else if (ret == PACKET_EAGAIN) { else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return ret;
} }
} }
@@ -1208,6 +1142,6 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
/* Only reached if the socket died */ /* Only reached if the socket died */
state->start = 0; state->start = 0;
return -1; return LIBSSH2_ERROR_SOCKET_DISCONNECT;
} }

View File

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

View File

@@ -37,6 +37,7 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include "libssh2_publickey.h" #include "libssh2_publickey.h"
#include "channel.h"
#define LIBSSH2_PUBLICKEY_VERSION 2 #define LIBSSH2_PUBLICKEY_VERSION 2
@@ -168,9 +169,9 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
int rc; int rc;
if (pkey->receive_state == libssh2_NB_state_idle) { if (pkey->receive_state == libssh2_NB_state_idle) {
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4); rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc != 4) { } else if (rc != 4) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid response from publickey subsystem", 0); "Invalid response from publickey subsystem", 0);
@@ -190,10 +191,10 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
} }
if (pkey->receive_state == libssh2_NB_state_sent) { if (pkey->receive_state == libssh2_NB_state_sent) {
rc = libssh2_channel_read_ex(channel, 0, (char *) pkey->receive_packet, rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet,
pkey->receive_packet_len); pkey->receive_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc != (int)pkey->receive_packet_len) { } else if (rc != (int)pkey->receive_packet_len) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for publickey subsystem response packet", "Timeout waiting for publickey subsystem response packet",
@@ -265,7 +266,7 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
while (1) { while (1) {
rc = publickey_packet_receive(pkey, &data, &data_len); rc = publickey_packet_receive(pkey, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from publickey subsystem", "Timeout waiting for response from publickey subsystem",
@@ -441,7 +442,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
} }
if (session->pkeyInit_state == libssh2_NB_state_sent2) { if (session->pkeyInit_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_write_ex(session->pkeyInit_channel, 0, rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
(char *) buffer, (s - buffer)); (char *) buffer, (s - buffer));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -678,10 +679,10 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
} }
if (pkey->add_state == libssh2_NB_state_created) { if (pkey->add_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->add_packet, rc = _libssh2_channel_write(channel, 0, (char *) pkey->add_packet,
(pkey->add_s - pkey->add_packet)); (pkey->add_s - pkey->add_packet));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if ((pkey->add_s - pkey->add_packet) != rc) { } else if ((pkey->add_s - pkey->add_packet) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey add packet", 0); "Unable to send publickey add packet", 0);
@@ -697,7 +698,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
rc = publickey_response_success(pkey); rc = publickey_response_success(pkey);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
pkey->add_state = libssh2_NB_state_idle; pkey->add_state = libssh2_NB_state_idle;
@@ -754,10 +755,10 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
} }
if (pkey->remove_state == libssh2_NB_state_created) { if (pkey->remove_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->remove_packet, rc = _libssh2_channel_write(channel, 0, (char *) pkey->remove_packet,
(pkey->remove_s - pkey->remove_packet)); (pkey->remove_s - pkey->remove_packet));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if ((pkey->remove_s - pkey->remove_packet) != rc) { } else if ((pkey->remove_s - pkey->remove_packet) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey remove packet", 0); "Unable to send publickey remove packet", 0);
@@ -774,7 +775,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
rc = publickey_response_success(pkey); rc = publickey_response_success(pkey);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
pkey->remove_state = libssh2_NB_state_idle; pkey->remove_state = libssh2_NB_state_idle;
@@ -815,12 +816,12 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
} }
if (pkey->listFetch_state == libssh2_NB_state_created) { if (pkey->listFetch_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, rc = _libssh2_channel_write(channel, 0,
(char *) pkey->listFetch_buffer, (char *) pkey->listFetch_buffer,
(pkey->listFetch_s - (pkey->listFetch_s -
pkey->listFetch_buffer)); pkey->listFetch_buffer));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) { } else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey list packet", 0); "Unable to send publickey list packet", 0);
@@ -835,7 +836,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
rc = publickey_packet_receive(pkey, &pkey->listFetch_data, rc = publickey_packet_receive(pkey, &pkey->listFetch_data,
&pkey->listFetch_data_len); &pkey->listFetch_data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from publickey subsystem", "Timeout waiting for response from publickey subsystem",
@@ -1040,6 +1041,7 @@ LIBSSH2_API int
libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey) libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
{ {
LIBSSH2_SESSION *session = pkey->channel->session; LIBSSH2_SESSION *session = pkey->channel->session;
int rc;
/* /*
* Make sure all memory used in the state variables are free * Make sure all memory used in the state variables are free
@@ -1061,9 +1063,9 @@ libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
pkey->listFetch_data = NULL; pkey->listFetch_data = NULL;
} }
if (libssh2_channel_free(pkey->channel) == PACKET_EAGAIN) { rc = libssh2_channel_free(pkey->channel);
return PACKET_EAGAIN; if (rc == PACKET_EAGAIN)
} return rc;
LIBSSH2_FREE(session, pkey); LIBSSH2_FREE(session, pkey);
return 0; return 0;

View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2009 by Daniel Stenberg
* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -39,6 +40,8 @@
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include "channel.h"
/* Max. length of a quoted string after libssh2_shell_quotearg() processing */ /* Max. length of a quoted string after libssh2_shell_quotearg() processing */
#define libssh2_shell_quotedsize(s) (3 * strlen(s) + 2) #define libssh2_shell_quotedsize(s) (3 * strlen(s) + 2)
@@ -258,13 +261,13 @@ libssh2_shell_quotearg(const char *path, unsigned char *buf,
} }
/* /*
* libssh2_scp_recv * scp_recv
* *
* Open a channel and request a remote file via SCP * Open a channel and request a remote file via SCP
* *
*/ */
LIBSSH2_API LIBSSH2_CHANNEL * static LIBSSH2_CHANNEL *
libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
{ {
int cmd_len; int cmd_len;
int rc; int rc;
@@ -355,7 +358,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
} }
if (session->scpRecv_state == libssh2_NB_state_sent1) { if (session->scpRecv_state == libssh2_NB_state_sent1) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0, rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session->scpRecv_response, 1); (char *) session->scpRecv_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -378,7 +381,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
unsigned char *s, *p; unsigned char *s, *p;
if (session->scpRecv_state == libssh2_NB_state_sent2) { if (session->scpRecv_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0, rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session-> (char *) session->
scpRecv_response + scpRecv_response +
session->scpRecv_response_len, 1); session->scpRecv_response_len, 1);
@@ -415,7 +418,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
session->scpRecv_err_len + 1); session->scpRecv_err_len + 1);
/* Read the remote error message */ /* Read the remote error message */
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0, rc = _libssh2_channel_read(session->scpRecv_channel, 0,
session->scpRecv_err_msg, session->scpRecv_err_msg,
session->scpRecv_err_len); session->scpRecv_err_len);
if (rc <= 0) { if (rc <= 0) {
@@ -555,7 +558,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
} }
if (session->scpRecv_state == libssh2_NB_state_sent3) { if (session->scpRecv_state == libssh2_NB_state_sent3) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0, rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session-> (char *) session->
scpRecv_response, 1); scpRecv_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
@@ -591,7 +594,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
char *s, *p, *e = NULL; char *s, *p, *e = NULL;
if (session->scpRecv_state == libssh2_NB_state_sent5) { if (session->scpRecv_state == libssh2_NB_state_sent5) {
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0, rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session-> (char *) session->
scpRecv_response + scpRecv_response +
session->scpRecv_response_len, 1); session->scpRecv_response_len, 1);
@@ -718,7 +721,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
} }
if (session->scpRecv_state == libssh2_NB_state_sent6) { if (session->scpRecv_state == libssh2_NB_state_sent6) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0, rc = _libssh2_channel_write(session->scpRecv_channel, 0,
(char *) session-> (char *) session->
scpRecv_response, 1); scpRecv_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
@@ -761,13 +764,27 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
} }
/* /*
* libssh2_scp_send_ex * libssh2_scp_recv
*
* Open a channel and request a remote file via SCP
*
*/
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb)
{
LIBSSH2_CHANNEL *ptr;
BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb));
return ptr;
}
/*
* scp_send()
* *
* Send a file using SCP * Send a file using SCP
* *
*/ */
LIBSSH2_API LIBSSH2_CHANNEL * static LIBSSH2_CHANNEL *
libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode, scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
size_t size, long mtime, long atime) size_t size, long mtime, long atime)
{ {
int cmd_len; int cmd_len;
@@ -857,7 +874,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
if (session->scpSend_state == libssh2_NB_state_sent1) { if (session->scpSend_state == libssh2_NB_state_sent1) {
/* Wait for ACK */ /* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1); (char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -885,7 +902,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
/* Send mtime and atime to be used for file */ /* Send mtime and atime to be used for file */
if (mtime || atime) { if (mtime || atime) {
if (session->scpSend_state == libssh2_NB_state_sent2) { if (session->scpSend_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_write_ex(session->scpSend_channel, 0, rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response, (char *) session->scpSend_response,
session->scpSend_response_len); session->scpSend_response_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
@@ -903,9 +920,8 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
if (session->scpSend_state == libssh2_NB_state_sent3) { if (session->scpSend_state == libssh2_NB_state_sent3) {
/* Wait for ACK */ /* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, (char *) session->scpSend_response, 1);
1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response", 0); "Would block waiting for response", 0);
@@ -944,7 +960,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
} }
if (session->scpSend_state == libssh2_NB_state_sent5) { if (session->scpSend_state == libssh2_NB_state_sent5) {
rc = libssh2_channel_write_ex(session->scpSend_channel, 0, rc = _libssh2_channel_write(session->scpSend_channel, 0,
(char *) session->scpSend_response, (char *) session->scpSend_response,
session->scpSend_response_len); session->scpSend_response_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
@@ -962,7 +978,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
if (session->scpSend_state == libssh2_NB_state_sent6) { if (session->scpSend_state == libssh2_NB_state_sent6) {
/* Wait for ACK */ /* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1); (char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -990,7 +1006,7 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1); memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
/* Read the remote error message */ /* Read the remote error message */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, rc = _libssh2_channel_read(session->scpSend_channel, 0,
session->scpSend_err_msg, session->scpSend_err_msg,
session->scpSend_err_len); session->scpSend_err_len);
if (rc <= 0) { if (rc <= 0) {
@@ -1021,3 +1037,17 @@ libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
return NULL; return NULL;
} }
/*
* libssh2_scp_send_ex
*
* Send a file using SCP
*/
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode,
size_t size, long mtime, long atime)
{
LIBSSH2_CHANNEL *ptr;
BLOCK_ADJUST_ERRNO(ptr, session,
scp_send(session, path, mode, size, mtime, atime));
return ptr;
}

View File

@@ -106,6 +106,9 @@ banner_receive(LIBSSH2_SESSION * session)
|| (session->banner_TxRx_banner[banner_len - 1] != '\n'))) { || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
char c = '\0'; char c = '\0';
/* no incoming block yet! */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
ret = _libssh2_recv(session->socket_fd, &c, 1, ret = _libssh2_recv(session->socket_fd, &c, 1,
LIBSSH2_SOCKET_RECV_FLAGS(session)); LIBSSH2_SOCKET_RECV_FLAGS(session));
@@ -207,6 +210,9 @@ banner_send(LIBSSH2_SESSION * session)
session->banner_TxRx_state = libssh2_NB_state_created; session->banner_TxRx_state = libssh2_NB_state_created;
} }
/* no outgoing block yet! */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
ret = _libssh2_send(session->socket_fd, ret = _libssh2_send(session->socket_fd,
banner + session->banner_TxRx_total_send, banner + session->banner_TxRx_total_send,
banner_len - session->banner_TxRx_total_send, banner_len - session->banner_TxRx_total_send,
@@ -238,7 +244,7 @@ banner_send(LIBSSH2_SESSION * session)
* is copied from the libcurl sources with permission. * is copied from the libcurl sources with permission.
*/ */
static int static int
session_nonblock(int sockfd, /* operate on this */ session_nonblock(libssh2_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */ ) int nonblock /* TRUE or FALSE */ )
{ {
#undef SETBLOCK #undef SETBLOCK
@@ -529,7 +535,7 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session)
} }
static int static int
session_startup(LIBSSH2_SESSION *session, int sock) session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
{ {
int rc; int rc;
@@ -556,35 +562,22 @@ session_startup(LIBSSH2_SESSION *session, int sock)
session->startup_state = libssh2_NB_state_created; session->startup_state = libssh2_NB_state_created;
} }
/* TODO: Liveness check */
if (session->startup_state == libssh2_NB_state_created) { if (session->startup_state == libssh2_NB_state_created) {
rc = banner_send(session); rc = banner_send(session);
if (rc == PACKET_EAGAIN) { if (rc) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, rc,
"Would block sending banner to remote host", 0); "Failed sending banner", 0);
return LIBSSH2_ERROR_EAGAIN; return rc;
} else if (rc) {
/* Unable to send banner? */
libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND,
"Error sending banner to remote host", 0);
return LIBSSH2_ERROR_BANNER_SEND;
} }
session->startup_state = libssh2_NB_state_sent; session->startup_state = libssh2_NB_state_sent;
} }
if (session->startup_state == libssh2_NB_state_sent) { if (session->startup_state == libssh2_NB_state_sent) {
rc = banner_receive(session); rc = banner_receive(session);
if (rc == PACKET_EAGAIN) { if (rc) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, rc,
"Would block waiting for banner", 0); "Failed getting banner", 0);
return LIBSSH2_ERROR_EAGAIN; return rc;
} else if (rc) {
/* Unable to receive banner from remote */
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE,
"Timeout waiting for banner", 0);
return LIBSSH2_ERROR_BANNER_NONE;
} }
session->startup_state = libssh2_NB_state_sent1; session->startup_state = libssh2_NB_state_sent1;
@@ -592,14 +585,10 @@ session_startup(LIBSSH2_SESSION *session, int sock)
if (session->startup_state == libssh2_NB_state_sent1) { if (session->startup_state == libssh2_NB_state_sent1) {
rc = libssh2_kex_exchange(session, 0, &session->startup_key_state); rc = libssh2_kex_exchange(session, 0, &session->startup_key_state);
if (rc == PACKET_EAGAIN) { if (rc) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, rc,
"Would block exchanging encryption keys", 0);
return LIBSSH2_ERROR_EAGAIN;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
"Unable to exchange encryption keys", 0); "Unable to exchange encryption keys", 0);
return LIBSSH2_ERROR_KEX_FAILURE; return rc;
} }
session->startup_state = libssh2_NB_state_sent2; session->startup_state = libssh2_NB_state_sent2;
@@ -622,15 +611,10 @@ session_startup(LIBSSH2_SESSION *session, int sock)
if (session->startup_state == libssh2_NB_state_sent3) { if (session->startup_state == libssh2_NB_state_sent3) {
rc = _libssh2_transport_write(session, session->startup_service, rc = _libssh2_transport_write(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1); sizeof("ssh-userauth") + 5 - 1);
if (rc == PACKET_EAGAIN) { if (rc) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, rc,
"Would block asking for ssh-userauth service", 0);
return LIBSSH2_ERROR_EAGAIN;
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to ask for ssh-userauth service", 0); "Unable to ask for ssh-userauth service", 0);
return LIBSSH2_ERROR_SOCKET_SEND; return rc;
} }
session->startup_state = libssh2_NB_state_sent4; session->startup_state = libssh2_NB_state_sent4;
@@ -641,11 +625,9 @@ session_startup(LIBSSH2_SESSION *session, int sock)
&session->startup_data, &session->startup_data,
&session->startup_data_len, 0, NULL, 0, &session->startup_data_len, 0, NULL, 0,
&session->startup_req_state); &session->startup_req_state);
if (rc == PACKET_EAGAIN) { if (rc)
return LIBSSH2_ERROR_EAGAIN; return rc;
} else if (rc) {
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
session->startup_service_length = session->startup_service_length =
_libssh2_ntohu32(session->startup_data + 1); _libssh2_ntohu32(session->startup_data + 1);
@@ -699,6 +681,9 @@ static int
session_free(LIBSSH2_SESSION *session) session_free(LIBSSH2_SESSION *session)
{ {
int rc; int rc;
LIBSSH2_PACKET *pkg;
LIBSSH2_CHANNEL *ch;
LIBSSH2_LISTENER *l;
if (session->free_state == libssh2_NB_state_idle) { if (session->free_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource", _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource",
@@ -708,13 +693,15 @@ session_free(LIBSSH2_SESSION *session)
} }
if (session->free_state == libssh2_NB_state_created) { if (session->free_state == libssh2_NB_state_created) {
while (session->channels.head) { while ((ch = _libssh2_list_first(&session->channels))) {
LIBSSH2_CHANNEL *tmp = session->channels.head;
rc = libssh2_channel_free(session->channels.head); rc = libssh2_channel_free(ch);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
return PACKET_EAGAIN; return rc;
} #if 0
/* Daniel's note: I'm leaving this code here right now since it
looks so weird I'm stumped. Why would libssh2_channel_free()
fail and forces this to be done? */
if (tmp == session->channels.head) { if (tmp == session->channels.head) {
/* channel_free couldn't do it's job, perform a messy cleanup */ /* channel_free couldn't do it's job, perform a messy cleanup */
tmp = session->channels.head; tmp = session->channels.head;
@@ -728,17 +715,17 @@ session_free(LIBSSH2_SESSION *session)
/* reverse linking isn't important here, we're killing the /* reverse linking isn't important here, we're killing the
* structure */ * structure */
} }
#endif
} }
session->state = libssh2_NB_state_sent; session->state = libssh2_NB_state_sent;
} }
if (session->state == libssh2_NB_state_sent) { if (session->state == libssh2_NB_state_sent) {
while (session->listeners) { while ((l = _libssh2_list_first(&session->listeners))) {
rc = libssh2_channel_forward_cancel(session->listeners); rc = libssh2_channel_forward_cancel(l);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN)
return PACKET_EAGAIN; return rc;
}
} }
session->state = libssh2_NB_state_sent1; session->state = libssh2_NB_state_sent1;
@@ -908,16 +895,14 @@ session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, session->err_msg); LIBSSH2_FREE(session, session->err_msg);
} }
/* Cleanup any remaining packets */ /* Cleanup all remaining packets */
while (session->packets.head) { while ((pkg = _libssh2_list_first(&session->packets))) {
LIBSSH2_PACKET *tmp = session->packets.head; /* unlink the node */
_libssh2_list_remove(&pkg->node);
/* unlink */
session->packets.head = tmp->next;
/* free */ /* free */
LIBSSH2_FREE(session, tmp->data); LIBSSH2_FREE(session, pkg->data);
LIBSSH2_FREE(session, tmp); LIBSSH2_FREE(session, pkg);
} }
if(session->socket_prev_blockstate) if(session->socket_prev_blockstate)
@@ -1007,7 +992,7 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
rc = _libssh2_transport_write(session, session->disconnect_data, rc = _libssh2_transport_write(session, session->disconnect_data,
session->disconnect_data_len); session->disconnect_data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
LIBSSH2_FREE(session, session->disconnect_data); LIBSSH2_FREE(session, session->disconnect_data);
@@ -1245,7 +1230,7 @@ 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_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
while (packet) { while (packet) {
if ( channel->local.id == _libssh2_ntohu32(packet->data + 1)) { if ( channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
@@ -1259,7 +1244,7 @@ libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
} }
/* else - no data of any type is ready to be read */ /* else - no data of any type is ready to be read */
} }
packet = packet->next; packet = _libssh2_list_next(&packet->node);
} }
return 0; return 0;
@@ -1285,7 +1270,7 @@ poll_channel_write(LIBSSH2_CHANNEL * channel)
static inline int static inline int
poll_listener_queued(LIBSSH2_LISTENER * listener) poll_listener_queued(LIBSSH2_LISTENER * listener)
{ {
return listener->queue ? 1 : 0; return _libssh2_list_first(&listener->queue) ? 1 : 0;
} }
/* /*
@@ -1346,7 +1331,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
} }
#elif defined(HAVE_SELECT) #elif defined(HAVE_SELECT)
LIBSSH2_SESSION *session = NULL; LIBSSH2_SESSION *session = NULL;
int maxfd = 0; libssh2_socket_t maxfd = 0;
fd_set rfds, wfds; fd_set rfds, wfds;
struct timeval tv; struct timeval tv;
@@ -1456,8 +1441,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
/* No connections known of yet */ /* No connections known of yet */
fds[i].revents |= fds[i].revents |=
poll_listener_queued(fds[i].fd. poll_listener_queued(fds[i].fd. listener) ?
listener) ?
LIBSSH2_POLLFD_POLLIN : 0; LIBSSH2_POLLFD_POLLIN : 0;
} }
if (fds[i].fd.listener->session->socket_state == if (fds[i].fd.listener->session->socket_state ==

View File

@@ -124,22 +124,15 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
if (!packet) { if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate datablock for SFTP packet", 0); "Unable to allocate datablock for SFTP packet", 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
memset(packet, 0, sizeof(LIBSSH2_PACKET)); memset(packet, 0, sizeof(LIBSSH2_PACKET));
packet->data = data; packet->data = data;
packet->data_len = data_len; packet->data_len = data_len;
packet->data_head = 5; packet->data_head = 5;
packet->brigade = &sftp->packets;
packet->next = NULL; _libssh2_list_add(&sftp->packets, &packet->node);
packet->prev = sftp->packets.tail;
if (packet->prev) {
packet->prev->next = packet;
} else {
sftp->packets.head = packet;
}
sftp->packets.tail = packet;
return 0; return 0;
} }
@@ -174,17 +167,17 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
"partial read cont, len: %lu", packet_len); "partial read cont, len: %lu", packet_len);
} }
else { else {
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4); rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
else if (4 != rc) { else if (4 != rc) {
/* TODO: this is stupid since we can in fact get 1-3 bytes in a /* TODO: this is stupid since we can in fact get 1-3 bytes in a
legitimate working case as well if the connection happens to be legitimate working case as well if the connection happens to be
super slow or something */ super slow or something */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Timeout waiting for FXP packet", 0); "Read part of packet", 0);
return -1; return LIBSSH2_ERROR_CHANNEL_FAILURE;
} }
packet_len = _libssh2_ntohu32(buffer); packet_len = _libssh2_ntohu32(buffer);
@@ -193,14 +186,14 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
if (packet_len > LIBSSH2_SFTP_PACKET_MAXLEN) { if (packet_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
"SFTP packet too large", 0); "SFTP packet too large", 0);
return -1; return LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED;
} }
packet = LIBSSH2_ALLOC(session, packet_len); packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) { if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate SFTP packet", 0); "Unable to allocate SFTP packet", 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
packet_received = 0; packet_received = 0;
@@ -209,7 +202,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
/* Read as much of the packet as we can */ /* Read as much of the packet as we can */
while (packet_len > packet_received) { while (packet_len > packet_received) {
bytes_received = bytes_received =
libssh2_channel_read_ex(channel, 0, _libssh2_channel_read(channel, 0,
(char *) packet + packet_received, (char *) packet + packet_received,
packet_len - packet_received); packet_len - packet_received);
@@ -223,20 +216,21 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
sftp->partial_received = packet_received; sftp->partial_received = packet_received;
packet = NULL; packet = NULL;
return PACKET_EAGAIN; return bytes_received;
} }
else if (bytes_received < 0) { else if (bytes_received < 0) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Receive error waiting for SFTP packet", 0); "Receive error waiting for SFTP packet", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
return -1; return bytes_received;
} }
packet_received += bytes_received; packet_received += bytes_received;
} }
if (sftp_packet_add(sftp, packet, packet_len)) { rc = sftp_packet_add(sftp, packet, packet_len);
if (rc) {
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
return -1; return rc;
} }
return packet[0]; return packet[0];
@@ -253,7 +247,7 @@ sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
unsigned long *data_len) unsigned long *data_len)
{ {
LIBSSH2_SESSION *session = sftp->channel->session; LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet = sftp->packets.head; LIBSSH2_PACKET *packet = _libssh2_list_first(&sftp->packets);
unsigned char match_buf[5]; unsigned char match_buf[5];
int match_len; int match_len;
@@ -277,24 +271,13 @@ sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
*data_len = packet->data_len; *data_len = packet->data_len;
/* unlink and free this struct */ /* unlink and free this struct */
if (packet->prev) { _libssh2_list_remove(&packet->node);
packet->prev->next = packet->next;
} else {
sftp->packets.head = packet->next;
}
if (packet->next) {
packet->next->prev = packet->prev;
} else {
sftp->packets.tail = packet->prev;
}
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
return 0; return 0;
} }
/* check next struct in the list */ /* check next struct in the list */
packet = packet->next; packet = _libssh2_list_next(&packet->node);
} }
return -1; return -1;
} }
@@ -323,7 +306,7 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
ret = sftp_packet_read(sftp); ret = sftp_packet_read(sftp);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return ret;
} else if (ret <= 0) { } else if (ret <= 0) {
return -1; return -1;
} }
@@ -338,7 +321,7 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
} }
/* Only reached if the socket died */ /* Only reached if the socket died */
return -1; return LIBSSH2_ERROR_SOCKET_DISCONNECT;
} }
/* sftp_packet_requirev /* sftp_packet_requirev
@@ -385,7 +368,7 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
return PACKET_TIMEOUT; return PACKET_TIMEOUT;
} }
else if (ret == PACKET_EAGAIN) { else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return ret;
} }
} }
} }
@@ -556,8 +539,8 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
* as the SFTP session is created they are cleared and can thus be * as the SFTP session is created they are cleared and can thus be
* re-used again to allow any amount of SFTP handles per sessions. * re-used again to allow any amount of SFTP handles per sessions.
* *
* Note that you MUST NOT try to call libssh2_sftp_init() to get * Note that you MUST NOT try to call libssh2_sftp_init() again to get
* another handle until the previous one has finished and either * another handle until the previous call has finished and either
* succesffully made a handle or failed and returned error (not * succesffully made a handle or failed and returned error (not
* including *EAGAIN). * including *EAGAIN).
*/ */
@@ -715,6 +698,8 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_sftp = NULL; session->sftpInit_sftp = NULL;
session->sftpInit_channel = NULL; session->sftpInit_channel = NULL;
_libssh2_list_init(&sftp_handle->sftp_handles);
return sftp_handle; return sftp_handle;
sftp_init_error: sftp_init_error:
@@ -798,6 +783,9 @@ sftp_shutdown(LIBSSH2_SFTP *sftp)
sftp->symlink_packet = NULL; sftp->symlink_packet = NULL;
} }
/* TODO: We should consider walking over the sftp_handles list and kill
* any remaining sftp handles ... */
rc = _libssh2_channel_free(sftp->channel); rc = _libssh2_channel_free(sftp->channel);
return rc; return rc;
@@ -810,8 +798,7 @@ LIBSSH2_API int
libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp) libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp)
{ {
int rc; int rc;
BLOCK_ADJUST(rc, sftp->channel->session, BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp));
sftp_shutdown(sftp));
return rc; return rc;
} }
@@ -920,7 +907,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
return NULL; return NULL;
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, rc,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
sftp->open_state = libssh2_NB_state_idle; sftp->open_state = libssh2_NB_state_idle;
return NULL; return NULL;
@@ -985,12 +972,10 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
memcpy(fp->handle, data + 9, fp->handle_len); memcpy(fp->handle, data + 9, fp->handle_len);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
/* Link the file and the sftp session together */ /* add this file handle to the list kept in the sftp session */
fp->next = sftp->handles; _libssh2_list_add(&sftp->sftp_handles, &fp->node);
if (fp->next) {
fp->next->prev = fp; fp->sftp = sftp; /* point to the parent struct */
}
fp->sftp = sftp;
fp->u.file.offset = 0; fp->u.file.offset = 0;
@@ -1106,7 +1091,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
sftp->read_packet = packet; sftp->read_packet = packet;
sftp->read_request_id = request_id; sftp->read_request_id = request_id;
sftp->read_total_read = total_read; sftp->read_total_read = total_read;
return PACKET_EAGAIN; return retcode;
} else if (packet_len != retcode) { } else if (packet_len != retcode) {
/* TODO: a partial write is not a critical error when in /* TODO: a partial write is not a critical error when in
non-blocking mode! */ non-blocking mode! */
@@ -1127,9 +1112,11 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
sftp_packet_requirev(sftp, 2, read_responses, sftp_packet_requirev(sftp, 2, read_responses,
request_id, &data, &data_len); request_id, &data, &data_len);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN; libssh2_error(session, retcode,
"Would block waiting for status message", 0);
return retcode;
} else if (retcode) { } else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, retcode,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle; sftp->read_state = libssh2_NB_state_idle;
@@ -1307,7 +1294,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
(char *) sftp->readdir_packet, (char *) sftp->readdir_packet,
packet_len); packet_len);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN; return retcode;
} }
else if (packet_len != retcode) { else if (packet_len != retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -1329,7 +1316,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
sftp->readdir_request_id, &data, sftp->readdir_request_id, &data,
&data_len); &data_len);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN; return retcode;
} else if (retcode) { } else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
@@ -1418,7 +1405,8 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
/* /*
* sftp_write * sftp_write
* *
* Write data to an SFTP handle * Write data to an SFTP handle. Returns the number of bytes written, or
* a negative error code.
*/ */
static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
size_t count) size_t count)
@@ -1449,7 +1437,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
if (!sftp->write_packet) { if (!sftp->write_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_WRITE", 0); "Unable to allocate memory for FXP_WRITE", 0);
return -1; return LIBSSH2_ERROR_ALLOC;
} }
_libssh2_htonu32(s, packet_len - 4); _libssh2_htonu32(s, packet_len - 4);
s += 4; s += 4;
@@ -1474,17 +1462,13 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
if (sftp->write_state == libssh2_NB_state_created) { if (sftp->write_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, (char *)sftp->write_packet, rc = _libssh2_channel_write(channel, 0, (char *)sftp->write_packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if(rc < 0) {
return PACKET_EAGAIN; /* error */
}
else if(rc < 0) {
/* an actual error */
return rc; return rc;
} }
else if(0 == rc) { else if(0 == rc) {
/* an actual error */ /* nothing sent is an error */
fprintf(stderr, "WEIRDNESS\n"); return LIBSSH2_ERROR_SOCKET_SEND;
return -1;
} }
else if (packet_len != rc) { else if (packet_len != rc) {
return rc; return rc;
@@ -1497,12 +1481,13 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->write_request_id, &data, &data_len); sftp->write_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { }
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, else if (rc) {
libssh2_error(session, rc,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
sftp->write_state = libssh2_NB_state_idle; sftp->write_state = libssh2_NB_state_idle;
return -1; return rc;
} }
sftp->write_state = libssh2_NB_state_idle; sftp->write_state = libssh2_NB_state_idle;
@@ -1518,7 +1503,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
0); 0);
sftp->last_errno = retcode; sftp->last_errno = retcode;
return -1; return LIBSSH2_ERROR_SFTP_PROTOCOL;
} }
/* libssh2_sftp_write /* libssh2_sftp_write
@@ -1587,7 +1572,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->fstat_packet, rc = _libssh2_channel_write(channel, 0, (char *) sftp->fstat_packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
(setstat ? "Unable to send FXP_FSETSTAT" (setstat ? "Unable to send FXP_FSETSTAT"
@@ -1607,7 +1592,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
sftp->fstat_request_id, &data, sftp->fstat_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
@@ -1733,7 +1718,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
rc = _libssh2_channel_write(channel, 0, (char *) handle->close_packet, rc = _libssh2_channel_write(channel, 0, (char *) handle->close_packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_CLOSE command", 0); "Unable to send FXP_CLOSE command", 0);
@@ -1753,7 +1738,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
handle->close_request_id, &data, handle->close_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
@@ -1775,12 +1760,8 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
return -1; return -1;
} }
if (handle == sftp->handles) { /* remove this handle from the parent's list */
sftp->handles = handle->next; _libssh2_list_remove(&handle->node);
}
if (handle->next) {
handle->next->prev = NULL;
}
if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR)
&& handle->u.dir.names_left) { && handle->u.dir.names_left) {
@@ -1849,7 +1830,7 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->unlink_packet, rc = _libssh2_channel_write(channel, 0, (char *) sftp->unlink_packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_REMOVE command", 0); "Unable to send FXP_REMOVE command", 0);
@@ -1868,7 +1849,7 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
sftp->unlink_request_id, &data, sftp->unlink_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
@@ -1972,7 +1953,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->rename_packet, rc = _libssh2_channel_write(channel, 0, (char *) sftp->rename_packet,
sftp->rename_s - sftp->rename_packet); sftp->rename_s - sftp->rename_packet);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_RENAME command", 0); "Unable to send FXP_RENAME command", 0);
@@ -1991,7 +1972,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
sftp->rename_request_id, &data, sftp->rename_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
@@ -2103,7 +2084,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) packet, packet_len); rc = _libssh2_channel_write(channel, 0, (char *) packet, packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
sftp->mkdir_packet = packet; sftp->mkdir_packet = packet;
return PACKET_EAGAIN; return rc;
} }
if (packet_len != rc) { if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -2120,7 +2101,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id, rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id,
&data, &data_len); &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
@@ -2201,7 +2182,7 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->rmdir_packet, rc = _libssh2_channel_write(channel, 0, (char *) sftp->rmdir_packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_RMDIR command", 0); "Unable to send FXP_RMDIR command", 0);
@@ -2219,7 +2200,7 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len); sftp->rmdir_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
@@ -2320,7 +2301,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->stat_packet, rc = _libssh2_channel_write(channel, 0, (char *) sftp->stat_packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send STAT/LSTAT/SETSTAT command", 0); "Unable to send STAT/LSTAT/SETSTAT command", 0);
@@ -2338,7 +2319,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_requirev(sftp, 2, stat_responses, rc = sftp_packet_requirev(sftp, 2, stat_responses,
sftp->stat_request_id, &data, &data_len); sftp->stat_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
@@ -2460,7 +2441,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
rc = _libssh2_channel_write(channel, 0, (char *) sftp->symlink_packet, rc = _libssh2_channel_write(channel, 0, (char *) sftp->symlink_packet,
packet_len); packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send SYMLINK/READLINK command", 0); "Unable to send SYMLINK/READLINK command", 0);
@@ -2479,7 +2460,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
sftp->symlink_request_id, &data, sftp->symlink_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,

View File

@@ -95,10 +95,10 @@ debugdump(LIBSSH2_SESSION * session,
/* decrypt() decrypts 'len' bytes from 'source' to 'dest'. /* decrypt() decrypts 'len' bytes from 'source' to 'dest'.
* *
* returns PACKET_NONE on success and PACKET_FAIL on failure * returns 0 on success and negative on failure
*/ */
static libssh2pack_t static int
decrypt(LIBSSH2_SESSION * session, unsigned char *source, decrypt(LIBSSH2_SESSION * session, unsigned char *source,
unsigned char *dest, int len) unsigned char *dest, int len)
{ {
@@ -134,7 +134,7 @@ decrypt(LIBSSH2_SESSION * session, unsigned char *source,
* fullpacket() gets called when a full packet has been received and properly * fullpacket() gets called when a full packet has been received and properly
* collected. * collected.
*/ */
static libssh2pack_t static int
fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
{ {
unsigned char macbuf[MAX_MACSIZE]; unsigned char macbuf[MAX_MACSIZE];
@@ -232,11 +232,8 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
rc = _libssh2_packet_add(session, p->payload, rc = _libssh2_packet_add(session, p->payload,
session->fullpacket_payload_len, session->fullpacket_payload_len,
session->fullpacket_macstate); session->fullpacket_macstate);
if (rc == PACKET_EAGAIN) { if (rc)
return PACKET_EAGAIN; return rc;
} else if (rc < 0) {
return PACKET_FAIL;
}
} }
session->fullpacket_state = libssh2_NB_state_idle; session->fullpacket_state = libssh2_NB_state_idle;
@@ -248,22 +245,21 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
/* /*
* _libssh2_transport_read * _libssh2_transport_read
* *
* Collect a packet into the input brigade block only controls whether or not * Collect a packet into the input queue.
* to wait for a packet to start.
* *
* Returns packet type added to input brigade (PACKET_NONE if nothing added), * Returns packet type added to input queue (0 if nothing added), or a
* or PACKET_FAIL on failure and PACKET_EAGAIN if it couldn't process a full * negative error number.
* packet.
*/ */
/* /*
* This function reads the binary stream as specified in chapter 6 of RFC4253 * This function reads the binary stream as specified in chapter 6 of RFC4253
* "The Secure Shell (SSH) Transport Layer Protocol" * "The Secure Shell (SSH) Transport Layer Protocol"
*
* DOES NOT call libssh2_error() for ANY error case.
*/ */
libssh2pack_t int _libssh2_transport_read(LIBSSH2_SESSION * session)
_libssh2_transport_read(LIBSSH2_SESSION * session)
{ {
libssh2pack_t rc = -1; int rc = LIBSSH2_ERROR_SOCKET_NONE;
struct transportpacket *p = &session->packet; struct transportpacket *p = &session->packet;
int remainbuf; int remainbuf;
int remainpack; int remainpack;
@@ -272,7 +268,6 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
unsigned char block[MAX_BLOCKSIZE]; unsigned char block[MAX_BLOCKSIZE];
int blocksize; int blocksize;
int encrypted = 1; int encrypted = 1;
int status;
/* default clear the bit */ /* default clear the bit */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
@@ -297,16 +292,9 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
*/ */
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the" _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the"
" key re-exchange"); " key re-exchange");
status = libssh2_kex_exchange(session, 1, &session->startup_key_state); rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
if (status == PACKET_EAGAIN) { if (rc)
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, return rc;
"Would block exchanging encryption keys", 0);
return PACKET_EAGAIN;
} else if (status) {
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
"Unable to exchange encryption keys",0);
return LIBSSH2_ERROR_KEX_FAILURE;
}
} }
/* /*
@@ -371,7 +359,7 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
/* check if this is due to EAGAIN and return the special /* check if this is due to EAGAIN and return the special
return code if so, error out normally otherwise */ return code if so, error out normally otherwise */
if ((nread < 0) && (errno == EAGAIN)) { if ((nread < 0) && (errno == EAGAIN)) {
session->socket_block_directions = session->socket_block_directions |=
LIBSSH2_SESSION_BLOCK_INBOUND; LIBSSH2_SESSION_BLOCK_INBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -400,6 +388,8 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
check is only done for the initial block since once we have check is only done for the initial block since once we have
got the start of a block we can in fact deal with fractions got the start of a block we can in fact deal with fractions
*/ */
session->socket_block_directions |=
LIBSSH2_SESSION_BLOCK_INBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -570,7 +560,7 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
session->readPack_state = libssh2_NB_state_jump1; session->readPack_state = libssh2_NB_state_jump1;
} }
return PACKET_EAGAIN; return rc;
} }
p->total_num = 0; /* no packet buffer available */ p->total_num = 0; /* no packet buffer available */
@@ -582,7 +572,7 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
return PACKET_FAIL; /* we never reach this point */ return PACKET_FAIL; /* we never reach this point */
} }
static libssh2pack_t static int
send_existing(LIBSSH2_SESSION * session, unsigned char *data, send_existing(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len, ssize_t * ret) unsigned long data_len, ssize_t * ret)
{ {
@@ -630,13 +620,13 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
/* send failure! */ /* send failure! */
return PACKET_FAIL; return PACKET_FAIL;
} }
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND; session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
p->osent += rc; /* we sent away this much data */ p->osent += rc; /* we sent away this much data */
return PACKET_NONE; return p->osent < data_len ? PACKET_EAGAIN : PACKET_NONE;
} }
/* /*
@@ -653,6 +643,8 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
* NOTE: this function does not verify that 'data_len' is less than ~35000 * 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. * which is what all implementations should support at least as packet size.
* (RFC4253 section 6.1) * (RFC4253 section 6.1)
*
* This function DOES not call libssh2_error() on any errors.
*/ */
int int
_libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
@@ -673,7 +665,7 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
int encrypted; int encrypted;
int i; int i;
ssize_t ret; ssize_t ret;
libssh2pack_t rc; int rc;
unsigned char *orgdata = data; unsigned char *orgdata = data;
unsigned long orgdata_len = data_len; unsigned long orgdata_len = data_len;
@@ -791,7 +783,7 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
if (ret != total_length) { if (ret != total_length) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) { if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
/* the whole packet could not be sent, save the rest */ /* the whole packet could not be sent, save the rest */
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND; session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
p->odata = orgdata; p->odata = orgdata;
p->olen = orgdata_len; p->olen = orgdata_len;
p->osent = (ret == -1) ? 0 : ret; p->osent = (ret == -1) ? 0 : ret;

View File

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

View File

@@ -266,7 +266,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
rc = _libssh2_transport_write(session, session->userauth_pswd_data, rc = _libssh2_transport_write(session, session->userauth_pswd_data,
session->userauth_pswd_data_len); session->userauth_pswd_data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-password request", 0); "Unable to send userauth-password request", 0);
@@ -294,7 +294,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
&session-> &session->
userauth_pswd_packet_requirev_state); userauth_pswd_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
session->userauth_pswd_state = libssh2_NB_state_idle; session->userauth_pswd_state = libssh2_NB_state_idle;
return -1; return -1;
@@ -402,7 +402,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
session-> session->
userauth_pswd_data_len); userauth_pswd_data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-password-change request", "Unable to send userauth-password-change request",
@@ -808,7 +808,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
session->userauth_host_s - session->userauth_host_s -
session->userauth_host_packet); session->userauth_host_packet);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-hostbased request", 0); "Unable to send userauth-hostbased request", 0);
@@ -831,7 +831,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
&session-> &session->
userauth_host_packet_requirev_state); userauth_host_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
session->userauth_host_state = libssh2_NB_state_idle; session->userauth_host_state = libssh2_NB_state_idle;
@@ -987,7 +987,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
rc = _libssh2_transport_write(session, session->userauth_pblc_packet, rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
session->userauth_pblc_packet_len); session->userauth_pblc_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-publickey request", 0); "Unable to send userauth-publickey request", 0);
@@ -1017,7 +1017,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
&session-> &session->
userauth_pblc_packet_requirev_state); userauth_pblc_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
LIBSSH2_FREE(session, session->userauth_pblc_packet); LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL; session->userauth_pblc_packet = NULL;
@@ -1163,7 +1163,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
session->userauth_pblc_s - session->userauth_pblc_s -
session->userauth_pblc_packet); session->userauth_pblc_packet);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-publickey request", 0); "Unable to send userauth-publickey request", 0);
@@ -1186,7 +1186,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
&session->userauth_pblc_data_len, 0, NULL, 0, &session->userauth_pblc_data_len, 0, NULL, 0,
&session->userauth_pblc_packet_requirev_state); &session->userauth_pblc_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
session->userauth_pblc_state = libssh2_NB_state_idle; session->userauth_pblc_state = libssh2_NB_state_idle;
return -1; return -1;
@@ -1326,7 +1326,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
rc = _libssh2_transport_write(session, session->userauth_kybd_data, rc = _libssh2_transport_write(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len); session->userauth_kybd_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send keyboard-interactive request", 0); "Unable to send keyboard-interactive request", 0);
@@ -1350,7 +1350,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
&session-> &session->
userauth_kybd_packet_requirev_state); userauth_kybd_packet_requirev_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} else if (rc) { } else if (rc) {
session->userauth_kybd_state = libssh2_NB_state_idle; session->userauth_kybd_state = libssh2_NB_state_idle;
return -1; return -1;
@@ -1527,7 +1527,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
rc = _libssh2_transport_write(session, session->userauth_kybd_data, rc = _libssh2_transport_write(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len); session->userauth_kybd_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return rc;
} }
if (rc) { if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,

View File

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

7
tests/.gitignore vendored
View File

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

View File

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

View File

@@ -10,12 +10,12 @@
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# ifdef HAVE_UNISTD_H # ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif

View File

@@ -9,15 +9,15 @@ srcdir=${srcdir:-$PWD}
SSHD=${SSHD:-/usr/sbin/sshd} SSHD=${SSHD:-/usr/sbin/sshd}
cmd="./ssh2${EXEEXT}" cmd="./ssh2${EXEEXT}"
srcdir=`cd $srcdir; pwd` srcdir=`cd "$srcdir"; pwd`
PRIVKEY=$srcdir/etc/user PRIVKEY=$srcdir/etc/user
export PRIVKEY export PRIVKEY
PUBKEY=$srcdir/etc/user.pub PUBKEY=$srcdir/etc/user.pub
export PUBKEY export PUBKEY
chmod go-r $srcdir/etc/host* chmod go-rwx "$srcdir"/etc/host*
$SSHD -f /dev/null -h $srcdir/etc/host \ $SSHD -f /dev/null -h "$srcdir"/etc/host \
-o 'Port 4711' \ -o 'Port 4711' \
-o 'Protocol 2' \ -o 'Protocol 2' \
-o "AuthorizedKeysFile $srcdir/etc/user.pub" \ -o "AuthorizedKeysFile $srcdir/etc/user.pub" \

View File

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