Compare commits
96 Commits
RELEASE.1.
...
libssh2-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
291ac7d433 | ||
![]() |
cccaa868f5 | ||
![]() |
08b0183d8e | ||
![]() |
231a97a95f | ||
![]() |
6c46bb4719 | ||
![]() |
8a0ba6f5f6 | ||
![]() |
143720e922 | ||
![]() |
0cad4c08e9 | ||
![]() |
dd38d0a929 | ||
![]() |
ba57d5ae3c | ||
![]() |
5ac67d1268 | ||
![]() |
6f4463e81f | ||
![]() |
690c3d42db | ||
![]() |
2b780fa02d | ||
![]() |
b363c84366 | ||
![]() |
35a9d4bc62 | ||
![]() |
686db51284 | ||
![]() |
2361f50e9a | ||
![]() |
e5d76b5468 | ||
![]() |
7eead1461b | ||
![]() |
c0d032a45c | ||
![]() |
0751067c2f | ||
![]() |
acbdbb8914 | ||
![]() |
bea1beb4fd | ||
![]() |
5b599fbf40 | ||
![]() |
75bec57c94 | ||
![]() |
b9b5e5fea5 | ||
![]() |
91bca481b5 | ||
![]() |
9a6ce012cc | ||
![]() |
a4c3f0d0a3 | ||
![]() |
320450201a | ||
![]() |
9f5c1caa81 | ||
![]() |
8b46528c04 | ||
![]() |
aeaf07576e | ||
![]() |
c01e147a40 | ||
![]() |
32080def94 | ||
![]() |
da1230b35b | ||
![]() |
d440995a80 | ||
![]() |
2a142a6524 | ||
![]() |
afcf63b433 | ||
![]() |
bc4c258842 | ||
![]() |
e52a1057fd | ||
![]() |
517909d37a | ||
![]() |
8cd76af353 | ||
![]() |
1d31dadc1e | ||
![]() |
2e990194ab | ||
![]() |
1afbbf4507 | ||
![]() |
82bdd12a8b | ||
![]() |
4df48aef41 | ||
![]() |
bc28d0146d | ||
![]() |
8b1ec197b2 | ||
![]() |
2436a4de60 | ||
![]() |
22014f074b | ||
![]() |
f35dbff3c4 | ||
![]() |
703fbd9d11 | ||
![]() |
5207690edf | ||
![]() |
eaa95e0331 | ||
![]() |
d965dda027 | ||
![]() |
bf884488ae | ||
![]() |
28b08e0b4d | ||
![]() |
1ffa2cb519 | ||
![]() |
279d6dd82a | ||
![]() |
49192598d2 | ||
![]() |
6b7c19ec26 | ||
![]() |
160e5aa763 | ||
![]() |
42e9f02025 | ||
![]() |
5a162ad9f8 | ||
![]() |
6ff83eab1b | ||
![]() |
8df3222d91 | ||
![]() |
0357ce6c48 | ||
![]() |
c5f335ad4f | ||
![]() |
fdc043e7b1 | ||
![]() |
fdaa5ad5b4 | ||
![]() |
f1f49c3cce | ||
![]() |
ad13de92d4 | ||
![]() |
b755f3eb10 | ||
![]() |
b95fe985af | ||
![]() |
035cb24fa0 | ||
![]() |
18e03739be | ||
![]() |
e367e1ad4e | ||
![]() |
f7149d1830 | ||
![]() |
042b545247 | ||
![]() |
4490c6b434 | ||
![]() |
d3542e6f7d | ||
![]() |
0cee15dc0c | ||
![]() |
4b991b232d | ||
![]() |
4bc1b8a1d7 | ||
![]() |
755e213ae6 | ||
![]() |
9412588373 | ||
![]() |
9f104cd883 | ||
![]() |
6409bb53ba | ||
![]() |
c306119dd6 | ||
![]() |
2b8038e175 | ||
![]() |
2a39b32b1a | ||
![]() |
e63cbd907f | ||
![]() |
cb66b7b94f |
32
.gitignore
vendored
Normal file
32
.gitignore
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
.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
|
||||||
|
*.o
|
||||||
|
*.lo
|
||||||
|
*.la
|
||||||
|
mkinstalldirs
|
51
AUTHORS
51
AUTHORS
@@ -1,15 +1,40 @@
|
|||||||
* Sara Golemon: Author / Project Manager
|
libssh2 is the result of many friendly people. This list is an attempt to
|
||||||
|
mention all contributors. If we've missed anyone, tell us!
|
||||||
|
|
||||||
* Daniel Stenberg: Co-maintainer
|
This list of names is a-z sorted.
|
||||||
|
|
||||||
* James Housleys: Nonblocking conversion
|
Adam Gobiowski
|
||||||
|
Alexander Holyapin
|
||||||
* Simon Josefsson: libgcrypt support
|
Alexander Lamaison
|
||||||
|
Bjorn Stenborg
|
||||||
* Mikhail Gusarov: Keyboard Interactive Authentication
|
Carlo Bramini
|
||||||
|
Dan Casey
|
||||||
* Wez Furlong & Edink Kadribasic: Windows Port
|
Dan Fandrich
|
||||||
|
Daniel Stenberg
|
||||||
* Dan Fandrich: bug fixes, cleanups
|
David J Sullivan
|
||||||
|
David Robins
|
||||||
* Guenter Knauf: win32 work and more
|
Edink Kadribasic
|
||||||
|
Erik Brossler
|
||||||
|
Guenter Knauf
|
||||||
|
Heiner Steven
|
||||||
|
James Housleys
|
||||||
|
Jean-Louis Charton
|
||||||
|
Markus Moeller
|
||||||
|
Mike Protts
|
||||||
|
Mikhail Gusarov
|
||||||
|
Neil Gierman
|
||||||
|
Olivier Hervieu
|
||||||
|
Peter O'Gorman
|
||||||
|
Peter Stuge
|
||||||
|
Romain Bondue
|
||||||
|
Sara Golemon
|
||||||
|
Satish Mittal
|
||||||
|
Sean Peterson
|
||||||
|
Selcuk Gueney
|
||||||
|
Simon Hart
|
||||||
|
Simon Josefsson
|
||||||
|
Steven Ayre
|
||||||
|
Vincent Jaulin
|
||||||
|
Vlad Grachov
|
||||||
|
Wez Furlong
|
||||||
|
Yang Tse
|
||||||
|
3
COPYING
3
COPYING
@@ -1,5 +1,6 @@
|
|||||||
/* 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
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
10
HACKING
10
HACKING
@@ -20,13 +20,3 @@ libssh2 source code style guide:
|
|||||||
- use braces even for single-statement blocks
|
- use braces even for single-statement blocks
|
||||||
|
|
||||||
- keep source lines shorter than 80 columns
|
- keep source lines shorter than 80 columns
|
||||||
|
|
||||||
------------
|
|
||||||
|
|
||||||
Older libssh2 code that still hasn't quite transitioned to the above
|
|
||||||
mentioned style, used a different style:
|
|
||||||
|
|
||||||
- indented with tabs (only)
|
|
||||||
|
|
||||||
- no line length limits
|
|
||||||
|
|
||||||
|
82
Makefile.am
82
Makefile.am
@@ -1,3 +1,5 @@
|
|||||||
|
AUTOMAKE_OPTIONS = foreign nostdinc
|
||||||
|
|
||||||
SUBDIRS = src example tests docs
|
SUBDIRS = src example tests docs
|
||||||
|
|
||||||
include_HEADERS = \
|
include_HEADERS = \
|
||||||
@@ -11,20 +13,26 @@ NETWAREFILES = nw/keepscreen.c \
|
|||||||
nw/nwlib.c \
|
nw/nwlib.c \
|
||||||
nw/test/Makefile.netware
|
nw/test/Makefile.netware
|
||||||
|
|
||||||
WIN32FILES = win32/libssh2_dll.dsp win32/libssh2.dsw win32/Makefile.win32 \
|
DSP = win32/libssh2.dsp
|
||||||
win32/config.mk win32/Makefile win32/test/Makefile.win32 win32/libssh2_lib.dsp \
|
VCPROJ = win32/libssh2.vcproj
|
||||||
win32/libssh2_config.h win32/tests.dsp win32/rules.mk
|
|
||||||
|
#Need to include $(VCPROJ) to CLEANFILES and WIN32FILES when I get a proper vc8proj.head|foot
|
||||||
|
CLEANFILES = $(DSP)
|
||||||
|
|
||||||
|
WIN32FILES = win32/Makefile.win32 win32/libssh2.dsw \
|
||||||
|
win32/config.mk win32/Makefile win32/test/Makefile.win32 \
|
||||||
|
win32/libssh2_config.h win32/tests.dsp win32/rules.mk $(DSP) \
|
||||||
|
win32/msvcproj.head win32/msvcproj.foot
|
||||||
|
|
||||||
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \
|
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \
|
||||||
maketgz NMakefile TODO
|
maketgz NMakefile TODO RELEASE-NOTES
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
.PHONY: ChangeLog
|
.PHONY: ChangeLog
|
||||||
ChangeLog:
|
ChangeLog:
|
||||||
if test -f .cvsusers; then \
|
echo "see NEWS" > ./ChangeLog
|
||||||
cvs2cl --utc --fsf --FSF --usermap .cvsusers -I ChangeLog -I .cvs; \
|
CLEANFILES += ChangeLog
|
||||||
fi
|
|
||||||
|
|
||||||
dist-hook:
|
dist-hook:
|
||||||
rm -rf $(top_builddir)/tests/log
|
rm -rf $(top_builddir)/tests/log
|
||||||
@@ -57,3 +65,63 @@ gen-coverage:
|
|||||||
--title "$(PACKAGE_NAME)"
|
--title "$(PACKAGE_NAME)"
|
||||||
|
|
||||||
coverage: init-coverage build-coverage gen-coverage
|
coverage: init-coverage build-coverage gen-coverage
|
||||||
|
|
||||||
|
# DSP/VCPROJ generation adapted from libcurl
|
||||||
|
# Makefile.inc provides the CSOURCES and HHEADERS defines
|
||||||
|
include Makefile.inc
|
||||||
|
|
||||||
|
WIN32SOURCES = $(CSOURCES)
|
||||||
|
WIN32HEADERS = $(HHEADERS) libssh2_config.h
|
||||||
|
|
||||||
|
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
|
||||||
|
echo "creating $(DSP)"
|
||||||
|
@(cp $(srcdir)/win32/msvcproj.head $(DSP); \
|
||||||
|
echo "# Begin Group \"Source Files\"" $(DSPOUT); \
|
||||||
|
echo "" $(DSPOUT); \
|
||||||
|
echo "# PROP Default_Filter \"cpp;c;cxx\"" $(DSPOUT); \
|
||||||
|
win32_srcs='$(WIN32SOURCES)'; \
|
||||||
|
sorted_srcs=`for file in $$win32_srcs; do echo $$file; done | sort`; \
|
||||||
|
for file in $$sorted_srcs; do \
|
||||||
|
echo "# Begin Source File" $(DSPOUT); \
|
||||||
|
echo "" $(DSPOUT); \
|
||||||
|
echo "SOURCE=..\\src\\"$$file $(DSPOUT); \
|
||||||
|
echo "# End Source File" $(DSPOUT); \
|
||||||
|
done; \
|
||||||
|
echo "# End Group" $(DSPOUT); \
|
||||||
|
echo "# Begin Group \"Header Files\"" $(DSPOUT); \
|
||||||
|
echo "" $(DSPOUT); \
|
||||||
|
echo "# PROP Default_Filter \"h;hpp;hxx\"" $(DSPOUT); \
|
||||||
|
win32_hdrs='$(WIN32HEADERS)'; \
|
||||||
|
sorted_hdrs=`for file in $$win32_hdrs; do echo $$file; done | sort`; \
|
||||||
|
for file in $$sorted_hdrs; do \
|
||||||
|
echo "# Begin Source File" $(DSPOUT); \
|
||||||
|
echo "" $(DSPOUT); \
|
||||||
|
if [ "$$file" == "libssh2_config.h" ]; \
|
||||||
|
then \
|
||||||
|
echo "SOURCE=.\\"$$file $(DSPOUT); \
|
||||||
|
else \
|
||||||
|
echo "SOURCE=..\\src\\"$$file $(DSPOUT); \
|
||||||
|
fi; \
|
||||||
|
echo "# End Source File" $(DSPOUT); \
|
||||||
|
done; \
|
||||||
|
echo "# End Group" $(DSPOUT); \
|
||||||
|
cat $(srcdir)/win32/msvcproj.foot $(DSPOUT) )
|
||||||
|
|
||||||
|
$(VCPROJ): win32/vc8proj.head win32/vc8proj.foot Makefile.am
|
||||||
|
echo "creating $(VCPROJ)"
|
||||||
|
@(cp $(srcdir)/vc8proj.head $(VCPROJ); \
|
||||||
|
win32_srcs='$(WIN32SOURCES)'; \
|
||||||
|
sorted_srcs=`for file in $$win32_srcs; do echo $$file; done | sort`; \
|
||||||
|
for file in $$sorted_srcs; do \
|
||||||
|
echo "<File RelativePath=\""..\src\$$file"\"></File>" $(VCPROJOUT); \
|
||||||
|
done; \
|
||||||
|
echo "</Filter><Filter Name=\"Header Files\">" $(VCPROJOUT); \
|
||||||
|
win32_hdrs='$(WIN32HEADERS)'; \
|
||||||
|
sorted_hdrs=`for file in $$win32_hdrs; do echo $$file; done | sort`; \
|
||||||
|
for file in $$sorted_hdrs; do \
|
||||||
|
echo "<File RelativePath=\""..\src\$$file"\"></File>" $(VCPROJOUT); \
|
||||||
|
done; \
|
||||||
|
cat $(srcdir)/vc8proj.foot $(VCPROJOUT) )
|
||||||
|
11
Makefile.inc
Normal file
11
Makefile.inc
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
|
||||||
|
packet.c publickey.c scp.c session.c sftp.c userauth.c transport.c \
|
||||||
|
version.c knownhost.c
|
||||||
|
|
||||||
|
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
|
80
NEWS
80
NEWS
@@ -1,3 +1,77 @@
|
|||||||
|
Version 1.2 (August 10, 2009)
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
* (August 02 2009) Alexander Lamaison:
|
||||||
|
|
||||||
|
- changed _libssh2_rsa_new_private and _libssh2_rsa_new_private so that they
|
||||||
|
no longer use the OpenSSL functions that take a FILE* argument. Passing
|
||||||
|
CRT-created objects across a DLL boundary causes crashes on Windows of the
|
||||||
|
DLL and the client aren't linked to the exact same verison of the CRT. Now
|
||||||
|
we pass the keys as strings to avoid this issue.
|
||||||
|
|
||||||
|
* (May 29 2009) Daniel Stenberg:
|
||||||
|
|
||||||
|
- Updated the knownhost API and there are now 9 functions, and all of them
|
||||||
|
have man pages. The libssh2.h now defines HAVE_LIBSSH2_KNOWNHOST_API to
|
||||||
|
ease things for applications to check for the correct release before trying
|
||||||
|
to use it.
|
||||||
|
|
||||||
|
* (May 23 2009) Daniel Stenberg:
|
||||||
|
|
||||||
|
- Anonymous bug report #2795816 revealed that doing subsequent
|
||||||
|
libssh2_sftp_init() calls on the same session failed.
|
||||||
|
|
||||||
|
* (May 20 2009) Daniel Stenberg:
|
||||||
|
|
||||||
|
- made libssh2_sftp_write() properly deal with huge/any sized input buffers.
|
||||||
|
|
||||||
|
- fixed libssh2_channel_write_ex() to return the correct return code, and
|
||||||
|
deal with sending off huge buffers better
|
||||||
|
|
||||||
|
* (May 7 2009) Daniel Stenberg:
|
||||||
|
|
||||||
|
- linked list code. I got a bit tired of the fact that we don't have any
|
||||||
|
generic linked-list functions within libssh2 so I wrote up the first embryo
|
||||||
|
for one that I use for this new functionality. The plan would then be to
|
||||||
|
move all existing code that uses linked lists to use this new set.
|
||||||
|
|
||||||
|
- base64 encode. I had to add a base64 encoding function which was missing
|
||||||
|
in the code base so it helps to "bloat" my patch.
|
||||||
|
|
||||||
|
- The knownhost API is currently:
|
||||||
|
|
||||||
|
_init() - init a bundle of known hosts
|
||||||
|
_add() - add a known host
|
||||||
|
_del() - delete a known host
|
||||||
|
_free() - free an entire bundle of known hosts
|
||||||
|
_check() - check if a host+key is present in the bundle
|
||||||
|
|
||||||
|
The convenience function:
|
||||||
|
|
||||||
|
_parsefile() - reads a ~/.ssh/known_hosts file and add all entries to the
|
||||||
|
given bundle
|
||||||
|
|
||||||
|
- there's no docs other than some comments in the code/headers yet
|
||||||
|
|
||||||
|
- the patch includes changes to example/simple/ssh2_exec.c that makes use of
|
||||||
|
a few of these functions. Using that I've verified that the functions in
|
||||||
|
fact can verify my localhost's key agains my ~/.ssh/known_hosts file
|
||||||
|
|
||||||
|
* (Apr 30 2009) Daniel Stenberg:
|
||||||
|
|
||||||
|
Markus posted a bug report about a bad 0-return from libssh2_channel_read:
|
||||||
|
http://libssh2.haxx.se/mail/libssh2-devel-archive-2009-04/0076.shtml
|
||||||
|
|
||||||
|
And it was indeed a bad loop that terminated too early due to a receveived
|
||||||
|
close packet.
|
||||||
|
|
||||||
|
* (Apr 14 2009) Daniel Stenberg:
|
||||||
|
|
||||||
|
libssh2_poll() and libssh2_poll_channel_read() are now considered and
|
||||||
|
documented deprecated and they will be removed at next soname bump. It also
|
||||||
|
saves us from fixing some rather quirky bugs in libssh2_poll()...
|
||||||
|
|
||||||
|
|
||||||
Version 1.1 (April 2, 2009)
|
Version 1.1 (April 2, 2009)
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
@@ -209,7 +283,7 @@ This release would not have been possible without these friendly contributors:
|
|||||||
James Housley, Simon Josefsson, Dan Fandrich, Guenter Knauf and I too did
|
James Housley, Simon Josefsson, Dan Fandrich, Guenter Knauf and I too did
|
||||||
some poking. (Sorry if I forgot anyone I should've mentioned here.)
|
some poking. (Sorry if I forgot anyone I should've mentioned here.)
|
||||||
|
|
||||||
Of course we would have nothing without the great work by Sara Golemon that
|
Of course we would have nothing without the great work by Sara Golemon that
|
||||||
we're extending and building upon.
|
we're extending and building upon.
|
||||||
|
|
||||||
Version 0.15 (June 15 2007)
|
Version 0.15 (June 15 2007)
|
||||||
@@ -224,12 +298,12 @@ Version 0.15 (June 15 2007)
|
|||||||
int libssh2_publickey_shutdown()
|
int libssh2_publickey_shutdown()
|
||||||
ssize_t libssh2_channel_read_ex()
|
ssize_t libssh2_channel_read_ex()
|
||||||
ssize_t libssh2_channel_write_ex()
|
ssize_t libssh2_channel_write_ex()
|
||||||
|
|
||||||
Added functions:
|
Added functions:
|
||||||
libssh2_session_last_errno(), libssh2_channel_handle_extended_data2(),
|
libssh2_session_last_errno(), libssh2_channel_handle_extended_data2(),
|
||||||
libssh2_channel_wait_closed(), libssh2_channel_wait_eof(),
|
libssh2_channel_wait_closed(), libssh2_channel_wait_eof(),
|
||||||
libssh2_session_set_blocking()
|
libssh2_session_set_blocking()
|
||||||
|
|
||||||
Removed functions:
|
Removed functions:
|
||||||
libssh2_channel_readnb_ex(), libssh2_channel_writenb_ex(),
|
libssh2_channel_readnb_ex(), libssh2_channel_writenb_ex(),
|
||||||
libssh2_sftp_readnb(), libssh2_sftp_writenb(),
|
libssh2_sftp_readnb(), libssh2_sftp_writenb(),
|
||||||
|
2
README
2
README
@@ -6,7 +6,7 @@ the revised BSD license.
|
|||||||
|
|
||||||
Web site: http://www.libssh2.org/
|
Web site: http://www.libssh2.org/
|
||||||
|
|
||||||
Mailing list: https://lists.sourceforge.net/lists/listinfo/libssh2-devel
|
Mailing list: http://cool.haxx.se/mailman/listinfo/libssh2-devel
|
||||||
|
|
||||||
Generic installation instructions are in INSTALL. Some ./configure
|
Generic installation instructions are in INSTALL. Some ./configure
|
||||||
options deserve additional comments:
|
options deserve additional comments:
|
||||||
|
40
RELEASE-NOTES
Normal file
40
RELEASE-NOTES
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
libssh2 1.2
|
||||||
|
|
||||||
|
This release includes the following changes:
|
||||||
|
|
||||||
|
o we've switched to using git for source code control
|
||||||
|
o we're offering an alternative web site at http://libssh2.haxx.se/
|
||||||
|
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:
|
||||||
|
|
||||||
|
o bad 0-return from libssh2_channel_read
|
||||||
|
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
|
||||||
|
advice from friends like these:
|
||||||
|
|
||||||
|
Simon Josefsson, Neil Gierman, Alexander Lamaison, Peter Stuge,
|
||||||
|
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)
|
35
TODO
35
TODO
@@ -1,19 +1,17 @@
|
|||||||
Things TODO
|
Things TODO
|
||||||
===========
|
===========
|
||||||
|
|
||||||
* Add one of the missing man pages:
|
* make sure the windowing code adapts better to slow situations so that it
|
||||||
|
doesn't then use as much memory as today
|
||||||
|
|
||||||
libssh2_channel_receive_window_adjust
|
* Introduce a 'libssh2_socket_t' type for sockets in internal code
|
||||||
libssh2_channel_request_pty_size_ex
|
|
||||||
libssh2_channel_window_read_ex
|
* Provide a libssh2_scp_send() API for files larger than 4GB (32bit size)
|
||||||
libssh2_channel_window_write_ex
|
|
||||||
libssh2_publickey_add_ex
|
* Convert the linked list code used all over to use the (new) generic linked
|
||||||
libssh2_publickey_init
|
list code. See the _libssh2_list_*() functions in src/misc.c
|
||||||
libssh2_publickey_list_fetch
|
|
||||||
libssh2_publickey_list_free
|
* Add more info to the man pages.
|
||||||
libssh2_publickey_remove_ex
|
|
||||||
libssh2_publickey_shutdown
|
|
||||||
libssh2_userauth_hostbased_fromfile_ex
|
|
||||||
|
|
||||||
* Decrease the number of mallocs. Everywhere.
|
* Decrease the number of mallocs. Everywhere.
|
||||||
|
|
||||||
@@ -21,8 +19,7 @@ Things TODO
|
|||||||
|
|
||||||
* Extend the test suite to actually test lots of aspects of libssh2
|
* Extend the test suite to actually test lots of aspects of libssh2
|
||||||
|
|
||||||
* libssh2_channel_receive_window_adjust() can return EAGAIN while documented
|
* Fix all compiler warnings (some can't be done without API changes)
|
||||||
to return the window as an "unsigned long".
|
|
||||||
|
|
||||||
At next SONAME bump
|
At next SONAME bump
|
||||||
===================
|
===================
|
||||||
@@ -30,9 +27,19 @@ At next SONAME bump
|
|||||||
* stop using #defined macros as part of the official API. The macros should
|
* stop using #defined macros as part of the official API. The macros should
|
||||||
either be turned into real functions or discarded from the API.
|
either be turned into real functions or discarded from the API.
|
||||||
|
|
||||||
|
* fix the parts of the API where object pointers and function pointers are
|
||||||
|
mixed like libssh2_session_callback_set()
|
||||||
|
|
||||||
* remove the following functions from the API/ABI
|
* remove the following functions from the API/ABI
|
||||||
|
|
||||||
libssh2_base64_decode()
|
libssh2_base64_decode()
|
||||||
libssh2_session_flag()
|
libssh2_session_flag()
|
||||||
libssh2_channel_handle_extended_data()
|
libssh2_channel_handle_extended_data()
|
||||||
libssh2_channel_receive_window_adjust()
|
libssh2_channel_receive_window_adjust()
|
||||||
|
libssh2_poll()
|
||||||
|
libssh2_poll_channel_read()
|
||||||
|
|
||||||
|
* Rename a few function:
|
||||||
|
|
||||||
|
libssh2_hostkey_hash => libssh2_session_hostkey_hash
|
||||||
|
libssh2_banner_set => libssh2_session_banner_set
|
94
acinclude.m4
94
acinclude.m4
@@ -288,3 +288,97 @@ dnl end of non-blocking try-compile test
|
|||||||
AC_MSG_WARN([non-block sockets disabled])
|
AC_MSG_WARN([non-block sockets disabled])
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl CURL_CHECK_NEED_REENTRANT_SYSTEM
|
||||||
|
dnl -------------------------------------------------
|
||||||
|
dnl Checks if the preprocessor _REENTRANT definition
|
||||||
|
dnl must be unconditionally done for this platform.
|
||||||
|
dnl Internal macro for CURL_CONFIGURE_REENTRANT.
|
||||||
|
|
||||||
|
AC_DEFUN([CURL_CHECK_NEED_REENTRANT_SYSTEM], [
|
||||||
|
case $host in
|
||||||
|
*-*-solaris*)
|
||||||
|
tmp_need_reentrant="yes"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
tmp_need_reentrant="no"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl CURL_CONFIGURE_FROM_NOW_ON_WITH_REENTRANT
|
||||||
|
dnl -------------------------------------------------
|
||||||
|
dnl This macro ensures that configuration tests done
|
||||||
|
dnl after this will execute with preprocessor symbol
|
||||||
|
dnl _REENTRANT defined. This macro also ensures that
|
||||||
|
dnl the generated config file defines NEED_REENTRANT
|
||||||
|
dnl and that in turn setup.h will define _REENTRANT.
|
||||||
|
dnl Internal macro for CURL_CONFIGURE_REENTRANT.
|
||||||
|
|
||||||
|
AC_DEFUN([CURL_CONFIGURE_FROM_NOW_ON_WITH_REENTRANT], [
|
||||||
|
AC_DEFINE(NEED_REENTRANT, 1,
|
||||||
|
[Define to 1 if _REENTRANT preprocessor symbol must be defined.])
|
||||||
|
cat >>confdefs.h <<_EOF
|
||||||
|
#ifndef _REENTRANT
|
||||||
|
# define _REENTRANT
|
||||||
|
#endif
|
||||||
|
_EOF
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl CURL_CONFIGURE_REENTRANT
|
||||||
|
dnl -------------------------------------------------
|
||||||
|
dnl This first checks if the preprocessor _REENTRANT
|
||||||
|
dnl symbol is already defined. If it isn't currently
|
||||||
|
dnl defined a set of checks are performed to verify
|
||||||
|
dnl if its definition is required to make visible to
|
||||||
|
dnl the compiler a set of *_r functions. Finally, if
|
||||||
|
dnl _REENTRANT is already defined or needed it takes
|
||||||
|
dnl care of making adjustments necessary to ensure
|
||||||
|
dnl that it is defined equally for further configure
|
||||||
|
dnl tests and generated config file.
|
||||||
|
|
||||||
|
AC_DEFUN([CURL_CONFIGURE_REENTRANT], [
|
||||||
|
AC_PREREQ([2.50])dnl
|
||||||
|
#
|
||||||
|
AC_MSG_CHECKING([if _REENTRANT is already defined])
|
||||||
|
AC_COMPILE_IFELSE([
|
||||||
|
AC_LANG_PROGRAM([[
|
||||||
|
]],[[
|
||||||
|
#ifdef _REENTRANT
|
||||||
|
int dummy=1;
|
||||||
|
#else
|
||||||
|
force compilation error
|
||||||
|
#endif
|
||||||
|
]])
|
||||||
|
],[
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
tmp_reentrant_initially_defined="yes"
|
||||||
|
],[
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
tmp_reentrant_initially_defined="no"
|
||||||
|
])
|
||||||
|
#
|
||||||
|
if test "$tmp_reentrant_initially_defined" = "no"; then
|
||||||
|
AC_MSG_CHECKING([if _REENTRANT is actually needed])
|
||||||
|
CURL_CHECK_NEED_REENTRANT_SYSTEM
|
||||||
|
|
||||||
|
if test "$tmp_need_reentrant" = "yes"; then
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
AC_MSG_CHECKING([if _REENTRANT is onwards defined])
|
||||||
|
if test "$tmp_reentrant_initially_defined" = "yes" ||
|
||||||
|
test "$tmp_need_reentrant" = "yes"; then
|
||||||
|
CURL_CONFIGURE_FROM_NOW_ON_WITH_REENTRANT
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
])
|
||||||
|
|
||||||
|
18
buildconf
18
buildconf
@@ -1,6 +1,22 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
${LIBTOOLIZE:-libtoolize} --copy --automake --force
|
LIBTOOLIZE="libtoolize"
|
||||||
|
|
||||||
|
if [ "x`which $LIBTOOLIZE`" == "x" ];
|
||||||
|
then
|
||||||
|
LIBTOOLIZE="glibtoolize";
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x`which $LIBTOOLIZE`" == "x" ];
|
||||||
|
then
|
||||||
|
echo "Neither libtoolize nor glibtoolize could be found!";
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
${LIBTOOLIZE} --copy --automake --force
|
||||||
${ACLOCAL:-aclocal} -I m4 $ACLOCAL_FLAGS
|
${ACLOCAL:-aclocal} -I m4 $ACLOCAL_FLAGS
|
||||||
${AUTOHEADER:-autoheader}
|
${AUTOHEADER:-autoheader}
|
||||||
# copy the private libssh2_config.h.in to the examples dir so that
|
# copy the private libssh2_config.h.in to the examples dir so that
|
||||||
|
@@ -50,6 +50,10 @@ AC_CHECK_TYPE(long long,
|
|||||||
[Define to 1 if the compiler supports the 'long long' data type.])]
|
[Define to 1 if the compiler supports the 'long long' data type.])]
|
||||||
longlong="yes"
|
longlong="yes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dnl Our configure and build reentrant settings
|
||||||
|
CURL_CONFIGURE_REENTRANT
|
||||||
|
|
||||||
# Some systems (Solaris?) have socket() in -lsocket.
|
# Some systems (Solaris?) have socket() in -lsocket.
|
||||||
AC_SEARCH_LIBS(socket, socket)
|
AC_SEARCH_LIBS(socket, socket)
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ EXTRA_DIST = template.3
|
|||||||
|
|
||||||
dist_man_MANS = \
|
dist_man_MANS = \
|
||||||
libssh2_banner_set.3 \
|
libssh2_banner_set.3 \
|
||||||
|
libssh2_base64_decode.3 \
|
||||||
libssh2_channel_close.3 \
|
libssh2_channel_close.3 \
|
||||||
libssh2_channel_direct_tcpip_ex.3 \
|
libssh2_channel_direct_tcpip_ex.3 \
|
||||||
libssh2_channel_eof.3 \
|
libssh2_channel_eof.3 \
|
||||||
@@ -21,23 +22,47 @@ dist_man_MANS = \
|
|||||||
libssh2_channel_receive_window_adjust.3 \
|
libssh2_channel_receive_window_adjust.3 \
|
||||||
libssh2_channel_receive_window_adjust2.3 \
|
libssh2_channel_receive_window_adjust2.3 \
|
||||||
libssh2_channel_request_pty_ex.3 \
|
libssh2_channel_request_pty_ex.3 \
|
||||||
|
libssh2_channel_request_pty_size_ex.3 \
|
||||||
libssh2_channel_send_eof.3 \
|
libssh2_channel_send_eof.3 \
|
||||||
libssh2_channel_set_blocking.3 \
|
libssh2_channel_set_blocking.3 \
|
||||||
libssh2_channel_setenv_ex.3 \
|
libssh2_channel_setenv_ex.3 \
|
||||||
libssh2_channel_wait_eof.3 \
|
|
||||||
libssh2_channel_wait_closed.3 \
|
libssh2_channel_wait_closed.3 \
|
||||||
|
libssh2_channel_wait_eof.3 \
|
||||||
libssh2_channel_window_read_ex.3 \
|
libssh2_channel_window_read_ex.3 \
|
||||||
libssh2_channel_window_write_ex.3 \
|
libssh2_channel_window_write_ex.3 \
|
||||||
libssh2_channel_write_ex.3 \
|
libssh2_channel_write_ex.3 \
|
||||||
libssh2_channel_x11_req_ex.3 \
|
libssh2_channel_x11_req_ex.3 \
|
||||||
|
libssh2_free_host_entry.3 \
|
||||||
|
libssh2_host_entry_match.3 \
|
||||||
libssh2_hostkey_hash.3 \
|
libssh2_hostkey_hash.3 \
|
||||||
|
libssh2_knownhost_add.3 \
|
||||||
|
libssh2_knownhost_check.3 \
|
||||||
|
libssh2_knownhost_del.3 \
|
||||||
|
libssh2_knownhost_get.3 \
|
||||||
|
libssh2_knownhost_init.3 \
|
||||||
|
libssh2_knownhost_readfile.3 \
|
||||||
|
libssh2_knownhost_readline.3 \
|
||||||
|
libssh2_knownhost_writefile.3 \
|
||||||
|
libssh2_knownhost_writeline.3 \
|
||||||
|
libssh2_new_host_entry.3 \
|
||||||
|
libssh2_poll.3 \
|
||||||
|
libssh2_poll_channel_read.3 \
|
||||||
|
libssh2_publickey_add_ex.3 \
|
||||||
|
libssh2_publickey_init.3 \
|
||||||
|
libssh2_publickey_list_fetch.3 \
|
||||||
|
libssh2_publickey_list_free.3 \
|
||||||
|
libssh2_publickey_remove_ex.3 \
|
||||||
|
libssh2_publickey_shutdown.3 \
|
||||||
libssh2_scp_recv.3 \
|
libssh2_scp_recv.3 \
|
||||||
libssh2_scp_send_ex.3 \
|
libssh2_scp_send_ex.3 \
|
||||||
libssh2_session_abstract.3 \
|
libssh2_session_abstract.3 \
|
||||||
libssh2_session_block_directions.3 \
|
libssh2_session_block_directions.3 \
|
||||||
libssh2_session_callback_set.3 \
|
libssh2_session_callback_set.3 \
|
||||||
libssh2_session_free.3 \
|
|
||||||
libssh2_session_disconnect_ex.3 \
|
libssh2_session_disconnect_ex.3 \
|
||||||
|
libssh2_session_flag.3 \
|
||||||
|
libssh2_session_free.3 \
|
||||||
|
libssh2_session_get_blocking.3 \
|
||||||
|
libssh2_session_hostkey.3 \
|
||||||
libssh2_session_init_ex.3 \
|
libssh2_session_init_ex.3 \
|
||||||
libssh2_session_last_errno.3 \
|
libssh2_session_last_errno.3 \
|
||||||
libssh2_session_last_error.3 \
|
libssh2_session_last_error.3 \
|
||||||
@@ -45,14 +70,12 @@ dist_man_MANS = \
|
|||||||
libssh2_session_methods.3 \
|
libssh2_session_methods.3 \
|
||||||
libssh2_session_set_blocking.3 \
|
libssh2_session_set_blocking.3 \
|
||||||
libssh2_session_startup.3 \
|
libssh2_session_startup.3 \
|
||||||
libssh2_poll.3 \
|
|
||||||
libssh2_poll_channel_read.3 \
|
|
||||||
libssh2_sftp_close_handle.3 \
|
libssh2_sftp_close_handle.3 \
|
||||||
libssh2_sftp_fstat_ex.3 \
|
libssh2_sftp_fstat_ex.3 \
|
||||||
libssh2_sftp_last_error.3 \
|
|
||||||
libssh2_sftp_init.3 \
|
libssh2_sftp_init.3 \
|
||||||
libssh2_sftp_open_ex.3 \
|
libssh2_sftp_last_error.3 \
|
||||||
libssh2_sftp_mkdir_ex.3 \
|
libssh2_sftp_mkdir_ex.3 \
|
||||||
|
libssh2_sftp_open_ex.3 \
|
||||||
libssh2_sftp_read.3 \
|
libssh2_sftp_read.3 \
|
||||||
libssh2_sftp_readdir_ex.3 \
|
libssh2_sftp_readdir_ex.3 \
|
||||||
libssh2_sftp_rename_ex.3 \
|
libssh2_sftp_rename_ex.3 \
|
||||||
@@ -65,24 +88,11 @@ dist_man_MANS = \
|
|||||||
libssh2_sftp_tell64.3 \
|
libssh2_sftp_tell64.3 \
|
||||||
libssh2_sftp_unlink_ex.3 \
|
libssh2_sftp_unlink_ex.3 \
|
||||||
libssh2_sftp_write.3 \
|
libssh2_sftp_write.3 \
|
||||||
|
libssh2_trace.3 \
|
||||||
libssh2_userauth_authenticated.3 \
|
libssh2_userauth_authenticated.3 \
|
||||||
|
libssh2_userauth_hostbased_fromfile_ex.3 \
|
||||||
libssh2_userauth_keyboard_interactive_ex.3 \
|
libssh2_userauth_keyboard_interactive_ex.3 \
|
||||||
libssh2_userauth_list.3 \
|
libssh2_userauth_list.3 \
|
||||||
libssh2_userauth_password_ex.3 \
|
libssh2_userauth_password_ex.3 \
|
||||||
libssh2_userauth_publickey_fromfile_ex.3 \
|
libssh2_userauth_publickey_fromfile_ex.3 \
|
||||||
libssh2_base64_decode.3 \
|
|
||||||
libssh2_trace.3 \
|
|
||||||
libssh2_version.3
|
libssh2_version.3
|
||||||
libssh2_channel_request_pty_size_ex.3 \
|
|
||||||
libssh2_free_host_entry.3 \
|
|
||||||
libssh2_host_entry_match.3 \
|
|
||||||
libssh2_new_host_entry.3 \
|
|
||||||
libssh2_publickey_add_ex.3 \
|
|
||||||
libssh2_publickey_init.3 \
|
|
||||||
libssh2_publickey_list_fetch.3 \
|
|
||||||
libssh2_publickey_list_free.3 \
|
|
||||||
libssh2_publickey_remove_ex.3 \
|
|
||||||
libssh2_publickey_shutdown.3 \
|
|
||||||
libssh2_session_flag.3 \
|
|
||||||
libssh2_session_get_blocking.3 \
|
|
||||||
libssh2_userauth_hostbased_fromfile_ex.3
|
|
||||||
|
@@ -13,16 +13,16 @@ LIBSSH2_CHANNEL *
|
|||||||
libssh2_channel_direct_tcpip(LIBSSH2_SESSION *session, const char *host, int port);
|
libssh2_channel_direct_tcpip(LIBSSH2_SESSION *session, const char *host, int port);
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
/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)
|
||||||
|
|
||||||
/fIhost/fP - Third party host to connect to using the SSH host as a proxy.
|
\fIhost\fP - Third party host to connect to using the SSH host as a proxy.
|
||||||
|
|
||||||
/fIport/fP - Port on third party host to connect to.
|
\fIport\fP - Port on third party host to connect to.
|
||||||
|
|
||||||
/fIshost/fP - Host to tell the SSH server the connection originated on.
|
\fIshost\fP - Host to tell the SSH server the connection originated on.
|
||||||
|
|
||||||
/fIsport/fP - Port to tell the SSH server the connection originated from.
|
\fIsport\fP - Port to tell the SSH server the connection originated from.
|
||||||
|
|
||||||
Tunnel a TCP/IP connection through the SSH transport via the remote host to
|
Tunnel a TCP/IP connection through the SSH transport via the remote host to
|
||||||
a third party. Communication from the client to the SSH server remains
|
a third party. Communication from the client to the SSH server remains
|
||||||
|
@@ -10,7 +10,7 @@ int
|
|||||||
libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
|
libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
/fIlistener/fP - Forwarding listener instance as returned by
|
\fIlistener\fP - Forwarding listener instance as returned by
|
||||||
.BR libssh2_channel_forward_listen_ex(3)
|
.BR libssh2_channel_forward_listen_ex(3)
|
||||||
|
|
||||||
Instruct the remote host to stop listening for new connections on a previously requested host/port.
|
Instruct the remote host to stop listening for new connections on a previously requested host/port.
|
||||||
|
58
docs/libssh2_knownhost_add.3
Normal file
58
docs/libssh2_knownhost_add.3
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_add 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_add - add a known host
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
char *host, char *salt,
|
||||||
|
char *key, size_t keylen,
|
||||||
|
int typemask,
|
||||||
|
struct libssh2_knownhost **store);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Adds a known host to the collection of known hosts identified by the 'hosts'
|
||||||
|
handle.
|
||||||
|
|
||||||
|
\fIhost\fP is a pointer the host name in plain text or hashed. If hashed, it
|
||||||
|
must be provided base64 encoded. The host name can be the IP numerical address
|
||||||
|
of the host or the full name.
|
||||||
|
|
||||||
|
\fIsalt\P is a pointer to the salt used for the host hashing, if the host is
|
||||||
|
provided hashed. If the host is provided in plain text, salt has no meaning.
|
||||||
|
The salt has to be provided base64 encoded with a trailing zero byte.
|
||||||
|
|
||||||
|
\fIkey\fP is a pointer to the key for the given host.
|
||||||
|
|
||||||
|
\fIkeylen\fP is the total size in bytes of the key pointed to by the \fIkey\fP
|
||||||
|
argument
|
||||||
|
|
||||||
|
\fItypemask\fP is a bitmask that specifies format and info about the data
|
||||||
|
passed to this function. Specificly, it details what format the host name is,
|
||||||
|
what format the key is and what key type it is.
|
||||||
|
|
||||||
|
The host name is given as one of the following types:
|
||||||
|
LIBSSH2_KNOWNHOST_TYPE_PLAIN, LIBSSH2_KNOWNHOST_TYPE_SHA1 or
|
||||||
|
LIBSSH2_KNOWNHOST_TYPE_CUSTOM.
|
||||||
|
|
||||||
|
The key is encoded using one of the following encodings:
|
||||||
|
LIBSSH2_KNOWNHOST_KEYENC_RAW or LIBSSH2_KNOWNHOST_KEYENC_BASE64.
|
||||||
|
|
||||||
|
The key is using one of these algorithms:
|
||||||
|
LIBSSH2_KNOWNHOST_KEY_RSA1, LIBSSH2_KNOWNHOST_KEY_SSHRSA or
|
||||||
|
LIBSSH2_KNOWNHOST_KEY_SSHDSS.
|
||||||
|
|
||||||
|
\fIstore\fP should point to a pointer that gets filled in to point to the
|
||||||
|
known host data after the addition. NULL can be passed if you don't care about
|
||||||
|
this pointer.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns a regular libssh2 error code, where negative values are error codes
|
||||||
|
and 0 indicates success.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_init(3)
|
||||||
|
.BR libssh2_knownhost_free(3)
|
||||||
|
.BR libssh2_knownhost_check(3)
|
57
docs/libssh2_knownhost_check.3
Normal file
57
docs/libssh2_knownhost_check.3
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_check 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_check - check a host+key against the list of known hosts
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
char *host, char *key, size_t keylen,
|
||||||
|
int typemask,
|
||||||
|
struct libssh2_knownhost **knownhost);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Checks a host and its associated key against the collection of known hosts,
|
||||||
|
and returns info back about the (partially) matched entry.
|
||||||
|
|
||||||
|
\fIhost\fP is a pointer the host name in plain text. The host name can be the
|
||||||
|
IP numerical address of the host or the full name.
|
||||||
|
|
||||||
|
\fIkey\fP is a pointer to the key for the given host.
|
||||||
|
|
||||||
|
\fIkeylen\fP is the total size in bytes of the key pointed to by the \fIkey\fP
|
||||||
|
argument
|
||||||
|
|
||||||
|
\fItypemask\fP is a bitmask that specifies format and info about the data
|
||||||
|
passed to this function. Specificly, it details what format the host name is,
|
||||||
|
what format the key is and what key type it is.
|
||||||
|
|
||||||
|
The host name is given as one of the following types:
|
||||||
|
LIBSSH2_KNOWNHOST_TYPE_PLAIN or LIBSSH2_KNOWNHOST_TYPE_CUSTOM.
|
||||||
|
|
||||||
|
The key is encoded using one of the following encodings:
|
||||||
|
LIBSSH2_KNOWNHOST_KEYENC_RAW or LIBSSH2_KNOWNHOST_KEYENC_BASE64.
|
||||||
|
|
||||||
|
\fIknownhost\fP if set to non-NULL, it must be a pointer to a 'struct
|
||||||
|
libssh2_knownhost' pointer that gets filled in to point to info about a known
|
||||||
|
host that matches or partially matches.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
\fIlibssh2_knownhost_check(3)\fP returns info about how well the provided
|
||||||
|
host + key pair matched one of the entries in the list of known hosts.
|
||||||
|
|
||||||
|
LIBSSH2_KNOWNHOST_CHECK_FAILURE - something prevented the check to be made
|
||||||
|
|
||||||
|
LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - no host match was found
|
||||||
|
|
||||||
|
LIBSSH2_KNOWNHOST_CHECK_MATCH - hosts and keys match.
|
||||||
|
|
||||||
|
LIBSSH2_KNOWNHOST_CHECK_MISMATCH - host was found, but the keys didn't match!
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH EXAMPLE
|
||||||
|
See the ssh2_exec.c example as provided in the tarball.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_init(3)
|
||||||
|
.BR libssh2_knownhost_free(3)
|
||||||
|
.BR libssh2_knownhost_add(3)
|
26
docs/libssh2_knownhost_del.3
Normal file
26
docs/libssh2_knownhost_del.3
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_del 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_del - delete a known host entry
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost *entry);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Delete a known host entry from the collection of known hosts.
|
||||||
|
|
||||||
|
\fIentry\fP is a pointer to a struct that you can extract with
|
||||||
|
\fIlibssh2_knownhost_check(3)\fP or \fIlibssh2_knownhost_get(3)\fP.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns a regular libssh2 error code, where negative values are error codes
|
||||||
|
and 0 indicates success.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_init(3)
|
||||||
|
.BR libssh2_knownhost_free(3)
|
||||||
|
.BR libssh2_knownhost_add(3)
|
||||||
|
.BR libssh2_knownhost_check(3)
|
35
docs/libssh2_knownhost_get.3
Normal file
35
docs/libssh2_knownhost_get.3
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_get 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_get - get a known host off the collection of known hosts
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost **store,
|
||||||
|
struct libssh2_knownhost *prev):
|
||||||
|
.SH DESCRIPTION
|
||||||
|
\fIlibssh2_knownhost_get(3)\fP allows an application to iterate over all known
|
||||||
|
hosts in the collection.
|
||||||
|
|
||||||
|
\fIstore\fP should point to a pointer that gets filled in to point to the
|
||||||
|
known host data.
|
||||||
|
|
||||||
|
\fIprev\fP is a pointer to a previous 'struct libssh2_knownhost' as returned
|
||||||
|
by a previous invoke of this function, or NULL to get the first entry in the
|
||||||
|
internal collection.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns 0 if everything is fine and information about a host was stored in
|
||||||
|
the \fIstore\fP struct.
|
||||||
|
|
||||||
|
Returns 1 if it reached the end of hosts.
|
||||||
|
|
||||||
|
Returns negative values for error
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_readfile(3)
|
||||||
|
.BR libssh2_knownhost_writefile(3)
|
||||||
|
.BR libssh2_knownhost_add(3)
|
22
docs/libssh2_knownhost_init.3
Normal file
22
docs/libssh2_knownhost_init.3
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_init 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_init - init a collection of known hosts
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
LIBSSH2_KNOWNHOSTS *libssh2_knownhost_init(LIBSSH2_SESSION *session);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Init a collection of known hosts for this session. Returns the handle to an
|
||||||
|
internal representation of a known host collection.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns a handle pointer or NULL if something went wrong. The returned handle
|
||||||
|
is used as input to all other known host related functions libssh2 provides.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_free(3)
|
||||||
|
.BR libssh2_knownhost_add(3)
|
||||||
|
.BR libssh2_knownhost_check(3)
|
29
docs/libssh2_knownhost_readfile.3
Normal file
29
docs/libssh2_knownhost_readfile.3
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_readfile 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_readfile - parse a file of known hosts
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *filename, int type);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Reads a collection of known hosts from a specified file and adds them to the
|
||||||
|
collection of known hosts.
|
||||||
|
|
||||||
|
\fIfilename\fP specifies which file to read
|
||||||
|
|
||||||
|
\fItype\fP specifies what file type it is, and
|
||||||
|
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
|
||||||
|
format. This file is normally found named ~/.ssh/known_hosts
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns a regular libssh2 error code, where negative values are error codes
|
||||||
|
and 0 indicates success.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_init(3)
|
||||||
|
.BR libssh2_knownhost_free(3)
|
||||||
|
.BR libssh2_knownhost_check(3)
|
30
docs/libssh2_knownhost_readline.3
Normal file
30
docs/libssh2_knownhost_readline.3
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_readline 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_readline - read a known host line
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *line, size_t len, int type):
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Tell libssh2 to read a buffer as it if is a line from a known hosts file.
|
||||||
|
|
||||||
|
\fIline\fP points to the start of the line
|
||||||
|
|
||||||
|
\fIlen\fP is the length of the line in bytes
|
||||||
|
|
||||||
|
\fItype\fP specifies what file type it is, and
|
||||||
|
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
|
||||||
|
format. This file is normally found named ~/.ssh/known_hosts
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns a regular libssh2 error code, where negative values are error codes
|
||||||
|
and 0 indicates success.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_get(3)
|
||||||
|
.BR libssh2_knownhost_writeline(3)
|
||||||
|
.BR libssh2_knownhost_readfile(3)
|
29
docs/libssh2_knownhost_writefile.3
Normal file
29
docs/libssh2_knownhost_writefile.3
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_writefile 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_writefile - write a collection of known hosts to a file
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *filename, int type);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Writes all the known hosts to the specified file using the specified file
|
||||||
|
format.
|
||||||
|
|
||||||
|
\fIfilename\fP specifies what filename to create
|
||||||
|
|
||||||
|
\fItype\fP specifies what file type it is, and
|
||||||
|
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
|
||||||
|
format.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns a regular libssh2 error code, where negative values are error codes
|
||||||
|
and 0 indicates success.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_readfile(3)
|
||||||
|
.BR libssh2_knownhost_add(3)
|
||||||
|
|
46
docs/libssh2_knownhost_writeline.3
Normal file
46
docs/libssh2_knownhost_writeline.3
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
.\"
|
||||||
|
.TH libssh2_knownhost_writeline 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_knownhost_writeline - convert a known host to a line for storage
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost *known,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
size_t *outlen,
|
||||||
|
int type);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Converts a single known host to a single line of output for storage, using
|
||||||
|
the 'type' output format.
|
||||||
|
|
||||||
|
\fIknown\fP identifies which particular known host
|
||||||
|
|
||||||
|
\fIbuffer\fP points to an allocated buffer
|
||||||
|
|
||||||
|
\fIbuflen\fP is the size of the \fIbuffer\fP. See RETURN VALUE about the size.
|
||||||
|
|
||||||
|
\fIoutlen\fP must be a pointer to a size_t variable that will get the output
|
||||||
|
length of the stored data chunk. The number does not included the trailing
|
||||||
|
zero!
|
||||||
|
|
||||||
|
\fItype\fP specifies what file type it is, and
|
||||||
|
\fILIBSSH2_KNOWNHOST_FILE_OPENSSH\fP is the only currently supported
|
||||||
|
format.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Returns a regular libssh2 error code, where negative values are error codes
|
||||||
|
and 0 indicates success.
|
||||||
|
|
||||||
|
If the provided buffer is deemed too small to fit the data libssh2 wants to
|
||||||
|
store in it, LIBSSH2_ERROR_BUFFER_TOO_SMALL will be returned. The application
|
||||||
|
is then adviced to call the function again with a larger buffer. The
|
||||||
|
\fIoutlen\fP size will then hold the requested size.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.2
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_get(3)
|
||||||
|
.BR libssh2_knownhost_readline(3)
|
||||||
|
.BR libssh2_knownhost_writefile(3)
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
.\" $Id: libssh2_poll.3,v 1.3 2007/06/13 12:51:11 jehousley Exp $
|
.\" $Id: libssh2_poll.3,v 1.4 2009/04/14 21:38:36 bagder Exp $
|
||||||
.\"
|
.\"
|
||||||
.TH libssh2_poll 3 "14 Dec 2006" "libssh2 0.15" "libssh2 manual"
|
.TH libssh2_poll 3 "14 Dec 2006" "libssh2 0.15" "libssh2 manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
@@ -8,6 +8,8 @@ libssh2_poll - poll for activity on a socket, channel or listener
|
|||||||
|
|
||||||
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
|
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
This function is deprecated. Do note use.
|
||||||
|
|
||||||
Poll for activity on a socket, channel, listener, or any combination of these
|
Poll for activity on a socket, channel, listener, or any combination of these
|
||||||
three types. The calling semantics for this function generally match
|
three types. The calling semantics for this function generally match
|
||||||
\fIpoll(2)\fP however the structure of fds is somewhat more complex in order
|
\fIpoll(2)\fP however the structure of fds is somewhat more complex in order
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
.\" $Id: libssh2_poll_channel_read.3,v 1.2 2007/06/13 12:51:11 jehousley Exp $
|
.\" $Id: libssh2_poll_channel_read.3,v 1.3 2009/04/14 21:38:36 bagder Exp $
|
||||||
.\"
|
.\"
|
||||||
.TH libssh2_poll_channel_read 3 "14 Dec 2006" "libssh2 0.15" "libssh2 manual"
|
.TH libssh2_poll_channel_read 3 "14 Dec 2006" "libssh2 0.15" "libssh2 manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
@@ -8,6 +8,8 @@ libssh2_poll_channel_read - check if data is available
|
|||||||
|
|
||||||
int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended);
|
int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended);
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
This function is deprecated. Do note use.
|
||||||
|
|
||||||
\fIlibssh2_poll_channel_read(3)\fP checks to see if data is available in the
|
\fIlibssh2_poll_channel_read(3)\fP checks to see if data is available in the
|
||||||
\fIchannel\fP's read buffer. No attempt is made with this method to see if
|
\fIchannel\fP's read buffer. No attempt is made with this method to see if
|
||||||
packets are available to be processed. For full polling support, use
|
packets are available to be processed. For full polling support, use
|
||||||
|
23
docs/libssh2_session_hostkey.3
Normal file
23
docs/libssh2_session_hostkey.3
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
.\" $Id: session_hostkey.3,v 1.4 2007/06/13 16:41:33 jehousley Exp $
|
||||||
|
.\"
|
||||||
|
.TH libssh2_session_hostkey 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_session_hostkey - get the remote key
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
const char *libssh2_session_hostkey(LIBSSH2_SESSION *session,
|
||||||
|
size_t *len, int *type);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Returns a pointer to the current host key, the value \fIlen\fP points to will
|
||||||
|
get the length of the key.
|
||||||
|
|
||||||
|
The value \fItype\fP points to the type of hostkey which is one of:
|
||||||
|
LIBSSH2_HOSTKEY_TYPE_RSA, LIBSSH2_HOSTKEY_TYPE_DSS, or
|
||||||
|
LIBSSH2_HOSTKEY_TYPE_UNKNOWN.
|
||||||
|
|
||||||
|
.SH RETURN VALUE
|
||||||
|
A pointer, or NULL if something went wrong.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_knownhost_check(3)
|
||||||
|
.BR libssh2_knownhost_add(3)
|
@@ -20,14 +20,10 @@ libssh2_sftp_closedir(LIBSSH2_SFTP_HANDLE *handle);
|
|||||||
\fIhandle\fP - SFTP File Handle as returned by \fBlibssh2_sftp_open_ex(3)\fP
|
\fIhandle\fP - SFTP File Handle as returned by \fBlibssh2_sftp_open_ex(3)\fP
|
||||||
or \fBlibssh2_sftp_opendir(3)\fP (which is a macro).
|
or \fBlibssh2_sftp_opendir(3)\fP (which is a macro).
|
||||||
|
|
||||||
Close an active LIBSSH2_SFTP_HANDLE. Because files and directories
|
Close an active LIBSSH2_SFTP_HANDLE. Because files and directories share the
|
||||||
share the same underlying storage mechanism these methods may be used
|
same underlying storage mechanism these methods may be used
|
||||||
interchangably. It is recommended that
|
interchangably. \fBlibssh2_sftp_close(3)\fP and \fBlibssh2_sftp_closedir(3)\fP
|
||||||
.BR libssh2_sftp_closedir()
|
are macros for \fBlibssh2_sftp_close_handle(3)\fP.
|
||||||
be used for files and that
|
|
||||||
.BR libssh2_sftp_closedir()
|
|
||||||
be used for directories so that future changes in the library may cause
|
|
||||||
minimal disruption. Both are macros for \fBlibssh2_sftp_close_handle\fP.
|
|
||||||
|
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Return 0 on success or negative on failure. It returns
|
Return 0 on success or negative on failure. It returns
|
||||||
|
18
example/simple/.gitignore
vendored
Normal file
18
example/simple/.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
*.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
|
||||||
|
config.h.in
|
||||||
|
ssh2_exec
|
@@ -8,7 +8,7 @@ noinst_PROGRAMS = ssh2 \
|
|||||||
sftp_write sftp_write_nonblock \
|
sftp_write sftp_write_nonblock \
|
||||||
sftp_mkdir sftp_mkdir_nonblock \
|
sftp_mkdir sftp_mkdir_nonblock \
|
||||||
sftp_RW_nonblock \
|
sftp_RW_nonblock \
|
||||||
sftpdir sftpdir_nonblock
|
sftpdir sftpdir_nonblock ssh2_exec
|
||||||
|
|
||||||
# the examples need the $(top_builddir)/src since when building outside of the
|
# the examples need the $(top_builddir)/src since when building outside of the
|
||||||
# source dir they still need to reach the libssh2_config.h header
|
# source dir they still need to reach the libssh2_config.h header
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: scp.c,v 1.11 2008/11/10 16:48:41 bagder Exp $
|
* $Id: scp.c,v 1.12 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do a simple SCP transfer.
|
* Sample showing how to do a simple SCP transfer.
|
||||||
*/
|
*/
|
||||||
@@ -164,10 +164,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "all done\n");
|
fprintf(stderr, "all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: scp_nonblock.c,v 1.15 2009/03/25 22:52:32 bagder Exp $
|
* $Id: scp_nonblock.c,v 1.16 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SCP transfers in a non-blocking manner.
|
* Sample showing how to do SCP transfers in a non-blocking manner.
|
||||||
*
|
*
|
||||||
@@ -132,23 +132,6 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set the socket non-blocking. We do it after the connect just to
|
|
||||||
simplify the example code. */
|
|
||||||
#ifdef F_SETFL
|
|
||||||
/* FIXME: this can/should be done in a more portable manner */
|
|
||||||
rc = fcntl(sock, F_GETFL, 0);
|
|
||||||
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
|
|
||||||
#elif defined(HAVE_IOCTLSOCKET)
|
|
||||||
ioctlsocket(sock, FIONBIO, &flag);
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
u_long mode = 1;
|
|
||||||
ioctlsocket (sock, FIONBIO, &mode);
|
|
||||||
#else
|
|
||||||
#error "add support for setting the socket non-blocking here"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create a session instance */
|
/* Create a session instance */
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
if (!session)
|
if (!session)
|
||||||
@@ -276,10 +259,8 @@ shutdown:
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "all done\n");
|
fprintf(stderr, "all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: scp_write.c,v 1.6 2008/11/10 16:48:41 bagder Exp $
|
* $Id: scp_write.c,v 1.7 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do a simple SCP transfer.
|
* Sample showing how to do a simple SCP transfer.
|
||||||
*/
|
*/
|
||||||
@@ -186,10 +186,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "all done\n");
|
fprintf(stderr, "all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: scp_write_nonblock.c,v 1.9 2008/11/10 16:48:41 bagder Exp $
|
* $Id: scp_write_nonblock.c,v 1.10 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do a simple SCP transfer.
|
* Sample showing how to do a simple SCP transfer.
|
||||||
*/
|
*/
|
||||||
@@ -102,23 +102,6 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set the socket non-blocking. We do it after the connect just to
|
|
||||||
simplify the example code. */
|
|
||||||
#ifdef F_SETFL
|
|
||||||
/* FIXME: this can/should be done in a more portable manner */
|
|
||||||
rc = fcntl(sock, F_GETFL, 0);
|
|
||||||
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
|
|
||||||
#elif defined(HAVE_IOCTLSOCKET)
|
|
||||||
ioctlsocket(sock, FIONBIO, &flag);
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
u_long mode = 1;
|
|
||||||
ioctlsocket (sock, FIONBIO, &mode);
|
|
||||||
#else
|
|
||||||
#error "add support for setting the socket non-blocking here"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create a session instance
|
/* Create a session instance
|
||||||
*/
|
*/
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
@@ -225,10 +208,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "all done\n");
|
fprintf(stderr, "all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftp.c,v 1.16 2009/03/31 12:20:36 bagder Exp $
|
* $Id: sftp.c,v 1.17 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SFTP transfers.
|
* Sample showing how to do SFTP transfers.
|
||||||
*
|
*
|
||||||
@@ -236,10 +236,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "all done\n");
|
fprintf(stderr, "all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftp_RW_nonblock.c,v 1.12 2008/11/10 16:48:41 bagder Exp $
|
* $Id: sftp_RW_nonblock.c,v 1.13 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SFTP transfers in a non-blocking manner.
|
* Sample showing how to do SFTP transfers in a non-blocking manner.
|
||||||
*
|
*
|
||||||
@@ -84,23 +84,6 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set the socket non-blocking. We do it after the connect just to
|
|
||||||
simplify the example code. */
|
|
||||||
#ifdef F_SETFL
|
|
||||||
/* FIXME: this can/should be done in a more portable manner */
|
|
||||||
rc = fcntl(sock, F_GETFL, 0);
|
|
||||||
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
|
|
||||||
#elif defined(HAVE_IOCTLSOCKET)
|
|
||||||
ioctlsocket(sock, FIONBIO, &flag);
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
u_long mode = 1;
|
|
||||||
ioctlsocket (sock, FIONBIO, &mode);
|
|
||||||
#else
|
|
||||||
#error "add support for setting the socket non-blocking here"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create a session instance
|
/* Create a session instance
|
||||||
*/
|
*/
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
@@ -293,10 +276,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done\n");
|
printf("all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftp_mkdir.c,v 1.8 2008/11/10 16:48:41 bagder Exp $
|
* $Id: sftp_mkdir.c,v 1.9 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SFTP mkdir
|
* Sample showing how to do SFTP mkdir
|
||||||
*
|
*
|
||||||
@@ -155,10 +155,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done\n");
|
printf("all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftp_mkdir_nonblock.c,v 1.11 2008/11/10 16:48:41 bagder Exp $
|
* $Id: sftp_mkdir_nonblock.c,v 1.12 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SFTP non-blocking mkdir.
|
* Sample showing how to do SFTP non-blocking mkdir.
|
||||||
*
|
*
|
||||||
@@ -88,23 +88,6 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set the socket non-blocking. We do it after the connect just to
|
|
||||||
simplify the example code. */
|
|
||||||
#ifdef F_SETFL
|
|
||||||
/* FIXME: this can/should be done in a more portable manner */
|
|
||||||
rc = fcntl(sock, F_GETFL, 0);
|
|
||||||
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
|
|
||||||
#elif defined(HAVE_IOCTLSOCKET)
|
|
||||||
ioctlsocket(sock, FIONBIO, &flag);
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
u_long mode = 1;
|
|
||||||
ioctlsocket (sock, FIONBIO, &mode);
|
|
||||||
#else
|
|
||||||
#error "add support for setting the socket non-blocking here"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create a session instance
|
/* Create a session instance
|
||||||
*/
|
*/
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
@@ -178,10 +161,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done\n");
|
printf("all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftp_nonblock.c,v 1.17 2009/03/13 22:14:47 bagder Exp $
|
* $Id: sftp_nonblock.c,v 1.18 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SFTP non-blocking transfers.
|
* Sample showing how to do SFTP non-blocking transfers.
|
||||||
*
|
*
|
||||||
@@ -133,23 +133,6 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set the socket non-blocking. We do it after the connect just to
|
|
||||||
simplify the example code. */
|
|
||||||
#ifdef F_SETFL
|
|
||||||
/* FIXME: this can/should be done in a more portable manner */
|
|
||||||
rc = fcntl(sock, F_GETFL, 0);
|
|
||||||
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
|
|
||||||
#elif defined(HAVE_IOCTLSOCKET)
|
|
||||||
ioctlsocket(sock, FIONBIO, &flag);
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
u_long mode = 1;
|
|
||||||
ioctlsocket (sock, FIONBIO, &mode);
|
|
||||||
#else
|
|
||||||
#error "add support for setting the socket non-blocking here"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create a session instance */
|
/* Create a session instance */
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
if (!session)
|
if (!session)
|
||||||
@@ -278,10 +261,8 @@ shutdown:
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "all done\n");
|
fprintf(stderr, "all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftp_write.c,v 1.10 2009/03/31 12:20:36 bagder Exp $
|
* $Id: sftp_write.c,v 1.11 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SFTP write transfers.
|
* Sample showing how to do SFTP write transfers.
|
||||||
*
|
*
|
||||||
@@ -195,10 +195,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done\n");
|
printf("all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftp_write_nonblock.c,v 1.13 2009/03/31 12:20:36 bagder Exp $
|
* $Id: sftp_write_nonblock.c,v 1.14 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SFTP non-blocking write transfers.
|
* Sample showing how to do SFTP non-blocking write transfers.
|
||||||
*
|
*
|
||||||
@@ -103,23 +103,6 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set the socket non-blocking. We do it after the connect just to
|
|
||||||
simplify the example code. */
|
|
||||||
#ifdef F_SETFL
|
|
||||||
/* FIXME: this can/should be done in a more portable manner */
|
|
||||||
rc = fcntl(sock, F_GETFL, 0);
|
|
||||||
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
|
|
||||||
#elif defined(HAVE_IOCTLSOCKET)
|
|
||||||
ioctlsocket(sock, FIONBIO, &flag);
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
u_long mode = 1;
|
|
||||||
ioctlsocket (sock, FIONBIO, &mode);
|
|
||||||
#else
|
|
||||||
#error "add support for setting the socket non-blocking here"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create a session instance
|
/* Create a session instance
|
||||||
*/
|
*/
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
@@ -139,11 +122,11 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point we havn't yet authenticated. The first thing to do
|
/* At this point we havn't yet authenticated. The first thing to do is
|
||||||
* is check the hostkey's fingerprint against our known hosts Your app
|
* check the hostkey's fingerprint against our known hosts Your app may
|
||||||
* may have it hard coded, may go to a file, may present it to the
|
* have it hard coded, may go to a file, may present it to the user,
|
||||||
* user, that's your call
|
* that's your call
|
||||||
*/
|
*/
|
||||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||||
printf("Fingerprint: ");
|
printf("Fingerprint: ");
|
||||||
for(i = 0; i < 16; i++) {
|
for(i = 0; i < 16; i++) {
|
||||||
@@ -224,10 +207,8 @@ shutdown:
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done\n");
|
printf("all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftpdir.c,v 1.10 2008/11/10 16:48:41 bagder Exp $
|
* $Id: sftpdir.c,v 1.11 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample doing an SFTP directory listing.
|
* Sample doing an SFTP directory listing.
|
||||||
*
|
*
|
||||||
@@ -207,10 +207,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done\n");
|
printf("all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: sftpdir_nonblock.c,v 1.12 2008/11/10 16:48:41 bagder Exp $
|
* $Id: sftpdir_nonblock.c,v 1.13 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample doing an SFTP directory listing.
|
* Sample doing an SFTP directory listing.
|
||||||
*
|
*
|
||||||
@@ -88,23 +88,6 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set the socket non-blocking. We do it after the connect just to
|
|
||||||
simplify the example code. */
|
|
||||||
#ifdef F_SETFL
|
|
||||||
/* FIXME: this can/should be done in a more portable manner */
|
|
||||||
rc = fcntl(sock, F_GETFL, 0);
|
|
||||||
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
|
|
||||||
#elif defined(HAVE_IOCTLSOCKET)
|
|
||||||
ioctlsocket(sock, FIONBIO, &flag);
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
u_long mode = 1;
|
|
||||||
ioctlsocket (sock, FIONBIO, &mode);
|
|
||||||
#else
|
|
||||||
#error "add support for setting the socket non-blocking here"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create a session instance
|
/* Create a session instance
|
||||||
*/
|
*/
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
@@ -236,10 +219,8 @@ int main(int argc, char *argv[])
|
|||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done\n");
|
printf("all done\n");
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: ssh2.c,v 1.18 2008/11/10 16:48:41 bagder Exp $
|
* $Id: ssh2.c,v 1.19 2009/04/28 10:35:30 bagder Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do SSH2 connect.
|
* Sample showing how to do SSH2 connect.
|
||||||
*
|
*
|
||||||
@@ -45,11 +45,12 @@ const char *username="username";
|
|||||||
const char *password="password";
|
const char *password="password";
|
||||||
|
|
||||||
|
|
||||||
static void kbd_callback(const char *name, int name_len,
|
static void kbd_callback(const char *name, int name_len,
|
||||||
const char *instruction, int instruction_len, int num_prompts,
|
const char *instruction, int instruction_len,
|
||||||
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
|
int num_prompts,
|
||||||
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
|
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
|
||||||
void **abstract)
|
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
|
||||||
|
void **abstract)
|
||||||
{
|
{
|
||||||
(void)name;
|
(void)name;
|
||||||
(void)name_len;
|
(void)name_len;
|
||||||
@@ -92,13 +93,11 @@ int main(int argc, char *argv[])
|
|||||||
password = argv[3];
|
password = argv[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ultra basic "connect to port 22 on localhost"
|
/* Ultra basic "connect to port 22 on localhost". Your code is
|
||||||
* Your code is responsible for creating the socket establishing the connection
|
* responsible for creating the socket establishing the connection
|
||||||
*/
|
*/
|
||||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
#ifndef WIN32
|
|
||||||
fcntl(sock, F_SETFL, 0);
|
|
||||||
#endif
|
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_port = htons(22);
|
sin.sin_port = htons(22);
|
||||||
sin.sin_addr.s_addr = hostaddr;
|
sin.sin_addr.s_addr = hostaddr;
|
||||||
@@ -108,8 +107,8 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a session instance and start it up
|
/* Create a session instance and start it up. This will trade welcome
|
||||||
* This will trade welcome banners, exchange keys, and setup crypto, compression, and MAC layers
|
* banners, exchange keys, and setup crypto, compression, and MAC layers
|
||||||
*/
|
*/
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
if (libssh2_session_startup(session, sock)) {
|
if (libssh2_session_startup(session, sock)) {
|
||||||
@@ -117,9 +116,10 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point we havn't authenticated,
|
/* At this point we havn't authenticated. The first thing to do is check
|
||||||
* The first thing to do is check the hostkey's fingerprint against our known hosts
|
* the hostkey's fingerprint against our known hosts Your app may have it
|
||||||
* Your app may have it hard coded, may go to a file, may present it to the user, that's your call
|
* hard coded, may go to a file, may present it to the user, that's your
|
||||||
|
* call
|
||||||
*/
|
*/
|
||||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||||
printf("Fingerprint: ");
|
printf("Fingerprint: ");
|
||||||
@@ -141,7 +141,7 @@ int main(int argc, char *argv[])
|
|||||||
auth_pw |= 4;
|
auth_pw |= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we got an 4. argument we set this option if supported */
|
/* if we got an 4. argument we set this option if supported */
|
||||||
if(argc > 4) {
|
if(argc > 4) {
|
||||||
if ((auth_pw & 1) && !strcasecmp(argv[4], "-p")) {
|
if ((auth_pw & 1) && !strcasecmp(argv[4], "-p")) {
|
||||||
auth_pw = 1;
|
auth_pw = 1;
|
||||||
@@ -164,7 +164,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
} else if (auth_pw & 2) {
|
} else if (auth_pw & 2) {
|
||||||
/* Or via keyboard-interactive */
|
/* Or via keyboard-interactive */
|
||||||
if (libssh2_userauth_keyboard_interactive(session, username, &kbd_callback) ) {
|
if (libssh2_userauth_keyboard_interactive(session, username,
|
||||||
|
&kbd_callback) ) {
|
||||||
printf("\tAuthentication by keyboard-interactive failed!\n");
|
printf("\tAuthentication by keyboard-interactive failed!\n");
|
||||||
goto shutdown;
|
goto shutdown;
|
||||||
} else {
|
} else {
|
||||||
@@ -172,7 +173,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
} else if (auth_pw & 4) {
|
} else if (auth_pw & 4) {
|
||||||
/* Or by public key */
|
/* Or by public key */
|
||||||
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) {
|
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1,
|
||||||
|
keyfile2, password)) {
|
||||||
printf("\tAuthentication by public key failed!\n");
|
printf("\tAuthentication by public key failed!\n");
|
||||||
goto shutdown;
|
goto shutdown;
|
||||||
} else {
|
} else {
|
||||||
@@ -235,14 +237,13 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
shutdown:
|
shutdown:
|
||||||
|
|
||||||
libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
|
libssh2_session_disconnect(session,
|
||||||
|
"Normal Shutdown, Thank you for playing");
|
||||||
libssh2_session_free(session);
|
libssh2_session_free(session);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
Sleep(1000);
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
|
||||||
close(sock);
|
close(sock);
|
||||||
#endif
|
#endif
|
||||||
printf("all done!\n");
|
printf("all done!\n");
|
||||||
|
291
example/simple/ssh2_exec.c
Normal file
291
example/simple/ssh2_exec.c
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
/*
|
||||||
|
* $Id: ssh2_exec.c,v 1.4 2009/05/07 20:30:22 bagder Exp $
|
||||||
|
*
|
||||||
|
* Sample showing how to use libssh2 to execute a command remotely.
|
||||||
|
*
|
||||||
|
* The sample code has fixed values for host name, user name, password
|
||||||
|
* and command to run.
|
||||||
|
*
|
||||||
|
* Run it like this:
|
||||||
|
*
|
||||||
|
* $ ./ssh2_exec 127.0.0.1 user password "uptime"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libssh2_config.h"
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
# include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
# include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
# ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
struct timeval timeout;
|
||||||
|
int rc;
|
||||||
|
fd_set fd;
|
||||||
|
fd_set *writefd = NULL;
|
||||||
|
fd_set *readfd = NULL;
|
||||||
|
int dir;
|
||||||
|
|
||||||
|
timeout.tv_sec = 10;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO(&fd);
|
||||||
|
|
||||||
|
FD_SET(socket_fd, &fd);
|
||||||
|
|
||||||
|
/* now make sure we wait in the correct direction */
|
||||||
|
dir = libssh2_session_block_directions(session);
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
|
||||||
|
readfd = &fd;
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
|
||||||
|
writefd = &fd;
|
||||||
|
|
||||||
|
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *hostname = "127.0.0.1";
|
||||||
|
const char *commandline = "uptime";
|
||||||
|
const char *username = "user";
|
||||||
|
const char *password = "password";
|
||||||
|
unsigned long hostaddr;
|
||||||
|
int sock;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
const char *fingerprint;
|
||||||
|
LIBSSH2_SESSION *session;
|
||||||
|
LIBSSH2_CHANNEL *channel;
|
||||||
|
int rc;
|
||||||
|
int exitcode;
|
||||||
|
int bytecount = 0;
|
||||||
|
size_t len;
|
||||||
|
LIBSSH2_KNOWNHOSTS *nh;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
WSADATA wsadata;
|
||||||
|
WSAStartup(MAKEWORD(2,0), &wsadata);
|
||||||
|
#endif
|
||||||
|
if (argc > 1)
|
||||||
|
/* must be ip address only */
|
||||||
|
hostname = argv[1];
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
username = argv[2];
|
||||||
|
}
|
||||||
|
if (argc > 3) {
|
||||||
|
password = argv[3];
|
||||||
|
}
|
||||||
|
if (argc > 4) {
|
||||||
|
commandline = argv[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
hostaddr = inet_addr(hostname);
|
||||||
|
|
||||||
|
/* Ultra basic "connect to port 22 on localhost"
|
||||||
|
* Your code is responsible for creating the socket establishing the
|
||||||
|
* connection
|
||||||
|
*/
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
sin.sin_port = htons(22);
|
||||||
|
sin.sin_addr.s_addr = hostaddr;
|
||||||
|
if (connect(sock, (struct sockaddr*)(&sin),
|
||||||
|
sizeof(struct sockaddr_in)) != 0) {
|
||||||
|
fprintf(stderr, "failed to connect!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a session instance */
|
||||||
|
session = libssh2_session_init();
|
||||||
|
if (!session)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* tell libssh2 we want it all done non-blocking */
|
||||||
|
libssh2_session_set_blocking(session, 0);
|
||||||
|
|
||||||
|
/* ... start it up. This will trade welcome banners, exchange keys,
|
||||||
|
* and setup crypto, compression, and MAC layers
|
||||||
|
*/
|
||||||
|
while ((rc = libssh2_session_startup(session, sock)) ==
|
||||||
|
LIBSSH2_ERROR_EAGAIN);
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nh = libssh2_knownhost_init(session);
|
||||||
|
if(!nh) {
|
||||||
|
/* eeek, do cleanup here */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read all hosts from here */
|
||||||
|
libssh2_knownhost_readfile(nh, "known_hosts",
|
||||||
|
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
|
||||||
|
|
||||||
|
/* store all known hosts to here */
|
||||||
|
libssh2_knownhost_writefile(nh, "dumpfile",
|
||||||
|
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
|
||||||
|
|
||||||
|
fingerprint = libssh2_session_hostkey(session, &len, &type);
|
||||||
|
if(fingerprint) {
|
||||||
|
struct libssh2_knownhost *host;
|
||||||
|
int check = libssh2_knownhost_check(nh, (char *)hostname,
|
||||||
|
(char *)fingerprint, len,
|
||||||
|
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
|
||||||
|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
|
||||||
|
&host);
|
||||||
|
|
||||||
|
fprintf(stderr, "Host check: %d, key: %s\n", check,
|
||||||
|
(check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
|
||||||
|
host->key:"<none>");
|
||||||
|
|
||||||
|
/*****
|
||||||
|
* At this point, we could verify that 'check' tells us the key is
|
||||||
|
* fine or bail out.
|
||||||
|
*****/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* eeek, do cleanup here */
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
libssh2_knownhost_free(nh);
|
||||||
|
|
||||||
|
if ( strlen(password) != 0 ) {
|
||||||
|
/* We could authenticate via password */
|
||||||
|
while ((rc = libssh2_userauth_password(session, username, password)) ==
|
||||||
|
LIBSSH2_ERROR_EAGAIN);
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stderr, "Authentication by password failed.\n");
|
||||||
|
goto shutdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Or by public key */
|
||||||
|
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
|
||||||
|
"/home/user/"
|
||||||
|
".ssh/id_rsa.pub",
|
||||||
|
"/home/user/"
|
||||||
|
".ssh/id_rsa",
|
||||||
|
password)) ==
|
||||||
|
LIBSSH2_ERROR_EAGAIN);
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stderr, "\tAuthentication by public key failed\n");
|
||||||
|
goto shutdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
libssh2_trace(session, ~0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Exec non-blocking on the remove host */
|
||||||
|
while( (channel = libssh2_channel_open_session(session)) == NULL &&
|
||||||
|
libssh2_session_last_error(session,NULL,NULL,0) ==
|
||||||
|
LIBSSH2_ERROR_EAGAIN )
|
||||||
|
{
|
||||||
|
waitsocket(sock, session);
|
||||||
|
}
|
||||||
|
if( channel == NULL )
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Error\n");
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
while( (rc = libssh2_channel_exec(channel, commandline)) ==
|
||||||
|
LIBSSH2_ERROR_EAGAIN )
|
||||||
|
{
|
||||||
|
waitsocket(sock, session);
|
||||||
|
}
|
||||||
|
if( rc != 0 )
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Error\n");
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* loop until we block */
|
||||||
|
int rc;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char buffer[0x4000];
|
||||||
|
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
|
||||||
|
if( rc > 0 )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bytecount += rc;
|
||||||
|
fprintf(stderr, "We read:\n");
|
||||||
|
for( i=0; i < rc; ++i )
|
||||||
|
fputc( buffer[i], stderr);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while( rc > 0 );
|
||||||
|
|
||||||
|
/* this is due to blocking that would occur otherwise so we loop on
|
||||||
|
this condition */
|
||||||
|
if( rc == LIBSSH2_ERROR_EAGAIN )
|
||||||
|
{
|
||||||
|
waitsocket(sock, session);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exitcode = 127;
|
||||||
|
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
|
||||||
|
waitsocket(sock, session);
|
||||||
|
|
||||||
|
if( rc == 0 )
|
||||||
|
{
|
||||||
|
exitcode = libssh2_channel_get_exit_status( channel );
|
||||||
|
}
|
||||||
|
printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
|
||||||
|
|
||||||
|
libssh2_channel_free(channel);
|
||||||
|
channel = NULL;
|
||||||
|
|
||||||
|
shutdown:
|
||||||
|
|
||||||
|
libssh2_session_disconnect(session,
|
||||||
|
"Normal Shutdown, Thank you for playing");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
closesocket(sock);
|
||||||
|
#else
|
||||||
|
close(sock);
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "all done\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
433
example/simple/x11.c
Normal file
433
example/simple/x11.c
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Sample showing how to makes SSH2 with X11 Forwarding works.
|
||||||
|
*
|
||||||
|
* Usage :
|
||||||
|
* "ssh2 host user password [DEBUG]"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
#define _PATH_UNIX_X "/tmp/.X11-unix/X%d"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chained list that contains channels and associated X11 socket for each X11
|
||||||
|
* connections
|
||||||
|
*/
|
||||||
|
struct chan_X11_list {
|
||||||
|
LIBSSH2_CHANNEL *chan;
|
||||||
|
int sock;
|
||||||
|
struct chan_X11_list *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chan_X11_list * gp_x11_chan = NULL;
|
||||||
|
struct termios _saved_tio;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to remove a Node of the chained list
|
||||||
|
*/
|
||||||
|
static void remove_node(struct chan_X11_list *elem)
|
||||||
|
{
|
||||||
|
struct chan_X11_list *current_node = NULL;
|
||||||
|
|
||||||
|
current_node = gp_x11_chan;
|
||||||
|
|
||||||
|
if (gp_x11_chan == elem) {
|
||||||
|
/* Removing the only one element in the list */
|
||||||
|
free(gp_x11_chan);
|
||||||
|
gp_x11_chan = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( current_node->next != NULL) {
|
||||||
|
if (current_node->next ==elem) {
|
||||||
|
current_node->next = current_node->next->next;
|
||||||
|
current_node = current_node->next;
|
||||||
|
free(current_node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void session_shutdown(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
libssh2_session_disconnect(session,
|
||||||
|
"Session Shutdown, Thank you for playing");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _raw_mode(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct termios tio;
|
||||||
|
|
||||||
|
rc = tcgetattr(fileno(stdin), &tio);
|
||||||
|
if (rc != -1) {
|
||||||
|
_saved_tio = tio;
|
||||||
|
cfmakeraw(&tio);
|
||||||
|
rc = tcsetattr(fileno(stdin), TCSADRAIN, &tio);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _normal_mode(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
rc = tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CallBack to initialize the forwarding.
|
||||||
|
* Save the channel to loop on it, save the X11 forwarded socket to send
|
||||||
|
* and receive info from our X server.
|
||||||
|
*/
|
||||||
|
static void x11_callback(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel,
|
||||||
|
char *shost, int sport, void **abstract)
|
||||||
|
{
|
||||||
|
const char * display = NULL;
|
||||||
|
char * ptr = NULL;
|
||||||
|
char * temp_buff = NULL;
|
||||||
|
int display_port = 0;
|
||||||
|
int sock = 0;
|
||||||
|
int rc = 0;
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
struct chan_X11_list *new;
|
||||||
|
struct chan_X11_list *chan_iter;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connect to the display
|
||||||
|
* Inspired by x11_connect_display in openssh
|
||||||
|
*/
|
||||||
|
display = getenv("DISPLAY");
|
||||||
|
if ( display != NULL) {
|
||||||
|
if (strncmp( display, "unix:", 5) == 0 ||
|
||||||
|
display[0] == ':') {
|
||||||
|
/* Connect to the local unix domain */
|
||||||
|
ptr = strrchr(display, ':');
|
||||||
|
temp_buff = (char *) calloc(strlen(ptr+1), sizeof(char));
|
||||||
|
memcpy(temp_buff, ptr+1, strlen(ptr+1));
|
||||||
|
display_port = atoi(temp_buff);
|
||||||
|
|
||||||
|
sock = socket(AF_UNIX,SOCK_STREAM, 0);
|
||||||
|
if (sock <0)
|
||||||
|
return;
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
snprintf(addr.sun_path, sizeof(addr.sun_path),
|
||||||
|
_PATH_UNIX_X, display_port);
|
||||||
|
rc = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
|
||||||
|
|
||||||
|
if (rc != -1){
|
||||||
|
/* Connection Successfull */
|
||||||
|
if (gp_x11_chan == NULL) {
|
||||||
|
/* Calloc ensure that gp_X11_chan is full of 0 */
|
||||||
|
gp_x11_chan = (struct chan_X11_list *)
|
||||||
|
calloc(1, sizeof(struct chan_X11_list));
|
||||||
|
gp_x11_chan->sock = sock;
|
||||||
|
gp_x11_chan->chan = channel;
|
||||||
|
gp_x11_chan->next = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chan_iter = gp_x11_chan;
|
||||||
|
while (chan_iter->next != NULL)
|
||||||
|
chan_iter = chan_iter->next;
|
||||||
|
/* Create the new Node */
|
||||||
|
new = (struct chan_X11_list *)
|
||||||
|
malloc(sizeof(struct chan_X11_list));
|
||||||
|
new->sock = sock;
|
||||||
|
new->chan = channel;
|
||||||
|
new->next = NULL;
|
||||||
|
chan_iter->next = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send and receive Data for the X11 channel.
|
||||||
|
* If the connection is closed, returns -1, 0 either.
|
||||||
|
*/
|
||||||
|
static int x11_send_receive(LIBSSH2_CHANNEL *channel, int sock)
|
||||||
|
{
|
||||||
|
char * buf = NULL;
|
||||||
|
int bufsize = 8192;
|
||||||
|
int rc = 0;
|
||||||
|
int nfds = 1;
|
||||||
|
LIBSSH2_POLLFD *fds = NULL;
|
||||||
|
fd_set set;
|
||||||
|
struct timeval timeval_out;
|
||||||
|
timeval_out.tv_sec = 0;
|
||||||
|
timeval_out.tv_usec = 0;
|
||||||
|
|
||||||
|
|
||||||
|
FD_ZERO(&set);
|
||||||
|
FD_SET(sock,&set);
|
||||||
|
|
||||||
|
if ((buf = calloc (bufsize, sizeof(char))) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((fds = malloc (sizeof (LIBSSH2_POLLFD))) == NULL) {
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fds[0].type = LIBSSH2_POLLFD_CHANNEL;
|
||||||
|
fds[0].fd.channel = channel;
|
||||||
|
fds[0].events = LIBSSH2_POLLFD_POLLIN;
|
||||||
|
fds[0].revents = LIBSSH2_POLLFD_POLLIN;
|
||||||
|
|
||||||
|
rc = libssh2_poll(fds, nfds, 0);
|
||||||
|
if (rc >0) {
|
||||||
|
rc = libssh2_channel_read(channel, buf,sizeof(buf));
|
||||||
|
rc = write(sock, buf, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = select(sock+1,&set,NULL,NULL,&timeval_out);
|
||||||
|
if (rc > 0) {
|
||||||
|
memset((void *)buf,0,bufsize);
|
||||||
|
|
||||||
|
/* Data in sock*/
|
||||||
|
rc = read(sock, buf,sizeof(buf));
|
||||||
|
if (rc > 0)
|
||||||
|
rc = libssh2_channel_write(channel,buf, rc);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fds);
|
||||||
|
free(buf);
|
||||||
|
if (libssh2_channel_eof (channel) == 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main, more than inspired by ssh2.c by Bagder
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned long hostaddr = 0;
|
||||||
|
int sock = 0;
|
||||||
|
int rc = 0;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
LIBSSH2_SESSION *session;
|
||||||
|
LIBSSH2_CHANNEL *channel;
|
||||||
|
char *username = NULL;
|
||||||
|
char *password = NULL;
|
||||||
|
size_t bufsiz = 8193;
|
||||||
|
char *buf = NULL;
|
||||||
|
int set_debug_on = 0;
|
||||||
|
int nfds = 1;
|
||||||
|
LIBSSH2_POLLFD *fds = NULL;
|
||||||
|
|
||||||
|
/* Chan List struct */
|
||||||
|
struct chan_X11_list *current_node = NULL;
|
||||||
|
|
||||||
|
/* Struct winsize for term size */
|
||||||
|
struct winsize w_size;
|
||||||
|
struct winsize w_size_bck;
|
||||||
|
|
||||||
|
/* For select on stdin */
|
||||||
|
fd_set set;
|
||||||
|
struct timeval timeval_out;
|
||||||
|
timeval_out.tv_sec = 0;
|
||||||
|
timeval_out.tv_usec = 10;
|
||||||
|
|
||||||
|
|
||||||
|
if (argc > 3) {
|
||||||
|
hostaddr = inet_addr(argv[1]);
|
||||||
|
username = argv[2];
|
||||||
|
password = argv[3];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Usage: %s destination username password",
|
||||||
|
argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 4) {
|
||||||
|
set_debug_on = 1;
|
||||||
|
fprintf (stderr, "DEBUG is ON: %d\n", set_debug_on);
|
||||||
|
}
|
||||||
|
|
||||||
|
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
sin.sin_port = htons (22);
|
||||||
|
sin.sin_addr.s_addr = hostaddr;
|
||||||
|
|
||||||
|
rc = connect(sock, (struct sockaddr *) &sin,
|
||||||
|
sizeof(struct sockaddr_in));
|
||||||
|
if (rc != 0) {
|
||||||
|
fprintf (stderr, "Failed to established connection!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Open a session */
|
||||||
|
session = libssh2_session_init ();
|
||||||
|
rc = libssh2_session_startup (session, sock);
|
||||||
|
if (rc != 0) {
|
||||||
|
fprintf(stderr, "Failed Start the SSH session\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_debug_on == 1)
|
||||||
|
libssh2_trace(session, LIBSSH2_TRACE_CONN);
|
||||||
|
|
||||||
|
/* Set X11 Callback */
|
||||||
|
libssh2_session_callback_set(session, LIBSSH2_CALLBACK_X11,
|
||||||
|
(void *)x11_callback);
|
||||||
|
|
||||||
|
/* Authenticate via password */
|
||||||
|
rc = libssh2_userauth_password(session, username, password);
|
||||||
|
if (rc != 0) {
|
||||||
|
fprintf(stderr, "Failed to authenticate\n");
|
||||||
|
session_shutdown(session);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open a channel */
|
||||||
|
channel = libssh2_channel_open_session(session);
|
||||||
|
if ( channel == NULL ) {
|
||||||
|
fprintf(stderr, "Failed to open a new channel\n");
|
||||||
|
session_shutdown(session);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Request a PTY */
|
||||||
|
rc = libssh2_channel_request_pty( channel, "xterm");
|
||||||
|
if (rc != 0) {
|
||||||
|
fprintf(stderr, "Failed to request a pty\n");
|
||||||
|
session_shutdown(session);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request X11 */
|
||||||
|
rc = libssh2_channel_x11_req(channel,0);
|
||||||
|
if(rc!=0) {
|
||||||
|
fprintf(stderr, "Failed to request X11 forwarding\n");
|
||||||
|
session_shutdown(session);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request a shell */
|
||||||
|
rc = libssh2_channel_shell(channel);
|
||||||
|
if (rc!=0) {
|
||||||
|
fprintf(stderr, "Failed to open a shell\n");
|
||||||
|
session_shutdown(session);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = _raw_mode();
|
||||||
|
if (rc != 0) {
|
||||||
|
fprintf(stderr, "Failed to entered in raw mode\n");
|
||||||
|
session_shutdown(session);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
FD_ZERO(&set);
|
||||||
|
FD_SET(fileno(stdin),&set);
|
||||||
|
|
||||||
|
/* Search if a resize pty has to be send */
|
||||||
|
ioctl(fileno(stdin), TIOCGWINSZ, &w_size);
|
||||||
|
if ((w_size.ws_row != w_size_bck.ws_row) ||
|
||||||
|
(w_size.ws_col != w_size_bck.ws_col)) {
|
||||||
|
w_size_bck = w_size;
|
||||||
|
|
||||||
|
libssh2_channel_request_pty_size(channel,
|
||||||
|
w_size.ws_col,
|
||||||
|
w_size.ws_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((buf = calloc (bufsiz, sizeof(char))) == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((fds = malloc (sizeof (LIBSSH2_POLLFD))) == NULL) {
|
||||||
|
free(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fds[0].type = LIBSSH2_POLLFD_CHANNEL;
|
||||||
|
fds[0].fd.channel = channel;
|
||||||
|
fds[0].events = LIBSSH2_POLLFD_POLLIN;
|
||||||
|
fds[0].revents = LIBSSH2_POLLFD_POLLIN;
|
||||||
|
|
||||||
|
rc = libssh2_poll(fds, nfds, 0);
|
||||||
|
if (rc >0) {
|
||||||
|
rc = libssh2_channel_read(channel, buf,sizeof(buf));
|
||||||
|
fprintf(stdout, "%s", buf);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Looping on X clients */
|
||||||
|
if (gp_x11_chan != NULL) {
|
||||||
|
current_node = gp_x11_chan;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
current_node = NULL;
|
||||||
|
|
||||||
|
while (current_node != NULL) {
|
||||||
|
rc = x11_send_receive(current_node->chan, current_node->sock);
|
||||||
|
if (rc == -1){
|
||||||
|
shutdown(current_node->sock,SHUT_RDWR);
|
||||||
|
close(current_node->sock);
|
||||||
|
remove_node(current_node);
|
||||||
|
|
||||||
|
}
|
||||||
|
current_node = current_node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rc = select(fileno(stdin)+1,&set,NULL,NULL,&timeval_out);
|
||||||
|
if (rc > 0) {
|
||||||
|
/* Data in stdin*/
|
||||||
|
rc = read(fileno(stdin), buf,1);
|
||||||
|
if (rc > 0)
|
||||||
|
libssh2_channel_write(channel,buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
free (fds);
|
||||||
|
free (buf);
|
||||||
|
|
||||||
|
if (libssh2_channel_eof (channel) == 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel) {
|
||||||
|
libssh2_channel_free (channel);
|
||||||
|
channel = NULL;
|
||||||
|
}
|
||||||
|
_normal_mode();
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
|
||||||
|
* Copyright (c) 2009 by Daniel Stenberg
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -87,13 +88,13 @@ typedef long long libssh2_int64_t;
|
|||||||
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_CVS"
|
#define LIBSSH2_VERSION "1.1.1_CVS"
|
||||||
|
|
||||||
/* 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 1
|
||||||
#define LIBSSH2_VERSION_PATCH 0
|
#define LIBSSH2_VERSION_PATCH 1
|
||||||
|
|
||||||
/* 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
|
||||||
@@ -110,7 +111,7 @@ 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 0x010100
|
#define LIBSSH2_VERSION_NUM 0x010101
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
@@ -240,6 +241,7 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
|
|||||||
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
|
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
|
||||||
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
|
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
|
||||||
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
|
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
|
||||||
|
typedef struct _LIBSSH2_KNOWNHOSTS LIBSSH2_KNOWNHOSTS;
|
||||||
|
|
||||||
typedef struct _LIBSSH2_POLLFD {
|
typedef struct _LIBSSH2_POLLFD {
|
||||||
unsigned char type; /* LIBSSH2_POLLFD_* below */
|
unsigned char type; /* LIBSSH2_POLLFD_* below */
|
||||||
@@ -292,6 +294,11 @@ typedef struct _LIBSSH2_POLLFD {
|
|||||||
#define LIBSSH2_HOSTKEY_HASH_MD5 1
|
#define LIBSSH2_HOSTKEY_HASH_MD5 1
|
||||||
#define LIBSSH2_HOSTKEY_HASH_SHA1 2
|
#define LIBSSH2_HOSTKEY_HASH_SHA1 2
|
||||||
|
|
||||||
|
/* Hostkey Types */
|
||||||
|
#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0
|
||||||
|
#define LIBSSH2_HOSTKEY_TYPE_RSA 1
|
||||||
|
#define LIBSSH2_HOSTKEY_TYPE_DSS 2
|
||||||
|
|
||||||
/* Disconnect Codes (defined by SSH protocol) */
|
/* Disconnect Codes (defined by SSH protocol) */
|
||||||
#define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
|
#define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
|
||||||
#define SSH_DISCONNECT_PROTOCOL_ERROR 2
|
#define SSH_DISCONNECT_PROTOCOL_ERROR 2
|
||||||
@@ -348,6 +355,7 @@ typedef struct _LIBSSH2_POLLFD {
|
|||||||
#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35
|
#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35
|
||||||
#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
|
||||||
|
|
||||||
/* Session API */
|
/* Session API */
|
||||||
LIBSSH2_API LIBSSH2_SESSION *
|
LIBSSH2_API LIBSSH2_SESSION *
|
||||||
@@ -377,6 +385,9 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session);
|
|||||||
LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session,
|
LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session,
|
||||||
int hash_type);
|
int hash_type);
|
||||||
|
|
||||||
|
LIBSSH2_API const char *libssh2_session_hostkey(LIBSSH2_SESSION *session,
|
||||||
|
size_t *len, int *type);
|
||||||
|
|
||||||
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session,
|
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session,
|
||||||
int method_type,
|
int method_type,
|
||||||
const char *prefs);
|
const char *prefs);
|
||||||
@@ -663,6 +674,197 @@ LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest,
|
|||||||
LIBSSH2_API
|
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 */
|
||||||
|
|
||||||
|
struct libssh2_knownhost {
|
||||||
|
unsigned int magic; /* magic stored by the library */
|
||||||
|
void *node; /* handle to the internal representation of this host */
|
||||||
|
char *name; /* this is NULL if no plain text host name exists */
|
||||||
|
char *key; /* key in base64/printable format */
|
||||||
|
int typemask;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_init
|
||||||
|
*
|
||||||
|
* Init a collection of known hosts. Returns the pointer to a collection.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API LIBSSH2_KNOWNHOSTS *
|
||||||
|
libssh2_knownhost_init(LIBSSH2_SESSION *session);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_add
|
||||||
|
*
|
||||||
|
* Add a host and its associated key to the collection of known hosts.
|
||||||
|
*
|
||||||
|
* The 'type' argument specifies on what format the given host is:
|
||||||
|
*
|
||||||
|
* plain - ascii "hostname.domain.tld"
|
||||||
|
* sha1 - SHA1(<salt> <host>) base64-encoded!
|
||||||
|
* custom - another hash
|
||||||
|
*
|
||||||
|
* If 'sha1' is selected as type, the salt must be provided to the salt
|
||||||
|
* argument. This too base64 encoded.
|
||||||
|
*
|
||||||
|
* The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If
|
||||||
|
* a custom type is used, salt is ignored and you must provide the host
|
||||||
|
* pre-hashed when checking for it in the libssh2_knownhost_check() function.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* host format (2 bits) */
|
||||||
|
#define LIBSSH2_KNOWNHOST_TYPE_MASK 0xffff
|
||||||
|
#define LIBSSH2_KNOWNHOST_TYPE_PLAIN 1
|
||||||
|
#define LIBSSH2_KNOWNHOST_TYPE_SHA1 2 /* always base64 encoded */
|
||||||
|
#define LIBSSH2_KNOWNHOST_TYPE_CUSTOM 3
|
||||||
|
|
||||||
|
/* key format (2 bits) */
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEYENC_MASK (3<<16)
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEYENC_RAW (1<<16)
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEYENC_BASE64 (2<<16)
|
||||||
|
|
||||||
|
/* type of key (2 bits) */
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEY_MASK (3<<18)
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18)
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18)
|
||||||
|
#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18)
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *host,
|
||||||
|
const char *salt,
|
||||||
|
const char *key, size_t keylen, int typemask,
|
||||||
|
struct libssh2_knownhost **store);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_check
|
||||||
|
*
|
||||||
|
* Check a host and its associated key against the collection of known hosts.
|
||||||
|
*
|
||||||
|
* The type is the type/format of the given host name.
|
||||||
|
*
|
||||||
|
* plain - ascii "hostname.domain.tld"
|
||||||
|
* custom - prehashed base64 encoded. Note that this cannot use any salts.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 'knownhost' may be set to NULL if you don't care about that info.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
* LIBSSH2_KNOWNHOST_CHECK_* values, see below
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIBSSH2_KNOWNHOST_CHECK_MATCH 0
|
||||||
|
#define LIBSSH2_KNOWNHOST_CHECK_MISMATCH 1
|
||||||
|
#define LIBSSH2_KNOWNHOST_CHECK_NOTFOUND 2
|
||||||
|
#define LIBSSH2_KNOWNHOST_CHECK_FAILURE 3
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *host, const char *key, size_t keylen,
|
||||||
|
int typemask,
|
||||||
|
struct libssh2_knownhost **knownhost);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_del
|
||||||
|
*
|
||||||
|
* Remove a host from the collection of known hosts. The 'entry' struct is
|
||||||
|
* retrieved by a call to libssh2_knownhost_check().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost *entry);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_free
|
||||||
|
*
|
||||||
|
* Free an entire collection of known hosts.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API void
|
||||||
|
libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_readline()
|
||||||
|
*
|
||||||
|
* Pass in a line of a file of 'type'. It makes libssh2 read this line.
|
||||||
|
*
|
||||||
|
* LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *line, size_t len, int type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_readfile
|
||||||
|
*
|
||||||
|
* Add hosts+key pairs from a given file.
|
||||||
|
*
|
||||||
|
* Returns a negative value for error or number of successfully added hosts.
|
||||||
|
*
|
||||||
|
* This implementation currently only knows one 'type' (openssh), all others
|
||||||
|
* are reserved for future use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIBSSH2_KNOWNHOST_FILE_OPENSSH 1
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *filename, int type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_writeline()
|
||||||
|
*
|
||||||
|
* Ask libssh2 to convert a known host to an output line for storage.
|
||||||
|
*
|
||||||
|
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
|
||||||
|
* output buffer is too small to hold the desired output.
|
||||||
|
*
|
||||||
|
* This implementation currently only knows one 'type' (openssh), all others
|
||||||
|
* are reserved for future use.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost *known,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
size_t *outlen, /* the amount of written data */
|
||||||
|
int type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_writefile
|
||||||
|
*
|
||||||
|
* Write hosts+key pairs to a given file.
|
||||||
|
*
|
||||||
|
* This implementation currently only knows one 'type' (openssh), all others
|
||||||
|
* are reserved for future use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *filename, int type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_get()
|
||||||
|
*
|
||||||
|
* Traverse the internal list of known hosts. Pass NULL to 'prev' to get
|
||||||
|
* the first one. Or pass a poiner to the previously returned one to get the
|
||||||
|
* next.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 if a fine host was stored in 'store'
|
||||||
|
* 1 if end of hosts
|
||||||
|
* [negative] on errors
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost **store,
|
||||||
|
struct libssh2_knownhost *prev);
|
||||||
|
|
||||||
/* NOTE NOTE NOTE
|
/* NOTE NOTE NOTE
|
||||||
libssh2_trace() has no function in builds that aren't built with debug
|
libssh2_trace() has no function in builds that aren't built with debug
|
||||||
|
@@ -46,6 +46,8 @@
|
|||||||
#ifndef LIBSSH2_PUBLICKEY_H
|
#ifndef LIBSSH2_PUBLICKEY_H
|
||||||
#define LIBSSH2_PUBLICKEY_H 1
|
#define LIBSSH2_PUBLICKEY_H 1
|
||||||
|
|
||||||
|
#include "libssh2.h"
|
||||||
|
|
||||||
typedef struct _LIBSSH2_PUBLICKEY LIBSSH2_PUBLICKEY;
|
typedef struct _LIBSSH2_PUBLICKEY LIBSSH2_PUBLICKEY;
|
||||||
|
|
||||||
typedef struct _libssh2_publickey_attribute {
|
typedef struct _libssh2_publickey_attribute {
|
||||||
|
@@ -38,6 +38,8 @@
|
|||||||
#ifndef LIBSSH2_SFTP_H
|
#ifndef LIBSSH2_SFTP_H
|
||||||
#define LIBSSH2_SFTP_H 1
|
#define LIBSSH2_SFTP_H 1
|
||||||
|
|
||||||
|
#include "libssh2.h"
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
5
m4/.gitignore
vendored
Normal file
5
m4/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
libtool.m4
|
||||||
|
ltoptions.m4
|
||||||
|
ltsugar.m4
|
||||||
|
ltversion.m4
|
||||||
|
lt~obsolete.m4
|
@@ -5,7 +5,7 @@
|
|||||||
##
|
##
|
||||||
## Comments to: Guenter Knauf <eflash@gmx.net>
|
## Comments to: Guenter Knauf <eflash@gmx.net>
|
||||||
##
|
##
|
||||||
## $Id: Makefile.netware,v 1.13 2009/03/06 07:25:37 gknauf Exp $
|
## $Id: Makefile.netware,v 1.14 2009/04/09 03:13:51 gknauf Exp $
|
||||||
#
|
#
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ endif
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
ifndef OPENSSL_PATH
|
ifndef OPENSSL_PATH
|
||||||
OPENSSL_PATH = ../../openssl-0.9.8j
|
OPENSSL_PATH = ../../openssl-0.9.8k
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Edit the path below to point to your Distribution folder.
|
# Edit the path below to point to your Distribution folder.
|
||||||
@@ -76,7 +76,7 @@ ifdef METROWERKS
|
|||||||
MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support/Metrowerks Support
|
MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support/Metrowerks Support
|
||||||
CC = mwccnlm
|
CC = mwccnlm
|
||||||
else
|
else
|
||||||
CC = gcc
|
CC = $(CROSSPREFIX)gcc
|
||||||
endif
|
endif
|
||||||
CP = cp -afv
|
CP = cp -afv
|
||||||
# RM = rm -f
|
# RM = rm -f
|
||||||
@@ -119,12 +119,12 @@ else
|
|||||||
CFLAGS += -align 1
|
CFLAGS += -align 1
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
LD = nlmconv
|
LD = $(CROSSPREFIX)nlmconv
|
||||||
LDFLAGS = -T
|
LDFLAGS = -T
|
||||||
AR = ar
|
AR = $(CROSSPREFIX)ar
|
||||||
ARFLAGS = -cq
|
ARFLAGS = -cq
|
||||||
LIBEXT = a
|
LIBEXT = a
|
||||||
RANLIB = ranlib
|
RANLIB = $(CROSSPREFIX)ranlib
|
||||||
CFLAGS += -fno-builtin -fpcc-struct-return -fno-strict-aliasing
|
CFLAGS += -fno-builtin -fpcc-struct-return -fno-strict-aliasing
|
||||||
CFLAGS += -Wall # -pedantic
|
CFLAGS += -Wall # -pedantic
|
||||||
#CFLAGS += -Wno-pointer-sign
|
#CFLAGS += -Wno-pointer-sign
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
##
|
##
|
||||||
## Comments to: Guenter Knauf <eflash@gmx.net>
|
## Comments to: Guenter Knauf <eflash@gmx.net>
|
||||||
##
|
##
|
||||||
## $Id: Makefile.netware,v 1.9 2009/03/06 07:25:37 gknauf Exp $
|
## $Id: Makefile.netware,v 1.10 2009/04/09 03:13:52 gknauf Exp $
|
||||||
#
|
#
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ endif
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
ifndef OPENSSL_PATH
|
ifndef OPENSSL_PATH
|
||||||
OPENSSL_PATH = ../../../openssl-0.9.8j
|
OPENSSL_PATH = ../../../openssl-0.9.8k
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Edit the var below to enable static linking of libssh2 and libz
|
# Edit the var below to enable static linking of libssh2 and libz
|
||||||
@@ -70,7 +70,7 @@ ifdef METROWERKS
|
|||||||
MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support/Metrowerks Support
|
MWCW_PATH = $(subst \,/,$(METROWERKS))/Novell Support/Metrowerks Support
|
||||||
CC = mwccnlm
|
CC = mwccnlm
|
||||||
else
|
else
|
||||||
CC = gcc
|
CC = $(CROSSPREFIX)gcc
|
||||||
endif
|
endif
|
||||||
CP = cp -afv
|
CP = cp -afv
|
||||||
# RM = rm -f
|
# RM = rm -f
|
||||||
@@ -131,7 +131,7 @@ SDK_CLIB = $(NDK_ROOT)/nwsdk
|
|||||||
SDK_LIBC = $(NDK_ROOT)/libc
|
SDK_LIBC = $(NDK_ROOT)/libc
|
||||||
SNPRINTF = $(NDKBASE)/snprintf
|
SNPRINTF = $(NDKBASE)/snprintf
|
||||||
|
|
||||||
INCLUDES = -I. -I../../include
|
INCLUDES = -I.. -I../../include
|
||||||
|
|
||||||
LDLIBS =
|
LDLIBS =
|
||||||
|
|
||||||
|
3
src/.gitignore
vendored
Normal file
3
src/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
libssh2_config.h
|
||||||
|
libssh2_config.h.in
|
||||||
|
stamp-h1
|
@@ -1,15 +1,10 @@
|
|||||||
# $Id: Makefile.am,v 1.19 2009/03/26 22:25:23 bagder Exp $
|
# $Id: Makefile.am,v 1.21 2009/05/07 17:21:56 bagder Exp $
|
||||||
AUTOMAKE_OPTIONS = foreign nostdinc
|
AUTOMAKE_OPTIONS = foreign nostdinc
|
||||||
|
|
||||||
libssh2_la_SOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
|
# Makefile.inc provides the CSOURCES and HHEADERS defines
|
||||||
packet.c publickey.c scp.c session.c sftp.c userauth.c libssh2_priv.h \
|
include ../Makefile.inc
|
||||||
openssl.h libgcrypt.h transport.c version.c transport.h channel.h comp.h mac.h
|
|
||||||
|
|
||||||
if LIBGCRYPT
|
libssh2_la_SOURCES = $(CSOURCES) $(HHEADERS)
|
||||||
libssh2_la_SOURCES += libgcrypt.c pem.c
|
|
||||||
else
|
|
||||||
libssh2_la_SOURCES += openssl.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
EXTRA_DIST = libssh2_config.h.in NMakefile
|
EXTRA_DIST = libssh2_config.h.in NMakefile
|
||||||
|
|
||||||
|
102
src/channel.c
102
src/channel.c
@@ -45,6 +45,7 @@
|
|||||||
#ifdef HAVE_INTTYPES_H
|
#ifdef HAVE_INTTYPES_H
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
@@ -88,14 +89,23 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session)
|
|||||||
* Locate a channel pointer by number
|
* Locate a channel pointer by number
|
||||||
*/
|
*/
|
||||||
LIBSSH2_CHANNEL *
|
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 = session->channels.head;
|
LIBSSH2_CHANNEL *channel;
|
||||||
while (channel) {
|
LIBSSH2_LISTENER *listener;
|
||||||
if (channel->local.id == channel_id) {
|
|
||||||
|
for(channel = session->channels.head; channel; channel = channel->next) {
|
||||||
|
if (channel->local.id == channel_id)
|
||||||
return channel;
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We didn't find the channel in the session, let's then check its
|
||||||
|
listeners... */
|
||||||
|
for(listener = session->listeners; listener; listener = listener->next) {
|
||||||
|
for(channel = listener->queue; channel; channel = channel->next) {
|
||||||
|
if (channel->local.id == channel_id)
|
||||||
|
return channel;
|
||||||
}
|
}
|
||||||
channel = channel->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -779,6 +789,8 @@ channel_forward_accept(LIBSSH2_LISTENER *listener)
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
|
||||||
|
"Channel not found", 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1758,28 +1770,18 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
"stream #%d",
|
"stream #%d",
|
||||||
(int) buflen, channel->local.id, channel->remote.id,
|
(int) buflen, channel->local.id, channel->remote.id,
|
||||||
stream_id);
|
stream_id);
|
||||||
|
|
||||||
rc = 1; /* set to >0 to let the while loop start */
|
|
||||||
|
|
||||||
/* process all pending incoming packets */
|
|
||||||
while (rc > 0)
|
|
||||||
rc = _libssh2_transport_read(session);
|
|
||||||
|
|
||||||
if ((rc < 0) && (rc != PACKET_EAGAIN))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
channel->read_state = libssh2_NB_state_created;
|
channel->read_state = libssh2_NB_state_created;
|
||||||
}
|
}
|
||||||
else {
|
rc = 1; /* set to >0 to let the while loop start */
|
||||||
/* We're not in the idle state, but in order to "even out" the network
|
|
||||||
readings we do a single shot read here as well. Tests prove that
|
/* Process all pending incoming packets in all states in order to "even
|
||||||
this way produces faster transfers. */
|
out" the network readings. Tests prove that this way produces faster
|
||||||
|
transfers. */
|
||||||
|
while (rc > 0)
|
||||||
rc = _libssh2_transport_read(session);
|
rc = _libssh2_transport_read(session);
|
||||||
|
|
||||||
/* ignore PACKET_EAGAIN but return failure for the rest */
|
if ((rc < 0) && (rc != PACKET_EAGAIN))
|
||||||
if ((rc < 0) && (rc != PACKET_EAGAIN))
|
return -1;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* =============================== NOTE ===============================
|
* =============================== NOTE ===============================
|
||||||
@@ -1794,8 +1796,15 @@ static ssize_t channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
|
|
||||||
channel->read_packet = session->packets.head;
|
channel->read_packet = session->packets.head;
|
||||||
while (channel->read_packet &&
|
while (channel->read_packet &&
|
||||||
!channel->remote.close &&
|
|
||||||
(bytes_read < (int) buflen)) {
|
(bytes_read < (int) buflen)) {
|
||||||
|
/* previously this loop condition also checked for
|
||||||
|
!channel->remote.close but we cannot let it do this:
|
||||||
|
|
||||||
|
We may have a series of packets to read that are still pending even
|
||||||
|
if a close has been received. Acknowledging the close too early
|
||||||
|
makes us flush buffers prematurely and loose data.
|
||||||
|
*/
|
||||||
|
|
||||||
LIBSSH2_PACKET *readpkt = channel->read_packet;
|
LIBSSH2_PACKET *readpkt = channel->read_packet;
|
||||||
|
|
||||||
/* In case packet gets destroyed during this iteration */
|
/* In case packet gets destroyed during this iteration */
|
||||||
@@ -1989,7 +1998,9 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
|
|||||||
/*
|
/*
|
||||||
* _libssh2_channel_write
|
* _libssh2_channel_write
|
||||||
*
|
*
|
||||||
* Send data to a channel
|
* Send data to a channel. Note that if this returns EAGAIN or simply didn't
|
||||||
|
* send the entire packet, the caller must call this function again with the
|
||||||
|
* SAME input arguments.
|
||||||
*/
|
*/
|
||||||
ssize_t
|
ssize_t
|
||||||
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||||
@@ -1997,6 +2008,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
{
|
{
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
libssh2pack_t rc;
|
libssh2pack_t rc;
|
||||||
|
ssize_t wrote = 0; /* counter for this specific this call */
|
||||||
|
|
||||||
if (channel->write_state == libssh2_NB_state_idle) {
|
if (channel->write_state == libssh2_NB_state_idle) {
|
||||||
channel->write_bufwrote = 0;
|
channel->write_bufwrote = 0;
|
||||||
@@ -2052,29 +2064,19 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
channel->write_s += 4;
|
channel->write_s += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* twiddle our thumbs until there's window space available */
|
/* drain the incoming flow first */
|
||||||
while (channel->local.window_size <= 0) {
|
do
|
||||||
/* Don't worry -- This is never hit unless it's a
|
|
||||||
blocking channel anyway */
|
|
||||||
rc = _libssh2_transport_read(session);
|
rc = _libssh2_transport_read(session);
|
||||||
|
while (rc > 0);
|
||||||
|
|
||||||
if (rc < 0) {
|
if(channel->local.window_size <= 0) {
|
||||||
/* Error or EAGAIN occurred, disconnect? */
|
/* there's no more room for data so we stop sending now */
|
||||||
if (rc != PACKET_EAGAIN) {
|
if(!wrote) {
|
||||||
LIBSSH2_FREE(session, channel->write_packet);
|
/* if nothing has been written at this point we're at an
|
||||||
channel->write_state = libssh2_NB_state_idle;
|
EAGAIN point */
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
/*
|
|
||||||
* if rc == 0, then fake EAGAIN to prevent busyloops until
|
|
||||||
* data arriaves on the network which seemed like a very
|
|
||||||
* bad idea
|
|
||||||
*/
|
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't exceed the remote end's limits */
|
/* Don't exceed the remote end's limits */
|
||||||
@@ -2132,15 +2134,9 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
buflen -= channel->write_bufwrite;
|
buflen -= channel->write_bufwrite;
|
||||||
buf += channel->write_bufwrite;
|
buf += channel->write_bufwrite;
|
||||||
channel->write_bufwrote += channel->write_bufwrite;
|
channel->write_bufwrote += channel->write_bufwrite;
|
||||||
|
wrote += channel->write_bufwrite;
|
||||||
|
|
||||||
channel->write_state = libssh2_NB_state_allocated;
|
channel->write_state = libssh2_NB_state_allocated;
|
||||||
|
|
||||||
/*
|
|
||||||
* Not sure this is still wanted
|
|
||||||
if (!channel->session->socket_block) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2149,7 +2145,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
|
|
||||||
channel->write_state = libssh2_NB_state_idle;
|
channel->write_state = libssh2_NB_state_idle;
|
||||||
|
|
||||||
return channel->write_bufwrote;
|
return wrote;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2440,6 +2436,8 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
|
|||||||
unsigned long data_len;
|
unsigned long data_len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(session);
|
||||||
|
|
||||||
if (channel->free_state == libssh2_NB_state_idle) {
|
if (channel->free_state == libssh2_NB_state_idle) {
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||||
"Freeing channel %lu/%lu resources", channel->local.id,
|
"Freeing channel %lu/%lu resources", channel->local.id,
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
|
* Copyright (c) 2009 by Daniel Stenberg
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libssh2_priv.h"
|
#include "libssh2_priv.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
/* Needed for struct iovec on some platforms */
|
/* Needed for struct iovec on some platforms */
|
||||||
#ifdef HAVE_SYS_UIO_H
|
#ifdef HAVE_SYS_UIO_H
|
||||||
@@ -453,3 +455,47 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hostkey_type(const unsigned char *hostkey, size_t len)
|
||||||
|
{
|
||||||
|
const unsigned char rsa[] = {
|
||||||
|
0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a'
|
||||||
|
};
|
||||||
|
const unsigned char dss[] = {
|
||||||
|
0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (len < 11)
|
||||||
|
return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
|
||||||
|
|
||||||
|
if (!memcmp(rsa, hostkey, 11))
|
||||||
|
return LIBSSH2_HOSTKEY_TYPE_RSA;
|
||||||
|
|
||||||
|
if (!memcmp(dss, hostkey, 11))
|
||||||
|
return LIBSSH2_HOSTKEY_TYPE_DSS;
|
||||||
|
|
||||||
|
return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_session_hostkey()
|
||||||
|
*
|
||||||
|
* Returns the server key and length.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API const char *
|
||||||
|
libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type)
|
||||||
|
{
|
||||||
|
if(session->server_hostkey_len) {
|
||||||
|
if(len)
|
||||||
|
*len = session->server_hostkey_len;
|
||||||
|
if (type)
|
||||||
|
*type = hostkey_type(session->server_hostkey,
|
||||||
|
session->server_hostkey_len);
|
||||||
|
return (char *) session->server_hostkey;
|
||||||
|
}
|
||||||
|
if(len)
|
||||||
|
*len = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
17
src/kex.c
17
src/kex.c
@@ -158,7 +158,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
|
|||||||
|
|
||||||
if (exchange_state->state == libssh2_NB_state_sent) {
|
if (exchange_state->state == libssh2_NB_state_sent) {
|
||||||
if (session->burn_optimistic_kexinit) {
|
if (session->burn_optimistic_kexinit) {
|
||||||
/* The first KEX packet to come along will be the guess initially
|
/* The first KEX packet to come along will be the guess initially
|
||||||
* sent by the server. That guess turned out to be wrong so we
|
* sent by the server. That guess turned out to be wrong so we
|
||||||
* need to silently ignore it */
|
* need to silently ignore it */
|
||||||
int burn_type;
|
int burn_type;
|
||||||
@@ -445,12 +445,12 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
/* The first key exchange has been performed,
|
/* The first key exchange has been performed,
|
||||||
switch to active crypt/comp/mac mode */
|
switch to active crypt/comp/mac mode */
|
||||||
session->state |= LIBSSH2_STATE_NEWKEYS;
|
session->state |= LIBSSH2_STATE_NEWKEYS;
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Received NEWKEYS message");
|
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Received NEWKEYS message");
|
||||||
|
|
||||||
/* This will actually end up being just packet_type(1)
|
/* This will actually end up being just packet_type(1)
|
||||||
for this packet type anyway */
|
for this packet type anyway */
|
||||||
LIBSSH2_FREE(session, exchange_state->tmp);
|
LIBSSH2_FREE(session, exchange_state->tmp);
|
||||||
|
|
||||||
@@ -641,11 +641,6 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
|
|||||||
exchange_state->k_value = NULL;
|
exchange_state->k_value = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->server_hostkey) {
|
|
||||||
LIBSSH2_FREE(session, session->server_hostkey);
|
|
||||||
session->server_hostkey = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
exchange_state->state = libssh2_NB_state_idle;
|
exchange_state->state = libssh2_NB_state_idle;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1013,7 +1008,7 @@ kex_method_list(unsigned char *buf, size_t list_strlen,
|
|||||||
*/
|
*/
|
||||||
static int kexinit(LIBSSH2_SESSION * session)
|
static int kexinit(LIBSSH2_SESSION * session)
|
||||||
{
|
{
|
||||||
/* 62 = packet_type(1) + cookie(16) + first_packet_follows(1) +
|
/* 62 = packet_type(1) + cookie(16) + first_packet_follows(1) +
|
||||||
reserved(4) + length longs(40) */
|
reserved(4) + length longs(40) */
|
||||||
size_t data_len = 62;
|
size_t data_len = 62;
|
||||||
size_t kex_len, hostkey_len = 0;
|
size_t kex_len, hostkey_len = 0;
|
||||||
@@ -1069,8 +1064,8 @@ static int kexinit(LIBSSH2_SESSION * session)
|
|||||||
libssh2_random(s, 16);
|
libssh2_random(s, 16);
|
||||||
s += 16;
|
s += 16;
|
||||||
|
|
||||||
/* Ennumerating through these lists twice is probably (certainly?)
|
/* Ennumerating through these lists twice is probably (certainly?)
|
||||||
inefficient from a CPU standpoint, but it saves multiple
|
inefficient from a CPU standpoint, but it saves multiple
|
||||||
malloc/realloc calls */
|
malloc/realloc calls */
|
||||||
LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs,
|
LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs,
|
||||||
libssh2_kex_methods);
|
libssh2_kex_methods);
|
||||||
|
843
src/knownhost.c
Normal file
843
src/knownhost.c
Normal file
@@ -0,0 +1,843 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms,
|
||||||
|
* with or without modification, are permitted provided
|
||||||
|
* that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the
|
||||||
|
* following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the copyright holder nor the names
|
||||||
|
* of any other contributors may be used to endorse or
|
||||||
|
* promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libssh2_priv.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
struct known_host {
|
||||||
|
struct list_node node;
|
||||||
|
char *name; /* points to the name or the hash (allocated) */
|
||||||
|
size_t name_len; /* needed for hashed data */
|
||||||
|
int typemask; /* plain, sha1, custom, ... */
|
||||||
|
char *salt; /* points to binary salt (allocated) */
|
||||||
|
size_t salt_len; /* size of salt */
|
||||||
|
char *key; /* the (allocated) associated key. This is kept base64
|
||||||
|
encoded in memory. */
|
||||||
|
|
||||||
|
/* this is the struct we expose externally */
|
||||||
|
struct libssh2_knownhost external;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _LIBSSH2_KNOWNHOSTS
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session; /* the session this "belongs to" */
|
||||||
|
struct list_head head;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void free_host(LIBSSH2_SESSION *session, struct known_host *entry)
|
||||||
|
{
|
||||||
|
if(entry) {
|
||||||
|
if(entry->key)
|
||||||
|
LIBSSH2_FREE(session, entry->key);
|
||||||
|
if(entry->salt)
|
||||||
|
LIBSSH2_FREE(session, entry->salt);
|
||||||
|
if(entry->name)
|
||||||
|
LIBSSH2_FREE(session, entry->name);
|
||||||
|
LIBSSH2_FREE(session, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_init
|
||||||
|
*
|
||||||
|
* Init a collection of known hosts. Returns the pointer to a collection.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API LIBSSH2_KNOWNHOSTS *
|
||||||
|
libssh2_knownhost_init(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
LIBSSH2_KNOWNHOSTS *knh =
|
||||||
|
LIBSSH2_ALLOC(session, sizeof(struct _LIBSSH2_KNOWNHOSTS));
|
||||||
|
|
||||||
|
if(!knh)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
knh->session = session;
|
||||||
|
|
||||||
|
_libssh2_list_init(&knh->head);
|
||||||
|
|
||||||
|
return knh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define KNOWNHOST_MAGIC 0xdeadcafe
|
||||||
|
/*
|
||||||
|
* knownhost_to_external()
|
||||||
|
*
|
||||||
|
* Copies data from the internal to the external representation struct.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static struct libssh2_knownhost *knownhost_to_external(struct known_host *node)
|
||||||
|
{
|
||||||
|
struct libssh2_knownhost *ext = &node->external;
|
||||||
|
|
||||||
|
ext->magic = KNOWNHOST_MAGIC;
|
||||||
|
ext->node = node;
|
||||||
|
ext->name = ((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
|
||||||
|
LIBSSH2_KNOWNHOST_TYPE_PLAIN)? node->name:NULL;
|
||||||
|
ext->key = node->key;
|
||||||
|
ext->typemask = node->typemask;
|
||||||
|
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_add
|
||||||
|
*
|
||||||
|
* Add a host and its associated key to the collection of known hosts.
|
||||||
|
*
|
||||||
|
* The 'type' argument specifies on what format the given host and keys are:
|
||||||
|
*
|
||||||
|
* plain - ascii "hostname.domain.tld"
|
||||||
|
* sha1 - SHA1(<salt> <host>) base64-encoded!
|
||||||
|
* custom - another hash
|
||||||
|
*
|
||||||
|
* If 'sha1' is selected as type, the salt must be provided to the salt
|
||||||
|
* argument. This too base64 encoded.
|
||||||
|
*
|
||||||
|
* The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If
|
||||||
|
* a custom type is used, salt is ignored and you must provide the host
|
||||||
|
* pre-hashed when checking for it in the libssh2_knownhost_check() function.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *host, const char *salt,
|
||||||
|
const char *key, size_t keylen,
|
||||||
|
int typemask, struct libssh2_knownhost **store)
|
||||||
|
{
|
||||||
|
struct known_host *entry =
|
||||||
|
LIBSSH2_ALLOC(hosts->session, sizeof(struct known_host));
|
||||||
|
size_t hostlen = strlen(host);
|
||||||
|
int rc = LIBSSH2_ERROR_ALLOC;
|
||||||
|
char *ptr;
|
||||||
|
unsigned int ptrlen;
|
||||||
|
|
||||||
|
if(!entry)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if(!(typemask & LIBSSH2_KNOWNHOST_KEY_MASK))
|
||||||
|
/* make sure we have a key type set */
|
||||||
|
return LIBSSH2_ERROR_INVAL;
|
||||||
|
|
||||||
|
memset(entry, 0, sizeof(struct known_host));
|
||||||
|
|
||||||
|
entry->typemask = typemask;
|
||||||
|
|
||||||
|
switch(entry->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
|
||||||
|
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
|
||||||
|
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
|
||||||
|
entry->name = LIBSSH2_ALLOC(hosts->session, hostlen+1);
|
||||||
|
if(!entry)
|
||||||
|
goto error;
|
||||||
|
memcpy(entry->name, host, hostlen+1);
|
||||||
|
break;
|
||||||
|
case LIBSSH2_KNOWNHOST_TYPE_SHA1:
|
||||||
|
rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen,
|
||||||
|
host, hostlen);
|
||||||
|
if(rc)
|
||||||
|
goto error;
|
||||||
|
entry->name = ptr;
|
||||||
|
entry->name_len = ptrlen;
|
||||||
|
|
||||||
|
rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen,
|
||||||
|
salt, strlen(salt));
|
||||||
|
if(rc)
|
||||||
|
goto error;
|
||||||
|
entry->salt = ptr;
|
||||||
|
entry->salt_len = ptrlen;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64) {
|
||||||
|
/* the provided key is base64 encoded already */
|
||||||
|
if(!keylen)
|
||||||
|
keylen = strlen(key);
|
||||||
|
entry->key = LIBSSH2_ALLOC(hosts->session, keylen+1);
|
||||||
|
if(!entry)
|
||||||
|
goto error;
|
||||||
|
memcpy(entry->key, key, keylen+1);
|
||||||
|
entry->key[keylen]=0; /* force a terminating zero trailer */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* key is raw, we base64 encode it and store it as such */
|
||||||
|
size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
|
||||||
|
&ptr);
|
||||||
|
if(!nlen)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
entry->key = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add this new host to the big list of known hosts */
|
||||||
|
_libssh2_list_add(&hosts->head, &entry->node);
|
||||||
|
|
||||||
|
if(store)
|
||||||
|
*store = knownhost_to_external(entry);
|
||||||
|
|
||||||
|
return LIBSSH2_ERROR_NONE;
|
||||||
|
error:
|
||||||
|
free_host(hosts->session, entry);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_check
|
||||||
|
*
|
||||||
|
* Check a host and its associated key against the collection of known hosts.
|
||||||
|
*
|
||||||
|
* The typemask is the type/format of the given host name and key
|
||||||
|
*
|
||||||
|
* plain - ascii "hostname.domain.tld"
|
||||||
|
* sha1 - NOT SUPPORTED AS INPUT
|
||||||
|
* custom - prehashed base64 encoded. Note that this cannot use any salts.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
* LIBSSH2_KNOWNHOST_CHECK_FAILURE
|
||||||
|
* LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
|
||||||
|
* LIBSSH2_KNOWNHOST_CHECK_MATCH
|
||||||
|
* LIBSSH2_KNOWNHOST_CHECK_MISMATCH
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *host, const char *key, size_t keylen,
|
||||||
|
int typemask,
|
||||||
|
struct libssh2_knownhost **ext)
|
||||||
|
{
|
||||||
|
struct known_host *node = _libssh2_list_first(&hosts->head);
|
||||||
|
struct known_host *badkey = NULL;
|
||||||
|
int type = typemask & LIBSSH2_KNOWNHOST_TYPE_MASK;
|
||||||
|
char *keyalloc = NULL;
|
||||||
|
int rc = LIBSSH2_KNOWNHOST_CHECK_NOTFOUND;
|
||||||
|
|
||||||
|
if(type == LIBSSH2_KNOWNHOST_TYPE_SHA1)
|
||||||
|
/* we can't work with a sha1 as given input */
|
||||||
|
return LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
|
||||||
|
|
||||||
|
if(!(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64)) {
|
||||||
|
/* we got a raw key input, convert it to base64 for the checks below */
|
||||||
|
size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
|
||||||
|
&keyalloc);
|
||||||
|
if(!nlen)
|
||||||
|
return LIBSSH2_KNOWNHOST_CHECK_FAILURE;
|
||||||
|
|
||||||
|
/* make the key point to this */
|
||||||
|
key = keyalloc;
|
||||||
|
keylen = nlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
int match = 0;
|
||||||
|
switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
|
||||||
|
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
|
||||||
|
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN)
|
||||||
|
match = !strcmp(host, node->name);
|
||||||
|
break;
|
||||||
|
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
|
||||||
|
if(type == LIBSSH2_KNOWNHOST_TYPE_CUSTOM)
|
||||||
|
match = !strcmp(host, node->name);
|
||||||
|
break;
|
||||||
|
case LIBSSH2_KNOWNHOST_TYPE_SHA1:
|
||||||
|
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) {
|
||||||
|
/* when we have the sha1 version stored, we can use a plain
|
||||||
|
input to produce a hash to compare with the stored hash.
|
||||||
|
*/
|
||||||
|
libssh2_hmac_ctx ctx;
|
||||||
|
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
if(SHA_DIGEST_LENGTH != node->name_len) {
|
||||||
|
/* the name hash length must be the sha1 size or
|
||||||
|
we can't match it */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
libssh2_hmac_sha1_init(&ctx, node->salt, node->salt_len);
|
||||||
|
libssh2_hmac_update(ctx, (unsigned char *)host, strlen(host));
|
||||||
|
libssh2_hmac_final(ctx, hash);
|
||||||
|
libssh2_hmac_cleanup(&ctx);
|
||||||
|
|
||||||
|
if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH))
|
||||||
|
/* this is a node we're interested in */
|
||||||
|
match = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: /* unsupported type */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(match) {
|
||||||
|
/* host name match, now compare the keys */
|
||||||
|
if(!strcmp(key, node->key)) {
|
||||||
|
/* they match! */
|
||||||
|
*ext = knownhost_to_external(node);
|
||||||
|
badkey = NULL;
|
||||||
|
rc = LIBSSH2_KNOWNHOST_CHECK_MATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* remember the first node that had a host match but a failed
|
||||||
|
key match since we continue our search from here */
|
||||||
|
if(!badkey)
|
||||||
|
badkey = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node= _libssh2_list_next(&node->node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(badkey) {
|
||||||
|
/* key mismatch */
|
||||||
|
*ext = knownhost_to_external(badkey);
|
||||||
|
rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(keyalloc)
|
||||||
|
LIBSSH2_FREE(hosts->session, keyalloc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_del
|
||||||
|
*
|
||||||
|
* Remove a host from the collection of known hosts.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost *entry)
|
||||||
|
{
|
||||||
|
struct known_host *node;
|
||||||
|
if(!entry || (entry->magic != KNOWNHOST_MAGIC))
|
||||||
|
/* check that this was retrieved the right way or get out */
|
||||||
|
return LIBSSH2_ERROR_INVAL;
|
||||||
|
|
||||||
|
/* get the internal node pointer */
|
||||||
|
node = entry->node;
|
||||||
|
|
||||||
|
/* unlink from the list of all hosts */
|
||||||
|
_libssh2_list_remove(&node->node);
|
||||||
|
|
||||||
|
/* free all resources */
|
||||||
|
free_host(hosts->session, node);
|
||||||
|
|
||||||
|
/* clear the struct now since this host entry has been removed! */
|
||||||
|
memset(entry, 0, sizeof(struct libssh2_knownhost));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_free
|
||||||
|
*
|
||||||
|
* Free an entire collection of known hosts.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API void
|
||||||
|
libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts)
|
||||||
|
{
|
||||||
|
struct known_host *node;
|
||||||
|
struct known_host *next;
|
||||||
|
|
||||||
|
for(node = _libssh2_list_first(&hosts->head); node; node = next) {
|
||||||
|
next = _libssh2_list_next(&node->node);
|
||||||
|
free_host(hosts->session, node);
|
||||||
|
}
|
||||||
|
LIBSSH2_FREE(hosts->session, hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hostline()
|
||||||
|
*
|
||||||
|
* Parse a single known_host line pre-split into host and key.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *host, size_t hostlen,
|
||||||
|
const char *key, size_t keylen)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
const char *orig = host;
|
||||||
|
const char *salt = NULL;
|
||||||
|
int rc;
|
||||||
|
int type = LIBSSH2_KNOWNHOST_TYPE_PLAIN;
|
||||||
|
const char *sep = NULL;
|
||||||
|
size_t seplen = 0;
|
||||||
|
char saltbuf[32];
|
||||||
|
char hostbuf[256];
|
||||||
|
|
||||||
|
/* Figure out host format */
|
||||||
|
if((hostlen >2) && memcmp(host, "|1|", 3)) {
|
||||||
|
/* old style plain text: [name][,][ip-address]
|
||||||
|
|
||||||
|
for the sake of simplicity, we add them as two hosts with the same
|
||||||
|
key
|
||||||
|
*/
|
||||||
|
size_t scan = hostlen;
|
||||||
|
|
||||||
|
while(scan && (*host != ',')) {
|
||||||
|
host++;
|
||||||
|
scan--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scan) {
|
||||||
|
sep = host+1;
|
||||||
|
seplen = scan-1;
|
||||||
|
hostlen -= scan; /* deduct what's left to scan from the first
|
||||||
|
host name */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
host = orig;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* |1|[salt]|[hash] */
|
||||||
|
type = LIBSSH2_KNOWNHOST_TYPE_SHA1;
|
||||||
|
|
||||||
|
salt = &host[3]; /* skip the magic marker */
|
||||||
|
hostlen -= 3; /* deduct the marker */
|
||||||
|
|
||||||
|
/* this is where the salt starts, find the end of it */
|
||||||
|
for(p = salt; *p && (*p != '|'); p++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if(*p=='|') {
|
||||||
|
const char *hash = NULL;
|
||||||
|
size_t saltlen = p - salt;
|
||||||
|
if(saltlen >= (sizeof(saltbuf)-1))
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED; /* weird length */
|
||||||
|
|
||||||
|
memcpy(saltbuf, salt, saltlen);
|
||||||
|
saltbuf[saltlen] = 0; /* zero terminate */
|
||||||
|
salt = saltbuf; /* point to the stack based buffer */
|
||||||
|
|
||||||
|
hash = p+1; /* the host hash is after the separator */
|
||||||
|
|
||||||
|
/* now make the host point to the hash */
|
||||||
|
host = hash;
|
||||||
|
hostlen -= saltlen+1; /* deduct the salt and separator */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make some checks that the lenghts seem sensible */
|
||||||
|
if((keylen < 20) ||
|
||||||
|
(seplen >= sizeof(hostbuf)-1) ||
|
||||||
|
(hostlen >= sizeof(hostbuf)-1))
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
switch(key[0]) {
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
type |= LIBSSH2_KNOWNHOST_KEY_RSA1;
|
||||||
|
|
||||||
|
/* Note that the old-style keys (RSA1) aren't truly base64, but we
|
||||||
|
* claim it is for now since we can get away with strcmp()ing the
|
||||||
|
* entire anything anyway! We need to check and fix these to make them
|
||||||
|
* work properly.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's': /* ssh-dss or ssh-rsa */
|
||||||
|
if(!strncmp(key, "ssh-dss", 7))
|
||||||
|
type |= LIBSSH2_KNOWNHOST_KEY_SSHDSS;
|
||||||
|
else if(!strncmp(key, "ssh-rsa", 7))
|
||||||
|
type |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
||||||
|
else
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED; /* unknown key type */
|
||||||
|
|
||||||
|
key += 7;
|
||||||
|
keylen -= 7;
|
||||||
|
|
||||||
|
/* skip whitespaces */
|
||||||
|
while((*key ==' ') || (*key == '\t')) {
|
||||||
|
key++;
|
||||||
|
keylen--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* unknown key format */
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sep) {
|
||||||
|
/* The second host after the comma, add this first. Copy it to the
|
||||||
|
temp buffer and zero terminate */
|
||||||
|
memcpy(hostbuf, sep, seplen);
|
||||||
|
hostbuf[seplen]=0;
|
||||||
|
|
||||||
|
rc = libssh2_knownhost_add(hosts, hostbuf, salt, key, keylen,
|
||||||
|
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
|
||||||
|
NULL);
|
||||||
|
if(rc)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!salt)
|
||||||
|
host = orig;
|
||||||
|
memcpy(hostbuf, host, hostlen);
|
||||||
|
hostbuf[hostlen]=0;
|
||||||
|
|
||||||
|
rc = libssh2_knownhost_add(hosts, hostbuf, salt, key, keylen,
|
||||||
|
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64,
|
||||||
|
NULL);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_readline()
|
||||||
|
*
|
||||||
|
* Pass in a line of a file of 'type'.
|
||||||
|
*
|
||||||
|
* LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
|
||||||
|
*
|
||||||
|
* OpenSSH line format:
|
||||||
|
*
|
||||||
|
* <host> <key>
|
||||||
|
*
|
||||||
|
* Where the two parts can be created like:
|
||||||
|
*
|
||||||
|
* <host> can be either
|
||||||
|
* <name> or <hash>
|
||||||
|
*
|
||||||
|
* <name> consists of
|
||||||
|
* [name,address] or just [name] or just [address]
|
||||||
|
*
|
||||||
|
* <hash> consists of
|
||||||
|
* |1|<salt>|hash
|
||||||
|
*
|
||||||
|
* <key> can be one of:
|
||||||
|
* [RSA bits] [e] [n as a decimal number]
|
||||||
|
* 'ssh-dss' [base64-encoded-key]
|
||||||
|
* 'ssh-rsa' [base64-encoded-key]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *line, size_t len, int type)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
const char *hostp;
|
||||||
|
const char *keyp;
|
||||||
|
size_t hostlen;
|
||||||
|
size_t keylen;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
cp = line;
|
||||||
|
|
||||||
|
/* skip leading whitespaces */
|
||||||
|
while(len && ((*cp==' ') || (*cp == '\t'))) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!len || !*cp || (*cp == '#') || (*cp == '\n'))
|
||||||
|
/* comment or empty line */
|
||||||
|
return LIBSSH2_ERROR_NONE;
|
||||||
|
|
||||||
|
/* the host part starts here */
|
||||||
|
hostp = cp;
|
||||||
|
|
||||||
|
/* move over the host to the separator */
|
||||||
|
while(len && *cp && (*cp!=' ') && (*cp != '\t')) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostlen = cp - hostp;
|
||||||
|
|
||||||
|
/* the key starts after the whitespaces */
|
||||||
|
while(len && *cp && ((*cp==' ') || (*cp == '\t'))) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!*cp || !len)
|
||||||
|
/* illegal line */
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
keyp = cp; /* the key starts here */
|
||||||
|
keylen = len;
|
||||||
|
|
||||||
|
/* check if the line (key) ends with a newline and if so kill it */
|
||||||
|
while(len && *cp && (*cp != '\n')) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zero terminate where the newline is */
|
||||||
|
if(*cp == '\n')
|
||||||
|
keylen--; /* don't include this in the count */
|
||||||
|
|
||||||
|
/* deal with this one host+key line */
|
||||||
|
rc = hostline(hosts, hostp, hostlen, keyp, keylen);
|
||||||
|
if(rc)
|
||||||
|
return rc; /* failed */
|
||||||
|
|
||||||
|
return LIBSSH2_ERROR_NONE; /* success */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_readfile
|
||||||
|
*
|
||||||
|
* Read hosts+key pairs from a given file.
|
||||||
|
*
|
||||||
|
* Returns a negative value for error or number of successfully added hosts.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *filename, int type)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
int num = 0;
|
||||||
|
char buf[2048];
|
||||||
|
|
||||||
|
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
file = fopen(filename, "r");
|
||||||
|
if(file) {
|
||||||
|
while(fgets(buf, sizeof(buf), file)) {
|
||||||
|
if(libssh2_knownhost_readline(hosts, buf, strlen(buf), type))
|
||||||
|
break;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return LIBSSH2_ERROR_FILE;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* knownhost_writeline()
|
||||||
|
*
|
||||||
|
* Ask libssh2 to convert a known host to an output line for storage.
|
||||||
|
*
|
||||||
|
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
|
||||||
|
* output buffer is too small to hold the desired output. The 'outlen' field
|
||||||
|
* will then contain the size libssh2 wanted to store, which then is the
|
||||||
|
* smallest sufficient buffer it would require.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct known_host *node,
|
||||||
|
char *buf, size_t buflen,
|
||||||
|
size_t *outlen, int type)
|
||||||
|
{
|
||||||
|
int rc = LIBSSH2_ERROR_NONE;
|
||||||
|
int tindex;
|
||||||
|
const char *keytypes[4]={
|
||||||
|
"", /* not used */
|
||||||
|
"", /* this type has no name in the file */
|
||||||
|
" ssh-rsa",
|
||||||
|
" ssh-dss"
|
||||||
|
};
|
||||||
|
const char *keytype;
|
||||||
|
size_t nlen;
|
||||||
|
|
||||||
|
/* we only support this single file type for now, bail out on all other
|
||||||
|
attempts */
|
||||||
|
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
tindex = (node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) >>
|
||||||
|
LIBSSH2_KNOWNHOST_KEY_SHIFT;
|
||||||
|
|
||||||
|
/* set the string used in the file */
|
||||||
|
keytype = keytypes[tindex];
|
||||||
|
|
||||||
|
if((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
|
||||||
|
LIBSSH2_KNOWNHOST_TYPE_SHA1) {
|
||||||
|
char *namealloc;
|
||||||
|
char *saltalloc;
|
||||||
|
nlen = _libssh2_base64_encode(hosts->session, node->name,
|
||||||
|
node->name_len, &namealloc);
|
||||||
|
if(!nlen)
|
||||||
|
return LIBSSH2_ERROR_ALLOC;
|
||||||
|
|
||||||
|
nlen = _libssh2_base64_encode(hosts->session,
|
||||||
|
node->salt, node->salt_len,
|
||||||
|
&saltalloc);
|
||||||
|
if(!nlen) {
|
||||||
|
free(namealloc);
|
||||||
|
return LIBSSH2_ERROR_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlen = strlen(saltalloc) + strlen(namealloc) + strlen(keytype) +
|
||||||
|
strlen(node->key) + 7; /* |1| + | + ' ' + \n + \0 = 7 */
|
||||||
|
|
||||||
|
if(nlen <= buflen)
|
||||||
|
sprintf(buf, "|1|%s|%s%s %s\n", saltalloc, namealloc, keytype,
|
||||||
|
node->key);
|
||||||
|
else
|
||||||
|
rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
free(namealloc);
|
||||||
|
free(saltalloc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nlen = strlen(node->name) + strlen(keytype) + strlen(node->key) + 3;
|
||||||
|
/* ' ' + '\n' + \0 = 3 */
|
||||||
|
if(nlen <= buflen)
|
||||||
|
/* these types have the plain name */
|
||||||
|
sprintf(buf, "%s%s %s\n", node->name, keytype, node->key);
|
||||||
|
else
|
||||||
|
rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we report the full length of the data with the trailing zero excluded */
|
||||||
|
*outlen = nlen-1;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_writeline()
|
||||||
|
*
|
||||||
|
* Ask libssh2 to convert a known host to an output line for storage.
|
||||||
|
*
|
||||||
|
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
|
||||||
|
* output buffer is too small to hold the desired output.
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost *known,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
size_t *outlen, /* the amount of written data */
|
||||||
|
int type)
|
||||||
|
{
|
||||||
|
struct known_host *node;
|
||||||
|
|
||||||
|
if(known->magic != KNOWNHOST_MAGIC)
|
||||||
|
return LIBSSH2_ERROR_INVAL;
|
||||||
|
|
||||||
|
node = known->node;
|
||||||
|
|
||||||
|
return knownhost_writeline(hosts, node, buffer, buflen, outlen, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_writefile()
|
||||||
|
*
|
||||||
|
* Write hosts+key pairs to the given file.
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *filename, int type)
|
||||||
|
{
|
||||||
|
struct known_host *node;
|
||||||
|
FILE *file;
|
||||||
|
int rc = LIBSSH2_ERROR_NONE;
|
||||||
|
char buffer[2048];
|
||||||
|
|
||||||
|
/* we only support this single file type for now, bail out on all other
|
||||||
|
attempts */
|
||||||
|
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
file = fopen(filename, "w");
|
||||||
|
if(!file)
|
||||||
|
return LIBSSH2_ERROR_FILE;
|
||||||
|
|
||||||
|
for(node = _libssh2_list_first(&hosts->head);
|
||||||
|
node;
|
||||||
|
node= _libssh2_list_next(&node->node) ) {
|
||||||
|
size_t wrote;
|
||||||
|
size_t nwrote;
|
||||||
|
rc = knownhost_writeline(hosts, node, buffer, sizeof(buffer), &wrote,
|
||||||
|
type);
|
||||||
|
if(rc)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nwrote = fwrite(buffer, 1, wrote, file);
|
||||||
|
if(nwrote != wrote) {
|
||||||
|
/* failed to write the whole thing, bail out */
|
||||||
|
rc = LIBSSH2_ERROR_FILE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_get()
|
||||||
|
*
|
||||||
|
* Traverse the internal list of known hosts. Pass NULL to 'prev' to get
|
||||||
|
* the first one.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 if a fine host was stored in 'store'
|
||||||
|
* 1 if end of hosts
|
||||||
|
* [negative] on errors
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
struct libssh2_knownhost **ext,
|
||||||
|
struct libssh2_knownhost *oprev)
|
||||||
|
{
|
||||||
|
struct known_host *node;
|
||||||
|
if(oprev && oprev->node) {
|
||||||
|
/* we have a starting point */
|
||||||
|
struct known_host *prev = oprev->node;
|
||||||
|
|
||||||
|
/* get the next node in the list */
|
||||||
|
node = _libssh2_list_next(&prev->node);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
node = _libssh2_list_first(&hosts->head);
|
||||||
|
|
||||||
|
if(!node)
|
||||||
|
/* no (more) node */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*ext = knownhost_to_external(node);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -39,6 +39,12 @@
|
|||||||
#ifndef LIBSSH2_PRIV_H
|
#ifndef LIBSSH2_PRIV_H
|
||||||
#define LIBSSH2_PRIV_H 1
|
#define LIBSSH2_PRIV_H 1
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||||
|
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||||
|
#endif /* _CRT_SECURE_NO_DEPRECATE */
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
#define LIBSSH2_LIBRARY
|
#define LIBSSH2_LIBRARY
|
||||||
#include "libssh2_config.h"
|
#include "libssh2_config.h"
|
||||||
|
|
||||||
@@ -881,7 +887,7 @@ struct _LIBSSH2_SESSION
|
|||||||
unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
|
unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
|
||||||
unsigned long scpRecv_response_len;
|
unsigned long scpRecv_response_len;
|
||||||
long scpRecv_mode;
|
long scpRecv_mode;
|
||||||
#if defined(HAVE_LONGLONG) && defined(strtoll)
|
#if defined(HAVE_LONGLONG) && defined(HAVE_STRTOLL)
|
||||||
/* we have the type and we can parse such numbers */
|
/* we have the type and we can parse such numbers */
|
||||||
long long scpRecv_size;
|
long long scpRecv_size;
|
||||||
#define scpsize_strtol strtoll
|
#define scpsize_strtol strtoll
|
||||||
@@ -922,7 +928,26 @@ struct _LIBSSH2_SESSION
|
|||||||
#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
|
#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */
|
/* -------- */
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
methods via .so/.dll */
|
||||||
|
|
||||||
struct _LIBSSH2_KEX_METHOD
|
struct _LIBSSH2_KEX_METHOD
|
||||||
{
|
{
|
||||||
@@ -1023,11 +1048,8 @@ struct _LIBSSH2_MAC_METHOD
|
|||||||
void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
|
void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
|
||||||
...);
|
...);
|
||||||
#else
|
#else
|
||||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__)
|
||||||
/* C99 style */
|
/* C99 supported and also by older GCC */
|
||||||
#define _libssh2_debug(x,y,z, __VA_ARGS__) do {} while (0)
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
/* GNU style */
|
|
||||||
#define _libssh2_debug(x,y,z,...) do {} while (0)
|
#define _libssh2_debug(x,y,z,...) do {} while (0)
|
||||||
#else
|
#else
|
||||||
/* no gcc and not C99, do static and hopefully inline */
|
/* no gcc and not C99, do static and hopefully inline */
|
||||||
|
145
src/misc.c
145
src/misc.c
@@ -37,6 +37,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libssh2_priv.h"
|
#include "libssh2_priv.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -176,7 +178,7 @@ static const short base64_reverse_table[256] = {
|
|||||||
* Decode a base64 chunk and store it into a newly alloc'd buffer
|
* Decode a base64 chunk and store it into a newly alloc'd buffer
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_base64_decode(LIBSSH2_SESSION * session, char **data,
|
libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
|
||||||
unsigned int *datalen, const char *src,
|
unsigned int *datalen, const char *src,
|
||||||
unsigned int src_len)
|
unsigned int src_len)
|
||||||
{
|
{
|
||||||
@@ -222,6 +224,86 @@ libssh2_base64_decode(LIBSSH2_SESSION * session, char **data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Base64 Encoding/Decoding Table --- */
|
||||||
|
static const char table64[]=
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _libssh2_base64_encode()
|
||||||
|
*
|
||||||
|
* Returns the length of the newly created base64 string. The third argument
|
||||||
|
* is a pointer to an allocated area holding the base64 data. If something
|
||||||
|
* went wrong, 0 is returned.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
|
||||||
|
const char *inp, size_t insize, char **outptr)
|
||||||
|
{
|
||||||
|
unsigned char ibuf[3];
|
||||||
|
unsigned char obuf[4];
|
||||||
|
int i;
|
||||||
|
int inputparts;
|
||||||
|
char *output;
|
||||||
|
char *base64data;
|
||||||
|
const char *indata = inp;
|
||||||
|
|
||||||
|
*outptr = NULL; /* set to NULL in case of failure before we reach the end */
|
||||||
|
|
||||||
|
if(0 == insize)
|
||||||
|
insize = strlen(indata);
|
||||||
|
|
||||||
|
base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4);
|
||||||
|
if(NULL == output)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while(insize > 0) {
|
||||||
|
for (i = inputparts = 0; i < 3; i++) {
|
||||||
|
if(insize > 0) {
|
||||||
|
inputparts++;
|
||||||
|
ibuf[i] = *indata;
|
||||||
|
indata++;
|
||||||
|
insize--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ibuf[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
|
||||||
|
obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
|
||||||
|
((ibuf[1] & 0xF0) >> 4));
|
||||||
|
obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
|
||||||
|
((ibuf[2] & 0xC0) >> 6));
|
||||||
|
obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
|
||||||
|
|
||||||
|
switch(inputparts) {
|
||||||
|
case 1: /* only one byte read */
|
||||||
|
snprintf(output, 5, "%c%c==",
|
||||||
|
table64[obuf[0]],
|
||||||
|
table64[obuf[1]]);
|
||||||
|
break;
|
||||||
|
case 2: /* two bytes read */
|
||||||
|
snprintf(output, 5, "%c%c%c=",
|
||||||
|
table64[obuf[0]],
|
||||||
|
table64[obuf[1]],
|
||||||
|
table64[obuf[2]]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(output, 5, "%c%c%c%c",
|
||||||
|
table64[obuf[0]],
|
||||||
|
table64[obuf[1]],
|
||||||
|
table64[obuf[2]],
|
||||||
|
table64[obuf[3]] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output += 4;
|
||||||
|
}
|
||||||
|
*output=0;
|
||||||
|
*outptr = base64data; /* make it return the actual data memory */
|
||||||
|
|
||||||
|
return strlen(base64data); /* return the length of the new data */
|
||||||
|
}
|
||||||
|
/* ---- End of Base64 Encoding ---- */
|
||||||
|
|
||||||
#ifdef LIBSSH2DEBUG
|
#ifdef LIBSSH2DEBUG
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
|
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
|
||||||
@@ -283,3 +365,64 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* init the list head */
|
||||||
|
void _libssh2_list_init(struct list_head *head)
|
||||||
|
{
|
||||||
|
head->first = head->last = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add a node to the list */
|
||||||
|
void _libssh2_list_add(struct list_head *head,
|
||||||
|
struct list_node *entry)
|
||||||
|
{
|
||||||
|
/* store a pointer to the head */
|
||||||
|
entry->head = head;
|
||||||
|
|
||||||
|
/* we add this entry at the "top" so it has no next */
|
||||||
|
entry->next = NULL;
|
||||||
|
|
||||||
|
/* make our prev point to what the head thinks is last */
|
||||||
|
entry->prev = head->last;
|
||||||
|
|
||||||
|
/* and make head's last be us now */
|
||||||
|
head->last = entry;
|
||||||
|
|
||||||
|
/* make sure our 'prev' node points to us next */
|
||||||
|
if(entry->prev)
|
||||||
|
entry->prev->next = entry;
|
||||||
|
else
|
||||||
|
head->first = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the "first" node in the list this head points to */
|
||||||
|
void *_libssh2_list_first(struct list_head *head)
|
||||||
|
{
|
||||||
|
return head->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the next node in the list */
|
||||||
|
void *_libssh2_list_next(struct list_node *node)
|
||||||
|
{
|
||||||
|
return node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the prev node in the list */
|
||||||
|
void *_libssh2_list_prev(struct list_node *node)
|
||||||
|
{
|
||||||
|
return node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove this node from the list */
|
||||||
|
void _libssh2_list_remove(struct list_node *entry)
|
||||||
|
{
|
||||||
|
if(entry->prev)
|
||||||
|
entry->prev->next = entry->next;
|
||||||
|
else
|
||||||
|
entry->head->first = entry->next;
|
||||||
|
|
||||||
|
if(entry->next)
|
||||||
|
entry->next->prev = entry->prev;
|
||||||
|
else
|
||||||
|
entry->head->last = entry->prev;
|
||||||
|
}
|
||||||
|
63
src/misc.h
Normal file
63
src/misc.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#ifndef __LIBSSH2_MISC_H
|
||||||
|
#define __LIBSSH2_MISC_H
|
||||||
|
/* Copyright (c) 2009 by Daniel Stenberg
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms,
|
||||||
|
* with or without modification, are permitted provided
|
||||||
|
* that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the
|
||||||
|
* following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the copyright holder nor the names
|
||||||
|
* of any other contributors may be used to endorse or
|
||||||
|
* promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libssh2_priv.h"
|
||||||
|
|
||||||
|
void _libssh2_list_init(struct list_head *head);
|
||||||
|
|
||||||
|
/* add a node first in the list */
|
||||||
|
void _libssh2_list_add(struct list_head *head,
|
||||||
|
struct list_node *entry);
|
||||||
|
|
||||||
|
/* return the "first" node in the list this head points to */
|
||||||
|
void *_libssh2_list_first(struct list_head *head);
|
||||||
|
|
||||||
|
/* return the next node in the list */
|
||||||
|
void *_libssh2_list_next(struct list_node *node);
|
||||||
|
|
||||||
|
/* return the prev node in the list */
|
||||||
|
void *_libssh2_list_prev(struct list_node *node);
|
||||||
|
|
||||||
|
/* remove this node from the list */
|
||||||
|
void _libssh2_list_remove(struct list_node *entry);
|
||||||
|
|
||||||
|
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
|
||||||
|
const char *inp, size_t insize, char **outptr);
|
||||||
|
#endif /* _LIBSSH2_MISC_H */
|
@@ -43,6 +43,9 @@
|
|||||||
#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,
|
||||||
@@ -212,12 +215,80 @@ 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 *,
|
||||||
|
void * u);
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_private_key_from_file(void ** key_ctx, LIBSSH2_SESSION * session,
|
||||||
|
pem_read_bio_func read_private_key,
|
||||||
|
FILE * fp, unsigned const char *passphrase)
|
||||||
|
{
|
||||||
|
char * key;
|
||||||
|
BIO * bp;
|
||||||
|
|
||||||
|
*key_ctx = NULL;
|
||||||
|
|
||||||
|
if(read_file_into_string(&key, session, fp)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bp = BIO_new_mem_buf(key, -1);
|
||||||
|
if (!bp) {
|
||||||
|
LIBSSH2_FREE(session, key);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*key_ctx = read_private_key(bp, NULL, (void *) passphrase_cb,
|
||||||
|
(void *) passphrase);
|
||||||
|
|
||||||
|
BIO_free(bp);
|
||||||
|
LIBSSH2_FREE(session, key);
|
||||||
|
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)
|
FILE * fp, unsigned const char *passphrase)
|
||||||
{
|
{
|
||||||
(void) session;
|
pem_read_bio_func read_rsa =
|
||||||
|
(pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
|
||||||
|
|
||||||
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.
|
||||||
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
|
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
|
||||||
@@ -225,12 +296,9 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
|
|||||||
*/
|
*/
|
||||||
OpenSSL_add_all_ciphers();
|
OpenSSL_add_all_ciphers();
|
||||||
}
|
}
|
||||||
*rsa = PEM_read_RSAPrivateKey(fp, NULL, (void *) passphrase_cb,
|
|
||||||
(void *) passphrase);
|
return read_private_key_from_file((void **) rsa, session, read_rsa, fp,
|
||||||
if (!*rsa) {
|
passphrase);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -238,7 +306,9 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
|||||||
LIBSSH2_SESSION * session,
|
LIBSSH2_SESSION * session,
|
||||||
FILE * fp, unsigned const char *passphrase)
|
FILE * fp, unsigned const char *passphrase)
|
||||||
{
|
{
|
||||||
(void) session;
|
pem_read_bio_func read_dsa =
|
||||||
|
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
|
||||||
|
|
||||||
if (!EVP_get_cipherbyname("des")) {
|
if (!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.
|
||||||
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
|
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
|
||||||
@@ -246,12 +316,9 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
|||||||
*/
|
*/
|
||||||
OpenSSL_add_all_ciphers();
|
OpenSSL_add_all_ciphers();
|
||||||
}
|
}
|
||||||
*dsa = PEM_read_DSAPrivateKey(fp, NULL, (void *) passphrase_cb,
|
|
||||||
(void *) passphrase);
|
return read_private_key_from_file((void **) dsa, session, read_dsa, fp,
|
||||||
if (!*dsa) {
|
passphrase);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@@ -123,7 +123,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
(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, *last_queued = listen->queue;
|
LIBSSH2_CHANNEL *channel = NULL, *last_queued = listen->queue;
|
||||||
|
|
||||||
last_queued = listen->queue;
|
last_queued = listen->queue;
|
||||||
if (listen_state->state == libssh2_NB_state_allocated) {
|
if (listen_state->state == libssh2_NB_state_allocated) {
|
||||||
@@ -288,7 +288,7 @@ packet_x11_open(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(X11FwdUnAvil) - 1);
|
unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1);
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
LIBSSH2_CHANNEL *channel;
|
LIBSSH2_CHANNEL *channel = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
(void) datalen;
|
(void) datalen;
|
||||||
@@ -1078,7 +1078,7 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
|
|||||||
return ret;
|
return ret;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
/* nothing available, wait until data arrives or we time out */
|
/* nothing available, wait until data arrives or we time out */
|
||||||
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
|
long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - state->start);
|
||||||
|
|
||||||
if (left <= 0) {
|
if (left <= 0) {
|
||||||
state->start = 0;
|
state->start = 0;
|
||||||
@@ -1187,7 +1187,7 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
|
long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - state->start);
|
||||||
|
|
||||||
if (left <= 0) {
|
if (left <= 0) {
|
||||||
state->start = 0;
|
state->start = 0;
|
||||||
|
@@ -427,7 +427,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
|||||||
local_realloc = my_realloc;
|
local_realloc = my_realloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
session = local_alloc(sizeof(LIBSSH2_SESSION), abstract);
|
session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract);
|
||||||
if (session) {
|
if (session) {
|
||||||
memset(session, 0, sizeof(LIBSSH2_SESSION));
|
memset(session, 0, sizeof(LIBSSH2_SESSION));
|
||||||
session->alloc = local_alloc;
|
session->alloc = local_alloc;
|
||||||
@@ -924,6 +924,10 @@ session_free(LIBSSH2_SESSION *session)
|
|||||||
/* if the socket was previously blocking, put it back so */
|
/* if the socket was previously blocking, put it back so */
|
||||||
session_nonblock(session->socket_fd, 0);
|
session_nonblock(session->socket_fd, 0);
|
||||||
|
|
||||||
|
if (session->server_hostkey) {
|
||||||
|
LIBSSH2_FREE(session, session->server_hostkey);
|
||||||
|
}
|
||||||
|
|
||||||
LIBSSH2_FREE(session, session);
|
LIBSSH2_FREE(session, session);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1164,9 +1168,10 @@ libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
|
|||||||
return session->err_code;
|
return session->err_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_session_last_error
|
/* libssh2_session_last_errno
|
||||||
* Returns error code
|
*
|
||||||
*/
|
* Returns error code
|
||||||
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_session_last_errno(LIBSSH2_SESSION * session)
|
libssh2_session_last_errno(LIBSSH2_SESSION * session)
|
||||||
{
|
{
|
||||||
@@ -1174,8 +1179,11 @@ libssh2_session_last_errno(LIBSSH2_SESSION * session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_session_flag
|
/* libssh2_session_flag
|
||||||
|
*
|
||||||
* Set/Get session flags
|
* Set/Get session flags
|
||||||
* Passing flag==0 will avoid changing session->flags while still returning its current value
|
*
|
||||||
|
* Passing flag==0 will avoid changing session->flags while still returning
|
||||||
|
* its current value
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
|
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
|
||||||
@@ -1594,7 +1602,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_session_block_direction
|
* libssh2_session_block_directions
|
||||||
*
|
*
|
||||||
* Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
|
* Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
|
||||||
* Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked
|
* Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked
|
||||||
|
140
src/sftp.c
140
src/sftp.c
@@ -93,17 +93,17 @@ static int sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
|
|||||||
static void
|
static void
|
||||||
_libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
|
_libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
|
||||||
{
|
{
|
||||||
unsigned long msl = ((libssh2_uint64_t)value >> 32);
|
unsigned long msl = (unsigned long)(value >> 32);
|
||||||
|
|
||||||
buf[0] = (msl >> 24) & 0xFF;
|
buf[0] = (unsigned char)((msl >> 24) & 0xFF);
|
||||||
buf[1] = (msl >> 16) & 0xFF;
|
buf[1] = (unsigned char)((msl >> 16) & 0xFF);
|
||||||
buf[2] = (msl >> 8) & 0xFF;
|
buf[2] = (unsigned char)((msl >> 8) & 0xFF);
|
||||||
buf[3] = msl & 0xFF;
|
buf[3] = (unsigned char)( msl & 0xFF);
|
||||||
|
|
||||||
buf[4] = (value >> 24) & 0xFF;
|
buf[4] = (unsigned char)((value >> 24) & 0xFF);
|
||||||
buf[5] = (value >> 16) & 0xFF;
|
buf[5] = (unsigned char)((value >> 16) & 0xFF);
|
||||||
buf[6] = (value >> 8) & 0xFF;
|
buf[6] = (unsigned char)((value >> 8) & 0xFF);
|
||||||
buf[7] = value & 0xFF;
|
buf[7] = (unsigned char)( value & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -378,7 +378,7 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
|
|||||||
} else if (ret <= 0) {
|
} else if (ret <= 0) {
|
||||||
/* prevent busy-looping */
|
/* prevent busy-looping */
|
||||||
long left =
|
long left =
|
||||||
LIBSSH2_READ_TIMEOUT - (time(NULL) - sftp->requirev_start);
|
LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - sftp->requirev_start);
|
||||||
|
|
||||||
if (left <= 0) {
|
if (left <= 0) {
|
||||||
sftp->requirev_start = 0;
|
sftp->requirev_start = 0;
|
||||||
@@ -521,20 +521,6 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
|
|||||||
(void) session_abstract;
|
(void) session_abstract;
|
||||||
(void) channel;
|
(void) channel;
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* EEEK! While it might sound like a neat idea to make this code loop over
|
|
||||||
all the outstanding handles and close them, that is going to cause
|
|
||||||
EAGAIN to get returned and this callback system is not designed to
|
|
||||||
handle this very nicely so thus we now DEMAND that the app closes its
|
|
||||||
handles instead!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Loop through handles closing them */
|
|
||||||
while (sftp->handles) {
|
|
||||||
sftp_close_handle(sftp->handles);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Free the partial packet storage for sftp_packet_read */
|
/* Free the partial packet storage for sftp_packet_read */
|
||||||
if (sftp->partial_packet) {
|
if (sftp->partial_packet) {
|
||||||
LIBSSH2_FREE(session, sftp->partial_packet);
|
LIBSSH2_FREE(session, sftp->partial_packet);
|
||||||
@@ -558,18 +544,31 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
|||||||
unsigned char *data, *s;
|
unsigned char *data, *s;
|
||||||
unsigned long data_len;
|
unsigned long data_len;
|
||||||
int rc;
|
int rc;
|
||||||
|
LIBSSH2_SFTP *sftp_handle;
|
||||||
|
|
||||||
if (session->sftpInit_state == libssh2_NB_state_idle) {
|
if (session->sftpInit_state == libssh2_NB_state_idle) {
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||||
"Initializing SFTP subsystem");
|
"Initializing SFTP subsystem");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the
|
||||||
|
* session struct are only to be used during the setup phase. As soon
|
||||||
|
* as the SFTP session is created they are cleared and can thus be
|
||||||
|
* re-used again to allow any amount of SFTP handles per sessions.
|
||||||
|
*
|
||||||
|
* Note that you MUST NOT try to call libssh2_sftp_init() to get
|
||||||
|
* another handle until the previous one has finished and either
|
||||||
|
* succesffully made a handle or failed and returned error (not
|
||||||
|
* including *EAGAIN).
|
||||||
|
*/
|
||||||
|
|
||||||
assert(session->sftpInit_sftp == NULL);
|
assert(session->sftpInit_sftp == NULL);
|
||||||
|
|
||||||
session->sftpInit_sftp = NULL;
|
session->sftpInit_sftp = NULL;
|
||||||
|
|
||||||
session->sftpInit_state = libssh2_NB_state_created;
|
session->sftpInit_state = libssh2_NB_state_created;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sftp_handle = session->sftpInit_sftp;
|
||||||
|
|
||||||
if (session->sftpInit_state == libssh2_NB_state_created) {
|
if (session->sftpInit_state == libssh2_NB_state_created) {
|
||||||
session->sftpInit_channel =
|
session->sftpInit_channel =
|
||||||
_libssh2_channel_open(session, "session", sizeof("session") - 1,
|
_libssh2_channel_open(session, "session", sizeof("session") - 1,
|
||||||
@@ -618,15 +617,17 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->sftpInit_sftp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP));
|
sftp_handle =
|
||||||
if (!session->sftpInit_sftp) {
|
session->sftpInit_sftp =
|
||||||
|
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP));
|
||||||
|
if (!sftp_handle) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate a new SFTP structure", 0);
|
"Unable to allocate a new SFTP structure", 0);
|
||||||
goto sftp_init_error;
|
goto sftp_init_error;
|
||||||
}
|
}
|
||||||
memset(session->sftpInit_sftp, 0, sizeof(LIBSSH2_SFTP));
|
memset(sftp_handle, 0, sizeof(LIBSSH2_SFTP));
|
||||||
session->sftpInit_sftp->channel = session->sftpInit_channel;
|
sftp_handle->channel = session->sftpInit_channel;
|
||||||
session->sftpInit_sftp->request_id = 0;
|
sftp_handle->request_id = 0;
|
||||||
|
|
||||||
_libssh2_htonu32(session->sftpInit_buffer, 5);
|
_libssh2_htonu32(session->sftpInit_buffer, 5);
|
||||||
session->sftpInit_buffer[4] = SSH_FXP_INIT;
|
session->sftpInit_buffer[4] = SSH_FXP_INIT;
|
||||||
@@ -655,7 +656,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
|||||||
session->sftpInit_state = libssh2_NB_state_sent3;
|
session->sftpInit_state = libssh2_NB_state_sent3;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
|
rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION,
|
||||||
0, &data, &data_len);
|
0, &data, &data_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||||
@@ -674,17 +675,17 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s = data + 1;
|
s = data + 1;
|
||||||
session->sftpInit_sftp->version = _libssh2_ntohu32(s);
|
sftp_handle->version = _libssh2_ntohu32(s);
|
||||||
s += 4;
|
s += 4;
|
||||||
if (session->sftpInit_sftp->version > LIBSSH2_SFTP_VERSION) {
|
if (sftp_handle->version > LIBSSH2_SFTP_VERSION) {
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||||
"Truncating remote SFTP version from %lu",
|
"Truncating remote SFTP version from %lu",
|
||||||
session->sftpInit_sftp->version);
|
sftp_handle->version);
|
||||||
session->sftpInit_sftp->version = LIBSSH2_SFTP_VERSION;
|
sftp_handle->version = LIBSSH2_SFTP_VERSION;
|
||||||
}
|
}
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||||
"Enabling SFTP version %lu compatability",
|
"Enabling SFTP version %lu compatability",
|
||||||
session->sftpInit_sftp->version);
|
sftp_handle->version);
|
||||||
while (s < (data + data_len)) {
|
while (s < (data + data_len)) {
|
||||||
unsigned char *extension_name, *extension_data;
|
unsigned char *extension_name, *extension_data;
|
||||||
unsigned long extname_len, extdata_len;
|
unsigned long extname_len, extdata_len;
|
||||||
@@ -705,11 +706,16 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
|||||||
|
|
||||||
/* Make sure that when the channel gets closed, the SFTP service is shut
|
/* Make sure that when the channel gets closed, the SFTP service is shut
|
||||||
down too */
|
down too */
|
||||||
session->sftpInit_sftp->channel->abstract = session->sftpInit_sftp;
|
sftp_handle->channel->abstract = sftp_handle;
|
||||||
session->sftpInit_sftp->channel->close_cb = libssh2_sftp_dtor;
|
sftp_handle->channel->close_cb = libssh2_sftp_dtor;
|
||||||
|
|
||||||
session->sftpInit_state = libssh2_NB_state_idle;
|
session->sftpInit_state = libssh2_NB_state_idle;
|
||||||
return session->sftpInit_sftp;
|
|
||||||
|
/* clear the sftp and channel pointers in this session struct now */
|
||||||
|
session->sftpInit_sftp = NULL;
|
||||||
|
session->sftpInit_channel = NULL;
|
||||||
|
|
||||||
|
return sftp_handle;
|
||||||
|
|
||||||
sftp_init_error:
|
sftp_init_error:
|
||||||
while (_libssh2_channel_free(session->sftpInit_channel) == PACKET_EAGAIN);
|
while (_libssh2_channel_free(session->sftpInit_channel) == PACKET_EAGAIN);
|
||||||
@@ -1105,7 +1111,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
|||||||
/* 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! */
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send FXP_READ command", 0);
|
"_libssh2_channel_write() failed", 0);
|
||||||
sftp->read_packet = NULL;
|
sftp->read_packet = NULL;
|
||||||
sftp->read_state = libssh2_NB_state_idle;
|
sftp->read_state = libssh2_NB_state_idle;
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1305,7 +1311,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
|||||||
}
|
}
|
||||||
else if (packet_len != retcode) {
|
else if (packet_len != retcode) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send FXP_READ command", 0);
|
"_libssh2_channel_write() failed", 0);
|
||||||
LIBSSH2_FREE(session, sftp->readdir_packet);
|
LIBSSH2_FREE(session, sftp->readdir_packet);
|
||||||
sftp->readdir_packet = NULL;
|
sftp->readdir_packet = NULL;
|
||||||
sftp->readdir_state = libssh2_NB_state_idle;
|
sftp->readdir_state = libssh2_NB_state_idle;
|
||||||
@@ -1409,10 +1415,12 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sftp_write
|
/*
|
||||||
* Write data to a file handle
|
* sftp_write
|
||||||
|
*
|
||||||
|
* Write data to an SFTP handle
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
{
|
{
|
||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
@@ -1421,20 +1429,28 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
|
|||||||
unsigned long data_len, retcode;
|
unsigned long data_len, retcode;
|
||||||
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
|
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
|
||||||
offset(8) + count(4) */
|
offset(8) + count(4) */
|
||||||
ssize_t packet_len = handle->handle_len + count + 25;
|
ssize_t packet_len;
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* There's no point in us accepting a VERY large packet here since we
|
||||||
|
cannot send it anyway. We just accept 4 times the big size to fill up
|
||||||
|
the queue somewhat. */
|
||||||
|
|
||||||
|
if(count > (MAX_SSH_PACKET_LEN*4))
|
||||||
|
count = MAX_SSH_PACKET_LEN*4;
|
||||||
|
|
||||||
|
packet_len = handle->handle_len + count + 25;
|
||||||
|
|
||||||
if (sftp->write_state == libssh2_NB_state_idle) {
|
if (sftp->write_state == libssh2_NB_state_idle) {
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
|
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
|
||||||
(unsigned long) count);
|
(unsigned long) count);
|
||||||
s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
|
s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
|
||||||
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 packet", 0);
|
"Unable to allocate memory for FXP_WRITE", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_libssh2_htonu32(s, packet_len - 4);
|
_libssh2_htonu32(s, packet_len - 4);
|
||||||
s += 4;
|
s += 4;
|
||||||
*(s++) = SSH_FXP_WRITE;
|
*(s++) = SSH_FXP_WRITE;
|
||||||
@@ -1456,19 +1472,23 @@ 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 == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
if (packet_len != rc) {
|
else if(rc < 0) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
/* an actual error */
|
||||||
"Unable to send FXP_READ command", 0);
|
return rc;
|
||||||
LIBSSH2_FREE(session, sftp->write_packet);
|
}
|
||||||
sftp->write_packet = NULL;
|
else if(0 == rc) {
|
||||||
sftp->write_state = libssh2_NB_state_idle;
|
/* an actual error */
|
||||||
|
fprintf(stderr, "WEIRDNESS\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (packet_len != rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
LIBSSH2_FREE(session, sftp->write_packet);
|
LIBSSH2_FREE(session, sftp->write_packet);
|
||||||
sftp->write_packet = NULL;
|
sftp->write_packet = NULL;
|
||||||
sftp->write_state = libssh2_NB_state_sent;
|
sftp->write_state = libssh2_NB_state_sent;
|
||||||
@@ -1654,7 +1674,10 @@ libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE * handle, libssh2_uint64_t offset)
|
|||||||
LIBSSH2_API size_t
|
LIBSSH2_API size_t
|
||||||
libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)
|
libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)
|
||||||
{
|
{
|
||||||
return handle->u.file.offset;
|
/* NOTE: this may very well truncate the size if it is larger than what
|
||||||
|
size_t can hold, so libssh2_sftp_tell64() is really the function you
|
||||||
|
should use */
|
||||||
|
return (size_t)(handle->u.file.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_tell64
|
/* libssh2_sftp_tell64
|
||||||
@@ -1894,7 +1917,8 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
|
|||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
unsigned long data_len, retcode;
|
unsigned long data_len;
|
||||||
|
int retcode;
|
||||||
ssize_t packet_len =
|
ssize_t packet_len =
|
||||||
source_filename_len + dest_filename_len + 17 + (sftp->version >=
|
source_filename_len + dest_filename_len + 17 + (sftp->version >=
|
||||||
5 ? 4 : 0);
|
5 ? 4 : 0);
|
||||||
@@ -2083,7 +2107,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
|
|||||||
}
|
}
|
||||||
if (packet_len != rc) {
|
if (packet_len != rc) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send FXP_READ command", 0);
|
"_libssh2_channel_write() failed", 0);
|
||||||
LIBSSH2_FREE(session, packet);
|
LIBSSH2_FREE(session, packet);
|
||||||
sftp->mkdir_state = libssh2_NB_state_idle;
|
sftp->mkdir_state = libssh2_NB_state_idle;
|
||||||
return -1;
|
return -1;
|
||||||
|
374
src/sshentry.c
374
src/sshentry.c
@@ -1,374 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "libssh2_priv.h"
|
|
||||||
|
|
||||||
static int
|
|
||||||
ssh_host_parse_hostnames (LIBSSH2_SESSION * session,
|
|
||||||
LIBSSH2_KNOWNHOSTS * s,
|
|
||||||
char *line,
|
|
||||||
char *end
|
|
||||||
);
|
|
||||||
|
|
||||||
static int
|
|
||||||
ssh_host_parse_key (LIBSSH2_SESSION * session,
|
|
||||||
LIBSSH2_KNOWNHOSTS * s,
|
|
||||||
char *line,
|
|
||||||
int is_base64_encoded
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Returns zero if successful, > zero for malformed data, < 0 not supported. */
|
|
||||||
LIBSSH2_API int
|
|
||||||
libssh2_new_host_entry(LIBSSH2_SESSION * session,
|
|
||||||
LIBSSH2_KNOWNHOSTS ** s,
|
|
||||||
char *line)
|
|
||||||
{
|
|
||||||
char *tmp = NULL;
|
|
||||||
LIBSSH2_KNOWNHOSTS *t = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (line == NULL || *line == 0)
|
|
||||||
return 1;
|
|
||||||
if (s == NULL)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
tmp = strchr (line, ' ');
|
|
||||||
if (tmp == NULL)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
|
|
||||||
t = (LIBSSH2_KNOWNHOSTS *)
|
|
||||||
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_KNOWNHOSTS));
|
|
||||||
|
|
||||||
t->hostname_line = NULL;
|
|
||||||
t->hostnames = NULL;
|
|
||||||
t->hostnames_size = t->bits = t->exponent = -1;
|
|
||||||
t->modulus = NULL;
|
|
||||||
t->modulus_length = -1;
|
|
||||||
t->ssh_version = -1;
|
|
||||||
t->md5 = NULL;
|
|
||||||
|
|
||||||
i = ssh_host_parse_hostnames (session, t, line, tmp);
|
|
||||||
if (i != 0) {
|
|
||||||
libssh2_free_host_entry (session, t);
|
|
||||||
return ((i > 0) ? 4 : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
line = tmp + 1;
|
|
||||||
tmp = strchr (line, ' ');
|
|
||||||
if (tmp != NULL)
|
|
||||||
tmp = strchr (tmp + 1, ' ');
|
|
||||||
|
|
||||||
i = ssh_host_parse_key (session, t, line, tmp == NULL ? 1 : 0);
|
|
||||||
if (i != 0) {
|
|
||||||
libssh2_free_host_entry (session, t);
|
|
||||||
return ((i > 0) ? 5 : -2);
|
|
||||||
}
|
|
||||||
|
|
||||||
*s = t;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
ssh_host_parse_hostnames(LIBSSH2_SESSION * session,
|
|
||||||
LIBSSH2_KNOWNHOSTS * s,
|
|
||||||
char *line,
|
|
||||||
char *end)
|
|
||||||
{
|
|
||||||
char *start;
|
|
||||||
char *comma = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* TODO: we don't handle the hashed name format because the hashing
|
|
||||||
* mechanism isnt defined (at least based on the man page)
|
|
||||||
*/
|
|
||||||
if (*line == '|')
|
|
||||||
return -1;
|
|
||||||
if (line == end || *line == ' ')
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
s->hostname_line = (char *) LIBSSH2_ALLOC (session, (end - line) + 1);
|
|
||||||
strncpy (s->hostname_line, line, (end - line) + 1);
|
|
||||||
start = end = s->hostname_line + (end - line);
|
|
||||||
*end = 0;
|
|
||||||
|
|
||||||
s->hostnames_size = 1;
|
|
||||||
comma = s->hostname_line;
|
|
||||||
while ((comma = strchr (comma, ',')) != NULL) {
|
|
||||||
comma++;
|
|
||||||
if (*comma == ',' || *comma == 0) {
|
|
||||||
LIBSSH2_FREE (session, s->hostname_line);
|
|
||||||
s->hostname_line = NULL;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
s->hostnames_size++;
|
|
||||||
}
|
|
||||||
s->hostnames = (char **) LIBSSH2_ALLOC
|
|
||||||
(session, sizeof (char *) * s->hostnames_size);
|
|
||||||
|
|
||||||
start = comma = s->hostname_line;
|
|
||||||
i = 0;
|
|
||||||
while ((comma = strchr (comma, ',')) != NULL) {
|
|
||||||
*comma = 0;
|
|
||||||
s->hostnames[i] = start;
|
|
||||||
|
|
||||||
comma++;
|
|
||||||
start = comma;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
s->hostnames[i] = start;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the number of bytes read or -1. */
|
|
||||||
static int
|
|
||||||
ssh_proto_str_read(LIBSSH2_SESSION * session,
|
|
||||||
char *line,
|
|
||||||
char **val,
|
|
||||||
char *end
|
|
||||||
)
|
|
||||||
{
|
|
||||||
unsigned int len;
|
|
||||||
|
|
||||||
if (line + 4 > end)
|
|
||||||
return -1;
|
|
||||||
len = (line[0] << 24) + (line[1] << 16) + (line[2] << 8) + line[3];
|
|
||||||
if (line + 4 + len > end)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
*val = LIBSSH2_ALLOC (session, len);
|
|
||||||
memcpy (*val, line + 4, len);
|
|
||||||
return len + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
ssh_host_parse_key(LIBSSH2_SESSION * session,
|
|
||||||
LIBSSH2_KNOWNHOSTS * s,
|
|
||||||
char *line,
|
|
||||||
int is_base64_encoded)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
char *tmp, *tmp2;
|
|
||||||
/* workaround for the MD5 stuff */
|
|
||||||
libssh2_md5_ctx ctx;
|
|
||||||
|
|
||||||
/* the bits, exponent, modulus format */
|
|
||||||
if (is_base64_encoded == 0) {
|
|
||||||
s->ssh_version = 1;
|
|
||||||
s->key_type = 0;
|
|
||||||
if (!isdigit (*line))
|
|
||||||
return -1;
|
|
||||||
if (sscanf (line, "%hu %hu ", &(s->bits), &(s->exponent)) != 2)
|
|
||||||
return -2;
|
|
||||||
/* TODO:
|
|
||||||
* There's probably an acceptable range...
|
|
||||||
*/
|
|
||||||
if (s->bits <= 0 || s->exponent <= 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
line = strchr (line, ' ');
|
|
||||||
if (line == NULL)
|
|
||||||
return -3;
|
|
||||||
line++;
|
|
||||||
line = strchr (line, ' ');
|
|
||||||
if (line == NULL)
|
|
||||||
return -4;
|
|
||||||
line++;
|
|
||||||
/* TODO:
|
|
||||||
* figure out what format modulus is in since its not clear
|
|
||||||
* from the man page
|
|
||||||
*/
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s->ssh_version = 2;
|
|
||||||
/* we only handle the rsa type */
|
|
||||||
if (strstr (line, "ssh-rsa") != line)
|
|
||||||
return -6;
|
|
||||||
s->key_type = 0;
|
|
||||||
line += 7;
|
|
||||||
if (*line != ' ')
|
|
||||||
return 2;
|
|
||||||
line++;
|
|
||||||
i = 0;
|
|
||||||
while (*line) {
|
|
||||||
if ((line[i] >= 0x30 && line[i] <= 0x39) ||
|
|
||||||
(line[i] >= 0x41 && line[i] <= 0x5a) ||
|
|
||||||
(line[i] >= 0x61 && line[i] <= 0x7a) ||
|
|
||||||
(line[i] == '+') || (line[i] == '/') || (line[i] == '='))
|
|
||||||
i++;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == 0)
|
|
||||||
return 3;
|
|
||||||
tmp = LIBSSH2_ALLOC (session, sizeof (char) * (i + 5));
|
|
||||||
strncpy (tmp, line, i);
|
|
||||||
/* this should hopefully avoid any issues with reading
|
|
||||||
* past the array if its malformed */
|
|
||||||
tmp[i] = tmp[i + 1] = tmp[i + 2] = tmp[i + 3] = tmp[i + 4] = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
/* TODO: rework the api interface instead of making a local
|
|
||||||
instance */
|
|
||||||
i = libssh2_base64_decode(session, &tmp2, (unsigned int *)&j,
|
|
||||||
tmp, strlen(tmp));
|
|
||||||
LIBSSH2_FREE(session, tmp);
|
|
||||||
if (i != 0)
|
|
||||||
return 4;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* printf("Decode Size: %d\n", i); */
|
|
||||||
/* free (tmp); */
|
|
||||||
|
|
||||||
|
|
||||||
#if LIBSSH2_MD5
|
|
||||||
s->md5 = LIBSSH2_ALLOC (session, 16);
|
|
||||||
|
|
||||||
libssh2_md5_init (&ctx);
|
|
||||||
libssh2_md5_update (ctx, tmp2, j);
|
|
||||||
libssh2_md5_final (ctx, s->md5);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
line = tmp2;
|
|
||||||
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
|
|
||||||
if (i < 0) {
|
|
||||||
LIBSSH2_FREE (session, tmp2);
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
/* TODO: verify that its ssh-rsa -- its the only one
|
|
||||||
* supported
|
|
||||||
*/
|
|
||||||
if (!(i == 11 && tmp[0] == 's' && tmp[1] == 's' &&
|
|
||||||
tmp[2] == 'h' && tmp[3] == '-' && tmp[4] == 'r' &&
|
|
||||||
tmp[5] == 's' && tmp[6] == 'a')) {
|
|
||||||
free (tmp);
|
|
||||||
free (tmp2);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBSSH2_FREE (session, tmp);
|
|
||||||
line += i;
|
|
||||||
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
|
|
||||||
if (i < 0) {
|
|
||||||
LIBSSH2_FREE (session, tmp2);
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
/* TODO: verify that the exponent is valid */
|
|
||||||
if (i == 5)
|
|
||||||
s->exponent = (unsigned short) ((unsigned char) *tmp);
|
|
||||||
else {
|
|
||||||
LIBSSH2_FREE (session, tmp);
|
|
||||||
LIBSSH2_FREE (session, tmp2);
|
|
||||||
return 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBSSH2_FREE (session, tmp);
|
|
||||||
line += i;
|
|
||||||
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
|
|
||||||
if (i < 0) {
|
|
||||||
LIBSSH2_FREE (session, tmp2);
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: the modulus may need to be converted to
|
|
||||||
* big integer format
|
|
||||||
*/
|
|
||||||
s->modulus_length = i - 4;
|
|
||||||
s->modulus = tmp;
|
|
||||||
|
|
||||||
s->bits = (s->modulus_length - 1) * 8;
|
|
||||||
|
|
||||||
LIBSSH2_FREE (session, tmp2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBSSH2_API void
|
|
||||||
libssh2_free_host_entry(LIBSSH2_SESSION * session, LIBSSH2_KNOWNHOSTS * s)
|
|
||||||
{
|
|
||||||
/* int i; */
|
|
||||||
if (s == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (s->hostname_line != NULL) {
|
|
||||||
LIBSSH2_FREE (session, s->hostname_line);
|
|
||||||
s->hostname_line = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->hostnames != NULL && s->hostnames_size > 0) {
|
|
||||||
LIBSSH2_FREE (session, s->hostnames);
|
|
||||||
s->hostnames = NULL;
|
|
||||||
}
|
|
||||||
s->hostnames_size = s->bits = s->exponent = -1;
|
|
||||||
|
|
||||||
if (s->modulus != NULL) {
|
|
||||||
LIBSSH2_FREE (session, s->modulus);
|
|
||||||
s->modulus = NULL;
|
|
||||||
}
|
|
||||||
s->modulus_length = -1;
|
|
||||||
s->ssh_version = -1;
|
|
||||||
|
|
||||||
if (s->md5 != NULL) {
|
|
||||||
LIBSSH2_FREE (session, s->md5);
|
|
||||||
s->md5 = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBSSH2_FREE (session, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSH_HOSTNAME_TESTS
|
|
||||||
int
|
|
||||||
ssh_unit_tests (int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *l[] = {
|
|
||||||
"closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net",
|
|
||||||
"cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
|
|
||||||
" cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
|
|
||||||
"",
|
|
||||||
",",
|
|
||||||
"f, ",
|
|
||||||
"cvs.example.net ssh-rsa AAAA1234.....=",
|
|
||||||
"192.168.30.118 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwWVqxKm2Biwilakq9Ex8/tzHVQjRrzEkwlrWTDneptodVgqAzXUFQSa6Oj9AwzdDPhKe71vTv7RhXYg0ZvB1a5dIkzgCdoF/mIuTb80LvK7f0NxCaAHWODuHbwlJeMmjHV0WFsjsdOf690fPqeinD/8jfBQB950M1K3Qesib9H75gsnawF06MzZ52nC1HHi8mG2tGy2PMyP+mJs7KN1v4T+nobZ10ePe1dMqYXMdro/PB0JQmuGL7bBR5GRDEkK6nFcp2HsvuzXSeWZJcmWDdo+1n0cNg2th5VEIxrrFG5iy0CA2AXVPMqkf3VrAXGXV66dJTGtBqZ5GoxJCxDgW6w==",
|
|
||||||
"|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsaAAAA1234.....="
|
|
||||||
};
|
|
||||||
int s;
|
|
||||||
int cases = sizeof (l) / sizeof (char *);
|
|
||||||
|
|
||||||
if (argc == 2) {
|
|
||||||
s = atoi (argv[1]);
|
|
||||||
if (s >= 0 && s < cases) {
|
|
||||||
LIBSSH2_KNOWNHOSTS *x = NULL;
|
|
||||||
printf ("%d\n", s = new_ssh_host_entry (&x, l[s]));
|
|
||||||
libssh2_free_host_entry (x);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Returns 0 for a match, non-zero otherwise. */
|
|
||||||
LIBSSH2_API int
|
|
||||||
libssh2_host_entry_match(LIBSSH2_KNOWNHOSTS * x, char *host)
|
|
||||||
{
|
|
||||||
/* TODO: Add pattern matching and/or DNS matching against
|
|
||||||
* to entries found in x
|
|
||||||
*/
|
|
||||||
int i;
|
|
||||||
if (host == NULL || x == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* FIXME: this should use a case-insensitive compare as dns hostnames
|
|
||||||
* are generally case insensitive anyways
|
|
||||||
*/
|
|
||||||
for (i = 0; i < x->hostnames_size; i++)
|
|
||||||
if (!strcmp (x->hostnames[i], host))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
@@ -263,7 +263,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
|||||||
libssh2pack_t
|
libssh2pack_t
|
||||||
_libssh2_transport_read(LIBSSH2_SESSION * session)
|
_libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||||
{
|
{
|
||||||
libssh2pack_t rc;
|
libssh2pack_t rc = -1;
|
||||||
struct transportpacket *p = &session->packet;
|
struct transportpacket *p = &session->packet;
|
||||||
int remainbuf;
|
int remainbuf;
|
||||||
int remainpack;
|
int remainpack;
|
||||||
@@ -272,9 +272,11 @@ _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;
|
int status;
|
||||||
|
|
||||||
|
/* default clear the bit */
|
||||||
|
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All channels, systems, subsystems, etc eventually make it down here
|
* All channels, systems, subsystems, etc eventually make it down here
|
||||||
* when looking for more incoming data. If a key exchange is going on
|
* when looking for more incoming data. If a key exchange is going on
|
||||||
@@ -294,17 +296,17 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
* is done!
|
* is done!
|
||||||
*/
|
*/
|
||||||
_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);
|
status = libssh2_kex_exchange(session, 1, &session->startup_key_state);
|
||||||
if (status == PACKET_EAGAIN) {
|
if (status == PACKET_EAGAIN) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||||
"Would block exchanging encryption keys", 0);
|
"Would block exchanging encryption keys", 0);
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (status) {
|
} else if (status) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
|
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 LIBSSH2_ERROR_KEX_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -363,8 +365,8 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
/* now read a big chunk from the network into the temp buffer */
|
/* now read a big chunk from the network into the temp buffer */
|
||||||
nread =
|
nread =
|
||||||
_libssh2_recv(session->socket_fd, &p->buf[remainbuf],
|
_libssh2_recv(session->socket_fd, &p->buf[remainbuf],
|
||||||
PACKETBUFSIZE - remainbuf,
|
PACKETBUFSIZE - remainbuf,
|
||||||
LIBSSH2_SOCKET_RECV_FLAGS(session));
|
LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||||
if (nread <= 0) {
|
if (nread <= 0) {
|
||||||
/* 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 */
|
||||||
@@ -375,6 +377,7 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
}
|
}
|
||||||
return PACKET_FAIL;
|
return PACKET_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugdump(session, "libssh2_transport_read() raw",
|
debugdump(session, "libssh2_transport_read() raw",
|
||||||
&p->buf[remainbuf], nread);
|
&p->buf[remainbuf], nread);
|
||||||
/* advance write pointer */
|
/* advance write pointer */
|
||||||
@@ -421,7 +424,12 @@ _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
* and we can extract packet and padding length from it
|
* and we can extract packet and padding length from it
|
||||||
*/
|
*/
|
||||||
p->packet_length = _libssh2_ntohu32(block);
|
p->packet_length = _libssh2_ntohu32(block);
|
||||||
|
if (p->packet_length < 1)
|
||||||
|
return PACKET_FAIL;
|
||||||
|
|
||||||
p->padding_length = block[4];
|
p->padding_length = block[4];
|
||||||
|
if (p->padding_length < 0)
|
||||||
|
return PACKET_FAIL;
|
||||||
|
|
||||||
/* total_num is the number of bytes following the initial
|
/* total_num is the number of bytes following the initial
|
||||||
(5 bytes) packet length and padding length fields */
|
(5 bytes) packet length and padding length fields */
|
||||||
@@ -603,14 +611,20 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
length = p->ototal_num - p->osent;
|
length = p->ototal_num - p->osent;
|
||||||
|
|
||||||
rc = _libssh2_send(session->socket_fd, &p->outbuf[p->osent], length,
|
rc = _libssh2_send(session->socket_fd, &p->outbuf[p->osent], length,
|
||||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||||
|
|
||||||
|
if(rc > 0) {
|
||||||
|
debugdump(session, "libssh2_transport_write send()",
|
||||||
|
&p->outbuf[p->osent], rc);
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == length) {
|
if (rc == length) {
|
||||||
/* the remainder of the package was sent */
|
/* the remainder of the package was sent */
|
||||||
LIBSSH2_FREE(session, p->outbuf);
|
LIBSSH2_FREE(session, p->outbuf);
|
||||||
p->outbuf = NULL;
|
p->outbuf = NULL;
|
||||||
p->ototal_num = 0;
|
p->ototal_num = 0;
|
||||||
} else if (rc < 0) {
|
}
|
||||||
|
else if (rc < 0) {
|
||||||
/* nothing was sent */
|
/* nothing was sent */
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
/* send failure! */
|
/* send failure! */
|
||||||
@@ -620,9 +634,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugdump(session, "libssh2_transport_write send()", &p->outbuf[p->osent],
|
p->osent += rc; /* we sent away this much data */
|
||||||
length);
|
|
||||||
p->osent += length; /* we sent away this much data */
|
|
||||||
|
|
||||||
return PACKET_NONE;
|
return PACKET_NONE;
|
||||||
}
|
}
|
||||||
@@ -667,6 +679,9 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
|
|
||||||
debugdump(session, "libssh2_transport_write plain", data, data_len);
|
debugdump(session, "libssh2_transport_write plain", data, data_len);
|
||||||
|
|
||||||
|
/* default clear the bit */
|
||||||
|
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
||||||
|
|
||||||
/* FIRST, check if we have a pending write to complete */
|
/* FIRST, check if we have a pending write to complete */
|
||||||
rc = send_existing(session, data, data_len, &ret);
|
rc = send_existing(session, data, data_len, &ret);
|
||||||
if (rc || ret) {
|
if (rc || ret) {
|
||||||
@@ -768,7 +783,7 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
session->local.seqno++;
|
session->local.seqno++;
|
||||||
|
|
||||||
ret = _libssh2_send(session->socket_fd, p->outbuf, total_length,
|
ret = _libssh2_send(session->socket_fd, p->outbuf, total_length,
|
||||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||||
|
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
|
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
|
||||||
@@ -794,6 +809,3 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
|
|
||||||
return PACKET_NONE; /* all is good */
|
return PACKET_NONE; /* all is good */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1
tests/.gitignore
vendored
Normal file
1
tests/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ssh2
|
@@ -5,7 +5,7 @@
|
|||||||
##
|
##
|
||||||
## Comments to: Guenter Knauf <eflash@gmx.net>
|
## Comments to: Guenter Knauf <eflash@gmx.net>
|
||||||
##
|
##
|
||||||
## $Id: Makefile.win32,v 1.10 2009/03/06 07:25:37 gknauf Exp $
|
## $Id: Makefile.win32,v 1.11 2009/04/09 03:13:52 gknauf Exp $
|
||||||
#
|
#
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ WITH_ZLIB = 1
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
ifndef OPENSSL_PATH
|
ifndef OPENSSL_PATH
|
||||||
OPENSSL_PATH = ../../openssl-0.9.8j
|
OPENSSL_PATH = ../../openssl-0.9.8k
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Edit the path below to point to your Distribution folder.
|
# Edit the path below to point to your Distribution folder.
|
||||||
@@ -63,7 +63,7 @@ endif
|
|||||||
ifdef METROWERKS
|
ifdef METROWERKS
|
||||||
CC = mwcc
|
CC = mwcc
|
||||||
else
|
else
|
||||||
CC = $(CRPREFIX)gcc
|
CC = $(CROSSPREFIX)gcc
|
||||||
endif
|
endif
|
||||||
CP = cp -afv
|
CP = cp -afv
|
||||||
# RM = rm -f
|
# RM = rm -f
|
||||||
@@ -91,13 +91,13 @@ CFLAGS += -nostdinc -gccinc -msgstyle gcc -inline off -opt nointrinsics -proc 58
|
|||||||
CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support"
|
CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support"
|
||||||
CFLAGS += -w on,nounused,nounusedexpr # -ansi strict
|
CFLAGS += -w on,nounused,nounusedexpr # -ansi strict
|
||||||
else
|
else
|
||||||
LD = $(CRPREFIX)gcc
|
LD = $(CROSSPREFIX)gcc
|
||||||
RC = $(CRPREFIX)windres
|
RC = $(CROSSPREFIX)windres
|
||||||
LDFLAGS = -s -shared -Wl,--out-implib,$(TARGET)dll.a
|
LDFLAGS = -s -shared -Wl,--out-implib,$(TARGET)dll.a
|
||||||
AR = $(CRPREFIX)ar
|
AR = $(CROSSPREFIX)ar
|
||||||
ARFLAGS = -cq
|
ARFLAGS = -cq
|
||||||
LIBEXT = a
|
LIBEXT = a
|
||||||
RANLIB = $(CRPREFIX)ranlib
|
RANLIB = $(CROSSPREFIX)ranlib
|
||||||
#LDLIBS += -lwsock32
|
#LDLIBS += -lwsock32
|
||||||
LDLIBS += -lws2_32
|
LDLIBS += -lws2_32
|
||||||
RCFLAGS = -O coff -i
|
RCFLAGS = -O coff -i
|
||||||
|
3
win32/msvcproj.foot
Normal file
3
win32/msvcproj.foot
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
|
|
145
win32/msvcproj.head
Normal file
145
win32/msvcproj.head
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="libssh2" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||||
|
|
||||||
|
CFG=libssh2 - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "libssh2.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "libssh2.mak" CFG="libssh2 - Win32 DLL Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "libssh2 - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "libssh2 - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "libssh2 - Win32 LIB Release" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE "libssh2 - Win32 LIB Debug" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "libssh2 - Win32 DLL Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release_dll"
|
||||||
|
# PROP BASE Intermediate_Dir "Release_dll"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release_dll"
|
||||||
|
# PROP Intermediate_Dir "Release_dll"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\win32" /I "..\include" /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# SUBTRACT CPP /YX
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib ws2_32.lib libeay32.lib ssleay32.lib zlib.lib /nologo /dll /map /debug /machine:I386 /out:"Release_dll/libssh2.dll"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "libssh2 - Win32 DLL Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug_dll"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug_dll"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug_dll"
|
||||||
|
# PROP Intermediate_Dir "Debug_dll"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\win32" /I "..\include" /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /WX /YX
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib ws2_32.lib libeay32.lib ssleay32.lib zlib.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug_dll/libssh2.dll" /pdbtype:sept
|
||||||
|
# SUBTRACT LINK32 /nodefaultlib
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "libssh2 - Win32 LIB Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release_lib"
|
||||||
|
# PROP BASE Intermediate_Dir "Release_lib"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release_lib"
|
||||||
|
# PROP Intermediate_Dir "Release_lib"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\win32" /I "..\include" /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo /out:"Release_lib\libssh.lib"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "libssh2 - Win32 LIB Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug_lib"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug_lib"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug_lib"
|
||||||
|
# PROP Intermediate_Dir "Debug_lib"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\win32" /I "..\include" /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo /out:"Debug_lib\libssh2d.lib"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "libssh2 - Win32 DLL Release"
|
||||||
|
# Name "libssh2 - Win32 DLL Debug"
|
||||||
|
# Name "libssh2 - Win32 LIB Release"
|
||||||
|
# Name "libssh2 - Win32 LIB Debug"
|
||||||
|
|
@@ -5,7 +5,7 @@
|
|||||||
##
|
##
|
||||||
## Comments to: Guenter Knauf <eflash@gmx.net>
|
## Comments to: Guenter Knauf <eflash@gmx.net>
|
||||||
##
|
##
|
||||||
## $Id: Makefile.win32,v 1.7 2009/03/06 07:25:49 gknauf Exp $
|
## $Id: Makefile.win32,v 1.8 2009/04/09 03:14:05 gknauf Exp $
|
||||||
#
|
#
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ endif
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
ifndef OPENSSL_PATH
|
ifndef OPENSSL_PATH
|
||||||
OPENSSL_PATH = ../../../openssl-0.9.8j
|
OPENSSL_PATH = ../../../openssl-0.9.8k
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Edit the var below to enable static linking of libssh2 and libz
|
# Edit the var below to enable static linking of libssh2 and libz
|
||||||
@@ -51,7 +51,7 @@ endif
|
|||||||
ifdef METROWERKS
|
ifdef METROWERKS
|
||||||
CC = mwcc
|
CC = mwcc
|
||||||
else
|
else
|
||||||
CC = gcc
|
CC = $(CROSSPREFIX)gcc
|
||||||
endif
|
endif
|
||||||
CP = cp -afv
|
CP = cp -afv
|
||||||
# RM = rm -f
|
# RM = rm -f
|
||||||
@@ -79,19 +79,20 @@ CFLAGS += -nostdinc -gccinc -msgstyle gcc -inline off -opt nointrinsics -proc 58
|
|||||||
CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support"
|
CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support"
|
||||||
CFLAGS += -w on,nounused,nounusedexpr # -ansi strict
|
CFLAGS += -w on,nounused,nounusedexpr # -ansi strict
|
||||||
else
|
else
|
||||||
LD = gcc
|
LD = $(CROSSPREFIX)gcc
|
||||||
RC = windres
|
RC = $(CROSSPREFIX)windres
|
||||||
LDFLAGS = -s
|
LDFLAGS = -s
|
||||||
AR = ar
|
AR = $(CROSSPREFIX)ar
|
||||||
ARFLAGS = -cq
|
ARFLAGS = -cq
|
||||||
LIBEXT = a
|
LIBEXT = a
|
||||||
#LDLIBS += -lwsock32
|
#LDLIBS += -lwsock32
|
||||||
LDLIBS += -lws2_32
|
LDLIBS += -lws2_32
|
||||||
RCFLAGS = -O coff -i
|
RCFLAGS = -O coff -i
|
||||||
CFLAGS += -fno-strict-aliasing -Wall -Wno-unused # -pedantic
|
CFLAGS += -fno-strict-aliasing
|
||||||
|
CFLAGS += -Wall #-Wno-unused #-pedantic
|
||||||
endif
|
endif
|
||||||
|
|
||||||
INCLUDES = -I. -I.. -I../../include
|
INCLUDES = -I.. -I../../include
|
||||||
INCLUDES += -I$(OPENSSL_PATH)/outinc -I$(OPENSSL_PATH)/outinc/openssl
|
INCLUDES += -I$(OPENSSL_PATH)/outinc -I$(OPENSSL_PATH)/outinc/openssl
|
||||||
#LIBPATH += -L$(OPENSSL_PATH)/out
|
#LIBPATH += -L$(OPENSSL_PATH)/out
|
||||||
LIBPATH += -L..
|
LIBPATH += -L..
|
||||||
|
Reference in New Issue
Block a user