Compare commits
96 Commits
libssh2-1.
...
libssh2-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c889058cb3 | ||
![]() |
69c876e210 | ||
![]() |
10f5c70ac0 | ||
![]() |
ea914c8b72 | ||
![]() |
64a6c255ec | ||
![]() |
e09d6ac653 | ||
![]() |
91841731af | ||
![]() |
a190437c4a | ||
![]() |
68a900d27a | ||
![]() |
e4b7baa885 | ||
![]() |
2622bbaf33 | ||
![]() |
d3dbe4c81e | ||
![]() |
095ccbf825 | ||
![]() |
8eafded280 | ||
![]() |
6df87e64b7 | ||
![]() |
3ddac8ac66 | ||
![]() |
6c543545fe | ||
![]() |
abd9bd0bbe | ||
![]() |
5dd4005ace | ||
![]() |
8f102b8f56 | ||
![]() |
7d71f92a9c | ||
![]() |
f6fab0d9ea | ||
![]() |
cc7f90f1d4 | ||
![]() |
6d55714ab5 | ||
![]() |
6b23f640f8 | ||
![]() |
2cb8866f0a | ||
![]() |
3b3e13366e | ||
![]() |
9f4292433a | ||
![]() |
f077984394 | ||
![]() |
44eba0c993 | ||
![]() |
474e38119b | ||
![]() |
7f27b0822d | ||
![]() |
e3d8c1cfed | ||
![]() |
11a114ee7c | ||
![]() |
e48907ee05 | ||
![]() |
3f6bc287f9 | ||
![]() |
e84fe88526 | ||
![]() |
73e37b3b49 | ||
![]() |
7926c9cfaa | ||
![]() |
63457dfa6c | ||
![]() |
d00e97a7f1 | ||
![]() |
8436e45ea6 | ||
![]() |
0b6e37872d | ||
![]() |
1b3b7b2214 | ||
![]() |
6a249d7b6c | ||
![]() |
87e32272f9 | ||
![]() |
bd0505d6b9 | ||
![]() |
f70dbfa3e6 | ||
![]() |
a2452d7eee | ||
![]() |
bbb2f29037 | ||
![]() |
3138b5891f | ||
![]() |
c573af83de | ||
![]() |
ea8babf6d1 | ||
![]() |
db26c4eace | ||
![]() |
7b351eed36 | ||
![]() |
58abc7e30b | ||
![]() |
0a3b350012 | ||
![]() |
b5e358618b | ||
![]() |
dd81bda112 | ||
![]() |
12433b4511 | ||
![]() |
39cbd17e19 | ||
![]() |
1f91ab049f | ||
![]() |
f2e5b49904 | ||
![]() |
b4c0821332 | ||
![]() |
70b199f476 | ||
![]() |
d142f385da | ||
![]() |
1a491c6f00 | ||
![]() |
1256c61815 | ||
![]() |
95f559a926 | ||
![]() |
052a68db30 | ||
![]() |
1aba38cd7d | ||
![]() |
7317edab61 | ||
![]() |
e642e2c202 | ||
![]() |
f07cf3afd3 | ||
![]() |
1e350754f6 | ||
![]() |
55031fa320 | ||
![]() |
355fbf4d5b | ||
![]() |
74c63852d7 | ||
![]() |
ebbd7c879b | ||
![]() |
b78f854d8b | ||
![]() |
1f0d47fa92 | ||
![]() |
463e09e55f | ||
![]() |
82bf39dbfa | ||
![]() |
e5f170bae2 | ||
![]() |
fc60563840 | ||
![]() |
b38b4fb859 | ||
![]() |
3182045c2d | ||
![]() |
60d73d5663 | ||
![]() |
1e80194b97 | ||
![]() |
0c13f7beda | ||
![]() |
b859f4d9d2 | ||
![]() |
13092c5a5e | ||
![]() |
22b73235d3 | ||
![]() |
55034294e8 | ||
![]() |
5e80055d22 | ||
![]() |
11ca8d5583 |
2
.gitattribute
Normal file
2
.gitattribute
Normal file
@@ -0,0 +1,2 @@
|
||||
win32/msvcproj.head -crlf
|
||||
win32/msvcproj.foot -crlf
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -31,3 +31,4 @@ install-sh
|
||||
*.la
|
||||
mkinstalldirs
|
||||
tags
|
||||
libssh2.pc
|
||||
|
1
COPYING
1
COPYING
@@ -1,6 +1,7 @@
|
||||
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2006-2007 The Written Word, Inc.
|
||||
* Copyright (c) 2009 Daniel Stenberg
|
||||
* Copyright (C) 2008, 2009 Simon Josefsson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
|
1
HACKING
1
HACKING
@@ -10,3 +10,4 @@ libssh2 source code style guide:
|
||||
}
|
||||
|
||||
- keep source lines shorter than 80 columns
|
||||
- See libssh2-style.el for how to achieve this within Emacs
|
||||
|
85
Makefile.am
85
Makefile.am
@@ -75,55 +75,54 @@ 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); \
|
||||
@( (cat $(srcdir)/win32/msvcproj.head; \
|
||||
echo "# Begin Group \"Source Files\""; \
|
||||
echo ""; \
|
||||
echo "# PROP Default_Filter \"cpp;c;cxx\""; \
|
||||
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"; \
|
||||
echo ""; \
|
||||
echo "SOURCE=..\\src\\"$$file; \
|
||||
echo "# End Source File"; \
|
||||
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); \
|
||||
echo "# End Group"; \
|
||||
echo "# Begin Group \"Header Files\""; \
|
||||
echo ""; \
|
||||
echo "# PROP Default_Filter \"h;hpp;hxx\""; \
|
||||
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"; \
|
||||
echo ""; \
|
||||
if [ "$$file" == "libssh2_config.h" ]; \
|
||||
then \
|
||||
echo "SOURCE=.\\"$$file; \
|
||||
else \
|
||||
echo "SOURCE=..\\src\\"$$file; \
|
||||
fi; \
|
||||
echo "# End Source File"; \
|
||||
done; \
|
||||
echo "# End Group" $(DSPOUT); \
|
||||
cat $(srcdir)/win32/msvcproj.foot $(DSPOUT) )
|
||||
echo "# End Group"; \
|
||||
cat $(srcdir)/win32/msvcproj.foot) | \
|
||||
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )
|
||||
|
||||
$(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); \
|
||||
@( (cat $(srcdir)/vc8proj.head; \
|
||||
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>"; \
|
||||
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); \
|
||||
echo "</Filter><Filter Name=\"Header Files\">"; \
|
||||
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>"; \
|
||||
done; \
|
||||
cat $(srcdir)/vc8proj.foot $(VCPROJOUT) )
|
||||
cat $(srcdir)/vc8proj.foot) | \
|
||||
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )
|
||||
|
@@ -1,5 +1,5 @@
|
||||
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 openssl.c libgcrypt.c pem.c
|
||||
version.c knownhost.c agent.c openssl.c libgcrypt.c pem.c
|
||||
|
||||
HHEADERS = libssh2_priv.h openssl.h libgcrypt.h transport.h channel.h comp.h mac.h misc.h
|
||||
|
52
NEWS
52
NEWS
@@ -1,3 +1,55 @@
|
||||
Version 1.2.4 (February 13, 2010)
|
||||
|
||||
o Resolve compile issues on Solaris x64 and UltraSPARC
|
||||
o Allow compiling with OpenSSL when AES isn't available
|
||||
o Fix Tru64 socklen_t compile issue with example/direct_tcpip.c
|
||||
|
||||
Version 1.2.3 (February 3, 2010)
|
||||
|
||||
o Added libssh2_trace_sethandler()
|
||||
o Added the direct_tcpip.c example
|
||||
o Fixed memory leak in userauth_publickey
|
||||
o Added support for authentication via SSH-Agent. By Daiki Ueno.
|
||||
|
||||
o Respond to unknown SSH_MSG_GLOBAL_REQUEST/SSH_MSG_CHANNEL_REQUEST
|
||||
with SSH_MSG_REQUEST_FAILURE/SSH_MSG_CHANNEL_FAILURE in order to
|
||||
make (at least) OpenSSH server keepalive work. Before OpenSSH
|
||||
servers (configured with a positive ClientAliveInterval) would
|
||||
terminate connections against libssh2 clients because libssh2 did
|
||||
not respond properly to the request. By Simon Josefsson.
|
||||
|
||||
Version 1.2.2 (November 16, 2009)
|
||||
|
||||
* This release includes the following changes:
|
||||
|
||||
o Fix crash when server sends an invalid SSH_MSG_IGNORE message.
|
||||
Reported by Bob Alexander <balexander@expressor-software.com> in
|
||||
<http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
|
||||
By Simon Josefsson.
|
||||
|
||||
o Support for the "aes128-ctr", "aes192-ctr", "aes256-ctr" ciphers
|
||||
as per RFC 4344 for libgcrypt and OpenSSL. They are now the
|
||||
preferred ciphers. By Simon Josefsson.
|
||||
|
||||
o Support for the "arcfour128" cipher as per RFC 4345 for libgcrypt
|
||||
and OpenSSL. It is preferred over the normal "arcfour" cipher
|
||||
which is somewhat broken. By Simon Josefsson.
|
||||
|
||||
o Add support for GCC visibility features. By Cristian Rodr<64>guez.
|
||||
|
||||
o Fix libssh2_channel_forward_accept. By Juzna.
|
||||
|
||||
o Generate Win32 files correctly. By Peter Stuge.
|
||||
|
||||
o Fix permission issue in ssh2 self test. By Dan Fandrich.
|
||||
|
||||
o Use memmove instead of memcpy in one place which copies
|
||||
overlapping memory areas.
|
||||
|
||||
o Cleanup hard coding of cipher modes in libgcrypt backend. By Simon.
|
||||
|
||||
o Added man page for libssh2_knownhost_free. By Daniel.
|
||||
|
||||
Version 1.2.1 (September 28, 2009)
|
||||
|
||||
* This release includes the following changes:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
!include "win32/config.mk"
|
||||
|
||||
# SUBDIRS=src example\simple
|
||||
# SUBDIRS=src example
|
||||
SUBDIRS=src
|
||||
|
||||
all-sub:
|
||||
|
@@ -1,27 +1,18 @@
|
||||
libssh2 1.2.1
|
||||
libssh2 1.2.4
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o generate and install libssh2.pc
|
||||
o
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o proper return codes returned from several functions
|
||||
o return EAGAIN internal cleanup
|
||||
o added knownhost.c to windows makefiles
|
||||
o pass private-key to OpenSSL as a filename with BIO_new_file().
|
||||
o make libssh2_scp_send/recv do blocking mode correctly
|
||||
o libssh2_channel_wait_closed() could hang
|
||||
o libssh2_channel_read_ex() must return 0 when closed
|
||||
o added gettimeofday() function for win32 for the debug trace outputs
|
||||
o transport layer bug causing invalid -39 (LIBSSH2_ERROR_BAD_USE) errors
|
||||
o scp examples now loop correctly over libssh2_channel_write()
|
||||
o Resolve compile issues on Solaris x64 and UltraSPARC
|
||||
o Allow compiling with OpenSSL when AES isn't available
|
||||
o Fix Tru64 socklen_t compile issue with example/direct_tcpip.c
|
||||
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Peter Stuge, Neil Gierman, Steven Van Ingelgem, Alexander Lamaison,
|
||||
Guenter Knauf, Simon Josefsson
|
||||
Dan Fandrich, Dave McCaldon, Peter Stuge
|
||||
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
2
TODO
2
TODO
@@ -18,6 +18,8 @@ Things TODO
|
||||
|
||||
* Fix all compiler warnings (some can't be done without API changes)
|
||||
|
||||
* Expose error messages sent by the server
|
||||
|
||||
At next SONAME bump
|
||||
===================
|
||||
|
||||
|
@@ -22,6 +22,6 @@ ${AUTOHEADER:-autoheader}
|
||||
# copy the private libssh2_config.h.in to the examples dir so that
|
||||
# it can be included without pointing the include path to the private
|
||||
# source dir
|
||||
cp src/libssh2_config.h.in example/simple/config.h.in
|
||||
cp src/libssh2_config.h.in example/libssh2_config.h.in
|
||||
${AUTOCONF:-autoconf}
|
||||
${AUTOMAKE:-automake} --add-missing --copy
|
||||
|
48
configure.ac
48
configure.ac
@@ -1,8 +1,8 @@
|
||||
# AC_PREREQ(2.57)
|
||||
AC_INIT(libssh2, [-], libssh2-devel@lists.sourceforge.net)
|
||||
AC_INIT(libssh2, [-], libssh2-devel@cool.haxx.se)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR([src])
|
||||
AC_CONFIG_HEADER([src/libssh2_config.h])
|
||||
AM_CONFIG_HEADER([src/libssh2_config.h example/libssh2_config.h])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
dnl SED is needed by some of the tools
|
||||
@@ -41,6 +41,9 @@ case "$host" in
|
||||
;;
|
||||
*hpux*)
|
||||
;;
|
||||
*osf*)
|
||||
CFLAGS="$CFLAGS -D_POSIX_PII_SOCKET"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
@@ -162,11 +165,51 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
dnl ************************************************************
|
||||
dnl Enable hiding of internal symbols in library to reduce its size and
|
||||
dnl speed dynamic linking of applications. This currently is only supported
|
||||
dnl on gcc >= 4.0 and SunPro C.
|
||||
dnl
|
||||
AC_MSG_CHECKING([whether to enable hidden symbols in the library])
|
||||
AC_ARG_ENABLE(hidden-symbols,
|
||||
AC_HELP_STRING([--enable-hidden-symbols],[Hide internal symbols in library])
|
||||
AC_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibility in library]),
|
||||
[ case "$enableval" in
|
||||
no)
|
||||
AC_MSG_RESULT(no)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_CHECKING([whether $CC supports it])
|
||||
if test "$GCC" = yes ; then
|
||||
if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(LIBSSH2_API, [__attribute__ ((visibility ("default")))], [to make a symbol visible])
|
||||
CFLAGS="$CFLAGS -fvisibility=hidden"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
else
|
||||
dnl Test for SunPro cc
|
||||
if $CC 2>&1 | grep flags >/dev/null && $CC -flags | grep xldscope= >/dev/null ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(LIBSSH2_API, [__global], [to make a symbol visible])
|
||||
CFLAGS="$CFLAGS -xldscope=hidden"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac ],
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
# Checks for header files.
|
||||
# AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
|
||||
AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/ioctl.h sys/time.h])
|
||||
AC_CHECK_HEADERS([arpa/inet.h netinet/in.h])
|
||||
AC_CHECK_HEADERS([sys/un.h])
|
||||
|
||||
case $host in
|
||||
*-*-cygwin* | *-*-cegcc*)
|
||||
@@ -213,7 +256,6 @@ AC_CONFIG_FILES([Makefile
|
||||
src/Makefile
|
||||
tests/Makefile
|
||||
example/Makefile
|
||||
example/simple/Makefile
|
||||
docs/Makefile
|
||||
libssh2.pc])
|
||||
AC_OUTPUT
|
||||
|
@@ -3,6 +3,13 @@
|
||||
EXTRA_DIST = template.3
|
||||
|
||||
dist_man_MANS = \
|
||||
libssh2_agent_connect.3 \
|
||||
libssh2_agent_disconnect.3 \
|
||||
libssh2_agent_free.3 \
|
||||
libssh2_agent_get_identity.3 \
|
||||
libssh2_agent_init.3 \
|
||||
libssh2_agent_list_identities.3 \
|
||||
libssh2_agent_userauth.3 \
|
||||
libssh2_banner_set.3 \
|
||||
libssh2_base64_decode.3 \
|
||||
libssh2_channel_close.3 \
|
||||
@@ -40,6 +47,7 @@ dist_man_MANS = \
|
||||
libssh2_knownhost_del.3 \
|
||||
libssh2_knownhost_get.3 \
|
||||
libssh2_knownhost_init.3 \
|
||||
libssh2_knownhost_free.3 \
|
||||
libssh2_knownhost_readfile.3 \
|
||||
libssh2_knownhost_readline.3 \
|
||||
libssh2_knownhost_writefile.3 \
|
||||
@@ -89,6 +97,7 @@ dist_man_MANS = \
|
||||
libssh2_sftp_unlink_ex.3 \
|
||||
libssh2_sftp_write.3 \
|
||||
libssh2_trace.3 \
|
||||
libssh2_trace_sethandler.3 \
|
||||
libssh2_userauth_authenticated.3 \
|
||||
libssh2_userauth_hostbased_fromfile_ex.3 \
|
||||
libssh2_userauth_keyboard_interactive_ex.3 \
|
||||
|
23
docs/libssh2_agent_connect.3
Normal file
23
docs/libssh2_agent_connect.3
Normal file
@@ -0,0 +1,23 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daiki Ueno
|
||||
.\"
|
||||
.TH libssh2_agent_connect 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_agent_connect - connect to an ssh-agent
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
int libssh2_agent_connect(LIBSSH2_AGENT *agent);
|
||||
.SH DESCRIPTION
|
||||
Connect to an ssh-agent running on the system.
|
||||
|
||||
Call \fBlibssh2_agent_disconnect(3)\fP to close the connection after
|
||||
you're doing using it.
|
||||
.SH RETURN VALUE
|
||||
Returns 0 if succeeded, or a negative value for error.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_agent_init(3)
|
||||
.BR libssh2_agent_disconnect(3)
|
||||
|
20
docs/libssh2_agent_disconnect.3
Normal file
20
docs/libssh2_agent_disconnect.3
Normal file
@@ -0,0 +1,20 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daiki Ueno
|
||||
.\"
|
||||
.TH libssh2_agent_disconnect 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_agent_disconnect - close a connection to an ssh-agent
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
int libssh2_agent_disconnect(LIBSSH2_AGENT *agent);
|
||||
.SH DESCRIPTION
|
||||
Close a connection to an ssh-agent.
|
||||
|
||||
.SH RETURN VALUE
|
||||
Returns 0 if succeeded, or a negative value for error.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_agent_connect(3)
|
||||
.BR libssh2_agent_free(3)
|
20
docs/libssh2_agent_free.3
Normal file
20
docs/libssh2_agent_free.3
Normal file
@@ -0,0 +1,20 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daiki Ueno
|
||||
.\"
|
||||
.TH libssh2_agent_free 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_agent_free - free an ssh-agent handle
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
void libssh2_agent_free(LIBSSH2_AGENT *agent);
|
||||
.SH DESCRIPTION
|
||||
Free an ssh-agent handle. This function also frees the internal
|
||||
collection of public keys.
|
||||
.SH RETURN VALUE
|
||||
None.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_agent_init(3)
|
||||
.BR libssh2_agent_disconnect(3)
|
34
docs/libssh2_agent_get_identity.3
Normal file
34
docs/libssh2_agent_get_identity.3
Normal file
@@ -0,0 +1,34 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daiki Ueno
|
||||
.\"
|
||||
.TH libssh2_agent_get_identity 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_agent_get_identity - get a public key off the collection of public keys managed by ssh-agent
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
int libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
|
||||
struct libssh2_agent_publickey **store,
|
||||
struct libssh2_agent_publickey *prev);
|
||||
.SH DESCRIPTION
|
||||
\fIlibssh2_agent_get_identity(3)\fP allows an application to iterate
|
||||
over all public keys in the collection managed by ssh-agent.
|
||||
|
||||
\fIstore\fP should point to a pointer that gets filled in to point to the
|
||||
public key data.
|
||||
|
||||
\fIprev\fP is a pointer to a previous 'struct libssh2_agent_publickey'
|
||||
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 public keys.
|
||||
|
||||
Returns negative values for error
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_agent_list_identities(3)
|
||||
.BR libssh2_agent_userauth(3)
|
26
docs/libssh2_agent_init.3
Normal file
26
docs/libssh2_agent_init.3
Normal file
@@ -0,0 +1,26 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daiki Ueno
|
||||
.\"
|
||||
.TH libssh2_agent_init 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_agent_init - init an ssh-agent handle
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
LIBSSH2_AGENT *libssh2_agent_init(LIBSSH2_SESSION *session);
|
||||
.SH DESCRIPTION
|
||||
Init an ssh-agent handle. Returns the handle to an internal
|
||||
representation of an ssh-agent connection. After the successful
|
||||
initialization, an application can call \fBlibssh2_agent_connect(3)\fP
|
||||
to connect to a running ssh-agent.
|
||||
|
||||
Call \fBlibssh2_agent_free(3)\fP to free the handle again after you're
|
||||
doing using it.
|
||||
.SH RETURN VALUE
|
||||
Returns a handle pointer or NULL if something went wrong. The returned handle
|
||||
is used as input to all other ssh-agent related functions libssh2 provides.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_agent_connect(3)
|
||||
.BR libssh2_agent_free(3)
|
24
docs/libssh2_agent_list_identities.3
Normal file
24
docs/libssh2_agent_list_identities.3
Normal file
@@ -0,0 +1,24 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daiki Ueno
|
||||
.\"
|
||||
.TH libssh2_agent_list_identities 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_agent_list_identities - request an ssh-agent to list of public keys.
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
int libssh2_agent_list_identities(LIBSSH2_AGENT *agent);
|
||||
.SH DESCRIPTION
|
||||
Request an ssh-agent to list of public keys, and stores them in the
|
||||
internal collection of the handle. Call
|
||||
\fIlibssh2_agent_get_identity(3)\fP to get a public key off the
|
||||
collection.
|
||||
|
||||
.SH RETURN VALUE
|
||||
Returns 0 if succeeded, or a negative value for error.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_agent_connect(3)
|
||||
.BR libssh2_agent_get_identity(3)
|
||||
|
29
docs/libssh2_agent_userauth.3
Normal file
29
docs/libssh2_agent_userauth.3
Normal file
@@ -0,0 +1,29 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daiki Ueno
|
||||
.\"
|
||||
.TH libssh2_agent_userauth 3 "23 Dec 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_agent_userauth - authenticate a session with a public key, with the help of ssh-agent
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
int libssh2_agent_userauth(LIBSSH2_AGENT *agent,
|
||||
const char *username,
|
||||
struct libssh2_agent_publickey *identity);
|
||||
.SH DESCRIPTION
|
||||
\fIagent\fP - ssh-agent handle as returned by
|
||||
.BR libssh2_agent_init(3)
|
||||
|
||||
\fIusername\fP - Remote user name to authenticate as.
|
||||
|
||||
\fIidentity\fP - Public key to authenticate with, as returned by
|
||||
.BR libssh2_agent_get_identity(3)
|
||||
|
||||
Attempt public key authentication with the help of ssh-agent.
|
||||
.SH RETURN VALUE
|
||||
Returns 0 if succeeded, or a negative value for error.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_agent_init(3)
|
||||
.BR libssh2_agent_get_identity(3)
|
20
docs/libssh2_knownhost_free.3
Normal file
20
docs/libssh2_knownhost_free.3
Normal file
@@ -0,0 +1,20 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 by Daniel Stenberg
|
||||
.\"
|
||||
.TH libssh2_knownhost_free 3 "28 May 2009" "libssh2 1.2" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_knownhost_free - free a collection of known hosts
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
void libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
|
||||
.SH DESCRIPTION
|
||||
Free a collection of known hosts.
|
||||
.SH RETURN VALUE
|
||||
None.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 1.2
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_knownhost_init(3)
|
||||
.BR libssh2_knownhost_add(3)
|
||||
.BR libssh2_knownhost_check(3)
|
@@ -11,6 +11,9 @@ 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.
|
||||
|
||||
Call \fBlibssh2_knownhost_free(3)\fP to free the collection again after you're
|
||||
doing using it.
|
||||
.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.
|
||||
|
@@ -11,21 +11,26 @@ ssize_t
|
||||
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count);
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fIhandle\fP - SFTP File Handle as returned by
|
||||
.BR libssh2_sftp_open_ex(3)
|
||||
\fIhandle\fP - SFTP file handle as returned by \fIlibssh2_sftp_open_ex(3)\fP.
|
||||
|
||||
\fIbuffer\fP - Pre-initialized data buffer to write to the LIBSSH2_SFTP_HANDLE.
|
||||
\fIbuffer\fP - points to the data to send off
|
||||
|
||||
\fIcount\fP - Number of bytes from buffer to write. Note that it may not
|
||||
be possible to write all bytes as requested.
|
||||
|
||||
Write a block of data to a LIBSSH2_SFTP_HANDLE. This method is modeled after the POSIX write() function and uses the same calling semantics.
|
||||
\fIcount\fP - Number of bytes from 'buffer' to write. Note that it may not be
|
||||
possible to write all bytes as requested.
|
||||
|
||||
\fBlibssh2_sftp_write(3)\fP writes a block of data to the SFTP server. This
|
||||
method is modeled after the POSIX write() function and uses the same calling
|
||||
semantics.
|
||||
.SH RETURN VALUE
|
||||
Actual number of bytes written or negative on failure. It returns
|
||||
LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
|
||||
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
Actual number of bytes written or negative on failure.
|
||||
|
||||
If used in non-blocking mode, it returns LIBSSH2_ERROR_EAGAIN when it would
|
||||
otherwise block. While LIBSSH2_ERROR_EAGAIN is a negative number, it isn't
|
||||
really a failure per se.
|
||||
|
||||
If this function returns 0 (zero) it should not be considered an error, but
|
||||
simply that there was no error but yet no payload data got sent to the other
|
||||
end.
|
||||
.SH ERRORS
|
||||
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
|
||||
|
||||
@@ -36,6 +41,5 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response was
|
||||
received on the socket, or an SFTP operation caused an errorcode to
|
||||
be returned by the server.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_sftp_open_ex(3)
|
||||
|
@@ -6,16 +6,18 @@ libssh2_trace - enable debug info from inside libssh2
|
||||
.SH SYNOPSIS
|
||||
#include <libssh2.h>
|
||||
|
||||
void libssh2_trace(int bitmask);
|
||||
void libssh2_trace(LIBSSH2_SESSION *session, int bitmask);
|
||||
|
||||
.SH DESCRIPTION
|
||||
This is a function present in the library that can be used to get debug info
|
||||
from within libssh2 when it is running. Helpful when trying to trace or debug
|
||||
behaviors. This function has no effect unless libssh2 was built to support
|
||||
this option, and a typical "release build" might not.
|
||||
behaviors. Note that this function has no effect unless libssh2 was built to
|
||||
support tracing! It is usually disabled in release builds.
|
||||
|
||||
\fBbitmask\fP can be set to none, one or more of these bits:
|
||||
\fBbitmask\fP can be set to the logical OR of none, one or more of these:
|
||||
.RS
|
||||
.IP LIBSSH2_TRACE_SOCKET
|
||||
Socket low-level debugging
|
||||
.IP LIBSSH2_TRACE_TRANS
|
||||
Transport layer debugging
|
||||
.IP LIBSSH2_TRACE_KEX
|
||||
|
30
docs/libssh2_trace_sethandler.3
Normal file
30
docs/libssh2_trace_sethandler.3
Normal file
@@ -0,0 +1,30 @@
|
||||
.\" $Id: libssh2_trace_sethandler.3,v 1.1 2008/12/26 07:46:45 bagder Exp $
|
||||
.\"
|
||||
.TH libssh2_trace_sethandler 3 "15 Jan 2010" "libssh2 1.2.3" "libssh2 manual"
|
||||
.SH NAME
|
||||
libssh2_trace_sethandler - set a trace output handler
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <libssh2.h>
|
||||
|
||||
typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION *session,
|
||||
void* context,
|
||||
const char *data,
|
||||
size_t length);
|
||||
|
||||
int libssh2_trace_sethandler(LIBSSH2_SESSION *session,
|
||||
void* context,
|
||||
libssh2_trace_handler_func callback);
|
||||
.SH DESCRIPTION
|
||||
libssh2_trace_sethandler installs a trace output handler for your application.
|
||||
By default, when tracing has been switched on via a call to libssh2_trace(),
|
||||
all output is written to stderr. By calling this method and passing a
|
||||
function pointer that matches the libssh2_trace_handler_func prototype,
|
||||
libssh2 will call back as it generates trace output. This can be used to
|
||||
capture the trace output and put it into a log file or diagnostic window.
|
||||
This function has no effect unless libssh2 was built to support this option,
|
||||
and a typical "release build" might not.
|
||||
|
||||
\fBcontext\fP can be used to pass arbitrary user defined data back into the callback when invoked.
|
||||
.SH AVAILABILITY
|
||||
Added in libssh2 version 1.2.3
|
@@ -39,5 +39,7 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
|
||||
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.
|
||||
|
||||
\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password or public/private key.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_session_init_ex(3)
|
||||
|
@@ -46,5 +46,7 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
|
||||
\fILIBSSH2_ERROR_PASSWORD_EXPIRED\fP -
|
||||
|
||||
\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password or public/private key.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_session_init_ex(3)
|
||||
|
@@ -40,12 +40,11 @@ LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
|
||||
|
||||
\fILIBSSH2_ERROR_SOCKET_TIMEOUT\fP -
|
||||
|
||||
\fILIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED\fP - >The username/public key
|
||||
\fILIBSSH2_ERROR_PUBLICKEY_UNVERIFIED\fP - The username/public key
|
||||
combination was invalid.
|
||||
|
||||
\fILIBSSH2_ERROR_PUBLICKEY_UNVERIFIED\fP - The username/public key
|
||||
combination was invalid, or the signature for the supplied public
|
||||
key was invalid.
|
||||
\fILIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - Authentication using the supplied
|
||||
public key was not accepted.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR libssh2_session_init_ex(3)
|
||||
|
23
example/.gitignore
vendored
23
example/.gitignore
vendored
@@ -1,2 +1,25 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.gcno
|
||||
*.gcda
|
||||
direct_tcpip
|
||||
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
|
||||
ssh2_agent
|
||||
libssh2_config.h
|
||||
libssh2_config.h.in
|
||||
stamp-h2
|
||||
|
@@ -1,2 +1,16 @@
|
||||
AUTOMAKE_OPTIONS = foreign nostdinc
|
||||
SUBDIRS = simple
|
||||
|
||||
EXTRA_DIST = libssh2_config.h.in
|
||||
|
||||
# samples
|
||||
noinst_PROGRAMS = direct_tcpip ssh2 \
|
||||
scp scp_nonblock \
|
||||
scp_write scp_write_nonblock \
|
||||
sftp sftp_nonblock \
|
||||
sftp_write sftp_write_nonblock \
|
||||
sftp_mkdir sftp_mkdir_nonblock \
|
||||
sftp_RW_nonblock \
|
||||
sftpdir sftpdir_nonblock ssh2_exec ssh2_agent
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/example
|
||||
LDADD = $(top_builddir)/src/libssh2.la
|
||||
|
275
example/direct_tcpip.c
Normal file
275
example/direct_tcpip.c
Normal file
@@ -0,0 +1,275 @@
|
||||
#include <libssh2.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE (in_addr_t)-1
|
||||
#endif
|
||||
|
||||
const char *keyfile1 = "/home/username/.ssh/id_rsa.pub";
|
||||
const char *keyfile2 = "/home/username/.ssh/id_rsa";
|
||||
const char *username = "username";
|
||||
const char *password = "";
|
||||
|
||||
const char *server_ip = "127.0.0.1";
|
||||
|
||||
const char *local_listenip = "127.0.0.1";
|
||||
unsigned int local_listenport = 2222;
|
||||
|
||||
const char *remote_desthost = "localhost"; /* resolved by the server */
|
||||
unsigned int remote_destport = 22;
|
||||
|
||||
enum {
|
||||
AUTH_NONE = 0,
|
||||
AUTH_PASSWORD,
|
||||
AUTH_PUBLICKEY
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc, sock = -1, listensock = -1, forwardsock = -1, i, auth = AUTH_NONE;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sinlen;
|
||||
const char *fingerprint;
|
||||
char *userauthlist;
|
||||
LIBSSH2_SESSION *session;
|
||||
LIBSSH2_CHANNEL *channel = NULL;
|
||||
const char *shost;
|
||||
unsigned int sport;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
ssize_t len, wr;
|
||||
char buf[16384];
|
||||
|
||||
#ifdef WIN32
|
||||
char sockopt;
|
||||
WSADATA wsadata;
|
||||
|
||||
WSAStartup(MAKEWORD(2,0), &wsadata);
|
||||
#else
|
||||
int sockopt;
|
||||
#endif
|
||||
|
||||
if (argc > 1)
|
||||
server_ip = argv[1];
|
||||
if (argc > 2)
|
||||
username = argv[2];
|
||||
if (argc > 3)
|
||||
password = argv[3];
|
||||
if (argc > 4)
|
||||
local_listenip = argv[4];
|
||||
if (argc > 5)
|
||||
local_listenport = atoi(argv[5]);
|
||||
if (argc > 6)
|
||||
remote_desthost = argv[6];
|
||||
if (argc > 7)
|
||||
remote_destport = atoi(argv[7]);
|
||||
|
||||
/* Connect to SSH server */
|
||||
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
sin.sin_family = AF_INET;
|
||||
if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(server_ip))) {
|
||||
perror("inet_addr");
|
||||
return -1;
|
||||
}
|
||||
sin.sin_port = htons(22);
|
||||
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) {
|
||||
fprintf(stderr, "Could not initialize SSH session!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ... start it up. This will trade welcome banners, exchange keys,
|
||||
* and setup crypto, compression, and MAC layers
|
||||
*/
|
||||
rc = libssh2_session_startup(session, sock);
|
||||
if(rc) {
|
||||
fprintf(stderr, "Error when starting up SSH session: %d\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* At this point we havn't yet authenticated. The first thing to do
|
||||
* is check the hostkey's fingerprint against our known hosts Your app
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
fprintf(stderr, "Fingerprint: ");
|
||||
for(i = 0; i < 20; i++)
|
||||
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
/* check what authentication methods are available */
|
||||
userauthlist = libssh2_userauth_list(session, username, strlen(username));
|
||||
printf("Authentication methods: %s\n", userauthlist);
|
||||
if (strstr(userauthlist, "password"))
|
||||
auth |= AUTH_PASSWORD;
|
||||
if (strstr(userauthlist, "publickey"))
|
||||
auth |= AUTH_PUBLICKEY;
|
||||
|
||||
/* check for options */
|
||||
if(argc > 8) {
|
||||
if ((auth & AUTH_PASSWORD) && !strcasecmp(argv[8], "-p"))
|
||||
auth = AUTH_PASSWORD;
|
||||
if ((auth & AUTH_PUBLICKEY) && !strcasecmp(argv[8], "-k"))
|
||||
auth = AUTH_PUBLICKEY;
|
||||
}
|
||||
|
||||
if (auth & AUTH_PASSWORD) {
|
||||
if (libssh2_userauth_password(session, username, password)) {
|
||||
fprintf(stderr, "Authentication by password failed.\n");
|
||||
goto shutdown;
|
||||
}
|
||||
} else if (auth & AUTH_PUBLICKEY) {
|
||||
if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) {
|
||||
printf("\tAuthentication by public key failed!\n");
|
||||
goto shutdown;
|
||||
}
|
||||
printf("\tAuthentication by public key succeeded.\n");
|
||||
} else {
|
||||
printf("No supported authentication methods found!\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
listensock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(local_listenport);
|
||||
if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(local_listenip))) {
|
||||
perror("inet_addr");
|
||||
goto shutdown;
|
||||
}
|
||||
sockopt = 1;
|
||||
setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
||||
sinlen=sizeof(sin);
|
||||
if (-1 == bind(listensock, (struct sockaddr *)&sin, sinlen)) {
|
||||
perror("bind");
|
||||
goto shutdown;
|
||||
}
|
||||
if (-1 == listen(listensock, 2)) {
|
||||
perror("listen");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
printf("Waiting for TCP connection on %s:%d...\n",
|
||||
inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
||||
|
||||
forwardsock = accept(listensock, (struct sockaddr *)&sin, &sinlen);
|
||||
if (-1 == forwardsock) {
|
||||
perror("accept");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
shost = inet_ntoa(sin.sin_addr);
|
||||
sport = ntohs(sin.sin_port);
|
||||
|
||||
printf("Forwarding connection from %s:%d here to remote %s:%d\n", shost,
|
||||
sport, remote_desthost, remote_destport);
|
||||
|
||||
channel = libssh2_channel_direct_tcpip_ex(session, remote_desthost,
|
||||
remote_destport, shost, sport);
|
||||
if (!channel) {
|
||||
fprintf(stderr, "Could not open the direct-tcpip channel!\n");
|
||||
fprintf(stderr, "(Note that this can be a problem at the server! Please review the server logs.)\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
/* Must use non-blocking IO hereafter due to the current libssh2 API */
|
||||
libssh2_session_set_blocking(session, 0);
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(forwardsock, &fds);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100000;
|
||||
rc = select(forwardsock + 1, &fds, NULL, NULL, &tv);
|
||||
if (-1 == rc) {
|
||||
perror("select");
|
||||
goto shutdown;
|
||||
}
|
||||
if (rc && FD_ISSET(forwardsock, &fds)) {
|
||||
len = recv(forwardsock, buf, sizeof(buf), 0);
|
||||
if (len < 0) {
|
||||
perror("read");
|
||||
goto shutdown;
|
||||
} else if (0 == len) {
|
||||
printf("The client at %s:%d disconnected!\n", shost, sport);
|
||||
goto shutdown;
|
||||
}
|
||||
wr = 0;
|
||||
do {
|
||||
i = libssh2_channel_write(channel, buf, len);
|
||||
if (i < 0) {
|
||||
fprintf(stderr, "libssh2_channel_write: %d\n", i);
|
||||
goto shutdown;
|
||||
}
|
||||
wr += i;
|
||||
} while(i > 0 && wr < len);
|
||||
}
|
||||
while (1) {
|
||||
len = libssh2_channel_read(channel, buf, sizeof(buf));
|
||||
if (LIBSSH2_ERROR_EAGAIN == len)
|
||||
break;
|
||||
else if (len < 0) {
|
||||
fprintf(stderr, "libssh2_channel_read: %d", (int)len);
|
||||
goto shutdown;
|
||||
}
|
||||
wr = 0;
|
||||
while (wr < len) {
|
||||
i = send(forwardsock, buf + wr, len - wr, 0);
|
||||
if (i <= 0) {
|
||||
perror("write");
|
||||
goto shutdown;
|
||||
}
|
||||
wr += i;
|
||||
}
|
||||
if (libssh2_channel_eof(channel)) {
|
||||
printf("The server at %s:%d disconnected!\n",
|
||||
remote_desthost, remote_destport);
|
||||
goto shutdown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shutdown:
|
||||
#ifdef WIN32
|
||||
closesocket(forwardsock);
|
||||
closesocket(listensock);
|
||||
#else
|
||||
close(forwardsock);
|
||||
close(listensock);
|
||||
#endif
|
||||
if (channel)
|
||||
libssh2_channel_free(channel);
|
||||
libssh2_session_disconnect(session, "Client disconnecting normally");
|
||||
libssh2_session_free(session);
|
||||
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
@@ -103,9 +103,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
fprintf(stderr, "Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
@@ -160,9 +160,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
fprintf(stderr, "Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
@@ -118,9 +118,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
fprintf(stderr, "Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
@@ -142,8 +142,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* Request a file via SCP */
|
||||
channel = libssh2_scp_send(session, scppath, 0x1FF & fileinfo.st_mode,
|
||||
/* Send a file via scp. The mode parameter must only have permissions! */
|
||||
channel = libssh2_scp_send(session, scppath, fileinfo.st_mode & 0777,
|
||||
(unsigned long)fileinfo.st_size);
|
||||
|
||||
if (!channel) {
|
@@ -126,9 +126,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
fprintf(stderr, "Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
@@ -153,9 +153,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* Request a file via SCP */
|
||||
/* Send a file via scp. The mode parameter must only have permissions! */
|
||||
do {
|
||||
channel = libssh2_scp_send(session, scppath, 0x1FF & fileinfo.st_mode,
|
||||
channel = libssh2_scp_send(session, scppath, fileinfo.st_mode & 0777,
|
||||
(unsigned long)fileinfo.st_size);
|
||||
|
||||
if ((!channel) && (libssh2_session_last_errno(session) !=
|
@@ -136,9 +136,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
fprintf(stderr, "Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
@@ -109,9 +109,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
@@ -105,9 +105,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
@@ -108,9 +108,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
@@ -161,9 +161,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
fprintf(stderr, "Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
@@ -123,9 +123,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
@@ -127,9 +127,9 @@ int main(int argc, char *argv[])
|
||||
* have it hard coded, may go to a file, may present it to the user,
|
||||
* that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
@@ -105,9 +105,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
@@ -111,9 +111,9 @@ int main(int argc, char *argv[])
|
||||
* may have it hard coded, may go to a file, may present it to the
|
||||
* user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
18
example/simple/.gitignore
vendored
18
example/simple/.gitignore
vendored
@@ -1,18 +0,0 @@
|
||||
*.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
|
@@ -1,16 +0,0 @@
|
||||
AUTOMAKE_OPTIONS = foreign nostdinc
|
||||
|
||||
# samples
|
||||
noinst_PROGRAMS = ssh2 \
|
||||
scp scp_nonblock \
|
||||
scp_write scp_write_nonblock \
|
||||
sftp sftp_nonblock \
|
||||
sftp_write sftp_write_nonblock \
|
||||
sftp_mkdir sftp_mkdir_nonblock \
|
||||
sftp_RW_nonblock \
|
||||
sftpdir sftpdir_nonblock ssh2_exec
|
||||
|
||||
# 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
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_builddir)/src
|
||||
LDADD = $(top_builddir)/src/libssh2.la
|
@@ -121,9 +121,9 @@ int main(int argc, char *argv[])
|
||||
* 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_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
229
example/ssh2_agent.c
Normal file
229
example/ssh2_agent.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Sample showing how to do SSH2 connect using ssh-agent.
|
||||
*
|
||||
* The sample code has default values for host name, user name:
|
||||
*
|
||||
* "ssh2_agent host user"
|
||||
*/
|
||||
|
||||
#include "libssh2_config.h"
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
# ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
# ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
const char *username="username";
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned long hostaddr;
|
||||
int sock = -1, i, j, rc;
|
||||
struct sockaddr_in sin;
|
||||
const char *fingerprint;
|
||||
char *userauthlist;
|
||||
LIBSSH2_SESSION *session;
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
LIBSSH2_AGENT *agent = NULL;
|
||||
struct libssh2_agent_publickey *identity, *prev_identity = NULL;
|
||||
#ifdef WIN32
|
||||
WSADATA wsadata;
|
||||
|
||||
WSAStartup(MAKEWORD(2,0), &wsadata);
|
||||
#endif
|
||||
|
||||
if (argc > 1) {
|
||||
hostaddr = inet_addr(argv[1]);
|
||||
} else {
|
||||
hostaddr = htonl(0x7F000001);
|
||||
}
|
||||
|
||||
if(argc > 2) {
|
||||
username = argv[2];
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (sock == -1) {
|
||||
fprintf(stderr, "failed to create socket!\n");
|
||||
rc = 1;
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
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");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
/* Create a session instance and start it up. This will trade welcome
|
||||
* banners, exchange keys, and setup crypto, compression, and MAC layers
|
||||
*/
|
||||
session = libssh2_session_init();
|
||||
if (libssh2_session_startup(session, sock)) {
|
||||
fprintf(stderr, "Failure establishing SSH session\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check what authentication methods are available */
|
||||
userauthlist = libssh2_userauth_list(session, username, strlen(username));
|
||||
printf("Authentication methods: %s\n", userauthlist);
|
||||
if (strstr(userauthlist, "publickey") == NULL) {
|
||||
fprintf(stderr, "\"publickey\" authentication is not supported\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
/* Connect to the ssh-agent */
|
||||
agent = libssh2_agent_init(session);
|
||||
if (!agent) {
|
||||
fprintf(stderr, "Failure initializing ssh-agent support\n");
|
||||
rc = 1;
|
||||
goto shutdown;
|
||||
}
|
||||
if (libssh2_agent_connect(agent)) {
|
||||
fprintf(stderr, "Failure connecting to ssh-agent\n");
|
||||
rc = 1;
|
||||
goto shutdown;
|
||||
}
|
||||
if (libssh2_agent_list_identities(agent)) {
|
||||
fprintf(stderr, "Failure requesting identities to ssh-agent\n");
|
||||
rc = 1;
|
||||
goto shutdown;
|
||||
}
|
||||
while (1) {
|
||||
rc = libssh2_agent_get_identity(agent, &identity, prev_identity);
|
||||
if (rc == 1)
|
||||
break;
|
||||
if (rc < 0) {
|
||||
fprintf(stderr,
|
||||
"Failure obtaining identity from ssh-agent support\n");
|
||||
rc = 1;
|
||||
goto shutdown;
|
||||
}
|
||||
if (libssh2_agent_userauth(agent, username, identity)) {
|
||||
printf("\tAuthentication with username %s and "
|
||||
"public key %s failed!\n",
|
||||
username, identity->comment);
|
||||
} else {
|
||||
printf("\tAuthentication with username %s and "
|
||||
"public key %s succeeded!\n",
|
||||
username, identity->comment);
|
||||
break;
|
||||
}
|
||||
prev_identity = identity;
|
||||
}
|
||||
if (rc) {
|
||||
fprintf(stderr, "Couldn't continue authentication\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
/* At this point we havn't authenticated. The first thing to do is check
|
||||
* the hostkey's fingerprint against our known hosts Your app may have it
|
||||
* hard coded, may go to a file, may present it to the user, that's your
|
||||
* call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* Request a shell */
|
||||
if (!(channel = libssh2_channel_open_session(session))) {
|
||||
fprintf(stderr, "Unable to open a session\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
/* Some environment variables may be set,
|
||||
* It's up to the server which ones it'll allow though
|
||||
*/
|
||||
libssh2_channel_setenv(channel, "FOO", "bar");
|
||||
|
||||
/* Request a terminal with 'vanilla' terminal emulation
|
||||
* See /etc/termcap for more options
|
||||
*/
|
||||
if (libssh2_channel_request_pty(channel, "vanilla")) {
|
||||
fprintf(stderr, "Failed requesting pty\n");
|
||||
goto skip_shell;
|
||||
}
|
||||
|
||||
/* Open a SHELL on that pty */
|
||||
if (libssh2_channel_shell(channel)) {
|
||||
fprintf(stderr, "Unable to request shell on allocated pty\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
/* At this point the shell can be interacted with using
|
||||
* libssh2_channel_read()
|
||||
* libssh2_channel_read_stderr()
|
||||
* libssh2_channel_write()
|
||||
* libssh2_channel_write_stderr()
|
||||
*
|
||||
* Blocking mode may be (en|dis)abled with: libssh2_channel_set_blocking()
|
||||
* If the server send EOF, libssh2_channel_eof() will return non-0
|
||||
* To send EOF to the server use: libssh2_channel_send_eof()
|
||||
* A channel can be closed with: libssh2_channel_close()
|
||||
* A channel can be freed with: libssh2_channel_free()
|
||||
*/
|
||||
|
||||
skip_shell:
|
||||
if (channel) {
|
||||
libssh2_channel_free(channel);
|
||||
channel = NULL;
|
||||
}
|
||||
|
||||
/* Other channel types are supported via:
|
||||
* libssh2_scp_send()
|
||||
* libssh2_scp_recv()
|
||||
* libssh2_channel_direct_tcpip()
|
||||
*/
|
||||
|
||||
shutdown:
|
||||
|
||||
libssh2_agent_disconnect(agent);
|
||||
libssh2_agent_free(agent);
|
||||
|
||||
libssh2_session_disconnect(session,
|
||||
"Normal Shutdown, Thank you for playing");
|
||||
libssh2_session_free(session);
|
||||
|
||||
if (sock != -1) {
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
}
|
||||
|
||||
printf("all done!\n");
|
||||
return rc;
|
||||
}
|
@@ -84,17 +84,17 @@ typedef unsigned long long libssh2_uint64_t;
|
||||
typedef long long libssh2_int64_t;
|
||||
#endif
|
||||
|
||||
/* We use underscore instead of dash when appending CVS in dev versions just
|
||||
/* We use underscore instead of dash when appending DEV in dev versions just
|
||||
to make the BANNER define (used by src/session.c) be a valid SSH
|
||||
banner. Release versions have no appended strings and may of course not
|
||||
have dashes either. */
|
||||
#define LIBSSH2_VERSION "1.2.1_CVS"
|
||||
#define LIBSSH2_VERSION "1.2.4_DEV"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBSSH2_VERSION_MAJOR 1
|
||||
#define LIBSSH2_VERSION_MINOR 2
|
||||
#define LIBSSH2_VERSION_PATCH 1
|
||||
#define LIBSSH2_VERSION_PATCH 4
|
||||
|
||||
/* This is the numeric version of the libssh2 version number, meant for easier
|
||||
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
|
||||
@@ -111,18 +111,18 @@ typedef long long libssh2_int64_t;
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
*/
|
||||
#define LIBSSH2_VERSION_NUM 0x010201
|
||||
#define LIBSSH2_VERSION_NUM 0x010204
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
* timestamp is not stored in CVS, as the timestamp is properly set in the
|
||||
* tarballs by the maketgz script.
|
||||
* timestamp is not stored in the source code repo, as the timestamp is
|
||||
* properly set in the tarballs by the maketgz script.
|
||||
*
|
||||
* The format of the date should follow this template:
|
||||
*
|
||||
* "Mon Feb 12 11:35:33 UTC 2007"
|
||||
*/
|
||||
#define LIBSSH2_TIMESTAMP "CVS"
|
||||
#define LIBSSH2_TIMESTAMP "DEV"
|
||||
|
||||
/* Part of every banner, user specified or not */
|
||||
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
|
||||
@@ -178,6 +178,11 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
|
||||
unsigned int length;
|
||||
} LIBSSH2_USERAUTH_KBDINT_RESPONSE;
|
||||
|
||||
/* 'publickey' authentication callback */
|
||||
#define LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC(name) \
|
||||
int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, \
|
||||
const unsigned char *data, size_t data_len, void **abstract)
|
||||
|
||||
/* 'keyboard-interactive' authentication callback */
|
||||
#define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) \
|
||||
void name_(const char* name, int name_len, const char* instruction, \
|
||||
@@ -242,6 +247,7 @@ typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
|
||||
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
|
||||
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
|
||||
typedef struct _LIBSSH2_KNOWNHOSTS LIBSSH2_KNOWNHOSTS;
|
||||
typedef struct _LIBSSH2_AGENT LIBSSH2_AGENT;
|
||||
|
||||
typedef struct _LIBSSH2_POLLFD {
|
||||
unsigned char type; /* LIBSSH2_POLLFD_* below */
|
||||
@@ -335,7 +341,8 @@ typedef struct _LIBSSH2_POLLFD {
|
||||
#define LIBSSH2_ERROR_PASSWORD_EXPIRED -15
|
||||
#define LIBSSH2_ERROR_FILE -16
|
||||
#define LIBSSH2_ERROR_METHOD_NONE -17
|
||||
#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED -18
|
||||
#define LIBSSH2_ERROR_AUTHENTICATION_FAILED -18
|
||||
#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED LIBSSH2_ERROR_AUTHENTICATION_FAILED
|
||||
#define LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED -19
|
||||
#define LIBSSH2_ERROR_CHANNEL_OUTOFORDER -20
|
||||
#define LIBSSH2_ERROR_CHANNEL_FAILURE -21
|
||||
@@ -359,6 +366,7 @@ typedef struct _LIBSSH2_POLLFD {
|
||||
#define LIBSSH2_ERROR_BAD_USE -39
|
||||
#define LIBSSH2_ERROR_COMPRESS -40
|
||||
#define LIBSSH2_ERROR_OUT_OF_BOUNDARY -41
|
||||
#define LIBSSH2_ERROR_AGENT_PROTOCOL -42
|
||||
|
||||
/* Session API */
|
||||
LIBSSH2_API LIBSSH2_SESSION *
|
||||
@@ -436,6 +444,14 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
|
||||
strlen(username), (publickey), \
|
||||
(privatekey), (passphrase))
|
||||
|
||||
LIBSSH2_API int
|
||||
libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
const char *username,
|
||||
const unsigned char *pubkeydata,
|
||||
size_t pubkeydata_len,
|
||||
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
|
||||
void **abstract);
|
||||
|
||||
LIBSSH2_API int
|
||||
libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
|
||||
const char *username,
|
||||
@@ -870,6 +886,93 @@ libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
struct libssh2_knownhost **store,
|
||||
struct libssh2_knownhost *prev);
|
||||
|
||||
#define HAVE_LIBSSH2_AGENT_API 0x010202 /* since 1.2.2 */
|
||||
|
||||
struct libssh2_agent_publickey {
|
||||
unsigned int magic; /* magic stored by the library */
|
||||
void *node; /* handle to the internal representation of key */
|
||||
unsigned char *blob; /* public key blob */
|
||||
size_t blob_len; /* length of the public key blob */
|
||||
char *comment; /* comment in printable format */
|
||||
};
|
||||
|
||||
/*
|
||||
* libssh2_agent_init
|
||||
*
|
||||
* Init an ssh-agent handle. Returns the pointer to the handle.
|
||||
*
|
||||
*/
|
||||
LIBSSH2_API LIBSSH2_AGENT *
|
||||
libssh2_agent_init(LIBSSH2_SESSION *session);
|
||||
|
||||
/*
|
||||
* libssh2_agent_connect()
|
||||
*
|
||||
* Connect to an ssh-agent.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_connect(LIBSSH2_AGENT *agent);
|
||||
|
||||
/*
|
||||
* libssh2_agent_list_identities()
|
||||
*
|
||||
* Request an ssh-agent to list identities.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_list_identities(LIBSSH2_AGENT *agent);
|
||||
|
||||
/*
|
||||
* libssh2_agent_get_identity()
|
||||
*
|
||||
* Traverse the internal list of public keys. 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 public key was stored in 'store'
|
||||
* 1 if end of public keys
|
||||
* [negative] on errors
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
|
||||
struct libssh2_agent_publickey **store,
|
||||
struct libssh2_agent_publickey *prev);
|
||||
|
||||
/*
|
||||
* libssh2_agent_userauth()
|
||||
*
|
||||
* Do publickey user authentication with the help of ssh-agent.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_userauth(LIBSSH2_AGENT *agent,
|
||||
const char *username,
|
||||
struct libssh2_agent_publickey *identity);
|
||||
|
||||
/*
|
||||
* libssh2_agent_disconnect()
|
||||
*
|
||||
* Close a connection to an ssh-agent.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_disconnect(LIBSSH2_AGENT *agent);
|
||||
|
||||
/*
|
||||
* libssh2_agent_free()
|
||||
*
|
||||
* Free an ssh-agent handle. This function also frees the internal
|
||||
* collection of public keys.
|
||||
*/
|
||||
LIBSSH2_API void
|
||||
libssh2_agent_free(LIBSSH2_AGENT *agent);
|
||||
|
||||
/* NOTE NOTE NOTE
|
||||
libssh2_trace() has no function in builds that aren't built with debug
|
||||
enabled
|
||||
@@ -883,6 +986,15 @@ LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask);
|
||||
#define LIBSSH2_TRACE_SFTP (1<<6)
|
||||
#define LIBSSH2_TRACE_ERROR (1<<7)
|
||||
#define LIBSSH2_TRACE_PUBLICKEY (1<<8)
|
||||
#define LIBSSH2_TRACE_SOCKET (1<<9)
|
||||
|
||||
typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*,
|
||||
void*,
|
||||
const char *,
|
||||
size_t);
|
||||
LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session,
|
||||
void* context,
|
||||
libssh2_trace_handler_func callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@@ -1,5 +0,0 @@
|
||||
libtool.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
lt~obsolete.m4
|
@@ -28,7 +28,7 @@ endif
|
||||
LINK_STATIC = 1
|
||||
|
||||
# Edit the vars below to change NLM target settings.
|
||||
SAMPLES = ../../example/simple
|
||||
SAMPLES = ../../example
|
||||
TARGETS := $(filter-out x11.nlm,$(patsubst $(SAMPLES)/%.c,%.nlm,$(strip $(wildcard $(SAMPLES)/*.c))))
|
||||
VERSION = $(LIBSSH2_VERSION)
|
||||
COPYR = Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
|
||||
|
@@ -1,20 +0,0 @@
|
||||
.deps
|
||||
.libs
|
||||
*.lib
|
||||
*.pdb
|
||||
*.dll
|
||||
*.exe
|
||||
*.obj
|
||||
*.gcno
|
||||
*.gcda
|
||||
.*.swp
|
||||
Debug
|
||||
Release
|
||||
*.exp
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.lo
|
||||
libssh2.la
|
||||
libssh2_config.h
|
||||
libssh2_config.h.in
|
||||
stamp-h1
|
759
src/agent.c
Normal file
759
src/agent.c
Normal file
@@ -0,0 +1,759 @@
|
||||
/*
|
||||
* Copyright (c) 2009 by Daiki Ueno
|
||||
* 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"
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#else
|
||||
/* Use the existence of sys/un.h as a test if Unix domain socket is
|
||||
supported. winsock*.h define PF_UNIX/AF_UNIX but do not actually
|
||||
support them. */
|
||||
#undef PF_UNIX
|
||||
#endif
|
||||
|
||||
/* Requests from client to agent for protocol 1 key operations */
|
||||
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||
#define SSH_AGENTC_RSA_CHALLENGE 3
|
||||
#define SSH_AGENTC_ADD_RSA_IDENTITY 7
|
||||
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
|
||||
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
|
||||
#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
|
||||
|
||||
/* Requests from client to agent for protocol 2 key operations */
|
||||
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
|
||||
#define SSH2_AGENTC_SIGN_REQUEST 13
|
||||
#define SSH2_AGENTC_ADD_IDENTITY 17
|
||||
#define SSH2_AGENTC_REMOVE_IDENTITY 18
|
||||
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
|
||||
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
|
||||
|
||||
/* Key-type independent requests from client to agent */
|
||||
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
|
||||
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
|
||||
#define SSH_AGENTC_LOCK 22
|
||||
#define SSH_AGENTC_UNLOCK 23
|
||||
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
|
||||
|
||||
/* Generic replies from agent to client */
|
||||
#define SSH_AGENT_FAILURE 5
|
||||
#define SSH_AGENT_SUCCESS 6
|
||||
|
||||
/* Replies from agent to client for protocol 1 key operations */
|
||||
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||
#define SSH_AGENT_RSA_RESPONSE 4
|
||||
|
||||
/* Replies from agent to client for protocol 2 key operations */
|
||||
#define SSH2_AGENT_IDENTITIES_ANSWER 12
|
||||
#define SSH2_AGENT_SIGN_RESPONSE 14
|
||||
|
||||
/* Key constraint identifiers */
|
||||
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
|
||||
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
|
||||
|
||||
/* non-blocking mode on agent connection is not yet implemented, but
|
||||
for future use. */
|
||||
typedef enum {
|
||||
agent_NB_state_init = 0,
|
||||
agent_NB_state_request_created,
|
||||
agent_NB_state_request_length_sent,
|
||||
agent_NB_state_request_sent,
|
||||
agent_NB_state_response_length_received,
|
||||
agent_NB_state_response_received
|
||||
} agent_nonblocking_states;
|
||||
|
||||
typedef struct agent_transaction_ctx {
|
||||
unsigned char *request;
|
||||
size_t request_len;
|
||||
unsigned char *response;
|
||||
size_t response_len;
|
||||
agent_nonblocking_states state;
|
||||
} *agent_transaction_ctx_t;
|
||||
|
||||
typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
|
||||
typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
|
||||
agent_transaction_ctx_t transctx);
|
||||
typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
|
||||
|
||||
struct agent_publickey {
|
||||
struct list_node node;
|
||||
|
||||
/* this is the struct we expose externally */
|
||||
struct libssh2_agent_publickey external;
|
||||
};
|
||||
|
||||
struct agent_ops {
|
||||
agent_connect_func connect;
|
||||
agent_transact_func transact;
|
||||
agent_disconnect_func disconnect;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_AGENT
|
||||
{
|
||||
LIBSSH2_SESSION *session; /* the session this "belongs to" */
|
||||
|
||||
libssh2_socket_t fd;
|
||||
|
||||
struct agent_ops *ops;
|
||||
|
||||
struct agent_transaction_ctx transctx;
|
||||
struct agent_publickey *identity;
|
||||
struct list_head head; /* list of public keys */
|
||||
};
|
||||
|
||||
#ifdef PF_UNIX
|
||||
static int
|
||||
agent_connect_unix(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
const char *path;
|
||||
struct sockaddr_un s_un;
|
||||
|
||||
path = getenv("SSH_AUTH_SOCK");
|
||||
if (!path) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
agent->fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (agent->fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_un.sun_family = AF_UNIX;
|
||||
strncpy (s_un.sun_path, path, sizeof s_un.sun_path);
|
||||
if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) {
|
||||
close (agent->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||
{
|
||||
unsigned char buf[4], *s;
|
||||
int rc;
|
||||
|
||||
/* Send the length of the request */
|
||||
if (transctx->state == agent_NB_state_request_created) {
|
||||
_libssh2_htonu32(buf, transctx->request_len);
|
||||
rc = send(agent->fd, buf, sizeof buf, 0);
|
||||
if (rc < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
transctx->state = agent_NB_state_request_length_sent;
|
||||
}
|
||||
|
||||
/* Send the request body */
|
||||
if (transctx->state == agent_NB_state_request_length_sent) {
|
||||
rc = send(agent->fd, transctx->request,
|
||||
transctx->request_len, 0);
|
||||
if (rc < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
transctx->state = agent_NB_state_request_sent;
|
||||
}
|
||||
|
||||
/* Receive the length of a response */
|
||||
if (transctx->state == agent_NB_state_request_sent) {
|
||||
rc = recv(agent->fd, buf, sizeof buf, 0);
|
||||
if (rc < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
transctx->response_len = _libssh2_ntohu32(buf);
|
||||
s = transctx->response = LIBSSH2_ALLOC(agent->session,
|
||||
transctx->response_len);
|
||||
if (!transctx->response) {
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
}
|
||||
transctx->state = agent_NB_state_response_length_received;
|
||||
}
|
||||
|
||||
/* Receive the response body */
|
||||
if (transctx->state == agent_NB_state_response_length_received) {
|
||||
rc = recv(agent->fd, transctx->response, transctx->response_len, 0);
|
||||
if (rc < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
transctx->state = agent_NB_state_response_received;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
agent_disconnect_unix(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
return close(agent->fd);
|
||||
}
|
||||
|
||||
struct agent_ops agent_ops_unix = {
|
||||
agent_connect_unix,
|
||||
agent_transact_unix,
|
||||
agent_disconnect_unix
|
||||
};
|
||||
#endif /* PF_UNIX */
|
||||
|
||||
#ifdef WIN32
|
||||
/* Code to talk to Pageant was taken from PuTTY.
|
||||
*
|
||||
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
|
||||
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas
|
||||
* Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,
|
||||
* Markus Kuhn, Colin Watson, and CORE SDI S.A.
|
||||
*/
|
||||
#define PAGEANT_COPYDATA_ID 0x804e50ba /* random goop */
|
||||
#define PAGEANT_MAX_MSGLEN 8192
|
||||
|
||||
static int
|
||||
agent_connect_pageant(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
HWND hwnd;
|
||||
hwnd = FindWindow("Pageant", "Pageant");
|
||||
if (!hwnd)
|
||||
return -1;
|
||||
agent->fd = 0; /* Mark as the connection has been established */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||
{
|
||||
HWND hwnd;
|
||||
char mapname[23];
|
||||
HANDLE filemap;
|
||||
unsigned char *p;
|
||||
int id;
|
||||
COPYDATASTRUCT cds;
|
||||
|
||||
if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) {
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
}
|
||||
hwnd = FindWindow("Pageant", "Pageant");
|
||||
if (!hwnd) {
|
||||
return -1;
|
||||
}
|
||||
sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());
|
||||
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
||||
0, PAGEANT_MAX_MSGLEN, mapname);
|
||||
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
|
||||
_libssh2_htonu32(p, transctx->request_len);
|
||||
memcpy(p + 4, transctx->request, transctx->request_len);
|
||||
cds.dwData = PAGEANT_COPYDATA_ID;
|
||||
cds.cbData = 1 + strlen(mapname);
|
||||
cds.lpData = mapname;
|
||||
|
||||
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
|
||||
if (id > 0) {
|
||||
transctx->response_len = _libssh2_ntohu32(p);
|
||||
if (transctx->response_len > PAGEANT_MAX_MSGLEN) {
|
||||
UnmapViewOfFile(p);
|
||||
CloseHandle(filemap);
|
||||
return LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
}
|
||||
transctx->response = LIBSSH2_ALLOC(agent->session,
|
||||
transctx->response_len);
|
||||
if (!transctx->response) {
|
||||
UnmapViewOfFile(p);
|
||||
CloseHandle(filemap);
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
}
|
||||
memcpy(transctx->response, p + 4, transctx->response_len);
|
||||
}
|
||||
|
||||
UnmapViewOfFile(p);
|
||||
CloseHandle(filemap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
agent_disconnect_pageant(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
agent->fd = INVALID_SOCKET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct agent_ops agent_ops_pageant = {
|
||||
agent_connect_pageant,
|
||||
agent_transact_pageant,
|
||||
agent_disconnect_pageant
|
||||
};
|
||||
#endif /* WIN32 */
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
struct agent_ops *ops;
|
||||
} supported_backends[] = {
|
||||
#ifdef WIN32
|
||||
{"Pageant", &agent_ops_pageant},
|
||||
#endif /* WIN32 */
|
||||
#ifdef PF_UNIX
|
||||
{"Unix", &agent_ops_unix},
|
||||
#endif /* PF_UNIX */
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static int
|
||||
agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
|
||||
const unsigned char *data, size_t data_len, void **abstract)
|
||||
{
|
||||
LIBSSH2_AGENT *agent = (LIBSSH2_AGENT *) (*abstract);
|
||||
agent_transaction_ctx_t transctx = &agent->transctx;
|
||||
struct agent_publickey *identity = agent->identity;
|
||||
ssize_t len = 1 + 4 + identity->external.blob_len + 4 + data_len + 4;
|
||||
ssize_t method_len;
|
||||
unsigned char *s;
|
||||
int rc;
|
||||
|
||||
/* Create a request to sign the data */
|
||||
if (transctx->state == agent_NB_state_init) {
|
||||
s = transctx->request = LIBSSH2_ALLOC(session, len);
|
||||
if (!transctx->request) {
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
}
|
||||
|
||||
*s++ = SSH2_AGENTC_SIGN_REQUEST;
|
||||
/* key blob */
|
||||
_libssh2_htonu32(s, identity->external.blob_len);
|
||||
s += 4;
|
||||
memcpy(s, identity->external.blob, identity->external.blob_len);
|
||||
s += identity->external.blob_len;
|
||||
/* data */
|
||||
_libssh2_htonu32(s, data_len);
|
||||
s += 4;
|
||||
memcpy(s, data, data_len);
|
||||
s += data_len;
|
||||
/* flags */
|
||||
_libssh2_htonu32(s, 0);
|
||||
s += 4;
|
||||
transctx->request_len = s - transctx->request;
|
||||
transctx->state = agent_NB_state_request_created;
|
||||
}
|
||||
|
||||
/* Make sure to be re-called as a result of EAGAIN. */
|
||||
if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST) {
|
||||
return LIBSSH2_ERROR_BAD_USE;
|
||||
}
|
||||
|
||||
rc = agent->ops->transact(agent, transctx);
|
||||
if (rc) {
|
||||
goto error;
|
||||
}
|
||||
LIBSSH2_FREE(session, transctx->request);
|
||||
transctx->request = NULL;
|
||||
|
||||
len = transctx->response_len;
|
||||
s = transctx->response;
|
||||
len--;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
if (*s != SSH2_AGENT_SIGN_RESPONSE) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
s++;
|
||||
|
||||
/* Skip the entire length of the signature */
|
||||
len -= 4;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
s += 4;
|
||||
|
||||
/* Skip signing method */
|
||||
len -= 4;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
method_len = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
len -= method_len;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
s += method_len;
|
||||
|
||||
/* Read the signature */
|
||||
len -= 4;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
*sig_len = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
len -= *sig_len;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
*sig = LIBSSH2_ALLOC(session, *sig_len);
|
||||
if (!*sig) {
|
||||
rc = LIBSSH2_ERROR_ALLOC;
|
||||
goto error;
|
||||
}
|
||||
memcpy(*sig, s, *sig_len);
|
||||
|
||||
error:
|
||||
LIBSSH2_FREE(session, transctx->request);
|
||||
transctx->request = NULL;
|
||||
|
||||
LIBSSH2_FREE(session, transctx->response);
|
||||
transctx->response = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
agent_list_identities(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
agent_transaction_ctx_t transctx = &agent->transctx;
|
||||
ssize_t len, num_identities;
|
||||
unsigned char *s;
|
||||
int rc;
|
||||
|
||||
/* Create a request to list identities */
|
||||
if (transctx->state == agent_NB_state_init) {
|
||||
unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES;
|
||||
transctx->request = &c;
|
||||
transctx->request_len = 1;
|
||||
transctx->state = agent_NB_state_request_created;
|
||||
}
|
||||
|
||||
/* Make sure to be re-called as a result of EAGAIN. */
|
||||
if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) {
|
||||
return LIBSSH2_ERROR_BAD_USE;
|
||||
}
|
||||
|
||||
rc = agent->ops->transact(agent, transctx);
|
||||
if (rc) {
|
||||
goto error;
|
||||
}
|
||||
transctx->request = NULL;
|
||||
|
||||
len = transctx->response_len;
|
||||
s = transctx->response;
|
||||
len--;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
if (*s != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
s++;
|
||||
|
||||
/* Read the length of identities */
|
||||
len -= 4;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
num_identities = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
|
||||
while (num_identities--) {
|
||||
struct agent_publickey *identity;
|
||||
ssize_t comment_len;
|
||||
|
||||
identity = LIBSSH2_ALLOC(agent->session, sizeof *identity);
|
||||
if (!identity) {
|
||||
rc = LIBSSH2_ERROR_ALLOC;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Read the length of the blob */
|
||||
len -= 4;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
identity->external.blob_len = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
|
||||
/* Read the blob */
|
||||
len -= identity->external.blob_len;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
identity->external.blob = LIBSSH2_ALLOC(agent->session,
|
||||
identity->external.blob_len);
|
||||
if (!identity->external.blob) {
|
||||
rc = LIBSSH2_ERROR_ALLOC;
|
||||
goto error;
|
||||
}
|
||||
memcpy(identity->external.blob, s, identity->external.blob_len);
|
||||
s += identity->external.blob_len;
|
||||
|
||||
/* Read the length of the comment */
|
||||
len -= 4;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
comment_len = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
|
||||
/* Read the comment */
|
||||
len -= comment_len;
|
||||
if (len < 0) {
|
||||
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
|
||||
goto error;
|
||||
}
|
||||
identity->external.comment = LIBSSH2_ALLOC(agent->session,
|
||||
comment_len + 1);
|
||||
if (!identity->external.comment) {
|
||||
rc = LIBSSH2_ERROR_ALLOC;
|
||||
goto error;
|
||||
}
|
||||
identity->external.comment[comment_len] = '\0';
|
||||
memcpy(identity->external.comment, s, comment_len);
|
||||
s += comment_len;
|
||||
|
||||
_libssh2_list_add(&agent->head, &identity->node);
|
||||
}
|
||||
error:
|
||||
LIBSSH2_FREE(agent->session, transctx->response);
|
||||
transctx->response = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
agent_free_identities(LIBSSH2_AGENT *agent) {
|
||||
struct agent_publickey *node;
|
||||
struct agent_publickey *next;
|
||||
|
||||
for (node = _libssh2_list_first(&agent->head); node; node = next) {
|
||||
next = _libssh2_list_next(&node->node);
|
||||
LIBSSH2_FREE(agent->session, node->external.blob);
|
||||
LIBSSH2_FREE(agent->session, node->external.comment);
|
||||
LIBSSH2_FREE(agent->session, node);
|
||||
}
|
||||
_libssh2_list_init(&agent->head);
|
||||
}
|
||||
|
||||
#define AGENT_PUBLICKEY_MAGIC 0x3bdefed2
|
||||
/*
|
||||
* agent_publickey_to_external()
|
||||
*
|
||||
* Copies data from the internal to the external representation struct.
|
||||
*
|
||||
*/
|
||||
static struct libssh2_agent_publickey *
|
||||
agent_publickey_to_external(struct agent_publickey *node)
|
||||
{
|
||||
struct libssh2_agent_publickey *ext = &node->external;
|
||||
|
||||
ext->magic = AGENT_PUBLICKEY_MAGIC;
|
||||
ext->node = node;
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_agent_init
|
||||
*
|
||||
* Init an ssh-agent handle. Returns the pointer to the handle.
|
||||
*
|
||||
*/
|
||||
LIBSSH2_API LIBSSH2_AGENT *
|
||||
libssh2_agent_init(LIBSSH2_SESSION *session)
|
||||
{
|
||||
LIBSSH2_AGENT *agent;
|
||||
|
||||
agent = LIBSSH2_ALLOC(session, sizeof *agent);
|
||||
if (!agent) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate space for agent connection", 0);
|
||||
return NULL;
|
||||
}
|
||||
memset(agent, 0, sizeof *agent);
|
||||
agent->session = session;
|
||||
_libssh2_list_init(&agent->head);
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_agent_connect()
|
||||
*
|
||||
* Connect to an ssh-agent.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_connect(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
int i, rc = -1;
|
||||
for (i = 0; supported_backends[i].name; i++) {
|
||||
agent->ops = supported_backends[i].ops;
|
||||
rc = agent->ops->connect(agent);
|
||||
if (!rc)
|
||||
return 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_agent_list_identities()
|
||||
*
|
||||
* Request ssh-agent to list identities.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_list_identities(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
memset(&agent->transctx, 0, sizeof agent->transctx);
|
||||
/* Abondon the last fetched identities */
|
||||
agent_free_identities(agent);
|
||||
return agent_list_identities(agent);
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_agent_get_identity()
|
||||
*
|
||||
* Traverse the internal list of public keys. 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 public key was stored in 'store'
|
||||
* 1 if end of public keys
|
||||
* [negative] on errors
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
|
||||
struct libssh2_agent_publickey **ext,
|
||||
struct libssh2_agent_publickey *oprev)
|
||||
{
|
||||
struct agent_publickey *node;
|
||||
if (oprev && oprev->node) {
|
||||
/* we have a starting point */
|
||||
struct agent_publickey *prev = oprev->node;
|
||||
|
||||
/* get the next node in the list */
|
||||
node = _libssh2_list_next(&prev->node);
|
||||
}
|
||||
else
|
||||
node = _libssh2_list_first(&agent->head);
|
||||
|
||||
if (!node)
|
||||
/* no (more) node */
|
||||
return 1;
|
||||
|
||||
*ext = agent_publickey_to_external(node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_agent_userauth()
|
||||
*
|
||||
* Do publickey user authentication with the help of ssh-agent.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_userauth(LIBSSH2_AGENT *agent,
|
||||
const char *username,
|
||||
struct libssh2_agent_publickey *identity)
|
||||
{
|
||||
void *abstract = agent;
|
||||
|
||||
if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
|
||||
memset(&agent->transctx, 0, sizeof agent->transctx);
|
||||
agent->identity = identity->node;
|
||||
}
|
||||
return libssh2_userauth_publickey(agent->session, username,
|
||||
identity->blob,
|
||||
identity->blob_len,
|
||||
agent_sign,
|
||||
&abstract);
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_agent_disconnect()
|
||||
*
|
||||
* Close a connection to an ssh-agent.
|
||||
*
|
||||
* Returns 0 if succeeded, or a negative value for error.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
if (agent->ops && agent->fd != INVALID_SOCKET)
|
||||
return agent->ops->disconnect(agent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_agent_free()
|
||||
*
|
||||
* Free an ssh-agent handle. This function also frees the internal
|
||||
* collection of public keys.
|
||||
*/
|
||||
LIBSSH2_API void
|
||||
libssh2_agent_free(LIBSSH2_AGENT *agent) {
|
||||
/* Allow connection freeing when the socket has lost its connection */
|
||||
if (agent->fd != INVALID_SOCKET) {
|
||||
libssh2_agent_disconnect(agent);
|
||||
}
|
||||
agent_free_identities(agent);
|
||||
LIBSSH2_FREE(agent->session, agent);
|
||||
}
|
@@ -78,7 +78,7 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session)
|
||||
* told...
|
||||
*/
|
||||
session->next_channel = id + 1;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Allocated new channel ID#%lu",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN, "Allocated new channel ID#%lu",
|
||||
id);
|
||||
return id;
|
||||
}
|
||||
@@ -149,7 +149,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
|
||||
memset(&session->open_packet_requirev_state, 0,
|
||||
sizeof(session->open_packet_requirev_state));
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Opening Channel - win %d pack %d", window_size,
|
||||
packet_size);
|
||||
session->open_channel =
|
||||
@@ -254,7 +254,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
|
||||
_libssh2_ntohu32(session->open_data + 9);
|
||||
session->open_channel->local.packet_size =
|
||||
_libssh2_ntohu32(session->open_data + 13);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Connection Established - ID: %lu/%lu win: %lu/%lu"
|
||||
" pack: %lu/%lu",
|
||||
session->open_channel->local.id,
|
||||
@@ -361,7 +361,7 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
|
||||
session->direct_message_len =
|
||||
session->direct_host_len + session->direct_shost_len + 16;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Requesting direct-tcpip session to from %s:%d to %s:%d",
|
||||
shost, sport, host, port);
|
||||
|
||||
@@ -455,7 +455,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
|
||||
memset(&session->fwdLstn_packet_requirev_state, 0,
|
||||
sizeof(session->fwdLstn_packet_requirev_state));
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Requesting tcpip-forward session for %s:%d", host,
|
||||
port);
|
||||
|
||||
@@ -552,7 +552,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
|
||||
listener->host[session->fwdLstn_host_len] = 0;
|
||||
if (data_len >= 5 && !port) {
|
||||
listener->port = _libssh2_ntohu32(data + 1);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Dynamic tcpip-forward port allocated: %d",
|
||||
listener->port);
|
||||
} else {
|
||||
@@ -625,7 +625,7 @@ static int channel_forward_cancel(LIBSSH2_LISTENER *listener)
|
||||
int rc;
|
||||
|
||||
if (listener->chanFwdCncl_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Cancelling tcpip-forward session for %s:%d",
|
||||
listener->host, listener->port);
|
||||
|
||||
@@ -725,11 +725,6 @@ channel_forward_accept(LIBSSH2_LISTENER *listener)
|
||||
|
||||
do {
|
||||
rc = _libssh2_transport_read(listener->session);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting for packet", 0);
|
||||
return NULL;
|
||||
}
|
||||
} while (rc > 0);
|
||||
|
||||
if (_libssh2_list_first(&listener->queue)) {
|
||||
@@ -746,8 +741,13 @@ channel_forward_accept(LIBSSH2_LISTENER *listener)
|
||||
return channel;
|
||||
}
|
||||
|
||||
libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
|
||||
"Channel not found", 0);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block waiting for packet", 0);
|
||||
}
|
||||
else
|
||||
libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
|
||||
"Channel not found", 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -791,7 +791,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
|
||||
memset(&channel->setenv_packet_requirev_state, 0,
|
||||
sizeof(channel->setenv_packet_requirev_state));
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Setting remote environment variable: %s=%s on "
|
||||
"channel %lu/%lu",
|
||||
varname, value, channel->local.id, channel->remote.id);
|
||||
@@ -922,7 +922,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
|
||||
memset(&channel->reqPTY_packet_requirev_state, 0,
|
||||
sizeof(channel->reqPTY_packet_requirev_state));
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Allocating tty on channel %lu/%lu", channel->local.id,
|
||||
channel->remote.id);
|
||||
|
||||
@@ -1049,7 +1049,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
|
||||
memset(&channel->reqPTY_packet_requirev_state, 0,
|
||||
sizeof(channel->reqPTY_packet_requirev_state));
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"changing tty size on channel %lu/%lu",
|
||||
channel->local.id,
|
||||
channel->remote.id);
|
||||
@@ -1153,7 +1153,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
|
||||
memset(&channel->reqX11_packet_requirev_state, 0,
|
||||
sizeof(channel->reqX11_packet_requirev_state));
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Requesting x11-req for channel %lu/%lu: single=%d "
|
||||
"proto=%s cookie=%s screen=%d",
|
||||
channel->local.id, channel->remote.id,
|
||||
@@ -1303,7 +1303,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
|
||||
channel->process_packet_len += message_len + 4;
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"starting request(%s) on channel %lu/%lu, message=%s",
|
||||
request, channel->local.id, channel->remote.id,
|
||||
message);
|
||||
@@ -1449,7 +1449,7 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
|
||||
&& (streamid == 0))) {
|
||||
int bytes_to_flush = packet->data_len - packet->data_head;
|
||||
|
||||
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
|
||||
"Flushing %d bytes of data from stream "
|
||||
"%lu on channel %lu/%lu",
|
||||
bytes_to_flush, packet_stream_id,
|
||||
@@ -1533,7 +1533,7 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
|
||||
if (!force
|
||||
&& (adjustment + channel->adjust_queue <
|
||||
LIBSSH2_CHANNEL_MINADJUST)) {
|
||||
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
|
||||
"Queueing %lu bytes for receive window adjustment "
|
||||
"for channel %lu/%lu",
|
||||
adjustment, channel->local.id, channel->remote.id);
|
||||
@@ -1556,7 +1556,7 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
|
||||
channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
|
||||
_libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id);
|
||||
_libssh2_htonu32(&channel->adjust_adjust[5], adjustment);
|
||||
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
|
||||
"Adjusting window %lu bytes for data on "
|
||||
"channel %lu/%lu",
|
||||
adjustment, channel->local.id, channel->remote.id);
|
||||
@@ -1643,7 +1643,7 @@ int
|
||||
_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
|
||||
{
|
||||
if (channel->extData2_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
|
||||
"Setting channel %lu/%lu handle_extended_data"
|
||||
" mode to %d",
|
||||
channel->local.id, channel->remote.id, ignore_mode);
|
||||
@@ -1720,7 +1720,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
LIBSSH2_PACKET *read_next;
|
||||
|
||||
if (channel->read_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"channel_read() wants %d bytes from channel %lu/%lu "
|
||||
"stream #%d",
|
||||
(int) buflen, channel->local.id, channel->remote.id,
|
||||
@@ -1797,7 +1797,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
unlink_packet = TRUE;
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"channel_read() got %d of data from %lu/%lu/%d%s",
|
||||
bytes_want, channel->local.id,
|
||||
channel->remote.id, stream_id,
|
||||
@@ -1856,7 +1856,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
if (rc == PACKET_EAGAIN)
|
||||
return rc;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"channel_read() filled %d adjusted %d",
|
||||
bytes_read, buflen);
|
||||
/* continue in 'created' state to drain the already read packages
|
||||
@@ -1966,7 +1966,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
if (channel->write_state == libssh2_NB_state_idle) {
|
||||
channel->write_bufwrote = 0;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Writing %d bytes on channel %lu/%lu, stream #%d",
|
||||
(int) buflen, channel->local.id, channel->remote.id,
|
||||
stream_id);
|
||||
@@ -2030,7 +2030,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
/* Don't exceed the remote end's limits */
|
||||
/* REMEMBER local means local as the SOURCE of the data */
|
||||
if (channel->write_bufwrite > channel->local.window_size) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Splitting write block due to %lu byte "
|
||||
"window_size on %lu/%lu/%d",
|
||||
channel->local.window_size, channel->local.id,
|
||||
@@ -2038,7 +2038,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
channel->write_bufwrite = channel->local.window_size;
|
||||
}
|
||||
if (channel->write_bufwrite > channel->local.packet_size) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Splitting write block due to %lu byte "
|
||||
"packet_size on %lu/%lu/%d",
|
||||
channel->local.packet_size, channel->local.id,
|
||||
@@ -2050,7 +2050,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
memcpy(channel->write_s, buf, channel->write_bufwrite);
|
||||
channel->write_s += channel->write_bufwrite;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Sending %d bytes on channel %lu/%lu, stream_id=%d",
|
||||
(int) channel->write_bufwrite, channel->local.id,
|
||||
channel->remote.id, stream_id);
|
||||
@@ -2122,7 +2122,7 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel)
|
||||
unsigned char packet[5]; /* packet_type(1) + channelno(4) */
|
||||
int rc;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Sending EOF on channel %lu/%lu",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN, "Sending EOF on channel %lu/%lu",
|
||||
channel->local.id, channel->remote.id);
|
||||
packet[0] = SSH_MSG_CHANNEL_EOF;
|
||||
_libssh2_htonu32(packet + 1, channel->remote.id);
|
||||
@@ -2188,7 +2188,7 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
|
||||
int rc;
|
||||
|
||||
if (channel->wait_eof_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Awaiting close of channel %lu/%lu", channel->local.id,
|
||||
channel->remote.id);
|
||||
|
||||
@@ -2246,7 +2246,7 @@ channel_close(LIBSSH2_CHANNEL * channel)
|
||||
}
|
||||
|
||||
if (channel->close_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Closing channel %lu/%lu",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu",
|
||||
channel->local.id, channel->remote.id);
|
||||
|
||||
channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE;
|
||||
@@ -2327,7 +2327,7 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
|
||||
}
|
||||
|
||||
if (channel->wait_closed_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Awaiting close of channel %lu/%lu", channel->local.id,
|
||||
channel->remote.id);
|
||||
|
||||
@@ -2386,7 +2386,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
|
||||
assert(session);
|
||||
|
||||
if (channel->free_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Freeing channel %lu/%lu resources", channel->local.id,
|
||||
channel->remote.id);
|
||||
|
||||
|
81
src/crypt.c
81
src/crypt.c
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
/* Copyright (c) 2009 Simon Josefsson <simon@josefsson.org>
|
||||
* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -114,6 +115,44 @@ crypt_dtor(LIBSSH2_SESSION * session, void **abstract)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LIBSSH2_AES_CTR
|
||||
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = {
|
||||
"aes128-ctr",
|
||||
16, /* blocksize */
|
||||
16, /* initial value length */
|
||||
16, /* secret length -- 16*8 == 128bit */
|
||||
0, /* flags */
|
||||
&crypt_init,
|
||||
&crypt_encrypt,
|
||||
&crypt_dtor,
|
||||
_libssh2_cipher_aes128ctr
|
||||
};
|
||||
|
||||
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = {
|
||||
"aes192-ctr",
|
||||
16, /* blocksize */
|
||||
16, /* initial value length */
|
||||
24, /* secret length -- 24*8 == 192bit */
|
||||
0, /* flags */
|
||||
&crypt_init,
|
||||
&crypt_encrypt,
|
||||
&crypt_dtor,
|
||||
_libssh2_cipher_aes192ctr
|
||||
};
|
||||
|
||||
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = {
|
||||
"aes256-ctr",
|
||||
16, /* blocksize */
|
||||
16, /* initial value length */
|
||||
32, /* secret length -- 32*8 == 256bit */
|
||||
0, /* flags */
|
||||
&crypt_init,
|
||||
&crypt_encrypt,
|
||||
&crypt_dtor,
|
||||
_libssh2_cipher_aes256ctr
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_AES
|
||||
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
|
||||
"aes128-cbc",
|
||||
@@ -192,6 +231,40 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
|
||||
&crypt_dtor,
|
||||
_libssh2_cipher_arcfour
|
||||
};
|
||||
|
||||
static int
|
||||
crypt_init_arcfour128(LIBSSH2_SESSION * session,
|
||||
const LIBSSH2_CRYPT_METHOD * method,
|
||||
unsigned char *iv, int *free_iv,
|
||||
unsigned char *secret, int *free_secret,
|
||||
int encrypt, void **abstract)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = crypt_init (session, method, iv, free_iv, secret, free_secret,
|
||||
encrypt, abstract);
|
||||
if (rc == 0) {
|
||||
struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
|
||||
unsigned char block[8];
|
||||
size_t discard = 1536;
|
||||
for (; discard; discard -= 8)
|
||||
_libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = {
|
||||
"arcfour128",
|
||||
8, /* blocksize */
|
||||
8, /* initial value length */
|
||||
16, /* secret length */
|
||||
0, /* flags */
|
||||
&crypt_init_arcfour128,
|
||||
&crypt_encrypt,
|
||||
&crypt_dtor,
|
||||
_libssh2_cipher_arcfour
|
||||
};
|
||||
#endif /* LIBSSH2_RC4 */
|
||||
|
||||
#if LIBSSH2_CAST
|
||||
@@ -223,6 +296,11 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
|
||||
#endif
|
||||
|
||||
static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
|
||||
#if LIBSSH2_AES_CTR
|
||||
&libssh2_crypt_method_aes128_ctr,
|
||||
&libssh2_crypt_method_aes192_ctr,
|
||||
&libssh2_crypt_method_aes256_ctr,
|
||||
#endif /* LIBSSH2_AES */
|
||||
#if LIBSSH2_AES
|
||||
&libssh2_crypt_method_aes256_cbc,
|
||||
&libssh2_crypt_method_rijndael_cbc_lysator_liu_se, /* == aes256-cbc */
|
||||
@@ -233,6 +311,7 @@ static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
|
||||
&libssh2_crypt_method_blowfish_cbc,
|
||||
#endif /* LIBSSH2_BLOWFISH */
|
||||
#if LIBSSH2_RC4
|
||||
&libssh2_crypt_method_arcfour128,
|
||||
&libssh2_crypt_method_arcfour,
|
||||
#endif /* LIBSSH2_RC4 */
|
||||
#if LIBSSH2_CAST
|
||||
|
72
src/kex.c
72
src/kex.c
@@ -135,7 +135,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
exchange_state->e_packet + 6);
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending KEX packet %d",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending KEX packet %d",
|
||||
(int) packet_type_init);
|
||||
exchange_state->state = libssh2_NB_state_created;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
* need to silently ignore it */
|
||||
int burn_type;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Waiting for badly guessed KEX packet (to be ignored)");
|
||||
burn_type =
|
||||
_libssh2_packet_burn(session, &exchange_state->burn_state);
|
||||
@@ -174,7 +174,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
}
|
||||
session->burn_optimistic_kexinit = 0;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Burnt packet of type: %02x",
|
||||
(unsigned int) burn_type);
|
||||
}
|
||||
@@ -233,7 +233,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
|
||||
}
|
||||
*(--fprint) = '\0';
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Server's MD5 Fingerprint: %s", fingerprint);
|
||||
}
|
||||
#endif /* LIBSSH2DEBUG */
|
||||
@@ -256,7 +256,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
|
||||
}
|
||||
*(--fprint) = '\0';
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Server's SHA1 Fingerprint: %s", fingerprint);
|
||||
}
|
||||
#endif /* LIBSSH2DEBUG */
|
||||
@@ -410,7 +410,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending NEWKEYS message");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending NEWKEYS message");
|
||||
exchange_state->c = SSH_MSG_NEWKEYS;
|
||||
|
||||
exchange_state->state = libssh2_NB_state_sent2;
|
||||
@@ -444,7 +444,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
/* The first key exchange has been performed,
|
||||
switch to active crypt/comp/mac mode */
|
||||
session->state |= LIBSSH2_STATE_NEWKEYS;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Received NEWKEYS message");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
|
||||
|
||||
/* This will actually end up being just packet_type(1)
|
||||
for this packet type anyway */
|
||||
@@ -461,7 +461,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
memcpy(session->session_id, exchange_state->h_sig_comp,
|
||||
SHA_DIGEST_LENGTH);
|
||||
session->session_id_len = SHA_DIGEST_LENGTH;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "session_id calculated");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated");
|
||||
}
|
||||
|
||||
/* Cleanup any existing cipher */
|
||||
@@ -509,7 +509,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
LIBSSH2_FREE(session, secret);
|
||||
}
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Client to Server IV and Key calculated");
|
||||
|
||||
if (session->remote.crypt->dtor) {
|
||||
@@ -556,7 +556,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
LIBSSH2_FREE(session, secret);
|
||||
}
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Server to Client IV and Key calculated");
|
||||
|
||||
if (session->local.mac->dtor) {
|
||||
@@ -582,7 +582,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
LIBSSH2_FREE(session, key);
|
||||
}
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Client to Server HMAC Key calculated");
|
||||
|
||||
if (session->remote.mac->dtor) {
|
||||
@@ -608,7 +608,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
LIBSSH2_FREE(session, key);
|
||||
}
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Server to Client HMAC Key calculated");
|
||||
}
|
||||
|
||||
@@ -684,7 +684,7 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
|
||||
_libssh2_bn_set_word(key_state->g, 2);
|
||||
_libssh2_bn_from_bin(key_state->p, 128, p_value);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Initiating Diffie-Hellman Group1 Key Exchange");
|
||||
|
||||
key_state->state = libssh2_NB_state_created;
|
||||
@@ -760,7 +760,7 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
|
||||
_libssh2_bn_set_word(key_state->g, 2);
|
||||
_libssh2_bn_from_bin(key_state->p, 256, p_value);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Initiating Diffie-Hellman Group14 Key Exchange");
|
||||
|
||||
key_state->state = libssh2_NB_state_created;
|
||||
@@ -806,13 +806,13 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
|
||||
_libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
|
||||
_libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
|
||||
key_state->request_len = 13;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Initiating Diffie-Hellman Group-Exchange (New Method)");
|
||||
#else
|
||||
key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
|
||||
_libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
|
||||
key_state->request_len = 5;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
|
||||
"Initiating Diffie-Hellman Group-Exchange (Old Method)");
|
||||
#endif
|
||||
|
||||
@@ -1090,25 +1090,25 @@ static int kexinit(LIBSSH2_SESSION * session)
|
||||
/* Funnily enough, they'll all "appear" to be '\0' terminated */
|
||||
unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent KEX: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent KEX: %s", p);
|
||||
p += kex_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent HOSTKEY: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent HOSTKEY: %s", p);
|
||||
p += hostkey_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_CS: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_CS: %s", p);
|
||||
p += crypt_cs_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_SC: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_SC: %s", p);
|
||||
p += crypt_sc_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_CS: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_CS: %s", p);
|
||||
p += mac_cs_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_SC: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_SC: %s", p);
|
||||
p += mac_sc_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_CS: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_CS: %s", p);
|
||||
p += comp_cs_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_SC: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_SC: %s", p);
|
||||
p += comp_sc_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_CS: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_CS: %s", p);
|
||||
p += lang_cs_len + 4;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_SC: %s", p);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_SC: %s", p);
|
||||
p += lang_sc_len + 4;
|
||||
}
|
||||
#endif /* LIBSSH2DEBUG */
|
||||
@@ -1607,24 +1607,24 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
return -1;
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on KEX method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on KEX method: %s",
|
||||
session->kex->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on HOSTKEY method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on HOSTKEY method: %s",
|
||||
session->hostkey->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_CS method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_CS method: %s",
|
||||
session->local.crypt->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_SC method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_SC method: %s",
|
||||
session->remote.crypt->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_CS method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_CS method: %s",
|
||||
session->local.mac->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_SC method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_SC method: %s",
|
||||
session->remote.mac->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_CS method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_CS method: %s",
|
||||
session->local.comp->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_SC method: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_SC method: %s",
|
||||
session->remote.comp->name);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_CS method:"); /* None yet */
|
||||
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_SC method:"); /* None yet */
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on LANG_CS method:"); /* None yet */
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on LANG_SC method:"); /* None yet */
|
||||
|
||||
/* Initialize compression layer */
|
||||
if (session->local.comp && session->local.comp->init &&
|
||||
|
@@ -424,61 +424,54 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(sig, 0, 40);
|
||||
|
||||
/* Extract R. */
|
||||
|
||||
data = gcry_sexp_find_token(sig_sexp, "r", 0);
|
||||
if (!data) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (!data)
|
||||
goto err;
|
||||
|
||||
tmp = gcry_sexp_nth_data(data, 1, &size);
|
||||
if (!tmp) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (!tmp)
|
||||
goto err;
|
||||
|
||||
if (tmp[0] == '\0') {
|
||||
tmp++;
|
||||
size--;
|
||||
}
|
||||
|
||||
if (size != 20) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (size < 1 || size > 20)
|
||||
goto err;
|
||||
|
||||
memcpy(sig, tmp, 20);
|
||||
memcpy(sig + (20 - size), tmp, size);
|
||||
|
||||
gcry_sexp_release(data);
|
||||
|
||||
/* Extract S. */
|
||||
|
||||
data = gcry_sexp_find_token(sig_sexp, "s", 0);
|
||||
if (!data) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (!data)
|
||||
goto err;
|
||||
|
||||
tmp = gcry_sexp_nth_data(data, 1, &size);
|
||||
if (!tmp) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (!tmp)
|
||||
goto err;
|
||||
|
||||
if (tmp[0] == '\0') {
|
||||
tmp++;
|
||||
size--;
|
||||
}
|
||||
|
||||
if (size != 20) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (size < 1 || size > 20)
|
||||
goto err;
|
||||
|
||||
memcpy(sig + 20, tmp, 20);
|
||||
memcpy(sig + 20 + (20 - size), tmp, size);
|
||||
goto out;
|
||||
|
||||
err:
|
||||
ret = -1;
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (sig_sexp) {
|
||||
gcry_sexp_release(sig_sexp);
|
||||
@@ -524,16 +517,14 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
|
||||
_libssh2_cipher_type(algo),
|
||||
unsigned char *iv, unsigned char *secret, int encrypt)
|
||||
{
|
||||
int mode = 0, ret;
|
||||
int keylen = gcry_cipher_get_algo_keylen(algo);
|
||||
int ret;
|
||||
int cipher = _libssh2_gcry_cipher (algo);
|
||||
int mode = _libssh2_gcry_mode (algo);
|
||||
int keylen = gcry_cipher_get_algo_keylen(cipher);
|
||||
|
||||
(void) encrypt;
|
||||
|
||||
if (algo != GCRY_CIPHER_ARCFOUR) {
|
||||
mode = GCRY_CIPHER_MODE_CBC;
|
||||
}
|
||||
|
||||
ret = gcry_cipher_open(h, algo, mode, 0);
|
||||
ret = gcry_cipher_open(h, cipher, mode, 0);
|
||||
if (ret) {
|
||||
return -1;
|
||||
}
|
||||
@@ -544,10 +535,13 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (algo != GCRY_CIPHER_ARCFOUR) {
|
||||
int blklen = gcry_cipher_get_algo_blklen(algo);
|
||||
ret = gcry_cipher_setiv(*h, iv, blklen);
|
||||
if (ret) {
|
||||
if (mode != GCRY_CIPHER_MODE_STREAM) {
|
||||
int blklen = gcry_cipher_get_algo_blklen(cipher);
|
||||
if (mode == GCRY_CIPHER_MODE_CTR)
|
||||
ret = gcry_cipher_setctr(*h, iv, blklen);
|
||||
else
|
||||
ret = gcry_cipher_setiv(*h, iv, blklen);
|
||||
if (ret) {
|
||||
gcry_cipher_close(*h);
|
||||
return -1;
|
||||
}
|
||||
@@ -561,8 +555,10 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
_libssh2_cipher_type(algo),
|
||||
int encrypt, unsigned char *block)
|
||||
{
|
||||
size_t blklen = gcry_cipher_get_algo_blklen(algo);
|
||||
int cipher = _libssh2_gcry_cipher (algo);
|
||||
size_t blklen = gcry_cipher_get_algo_blklen(cipher);
|
||||
int ret;
|
||||
|
||||
if (blklen == 1) {
|
||||
/* Hack for arcfour. */
|
||||
blklen = 8;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/* Copyright (C) 2006, 2007, The Written Word, Inc.
|
||||
* Copyright (C) 2008, Simon Josefsson
|
||||
/*
|
||||
* Copyright (C) 2008, 2009 Simon Josefsson
|
||||
* Copyright (C) 2006, 2007, The Written Word, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -43,6 +44,7 @@
|
||||
#define LIBSSH2_HMAC_RIPEMD 1
|
||||
|
||||
#define LIBSSH2_AES 1
|
||||
#define LIBSSH2_AES_CTR 1
|
||||
#define LIBSSH2_BLOWFISH 1
|
||||
#define LIBSSH2_RC4 1
|
||||
#define LIBSSH2_CAST 1
|
||||
@@ -155,13 +157,30 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
#define _libssh2_cipher_type(name) int name
|
||||
#define _libssh2_cipher_ctx gcry_cipher_hd_t
|
||||
|
||||
#define _libssh2_cipher_aes256 GCRY_CIPHER_AES256
|
||||
#define _libssh2_cipher_aes192 GCRY_CIPHER_AES192
|
||||
#define _libssh2_cipher_aes128 GCRY_CIPHER_AES128
|
||||
#define _libssh2_cipher_blowfish GCRY_CIPHER_BLOWFISH
|
||||
#define _libssh2_cipher_arcfour GCRY_CIPHER_ARCFOUR
|
||||
#define _libssh2_cipher_cast5 GCRY_CIPHER_CAST5
|
||||
#define _libssh2_cipher_3des GCRY_CIPHER_3DES
|
||||
#define _libssh2_gcry_ciphermode(c,m) ((c << 8) | m)
|
||||
#define _libssh2_gcry_cipher(c) (c >> 8)
|
||||
#define _libssh2_gcry_mode(m) (m & 0xFF)
|
||||
|
||||
#define _libssh2_cipher_aes256ctr \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR)
|
||||
#define _libssh2_cipher_aes192ctr \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR)
|
||||
#define _libssh2_cipher_aes128ctr \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR)
|
||||
#define _libssh2_cipher_aes256 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_aes192 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_aes128 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_blowfish \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_arcfour \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM)
|
||||
#define _libssh2_cipher_cast5 \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC)
|
||||
#define _libssh2_cipher_3des \
|
||||
_libssh2_gcry_ciphermode(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC)
|
||||
|
||||
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
|
||||
_libssh2_cipher_type(algo),
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2009 by Daniel Stenberg
|
||||
* Copyright (c) 2010 Simon Josefsson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -153,6 +154,7 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
|
||||
typedef SOCKET libssh2_socket_t;
|
||||
#else /* !WIN32 */
|
||||
typedef int libssh2_socket_t;
|
||||
#define INVALID_SOCKET -1
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* RFC4253 section 6.1 Maximum Packet Length says:
|
||||
@@ -209,7 +211,9 @@ typedef enum
|
||||
libssh2_NB_state_sent7,
|
||||
libssh2_NB_state_jump1,
|
||||
libssh2_NB_state_jump2,
|
||||
libssh2_NB_state_jump3
|
||||
libssh2_NB_state_jump3,
|
||||
libssh2_NB_state_jump4,
|
||||
libssh2_NB_state_jump5
|
||||
} libssh2_nonblocking_states;
|
||||
|
||||
typedef struct packet_require_state_t
|
||||
@@ -735,6 +739,8 @@ struct _LIBSSH2_SESSION
|
||||
struct transportpacket packet;
|
||||
#ifdef LIBSSH2DEBUG
|
||||
int showmask; /* what debug/trace messages to display */
|
||||
libssh2_trace_handler_func tracehandler; /* callback to display trace messages */
|
||||
void* tracehandler_context; /* context for the trace handler */
|
||||
#endif
|
||||
|
||||
/* State variables used in libssh2_banner_send() */
|
||||
@@ -1014,14 +1020,6 @@ struct _LIBSSH2_MAC_METHOD
|
||||
int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
|
||||
};
|
||||
|
||||
#define LIBSSH2_DBG_TRANS 1
|
||||
#define LIBSSH2_DBG_KEX 2
|
||||
#define LIBSSH2_DBG_AUTH 3
|
||||
#define LIBSSH2_DBG_CONN 4
|
||||
#define LIBSSH2_DBG_SCP 5
|
||||
#define LIBSSH2_DBG_SFTP 6
|
||||
#define LIBSSH2_DBG_ERROR 7
|
||||
#define LIBSSH2_DBG_PUBLICKEY 8
|
||||
#ifdef LIBSSH2DEBUG
|
||||
void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
|
||||
...);
|
||||
@@ -1048,7 +1046,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
session->err_msglen = strlen(errmsg); \
|
||||
session->err_should_free = should_free; \
|
||||
session->err_code = errcode; \
|
||||
_libssh2_debug(session, LIBSSH2_DBG_ERROR, "%d - %s", session->err_code, session->err_msg); \
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code, session->err_msg); \
|
||||
}
|
||||
|
||||
#else /* ! LIBSSH2DEBUG */
|
||||
@@ -1271,4 +1269,7 @@ int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
|
||||
} while(1)
|
||||
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0]))
|
||||
|
||||
|
||||
#endif /* LIBSSH2_H */
|
||||
|
@@ -167,6 +167,7 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1_96 = {
|
||||
mac_method_common_dtor,
|
||||
};
|
||||
|
||||
#if LIBSSH2_MD5
|
||||
/* mac_method_hmac_md5_hash
|
||||
* Calculate hash using full md5 value
|
||||
*/
|
||||
@@ -235,6 +236,7 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_md5_96 = {
|
||||
mac_method_hmac_md5_96_hash,
|
||||
mac_method_common_dtor,
|
||||
};
|
||||
#endif /* LIBSSH2_MD5 */
|
||||
|
||||
#if LIBSSH2_HMAC_RIPEMD
|
||||
/* mac_method_hmac_ripemd160_hash
|
||||
@@ -291,8 +293,10 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160_openssh_com = {
|
||||
static const LIBSSH2_MAC_METHOD *mac_methods[] = {
|
||||
&mac_method_hmac_sha1,
|
||||
&mac_method_hmac_sha1_96,
|
||||
#if LIBSSH2_MD5
|
||||
&mac_method_hmac_md5,
|
||||
&mac_method_hmac_md5_96,
|
||||
#endif
|
||||
#if LIBSSH2_HMAC_RIPEMD
|
||||
&mac_method_hmac_ripemd160,
|
||||
&mac_method_hmac_ripemd160_openssh_com,
|
||||
|
48
src/misc.c
48
src/misc.c
@@ -312,6 +312,14 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBSSH2_API int
|
||||
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, libssh2_trace_handler_func callback)
|
||||
{
|
||||
session->tracehandler = callback;
|
||||
session->tracehandler_context = handler_context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
{
|
||||
@@ -320,7 +328,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
va_list vargs;
|
||||
struct timeval now;
|
||||
static int firstsec;
|
||||
static const char *const contexts[9] = {
|
||||
static const char *const contexts[] = {
|
||||
"Unknown",
|
||||
"Transport",
|
||||
"Key Ex",
|
||||
@@ -330,15 +338,24 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
"SFTP",
|
||||
"Failure Event",
|
||||
"Publickey",
|
||||
"Socket",
|
||||
};
|
||||
const char* contexttext = contexts[0];
|
||||
unsigned int contextindex;
|
||||
|
||||
if (context < 1 || context > 8) {
|
||||
context = 0;
|
||||
}
|
||||
if (!(session->showmask & (1 << context))) {
|
||||
if (!(session->showmask & context)) {
|
||||
/* no such output asked for */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the first matching context string for this message */
|
||||
for (contextindex = 0; contextindex < ARRAY_SIZE(contexts); contextindex++) {
|
||||
if ((context & (1 << contextindex)) != 0) {
|
||||
contexttext = contexts[contextindex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
if(!firstsec) {
|
||||
firstsec = now.tv_sec;
|
||||
@@ -346,14 +363,18 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
now.tv_sec -= firstsec;
|
||||
|
||||
len = snprintf(buffer, sizeof(buffer), "[libssh2] %d.%06d %s: ",
|
||||
(int)now.tv_sec, (int)now.tv_usec, contexts[context]);
|
||||
(int)now.tv_sec, (int)now.tv_usec, contexttext);
|
||||
|
||||
va_start(vargs, format);
|
||||
len += vsnprintf(buffer + len, 1535 - len, format, vargs);
|
||||
buffer[len] = '\n';
|
||||
va_end(vargs);
|
||||
write(2, buffer, len + 1);
|
||||
|
||||
if (session->tracehandler) {
|
||||
(session->tracehandler)(session, session->tracehandler_context, buffer, len + 1);
|
||||
} else {
|
||||
write(2, buffer, len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -364,6 +385,15 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
|
||||
(void) bitmask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBSSH2_API int
|
||||
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, libssh2_trace_handler_func callback)
|
||||
{
|
||||
(void) session;
|
||||
(void) handler_context;
|
||||
(void) callback;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* init the list head */
|
||||
@@ -442,6 +472,10 @@ void _libssh2_list_insert(struct list_node *after, /* insert before this */
|
||||
and must be made to point to 'entry' correctly */
|
||||
if(entry->prev)
|
||||
entry->prev->next = entry;
|
||||
else
|
||||
/* there was no node before this, so we make sure we point the head
|
||||
pointer to this node */
|
||||
after->head->first = entry;
|
||||
|
||||
/* after's prev entry points back to entry */
|
||||
after->prev = entry;
|
||||
|
134
src/openssl.c
134
src/openssl.c
@@ -1,7 +1,9 @@
|
||||
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
||||
* Author: Simon Josefsson
|
||||
/* Copyright (C) 2009 Simon Josefsson
|
||||
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
||||
* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||
*
|
||||
* Author: Simon Josefsson
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
@@ -197,6 +199,110 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
return ret == 1 ? 0 : 1;
|
||||
}
|
||||
|
||||
#if LIBSSH2_AES_CTR
|
||||
#include <openssl/aes.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AES_KEY key;
|
||||
unsigned char ctr[AES_BLOCK_SIZE];
|
||||
} aes_ctr_ctx;
|
||||
|
||||
static int
|
||||
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc) /* init key */
|
||||
{
|
||||
aes_ctr_ctx *c = malloc(sizeof(*c));
|
||||
(void) enc;
|
||||
|
||||
if (c == NULL)
|
||||
return 0;
|
||||
|
||||
AES_set_encrypt_key(key, 8 * ctx->key_len, &c->key);
|
||||
memcpy(c->ctr, iv, AES_BLOCK_SIZE);
|
||||
|
||||
EVP_CIPHER_CTX_set_app_data(ctx, c);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in,
|
||||
unsigned int inl) /* encrypt/decrypt data */
|
||||
{
|
||||
aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
|
||||
unsigned char b1[AES_BLOCK_SIZE];
|
||||
size_t i;
|
||||
|
||||
if (inl != 16) /* libssh2 only ever encrypt one block */
|
||||
return 0;
|
||||
|
||||
/*
|
||||
To encrypt a packet P=P1||P2||...||Pn (where P1, P2, ..., Pn are each
|
||||
blocks of length L), the encryptor first encrypts <X> with <cipher>
|
||||
to obtain a block B1. The block B1 is then XORed with P1 to generate
|
||||
the ciphertext block C1. The counter X is then incremented
|
||||
*/
|
||||
|
||||
AES_encrypt(c->ctr, b1, &c->key);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
*out++ = *in++ ^ b1[i];
|
||||
|
||||
i = 15;
|
||||
while (c->ctr[i]++ == 0xFF) {
|
||||
if (i == 0)
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
|
||||
{
|
||||
free(EVP_CIPHER_CTX_get_app_data(ctx));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_CIPHER *
|
||||
make_ctr_evp (size_t keylen)
|
||||
{
|
||||
static EVP_CIPHER aes_ctr_cipher;
|
||||
|
||||
memset(&aes_ctr_cipher, 0, sizeof(aes_ctr_cipher));
|
||||
|
||||
aes_ctr_cipher.block_size = 16;
|
||||
aes_ctr_cipher.key_len = keylen;
|
||||
aes_ctr_cipher.iv_len = 16;
|
||||
aes_ctr_cipher.init = aes_ctr_init;
|
||||
aes_ctr_cipher.do_cipher = aes_ctr_do_cipher;
|
||||
aes_ctr_cipher.cleanup = aes_ctr_cleanup;
|
||||
|
||||
return &aes_ctr_cipher;
|
||||
}
|
||||
|
||||
const EVP_CIPHER *
|
||||
_libssh2_EVP_aes_128_ctr(void)
|
||||
{
|
||||
return make_ctr_evp (16);
|
||||
}
|
||||
|
||||
const EVP_CIPHER *
|
||||
_libssh2_EVP_aes_192_ctr(void)
|
||||
{
|
||||
return make_ctr_evp (24);
|
||||
}
|
||||
|
||||
const EVP_CIPHER *
|
||||
_libssh2_EVP_aes_256_ctr(void)
|
||||
{
|
||||
return make_ctr_evp (32);
|
||||
}
|
||||
#endif /* LIBSSH2_AES_CTR */
|
||||
|
||||
/* TODO: Optionally call a passphrase callback specified by the
|
||||
* calling program
|
||||
*/
|
||||
@@ -219,7 +325,7 @@ 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,
|
||||
read_private_key_from_file(void ** key_ctx,
|
||||
pem_read_bio_func read_private_key,
|
||||
const char * filename,
|
||||
unsigned const char *passphrase)
|
||||
@@ -233,7 +339,7 @@ read_private_key_from_file(void ** key_ctx, LIBSSH2_SESSION * session,
|
||||
return -1;
|
||||
}
|
||||
|
||||
*key_ctx = read_private_key(bp, NULL, (void *) passphrase_cb,
|
||||
*key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb,
|
||||
(void *) passphrase);
|
||||
|
||||
BIO_free(bp);
|
||||
@@ -257,7 +363,7 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
|
||||
OpenSSL_add_all_ciphers();
|
||||
}
|
||||
|
||||
return read_private_key_from_file((void **) rsa, session, read_rsa,
|
||||
return read_private_key_from_file((void **) rsa, read_rsa,
|
||||
filename, passphrase);
|
||||
}
|
||||
|
||||
@@ -268,6 +374,7 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
{
|
||||
pem_read_bio_func read_dsa =
|
||||
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
|
||||
(void) session;
|
||||
|
||||
if (!EVP_get_cipherbyname("des")) {
|
||||
/* If this cipher isn't loaded it's a pretty good indication that none are.
|
||||
@@ -277,7 +384,7 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
OpenSSL_add_all_ciphers();
|
||||
}
|
||||
|
||||
return read_private_key_from_file((void **) dsa, session, read_dsa,
|
||||
return read_private_key_from_file((void **) dsa, read_dsa,
|
||||
filename, passphrase);
|
||||
}
|
||||
|
||||
@@ -318,7 +425,7 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
unsigned long hash_len, unsigned char *signature)
|
||||
{
|
||||
DSA_SIG *sig;
|
||||
int r_len, s_len, rs_pad;
|
||||
int r_len, s_len;
|
||||
(void) hash_len;
|
||||
|
||||
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
|
||||
@@ -327,15 +434,20 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
}
|
||||
|
||||
r_len = BN_num_bytes(sig->r);
|
||||
if (r_len < 1 || r_len > 20) {
|
||||
DSA_SIG_free(sig);
|
||||
return -1;
|
||||
}
|
||||
s_len = BN_num_bytes(sig->s);
|
||||
rs_pad = (2 * SHA_DIGEST_LENGTH) - (r_len + s_len);
|
||||
if (rs_pad < 0) {
|
||||
if (s_len < 1 || s_len > 20) {
|
||||
DSA_SIG_free(sig);
|
||||
return -1;
|
||||
}
|
||||
|
||||
BN_bn2bin(sig->r, signature + rs_pad);
|
||||
BN_bn2bin(sig->s, signature + rs_pad + r_len);
|
||||
memset(signature, 0, 40);
|
||||
|
||||
BN_bn2bin(sig->r, signature + (20 - r_len));
|
||||
BN_bn2bin(sig->s, signature + 20 + (20 - s_len));
|
||||
|
||||
DSA_SIG_free(sig);
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
||||
/* Copyright (C) 2009 Simon Josefsson
|
||||
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
||||
*
|
||||
* Author: Simon Josefsson
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -71,6 +73,7 @@
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
|
||||
# define LIBSSH2_AES_CTR 1
|
||||
# define LIBSSH2_AES 1
|
||||
#else
|
||||
# define LIBSSH2_AES 0
|
||||
@@ -194,6 +197,9 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
#define _libssh2_cipher_aes256 EVP_aes_256_cbc
|
||||
#define _libssh2_cipher_aes192 EVP_aes_192_cbc
|
||||
#define _libssh2_cipher_aes128 EVP_aes_128_cbc
|
||||
#define _libssh2_cipher_aes128ctr _libssh2_EVP_aes_128_ctr
|
||||
#define _libssh2_cipher_aes192ctr _libssh2_EVP_aes_192_ctr
|
||||
#define _libssh2_cipher_aes256ctr _libssh2_EVP_aes_256_ctr
|
||||
#define _libssh2_cipher_blowfish EVP_bf_cbc
|
||||
#define _libssh2_cipher_arcfour EVP_rc4
|
||||
#define _libssh2_cipher_cast5 EVP_cast5_cbc
|
||||
@@ -223,3 +229,7 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
#define _libssh2_bn_bytes(bn) BN_num_bytes(bn)
|
||||
#define _libssh2_bn_bits(bn) BN_num_bits(bn)
|
||||
#define _libssh2_bn_free(bn) BN_clear_free(bn)
|
||||
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);
|
||||
|
117
src/packet.c
117
src/packet.c
@@ -1,5 +1,6 @@
|
||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2009 by Daniel Stenberg
|
||||
* Copyright (c) 2010 Simon Josefsson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -108,7 +109,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
listen_state->sport = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Remote received connection from %s:%ld to %s:%ld",
|
||||
listen_state->shost, listen_state->sport,
|
||||
listen_state->host, listen_state->port);
|
||||
@@ -131,7 +132,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
(listen->queue_maxsize <= listen->queue_size)) {
|
||||
/* Queue is full */
|
||||
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Listener queue full, ignoring");
|
||||
listen_state->state = libssh2_NB_state_sent;
|
||||
break;
|
||||
@@ -146,6 +147,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
listen_state->state = libssh2_NB_state_sent;
|
||||
break;
|
||||
}
|
||||
listen_state->channel = channel;
|
||||
|
||||
memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
|
||||
|
||||
channel->session = session;
|
||||
@@ -181,7 +184,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
listen_state->initial_window_size;
|
||||
channel->local.packet_size = listen_state->packet_size;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Connection queued: channel %lu/%lu win %lu/%lu packet %lu/%lu",
|
||||
channel->local.id, channel->remote.id,
|
||||
channel->local.window_size,
|
||||
@@ -292,7 +295,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
x11open_state->sport = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"X11 Connection Received from %s:%ld on channel %lu",
|
||||
x11open_state->shost, x11open_state->sport,
|
||||
x11open_state->sender_channel);
|
||||
@@ -340,7 +343,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
channel->local.window_size = x11open_state->initial_window_size;
|
||||
channel->local.packet_size = x11open_state->packet_size;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"X11 Connection established: channel %lu/%lu win %lu/%lu packet %lu/%lu",
|
||||
channel->local.id, channel->remote.id,
|
||||
channel->local.window_size,
|
||||
@@ -418,7 +421,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
* _libssh2_packet_add
|
||||
*
|
||||
* Create a new packet and attach it to the brigade. Called from the transport
|
||||
* layer when it as received a packet.
|
||||
* layer when it has received a packet.
|
||||
*
|
||||
* The input pointer 'data' is pointing to allocated data that this function
|
||||
* is asked to deal with so on failure OR success, it must be freed fine.
|
||||
@@ -444,7 +447,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
memset(&session->packAdd_x11open_state, 0,
|
||||
sizeof(session->packAdd_x11open_state));
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Packet type %d received, length=%d",
|
||||
(int) data[0], (int) datalen);
|
||||
if (macstate == LIBSSH2_MAC_INVALID) {
|
||||
@@ -481,8 +484,16 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
goto libssh2_packet_add_jump_point2;
|
||||
} else if (session->packAdd_state == libssh2_NB_state_jump3) {
|
||||
goto libssh2_packet_add_jump_point3;
|
||||
} else if (session->packAdd_state == libssh2_NB_state_jump4) {
|
||||
goto libssh2_packet_add_jump_point4;
|
||||
} else if (session->packAdd_state == libssh2_NB_state_jump5) {
|
||||
goto libssh2_packet_add_jump_point5;
|
||||
}
|
||||
|
||||
/* FIXME: I've noticed that DATA is accessed without proper
|
||||
* out-of-bounds checking (i.e., DATALEN) in many places
|
||||
* below. --simon */
|
||||
|
||||
if (session->packAdd_state == libssh2_NB_state_allocated) {
|
||||
/* A couple exceptions to the packet adding rule: */
|
||||
switch (data[0]) {
|
||||
@@ -510,7 +521,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
message[message_len] = '\0';
|
||||
language = (char *) data + 9 + message_len + 3;
|
||||
if (language_len) {
|
||||
memcpy(language, language + 1, language_len);
|
||||
memmove(language, language + 1, language_len);
|
||||
}
|
||||
language[language_len] = '\0';
|
||||
|
||||
@@ -518,7 +529,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
LIBSSH2_DISCONNECT(session, reason, message,
|
||||
message_len, language, language_len);
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Disconnect(%d): %s(%s)", reason,
|
||||
message, language);
|
||||
LIBSSH2_FREE(session, data);
|
||||
@@ -531,11 +542,15 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
break;
|
||||
|
||||
case SSH_MSG_IGNORE:
|
||||
/* As with disconnect, back it up one and add a trailing NULL */
|
||||
memcpy(data + 4, data + 5, datalen - 5);
|
||||
data[datalen] = '\0';
|
||||
if (session->ssh_msg_ignore) {
|
||||
LIBSSH2_IGNORE(session, (char *) data + 4, datalen - 5);
|
||||
if (datalen >= 5) {
|
||||
/* Back it up one and add a trailing NULL */
|
||||
memmove(data, data + 1, datalen - 1);
|
||||
data[datalen] = '\0';
|
||||
if (session->ssh_msg_ignore) {
|
||||
LIBSSH2_IGNORE(session, (char *) data + 4, datalen - 1);
|
||||
}
|
||||
} else if (session->ssh_msg_ignore) {
|
||||
LIBSSH2_IGNORE(session, "", 0);
|
||||
}
|
||||
LIBSSH2_FREE(session, data);
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
@@ -565,7 +580,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
message[message_len] = '\0';
|
||||
language = (char *) data + 6 + message_len + 3;
|
||||
if (language_len) {
|
||||
memcpy(language, language + 1, language_len);
|
||||
memmove(language, language + 1, language_len);
|
||||
}
|
||||
language[language_len] = '\0';
|
||||
|
||||
@@ -577,7 +592,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
* _libssh2_debug will actually truncate this for us so
|
||||
* that it's not an inordinate about of data
|
||||
*/
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Debug Packet: %s", message);
|
||||
LIBSSH2_FREE(session, data);
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
@@ -585,6 +600,30 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
}
|
||||
break;
|
||||
|
||||
case SSH_MSG_GLOBAL_REQUEST:
|
||||
{
|
||||
uint32_t strlen = _libssh2_ntohu32(data + 1);
|
||||
unsigned char want_reply = data[5 + strlen];
|
||||
|
||||
_libssh2_debug(session,
|
||||
LIBSSH2_TRACE_CONN,
|
||||
"Received global request type %.*s (wr %X)",
|
||||
strlen, data + 5, want_reply);
|
||||
|
||||
if (want_reply) {
|
||||
libssh2_packet_add_jump_point5:
|
||||
session->packAdd_state = libssh2_NB_state_jump5;
|
||||
data[0] = SSH_MSG_REQUEST_FAILURE;
|
||||
rc = _libssh2_transport_write(session, data, 1);
|
||||
if (rc == PACKET_EAGAIN)
|
||||
return rc;
|
||||
LIBSSH2_FREE(session, data);
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SSH_MSG_CHANNEL_EXTENDED_DATA:
|
||||
/* streamid(4) */
|
||||
session->packAdd_data_head += 4;
|
||||
@@ -610,7 +649,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
stream_id = _libssh2_ntohu32(data + 5);
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"%d bytes packet_add() for %lu/%lu/%lu",
|
||||
(int) (datalen - session->packAdd_data_head),
|
||||
session->packAdd_channel->local.id,
|
||||
@@ -624,7 +663,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
/* Pretend we didn't receive this */
|
||||
LIBSSH2_FREE(session, data);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Ignoring extended data and refunding %d bytes",
|
||||
(int) (datalen - 13));
|
||||
/* Adjust the window based on the block we just freed */
|
||||
@@ -707,7 +746,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
}
|
||||
|
||||
_libssh2_debug(session,
|
||||
LIBSSH2_DBG_CONN,
|
||||
LIBSSH2_TRACE_CONN,
|
||||
"EOF received for channel %lu/%lu",
|
||||
session->packAdd_channel->local.id,
|
||||
session->packAdd_channel->remote.id);
|
||||
@@ -718,19 +757,28 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
return 0;
|
||||
|
||||
case SSH_MSG_CHANNEL_REQUEST:
|
||||
if (_libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1
|
||||
{
|
||||
uint32_t channel = _libssh2_ntohu32(data + 1);
|
||||
uint32_t strlen = _libssh2_ntohu32(data + 5);
|
||||
unsigned char want_reply = data[9 + strlen];
|
||||
|
||||
_libssh2_debug(session,
|
||||
LIBSSH2_TRACE_CONN,
|
||||
"Channel %d received request type %.*s (wr %X)",
|
||||
channel, strlen, data + 9, want_reply);
|
||||
|
||||
if (strlen == sizeof("exit-status") - 1
|
||||
&& !memcmp("exit-status", data + 9,
|
||||
sizeof("exit-status") - 1)) {
|
||||
|
||||
/* we've got "exit-status" packet. Set the session value */
|
||||
session->packAdd_channel =
|
||||
_libssh2_channel_locate(session,
|
||||
_libssh2_ntohu32(data + 1));
|
||||
_libssh2_channel_locate(session, channel);
|
||||
|
||||
if (session->packAdd_channel) {
|
||||
session->packAdd_channel->exit_status =
|
||||
_libssh2_ntohu32(data + 9 + sizeof("exit-status"));
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Exit status %lu received for channel %lu/%lu",
|
||||
session->packAdd_channel->exit_status,
|
||||
session->packAdd_channel->local.id,
|
||||
@@ -741,7 +789,20 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (want_reply) {
|
||||
libssh2_packet_add_jump_point4:
|
||||
session->packAdd_state = libssh2_NB_state_jump4;
|
||||
data[0] = SSH_MSG_CHANNEL_FAILURE;
|
||||
rc = _libssh2_transport_write(session, data, 5);
|
||||
if (rc == PACKET_EAGAIN)
|
||||
return rc;
|
||||
LIBSSH2_FREE(session, data);
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SSH_MSG_CHANNEL_CLOSE:
|
||||
session->packAdd_channel =
|
||||
@@ -753,7 +814,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
return 0;
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Close received for channel %lu/%lu",
|
||||
session->packAdd_channel->local.id,
|
||||
session->packAdd_channel->remote.id);
|
||||
@@ -810,7 +871,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
if (session->packAdd_channel && bytestoadd) {
|
||||
session->packAdd_channel->local.window_size += bytestoadd;
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Window adjust received for channel %lu/%lu, adding %lu bytes, new window_size=%lu",
|
||||
session->packAdd_channel->local.id,
|
||||
session->packAdd_channel->remote.id,
|
||||
@@ -858,7 +919,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
* Well, it's already in the brigade,
|
||||
* let's just call back into ourselves
|
||||
*/
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Renegotiating Keys");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Renegotiating Keys");
|
||||
|
||||
session->packAdd_state = libssh2_NB_state_sent2;
|
||||
}
|
||||
@@ -909,7 +970,7 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
|
||||
{
|
||||
LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Looking for packet of type: %d", (int) packet_type);
|
||||
|
||||
while (packet) {
|
||||
@@ -1048,7 +1109,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
|
||||
return i;
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Blocking until packet becomes available to burn");
|
||||
*state = libssh2_NB_state_created;
|
||||
}
|
||||
|
@@ -353,7 +353,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
|
||||
session->pkeyInit_pkey = NULL;
|
||||
session->pkeyInit_channel = NULL;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
|
||||
"Initializing publickey subsystem");
|
||||
|
||||
session->pkeyInit_state = libssh2_NB_state_allocated;
|
||||
@@ -434,7 +434,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
|
||||
_libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION);
|
||||
s += 4;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
|
||||
"Sending publickey version packet advertising version %d support",
|
||||
(int) LIBSSH2_PUBLICKEY_VERSION);
|
||||
|
||||
@@ -519,13 +519,13 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
|
||||
session->pkeyInit_pkey->version = _libssh2_ntohu32(s);
|
||||
if (session->pkeyInit_pkey->version >
|
||||
LIBSSH2_PUBLICKEY_VERSION) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
|
||||
"Truncating remote publickey version from %lu",
|
||||
session->pkeyInit_pkey->version);
|
||||
session->pkeyInit_pkey->version =
|
||||
LIBSSH2_PUBLICKEY_VERSION;
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
|
||||
"Enabling publickey subsystem version %lu",
|
||||
session->pkeyInit_pkey->version);
|
||||
LIBSSH2_FREE(session, session->pkeyInit_data);
|
||||
@@ -590,7 +590,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
|
||||
if (pkey->add_state == libssh2_NB_state_idle) {
|
||||
pkey->add_packet = NULL;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Adding %s publickey",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, "Adding %s publickey",
|
||||
name);
|
||||
|
||||
if (pkey->version == 1) {
|
||||
@@ -671,7 +671,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
|
||||
}
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
|
||||
"Sending publickey \"add\" packet: type=%s blob_len=%ld num_attrs=%ld",
|
||||
name, blob_len, num_attrs);
|
||||
|
||||
@@ -747,7 +747,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
|
||||
memcpy(pkey->remove_s, blob, blob_len);
|
||||
pkey->remove_s += blob_len;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
|
||||
"Sending publickey \"remove\" packet: type=%s blob_len=%ld",
|
||||
name, blob_len);
|
||||
|
||||
@@ -809,7 +809,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
|
||||
memcpy(pkey->listFetch_s, "list", sizeof("list") - 1);
|
||||
pkey->listFetch_s += sizeof("list") - 1;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
|
||||
"Sending publickey \"list\" packet");
|
||||
|
||||
pkey->listFetch_state = libssh2_NB_state_created;
|
||||
|
14
src/scp.c
14
src/scp.c
@@ -301,7 +301,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
session->scpRecv_command_len - cmd_len);
|
||||
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SCP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
|
||||
"Opening channel for SCP receive");
|
||||
|
||||
session->scpRecv_state = libssh2_NB_state_created;
|
||||
@@ -350,7 +350,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
LIBSSH2_FREE(session, session->scpRecv_command);
|
||||
session->scpRecv_command = NULL;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sending initial wakeup");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sending initial wakeup");
|
||||
/* SCP ACK */
|
||||
session->scpRecv_response[0] = '\0';
|
||||
|
||||
@@ -569,7 +569,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
goto scp_recv_error;
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SCP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
|
||||
"mtime = %ld, atime = %ld",
|
||||
session->scpRecv_mtime, session->scpRecv_atime);
|
||||
|
||||
@@ -731,7 +731,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
} else if (rc != 1) {
|
||||
goto scp_recv_error;
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SCP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
|
||||
"mode = 0%lo size = %ld", session->scpRecv_mode,
|
||||
session->scpRecv_size);
|
||||
|
||||
@@ -816,7 +816,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
|
||||
session->scpSend_command[session->scpSend_command_len - 1] = '\0';
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SCP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
|
||||
"Opening channel for SCP send");
|
||||
/* Allocate a channel */
|
||||
|
||||
@@ -892,7 +892,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
snprintf((char *) session->scpSend_response,
|
||||
LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime,
|
||||
atime);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
|
||||
session->scpSend_response);
|
||||
}
|
||||
|
||||
@@ -953,7 +953,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
snprintf((char *) session->scpSend_response,
|
||||
LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode,
|
||||
(unsigned long) size, base);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
|
||||
session->scpSend_response);
|
||||
|
||||
session->scpSend_state = libssh2_NB_state_sent5;
|
||||
|
@@ -111,6 +111,12 @@ banner_receive(LIBSSH2_SESSION * session)
|
||||
|
||||
ret = _libssh2_recv(session->socket_fd, &c, 1,
|
||||
LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||
if (ret < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error recving %d bytes to %p: %d", 1, &c, errno);
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Recved %d bytes to %p", ret, &c);
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
@@ -162,7 +168,7 @@ banner_receive(LIBSSH2_SESSION * session)
|
||||
}
|
||||
memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
|
||||
session->remote.banner[banner_len] = '\0';
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Received Banner: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
|
||||
session->remote.banner);
|
||||
return 0;
|
||||
}
|
||||
@@ -203,7 +209,7 @@ banner_send(LIBSSH2_SESSION * session)
|
||||
banner[255] = '\0';
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending Banner: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s",
|
||||
banner_dup);
|
||||
#endif
|
||||
|
||||
@@ -217,6 +223,15 @@ banner_send(LIBSSH2_SESSION * session)
|
||||
banner + session->banner_TxRx_total_send,
|
||||
banner_len - session->banner_TxRx_total_send,
|
||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||
if (ret < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error sending %d bytes: %d",
|
||||
banner_len - session->banner_TxRx_total_send, errno);
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Sent %d/%d bytes at %p+%d", ret,
|
||||
banner_len - session->banner_TxRx_total_send,
|
||||
banner, session->banner_TxRx_total_send);
|
||||
|
||||
if (ret != (banner_len - session->banner_TxRx_total_send)) {
|
||||
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
|
||||
@@ -395,7 +410,7 @@ libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
|
||||
|
||||
memcpy(session->local.banner, banner, banner_len);
|
||||
session->local.banner[banner_len] = '\0';
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting local Banner: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s",
|
||||
session->local.banner);
|
||||
session->local.banner[banner_len++] = '\r';
|
||||
session->local.banner[banner_len++] = '\n';
|
||||
@@ -441,7 +456,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
||||
session->realloc = local_realloc;
|
||||
session->abstract = abstract;
|
||||
session->api_block_mode = 1; /* blocking API by default */
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"New session resource allocated");
|
||||
libssh2_crypto_init();
|
||||
}
|
||||
@@ -490,7 +505,7 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session,
|
||||
return oldcb;
|
||||
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting Callback %d", cbtype);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -540,10 +555,9 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
int rc;
|
||||
|
||||
if (session->startup_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"session_startup for socket %d", sock);
|
||||
/* FIXME: on some platforms (like win32) sockets are unsigned */
|
||||
if (sock < 0) {
|
||||
if (INVALID_SOCKET == sock) {
|
||||
/* Did we forget something? */
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE,
|
||||
"Bad socket provided", 0);
|
||||
@@ -595,7 +609,7 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
}
|
||||
|
||||
if (session->startup_state == libssh2_NB_state_sent2) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Requesting userauth service");
|
||||
|
||||
/* Request the userauth service */
|
||||
@@ -686,7 +700,7 @@ session_free(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_LISTENER *l;
|
||||
|
||||
if (session->free_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource",
|
||||
session->remote.banner);
|
||||
|
||||
session->state = libssh2_NB_state_created;
|
||||
@@ -946,7 +960,7 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
|
||||
int rc;
|
||||
|
||||
if (session->disconnect_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Disconnecting: reason=%d, desc=%s, lang=%s", reason,
|
||||
description, lang);
|
||||
if (description) {
|
||||
@@ -1192,7 +1206,7 @@ int
|
||||
_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
|
||||
{
|
||||
int bl = session->api_block_mode;
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"Setting blocking mode %s", blocking?"ON":"OFF");
|
||||
session->api_block_mode = blocking;
|
||||
|
||||
|
65
src/sftp.c
65
src/sftp.c
@@ -118,7 +118,7 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
|
||||
LIBSSH2_SESSION *session = sftp->channel->session;
|
||||
LIBSSH2_PACKET *packet;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d (len %d)",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet %d (len %d)",
|
||||
(int) data[0], data_len);
|
||||
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
|
||||
if (!packet) {
|
||||
@@ -153,7 +153,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
|
||||
ssize_t bytes_received;
|
||||
int rc;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "recv packet");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "recv packet");
|
||||
|
||||
/* If there was a previous partial, start using it */
|
||||
if (sftp->partial_packet) {
|
||||
@@ -163,7 +163,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
|
||||
packet_received = sftp->partial_received;
|
||||
sftp->partial_packet = NULL;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"partial read cont, len: %lu", packet_len);
|
||||
}
|
||||
else {
|
||||
@@ -181,7 +181,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
|
||||
}
|
||||
|
||||
packet_len = _libssh2_ntohu32(buffer);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Data begin - Packet Length: %lu", packet_len);
|
||||
if (packet_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
|
||||
@@ -251,7 +251,7 @@ sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
|
||||
unsigned char match_buf[5];
|
||||
int match_len;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Asking for %d packet",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Asking for %d packet",
|
||||
(int) packet_type);
|
||||
|
||||
match_buf[0] = packet_type;
|
||||
@@ -293,12 +293,12 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
|
||||
LIBSSH2_SESSION *session = sftp->channel->session;
|
||||
int ret;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring packet %d id %ld",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld",
|
||||
(int) packet_type, request_id);
|
||||
|
||||
if (sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) {
|
||||
/* The right packet was available in the packet brigade */
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Got %d",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
|
||||
(int) packet_type);
|
||||
return 0;
|
||||
}
|
||||
@@ -314,7 +314,7 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
|
||||
/* data was read, check the queue again */
|
||||
if (!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) {
|
||||
/* The right packet was available in the packet brigade */
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Got %d",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
|
||||
(int) packet_type);
|
||||
return 0;
|
||||
}
|
||||
@@ -530,7 +530,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_SFTP *sftp_handle;
|
||||
|
||||
if (session->sftpInit_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Initializing SFTP subsystem");
|
||||
|
||||
/*
|
||||
@@ -616,7 +616,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
||||
session->sftpInit_buffer[4] = SSH_FXP_INIT;
|
||||
_libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Sending FXP_INIT packet advertising version %d support",
|
||||
(int) LIBSSH2_SFTP_VERSION);
|
||||
|
||||
@@ -661,12 +661,12 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
||||
sftp_handle->version = _libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
if (sftp_handle->version > LIBSSH2_SFTP_VERSION) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Truncating remote SFTP version from %lu",
|
||||
sftp_handle->version);
|
||||
sftp_handle->version = LIBSSH2_SFTP_VERSION;
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Enabling SFTP version %lu compatability",
|
||||
sftp_handle->version);
|
||||
while (s < (data + data_len)) {
|
||||
@@ -864,7 +864,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
|
||||
s += sftp_attr2bin(s, &attrs);
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Sending %s open request",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Sending %s open request",
|
||||
(open_type ==
|
||||
LIBSSH2_SFTP_OPENFILE) ? "file" : "directory");
|
||||
|
||||
@@ -925,7 +925,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
|
||||
sftp->last_errno = _libssh2_ntohu32(data + 5);
|
||||
|
||||
if(LIBSSH2_FX_OK == sftp->last_errno) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got HANDLE FXOK!");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got HANDLE FXOK!");
|
||||
|
||||
/* silly situation, but check for a HANDLE */
|
||||
rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
|
||||
@@ -943,7 +943,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
|
||||
if(badness) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
|
||||
"Failed opening remote file", 0);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got FXP_STATUS %d",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got FXP_STATUS %d",
|
||||
sftp->last_errno);
|
||||
LIBSSH2_FREE(session, data);
|
||||
return NULL;
|
||||
@@ -979,7 +979,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
|
||||
|
||||
fp->u.file.offset = 0;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Open command successful");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Open command successful");
|
||||
return fp;
|
||||
}
|
||||
|
||||
@@ -1019,7 +1019,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
int retcode;
|
||||
|
||||
if (sftp->read_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Reading %lu bytes from SFTP handle",
|
||||
(unsigned long) buffer_maxlen);
|
||||
packet = handle->request_packet;
|
||||
@@ -1057,7 +1057,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 13;
|
||||
}
|
||||
#ifdef LIBSSH2_DEBUG_SFTP
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Requesting %lu bytes from SFTP handle",
|
||||
(unsigned long) bytes_requested);
|
||||
#endif
|
||||
@@ -1153,7 +1153,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
return -1;
|
||||
}
|
||||
#ifdef LIBSSH2_DEBUG_SFTP
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu bytes returned",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu bytes returned",
|
||||
(unsigned long) bytes_read);
|
||||
#endif
|
||||
memcpy(buffer + total_read, data + 9, bytes_read);
|
||||
@@ -1257,7 +1257,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
||||
LIBSSH2_FREE(session, handle->u.dir.names_packet);
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"libssh2_sftp_readdir_ex() return %d",
|
||||
filename_len);
|
||||
return filename_len;
|
||||
@@ -1288,7 +1288,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
||||
}
|
||||
|
||||
if (sftp->readdir_state == libssh2_NB_state_created) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Reading entries from directory handle");
|
||||
retcode = _libssh2_channel_write(channel, 0,
|
||||
(char *) sftp->readdir_packet,
|
||||
@@ -1340,7 +1340,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
||||
}
|
||||
|
||||
num_names = _libssh2_ntohu32(data + 5);
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu entries returned",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned",
|
||||
num_names);
|
||||
if (num_names <= 0) {
|
||||
LIBSSH2_FREE(session, data);
|
||||
@@ -1431,7 +1431,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
|
||||
packet_len = handle->handle_len + count + 25;
|
||||
|
||||
if (sftp->write_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Writing %lu bytes",
|
||||
(unsigned long) count);
|
||||
s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
|
||||
if (!sftp->write_packet) {
|
||||
@@ -1541,7 +1541,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
|
||||
int rc;
|
||||
|
||||
if (sftp->fstat_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Issuing %s command",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command",
|
||||
setstat ? "set-stat" : "stat");
|
||||
s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
|
||||
if (!sftp->fstat_packet) {
|
||||
@@ -1618,6 +1618,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
|
||||
}
|
||||
|
||||
sftp_bin2attr(attrs, data + 5);
|
||||
LIBSSH2_FREE(session, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1692,7 +1693,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
|
||||
int rc;
|
||||
|
||||
if (handle->close_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Closing handle");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle");
|
||||
s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
|
||||
if (!handle->close_packet) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
@@ -1803,7 +1804,7 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
|
||||
int rc;
|
||||
|
||||
if (sftp->unlink_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Unlinking %s", filename);
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename);
|
||||
s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
|
||||
if (!sftp->unlink_packet) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
@@ -1915,7 +1916,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
|
||||
}
|
||||
|
||||
if (sftp->rename_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Renaming %s to %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s",
|
||||
source_filename, dest_filename);
|
||||
sftp->rename_s = sftp->rename_packet =
|
||||
LIBSSH2_ALLOC(session, packet_len);
|
||||
@@ -2051,7 +2052,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
|
||||
int rc;
|
||||
|
||||
if (sftp->mkdir_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
|
||||
"Creating directory %s with mode 0%lo", path, mode);
|
||||
s = packet = LIBSSH2_ALLOC(session, packet_len);
|
||||
if (!packet) {
|
||||
@@ -2115,7 +2116,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
|
||||
LIBSSH2_FREE(session, data);
|
||||
|
||||
if (retcode == LIBSSH2_FX_OK) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "OK!");
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!");
|
||||
return 0;
|
||||
} else {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
|
||||
@@ -2155,7 +2156,7 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
|
||||
int rc;
|
||||
|
||||
if (sftp->rmdir_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Removing directory: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s",
|
||||
path);
|
||||
s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
|
||||
if (!sftp->rmdir_packet) {
|
||||
@@ -2257,7 +2258,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
|
||||
int rc;
|
||||
|
||||
if (sftp->stat_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s",
|
||||
(stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
|
||||
(stat_type ==
|
||||
LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
|
||||
@@ -2399,7 +2400,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
|
||||
return -1;
|
||||
}
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s on %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s on %s",
|
||||
(link_type ==
|
||||
LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading",
|
||||
(link_type ==
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "libssh2_priv.h"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -57,36 +58,58 @@ debugdump(LIBSSH2_SESSION * session,
|
||||
{
|
||||
size_t i;
|
||||
size_t c;
|
||||
FILE *stream = stderr;
|
||||
unsigned int width = 0x10;
|
||||
char buffer[256]; /* Must be enough for width*4 + about 30 or so */
|
||||
size_t used;
|
||||
static const char* hex_chars = "0123456789ABCDEF";
|
||||
|
||||
if (!(session->showmask & (1 << LIBSSH2_DBG_TRANS))) {
|
||||
if (!(session->showmask & LIBSSH2_TRACE_TRANS)) {
|
||||
/* not asked for, bail out */
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stream, "=> %s (%d bytes)\n", desc, (int) size);
|
||||
used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n",
|
||||
desc, (int) size);
|
||||
if (session->tracehandler)
|
||||
(session->tracehandler)(session, session->tracehandler_context, buffer, used);
|
||||
else
|
||||
write(2 /* stderr */, buffer, used);
|
||||
|
||||
for(i = 0; i < size; i += width) {
|
||||
|
||||
fprintf(stream, "%04lx: ", (long)i);
|
||||
used = snprintf(buffer, sizeof(buffer), "%04lx: ", (long)i);
|
||||
|
||||
/* hex not disabled, show it */
|
||||
for(c = 0; c < width; c++) {
|
||||
if (i + c < size)
|
||||
fprintf(stream, "%02x ", ptr[i + c]);
|
||||
else
|
||||
fputs(" ", stream);
|
||||
if (i + c < size) {
|
||||
buffer[used++] = hex_chars[(ptr[i+c] >> 4) & 0xF];
|
||||
buffer[used++] = hex_chars[ptr[i+c] & 0xF];
|
||||
}
|
||||
else {
|
||||
buffer[used++] = ' ';
|
||||
buffer[used++] = ' ';
|
||||
}
|
||||
|
||||
buffer[used++] = ' ';
|
||||
if ((width/2) - 1 == c)
|
||||
buffer[used++] = ' ';
|
||||
}
|
||||
|
||||
buffer[used++] = ':';
|
||||
buffer[used++] = ' ';
|
||||
|
||||
for(c = 0; (c < width) && (i + c < size); c++) {
|
||||
fprintf(stream, "%c",
|
||||
(ptr[i + c] >= 0x20) &&
|
||||
(ptr[i + c] < 0x80) ? ptr[i + c] : UNPRINTABLE_CHAR);
|
||||
buffer[used++] = isprint(ptr[i + c]) ?
|
||||
ptr[i + c] : UNPRINTABLE_CHAR;
|
||||
}
|
||||
fputc('\n', stream); /* newline */
|
||||
buffer[used++] = '\n';
|
||||
buffer[used] = 0;
|
||||
|
||||
if (session->tracehandler)
|
||||
(session->tracehandler)(session, session->tracehandler_context, buffer, used);
|
||||
else
|
||||
write(2, buffer, used);
|
||||
}
|
||||
fflush(stream);
|
||||
}
|
||||
#else
|
||||
#define debugdump(a,x,y,z)
|
||||
@@ -290,7 +313,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
/* Whoever wants a packet won't get anything until the key re-exchange
|
||||
* is done!
|
||||
*/
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the"
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
|
||||
" key re-exchange");
|
||||
rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
|
||||
if (rc)
|
||||
@@ -355,6 +378,15 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
_libssh2_recv(session->socket_fd, &p->buf[remainbuf],
|
||||
PACKETBUFSIZE - remainbuf,
|
||||
LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||
if (nread < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error recving %d bytes to %p+%d: %d",
|
||||
PACKETBUFSIZE - remainbuf, p->buf, remainbuf,
|
||||
errno);
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Recved %d/%d bytes to %p+%d", nread,
|
||||
PACKETBUFSIZE - remainbuf, p->buf, remainbuf);
|
||||
if (nread <= 0) {
|
||||
/* check if this is due to EAGAIN and return the special
|
||||
return code if so, error out normally otherwise */
|
||||
@@ -602,6 +634,13 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
|
||||
rc = _libssh2_send(session->socket_fd, &p->outbuf[p->osent], length,
|
||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||
if (rc < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error sending %d bytes: %d", length, errno);
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Sent %d/%d bytes at %p+%d", rc, length, p->outbuf,
|
||||
p->osent);
|
||||
|
||||
if(rc > 0) {
|
||||
debugdump(session, "libssh2_transport_write send()",
|
||||
@@ -626,7 +665,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
|
||||
p->osent += rc; /* we sent away this much data */
|
||||
|
||||
return p->osent < data_len ? PACKET_EAGAIN : PACKET_NONE;
|
||||
return rc < length ? PACKET_EAGAIN : PACKET_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -671,15 +710,15 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
|
||||
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 */
|
||||
rc = send_existing(session, data, data_len, &ret);
|
||||
if (rc || ret) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* default clear the bit */
|
||||
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
||||
|
||||
encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
|
||||
|
||||
/* check if we should compress */
|
||||
@@ -776,6 +815,12 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
|
||||
ret = _libssh2_send(session->socket_fd, p->outbuf, total_length,
|
||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||
if (ret < 0)
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||
"Error sending %d bytes: %d", total_length, errno);
|
||||
else
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p",
|
||||
ret, total_length, p->outbuf);
|
||||
|
||||
if (ret != -1) {
|
||||
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
|
||||
|
313
src/userauth.c
313
src/userauth.c
@@ -41,6 +41,8 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* Needed for struct iovec on some platforms */
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
@@ -104,7 +106,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
||||
|
||||
if (session->userauth_list_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_list_data,
|
||||
session->userauth_list_data_len);
|
||||
session->userauth_list_data_len);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block requesting userauth list", 0);
|
||||
@@ -155,7 +157,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
||||
memmove(session->userauth_list_data, session->userauth_list_data + 5,
|
||||
methods_len);
|
||||
session->userauth_list_data[methods_len] = '\0';
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Permitted auth methods: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Permitted auth methods: %s",
|
||||
session->userauth_list_data);
|
||||
}
|
||||
|
||||
@@ -206,8 +208,8 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
unsigned char *s;
|
||||
static const unsigned char reply_codes[4] =
|
||||
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
|
||||
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0
|
||||
};
|
||||
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0
|
||||
};
|
||||
int rc;
|
||||
|
||||
if (session->userauth_pswd_state == libssh2_NB_state_idle) {
|
||||
@@ -256,7 +258,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
memcpy(s, password, password_len);
|
||||
s += password_len;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Attempting to login using password authentication");
|
||||
|
||||
session->userauth_pswd_state = libssh2_NB_state_created;
|
||||
@@ -264,7 +266,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
|
||||
if (session->userauth_pswd_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_pswd_data,
|
||||
session->userauth_pswd_data_len);
|
||||
session->userauth_pswd_data_len);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
@@ -301,13 +303,24 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
}
|
||||
|
||||
if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Password authentication successful");
|
||||
LIBSSH2_FREE(session, session->userauth_pswd_data);
|
||||
session->userauth_pswd_data = NULL;
|
||||
session->state |= LIBSSH2_STATE_AUTHENTICATED;
|
||||
session->userauth_pswd_state = libssh2_NB_state_idle;
|
||||
return 0;
|
||||
} else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Password authentication failed");
|
||||
LIBSSH2_FREE(session, session->userauth_pswd_data);
|
||||
session->userauth_pswd_data = NULL;
|
||||
session->userauth_pswd_state = libssh2_NB_state_idle;
|
||||
libssh2_error(session,
|
||||
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
|
||||
"Authentication failed (username/password)",
|
||||
0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->userauth_pswd_newpw = NULL;
|
||||
@@ -325,7 +338,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
if ((session->userauth_pswd_state == libssh2_NB_state_sent1) ||
|
||||
(session->userauth_pswd_state == libssh2_NB_state_sent2)) {
|
||||
if (session->userauth_pswd_state == libssh2_NB_state_sent1) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Password change required");
|
||||
LIBSSH2_FREE(session, session->userauth_pswd_data);
|
||||
session->userauth_pswd_data = NULL;
|
||||
@@ -398,9 +411,9 @@ userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||
|
||||
if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
|
||||
rc = _libssh2_transport_write(session,
|
||||
session->userauth_pswd_data,
|
||||
session->
|
||||
userauth_pswd_data_len);
|
||||
session->userauth_pswd_data,
|
||||
session->
|
||||
userauth_pswd_data_len);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
@@ -469,7 +482,10 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
|
||||
*
|
||||
* Read a public key from an id_???.pub style file
|
||||
*
|
||||
* Returns an allocated string in *pubkeydata on success.
|
||||
* Returns an allocated string containing the decoded key in *pubkeydata
|
||||
* on success.
|
||||
* Returns an allocated string containing the key method (e.g. "ssh-dss")
|
||||
* in method on success.
|
||||
*/
|
||||
static int
|
||||
file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
||||
@@ -484,7 +500,7 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
||||
size_t pubkey_len = 0;
|
||||
unsigned int tmp_len;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading public key file: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s",
|
||||
pubkeyfile);
|
||||
/* Read Public Key */
|
||||
fd = fopen(pubkeyfile, "r");
|
||||
@@ -542,15 +558,10 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
||||
LIBSSH2_FREE(session, pubkey);
|
||||
return -1;
|
||||
}
|
||||
/* Wasting some bytes here (okay, more than some),
|
||||
* but since it's likely to be freed soon anyway,
|
||||
* we'll just avoid the extra free/alloc and call it a wash */
|
||||
*method = pubkey;
|
||||
*method_len = sp1 - pubkey;
|
||||
|
||||
sp1++;
|
||||
|
||||
if ((sp2 = memchr(sp1, ' ', pubkey_len - *method_len)) == NULL) {
|
||||
if ((sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey - 1))) == NULL) {
|
||||
/* Assume that the id string is missing, but that it's okay */
|
||||
sp2 = pubkey + pubkey_len;
|
||||
}
|
||||
@@ -562,6 +573,13 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
||||
LIBSSH2_FREE(session, pubkey);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wasting some bytes here (okay, more than some), but since it's likely
|
||||
* to be freed soon anyway, we'll just avoid the extra free/alloc and call
|
||||
* it a wash */
|
||||
*method = pubkey;
|
||||
*method_len = sp1 - pubkey - 1;
|
||||
|
||||
*pubkeydata = tmp;
|
||||
*pubkeydata_len = tmp_len;
|
||||
|
||||
@@ -583,7 +601,7 @@ file_read_privatekey(LIBSSH2_SESSION * session,
|
||||
const LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail =
|
||||
libssh2_hostkey_methods();
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading private key file: %s",
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading private key file: %s",
|
||||
privkeyfile);
|
||||
*hostkey_method = NULL;
|
||||
*hostkey_abstract = NULL;
|
||||
@@ -613,6 +631,45 @@ file_read_privatekey(LIBSSH2_SESSION * session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct privkey_file {
|
||||
const char *filename;
|
||||
const char *passphrase;
|
||||
};
|
||||
|
||||
static int
|
||||
sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
|
||||
const unsigned char *data, size_t data_len, void **abstract)
|
||||
{
|
||||
struct privkey_file *privkey_file = (struct privkey_file *) (*abstract);
|
||||
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
|
||||
void *hostkey_abstract;
|
||||
struct iovec datavec;
|
||||
|
||||
if (file_read_privatekey(session, &privkeyobj, &hostkey_abstract,
|
||||
session->userauth_pblc_method,
|
||||
session->userauth_pblc_method_len,
|
||||
privkey_file->filename,
|
||||
privkey_file->passphrase)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
datavec.iov_base = (unsigned char *)data;
|
||||
datavec.iov_len = data_len;
|
||||
|
||||
if (privkeyobj->signv(session, sig, (unsigned long *)sig_len, 1, &datavec,
|
||||
&hostkey_abstract)) {
|
||||
if (privkeyobj->dtor) {
|
||||
privkeyobj->dtor(session, abstract);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (privkeyobj->dtor) {
|
||||
privkeyobj->dtor(session, &hostkey_abstract);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* userauth_hostbased_fromfile
|
||||
@@ -627,8 +684,6 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||
const char *local_username,
|
||||
unsigned int local_username_len)
|
||||
{
|
||||
static const unsigned char reply_codes[3] =
|
||||
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
|
||||
int rc;
|
||||
|
||||
if (session->userauth_host_state == libssh2_NB_state_idle) {
|
||||
@@ -797,7 +852,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||
session->userauth_host_s += sig_len;
|
||||
LIBSSH2_FREE(session, sig);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Attempting hostbased authentication");
|
||||
|
||||
session->userauth_host_state = libssh2_NB_state_created;
|
||||
@@ -824,6 +879,8 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_host_state == libssh2_NB_state_sent) {
|
||||
static const unsigned char reply_codes[3] =
|
||||
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
|
||||
unsigned long data_len;
|
||||
rc = _libssh2_packet_requirev(session, reply_codes,
|
||||
&session->userauth_host_data,
|
||||
@@ -839,7 +896,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||
return -1;
|
||||
|
||||
if (session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Hostbased authentication successful");
|
||||
/* We are us and we've proved it. */
|
||||
LIBSSH2_FREE(session, session->userauth_host_data);
|
||||
@@ -885,37 +942,47 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* userauth_publickey_fromfile
|
||||
* Authenticate using a keypair found in the named files
|
||||
*/
|
||||
static int
|
||||
userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
const char *username,
|
||||
unsigned int username_len,
|
||||
const char *publickey,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
userauth_publickey(LIBSSH2_SESSION *session,
|
||||
const char *username,
|
||||
unsigned int username_len,
|
||||
const unsigned char *pubkeydata,
|
||||
unsigned long pubkeydata_len,
|
||||
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
|
||||
void *abstract)
|
||||
{
|
||||
unsigned long pubkeydata_len = 0;
|
||||
unsigned char reply_codes[4] =
|
||||
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
|
||||
SSH_MSG_USERAUTH_PK_OK, 0
|
||||
};
|
||||
SSH_MSG_USERAUTH_PK_OK, 0
|
||||
};
|
||||
int rc;
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
|
||||
unsigned char *pubkeydata;
|
||||
|
||||
/* Zero the whole thing out */
|
||||
memset(&session->userauth_pblc_packet_requirev_state, 0,
|
||||
sizeof(session->userauth_pblc_packet_requirev_state));
|
||||
|
||||
if (file_read_publickey(session, &session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len,publickey)) {
|
||||
return -1;
|
||||
/*
|
||||
* As an optimisation, userauth_publickey_fromfile reuses a
|
||||
* previously allocated copy of the method name to avoid an extra
|
||||
* allocation/free.
|
||||
* For other uses, we allocate and populate it here.
|
||||
*/
|
||||
if (!session->userauth_pblc_method) {
|
||||
session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata);
|
||||
session->userauth_pblc_method =
|
||||
LIBSSH2_ALLOC(session, session->userauth_pblc_method_len);
|
||||
if (!session->userauth_pblc_method) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate memory for public key "
|
||||
"data", 0);
|
||||
return -1;
|
||||
}
|
||||
memcpy(session->userauth_pblc_method, pubkeydata + 4,
|
||||
session->userauth_pblc_method_len);
|
||||
}
|
||||
assert( /* preallocated method len should match what we expect */
|
||||
session->userauth_pblc_method_len == _libssh2_ntohu32(pubkeydata));
|
||||
|
||||
/*
|
||||
* 45 = packet_type(1) + username_len(4) + servicename_len(4) +
|
||||
@@ -940,7 +1007,6 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
if (!session->userauth_pblc_packet) {
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
||||
session->userauth_pblc_method = NULL;
|
||||
LIBSSH2_FREE(session, pubkeydata);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -965,7 +1031,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
*(session->userauth_pblc_s++) = 0;
|
||||
|
||||
_libssh2_htonu32(session->userauth_pblc_s,
|
||||
session->userauth_pblc_method_len);
|
||||
session->userauth_pblc_method_len);
|
||||
session->userauth_pblc_s += 4;
|
||||
memcpy(session->userauth_pblc_s, session->userauth_pblc_method,
|
||||
session->userauth_pblc_method_len);
|
||||
@@ -975,9 +1041,8 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
session->userauth_pblc_s += 4;
|
||||
memcpy(session->userauth_pblc_s, pubkeydata, pubkeydata_len);
|
||||
session->userauth_pblc_s += pubkeydata_len;
|
||||
LIBSSH2_FREE(session, pubkeydata);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Attempting publickey authentication");
|
||||
|
||||
session->userauth_pblc_state = libssh2_NB_state_created;
|
||||
@@ -985,7 +1050,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
|
||||
session->userauth_pblc_packet_len);
|
||||
session->userauth_pblc_packet_len);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
@@ -1003,13 +1068,6 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_sent) {
|
||||
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
|
||||
void *abstract;
|
||||
unsigned char buf[5];
|
||||
struct iovec datavec[4];
|
||||
unsigned char *sig;
|
||||
unsigned long sig_len;
|
||||
|
||||
rc = _libssh2_packet_requirev(session, reply_codes,
|
||||
&session->userauth_pblc_data,
|
||||
&session->userauth_pblc_data_len, 0,
|
||||
@@ -1028,7 +1086,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Pubkey authentication prematurely successful");
|
||||
/*
|
||||
* God help any SSH server that allows an UNVERIFIED
|
||||
@@ -1053,7 +1111,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
session->userauth_pblc_packet = NULL;
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
||||
session->userauth_pblc_method = NULL;
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED,
|
||||
libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED,
|
||||
"Username/PublicKey combination invalid", 0);
|
||||
session->userauth_pblc_state = libssh2_NB_state_idle;
|
||||
return -1;
|
||||
@@ -1063,44 +1121,45 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_data);
|
||||
session->userauth_pblc_data = NULL;
|
||||
|
||||
if (file_read_privatekey(session, &privkeyobj, &abstract,
|
||||
session->userauth_pblc_method,
|
||||
session->userauth_pblc_method_len,
|
||||
privatekey, passphrase)) {
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
||||
session->userauth_pblc_method = NULL;
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_packet);
|
||||
session->userauth_pblc_packet = NULL;
|
||||
session->userauth_pblc_state = libssh2_NB_state_idle;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*session->userauth_pblc_b = 0x01;
|
||||
session->userauth_pblc_state = libssh2_NB_state_sent1;
|
||||
}
|
||||
|
||||
_libssh2_htonu32(buf, session->session_id_len);
|
||||
datavec[0].iov_base = buf;
|
||||
datavec[0].iov_len = 4;
|
||||
datavec[1].iov_base = session->session_id;
|
||||
datavec[1].iov_len = session->session_id_len;
|
||||
datavec[2].iov_base = session->userauth_pblc_packet;
|
||||
datavec[2].iov_len = session->userauth_pblc_packet_len;
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
|
||||
unsigned char *buf, *s;
|
||||
unsigned char *sig;
|
||||
size_t sig_len;
|
||||
|
||||
if (privkeyobj->signv(session, &sig, &sig_len, 3, datavec, &abstract)) {
|
||||
s = buf = LIBSSH2_ALLOC(session, 4 + session->session_id_len
|
||||
+ session->userauth_pblc_packet_len);
|
||||
if (!buf) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate memory for userauth-publickey "
|
||||
"signed data", 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_libssh2_htonu32(s, session->session_id_len);
|
||||
s += 4;
|
||||
memcpy (s, session->session_id, session->session_id_len);
|
||||
s += session->session_id_len;
|
||||
memcpy (s, session->userauth_pblc_packet,
|
||||
session->userauth_pblc_packet_len);
|
||||
s += session->userauth_pblc_packet_len;
|
||||
|
||||
rc = sign_callback(session, &sig, &sig_len, buf, s - buf, abstract);
|
||||
LIBSSH2_FREE(session, buf);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
||||
session->userauth_pblc_method = NULL;
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_packet);
|
||||
session->userauth_pblc_packet = NULL;
|
||||
if (privkeyobj->dtor) {
|
||||
privkeyobj->dtor(session, &abstract);
|
||||
}
|
||||
session->userauth_pblc_state = libssh2_NB_state_idle;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (privkeyobj->dtor) {
|
||||
privkeyobj->dtor(session, &abstract);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this function was restarted, pubkeydata_len might still be 0
|
||||
* which will cause an unnecessary but harmless realloc here.
|
||||
@@ -1152,13 +1211,13 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
session->userauth_pblc_s += sig_len;
|
||||
LIBSSH2_FREE(session, sig);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Attempting publickey authentication -- phase 2");
|
||||
|
||||
session->userauth_pblc_state = libssh2_NB_state_sent1;
|
||||
session->userauth_pblc_state = libssh2_NB_state_sent2;
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_sent2) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
|
||||
session->userauth_pblc_s -
|
||||
session->userauth_pblc_packet);
|
||||
@@ -1175,7 +1234,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_packet);
|
||||
session->userauth_pblc_packet = NULL;
|
||||
|
||||
session->userauth_pblc_state = libssh2_NB_state_sent2;
|
||||
session->userauth_pblc_state = libssh2_NB_state_sent3;
|
||||
}
|
||||
|
||||
/* PK_OK is no longer valid */
|
||||
@@ -1193,7 +1252,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Publickey authentication successful");
|
||||
/* We are us and we've proved it. */
|
||||
LIBSSH2_FREE(session, session->userauth_pblc_data);
|
||||
@@ -1214,6 +1273,44 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* userauth_publickey_fromfile
|
||||
* Authenticate using a keypair found in the named files
|
||||
*/
|
||||
static int
|
||||
userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||
const char *username,
|
||||
unsigned int username_len,
|
||||
const char *publickey,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *pubkeydata = NULL;
|
||||
unsigned long pubkeydata_len = 0;
|
||||
struct privkey_file privkey_file;
|
||||
void *abstract = &privkey_file;
|
||||
int rc;
|
||||
|
||||
privkey_file.filename = privatekey;
|
||||
privkey_file.passphrase = passphrase;
|
||||
|
||||
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
|
||||
if (file_read_publickey(session, &session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len, publickey)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = userauth_publickey(session, username, username_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
sign_fromfile, &abstract);
|
||||
if(pubkeydata)
|
||||
LIBSSH2_FREE(session, pubkeydata);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* libssh2_userauth_publickey_fromfile_ex
|
||||
* Authenticate using a keypair found in the named files
|
||||
*/
|
||||
@@ -1233,6 +1330,25 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* libssh2_userauth_publickey_ex
|
||||
* Authenticate using an external callback function
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
const char *user,
|
||||
const unsigned char *pubkeydata,
|
||||
size_t pubkeydata_len,
|
||||
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
|
||||
void **abstract)
|
||||
{
|
||||
int rc;
|
||||
BLOCK_ADJUST(rc, session,
|
||||
userauth_publickey(session, user, strlen(user),
|
||||
pubkeydata, pubkeydata_len,
|
||||
sign_callback, abstract));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -1249,7 +1365,8 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
unsigned char *s;
|
||||
int rc;
|
||||
|
||||
static const unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS,
|
||||
static const unsigned char reply_codes[4] = {
|
||||
SSH_MSG_USERAUTH_SUCCESS,
|
||||
SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_INFO_REQUEST, 0
|
||||
};
|
||||
unsigned int language_tag_len;
|
||||
@@ -1316,7 +1433,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
_libssh2_htonu32(s, 0);
|
||||
s += 4;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Attempting keyboard-interactive authentication");
|
||||
|
||||
session->userauth_kybd_state = libssh2_NB_state_created;
|
||||
@@ -1324,7 +1441,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
|
||||
if (session->userauth_kybd_state == libssh2_NB_state_created) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
|
||||
session->userauth_kybd_packet_len);
|
||||
session->userauth_kybd_packet_len);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
@@ -1357,7 +1474,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
}
|
||||
|
||||
if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Keyboard-interactive authentication successful");
|
||||
LIBSSH2_FREE(session, session->userauth_kybd_data);
|
||||
session->userauth_kybd_data = NULL;
|
||||
@@ -1367,9 +1484,15 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
}
|
||||
|
||||
if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Keyboard-interactive authentication failed");
|
||||
LIBSSH2_FREE(session, session->userauth_kybd_data);
|
||||
session->userauth_kybd_data = NULL;
|
||||
session->userauth_kybd_state = libssh2_NB_state_idle;
|
||||
libssh2_error(session,
|
||||
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
|
||||
"Authentication failed (keyboard-interactive)",
|
||||
0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1482,7 +1605,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
session->userauth_kybd_responses,
|
||||
&session->abstract);
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||
"Keyboard-interactive response callback function"
|
||||
" invoked");
|
||||
|
||||
@@ -1525,7 +1648,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||
|
||||
if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
|
||||
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
|
||||
session->userauth_kybd_packet_len);
|
||||
session->userauth_kybd_packet_len);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return rc;
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Self test, based on examples/simple/ssh2.c. */
|
||||
/* Self test, based on examples/ssh2.c. */
|
||||
|
||||
#include "libssh2_config.h"
|
||||
#include <libssh2.h>
|
||||
@@ -59,7 +59,7 @@ int main(int argc, char *argv[])
|
||||
if (getenv ("PRIVKEY"))
|
||||
privkeyfile = getenv ("PRIVKEY");
|
||||
|
||||
if (getenv ("PRIVKEY"))
|
||||
if (getenv ("PUBKEY"))
|
||||
pubkeyfile = getenv ("PUBKEY");
|
||||
|
||||
hostaddr = htonl(0x7F000001);
|
||||
@@ -90,9 +90,9 @@ int main(int argc, char *argv[])
|
||||
* The first thing to do is check the hostkey's fingerprint against our known hosts
|
||||
* Your app may have it hard coded, may go to a file, may present it to the user, that's your call
|
||||
*/
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
printf("Fingerprint: ");
|
||||
for(i = 0; i < 16; i++) {
|
||||
for(i = 0; i < 20; i++) {
|
||||
printf("%02X ", (unsigned char)fingerprint[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
@@ -9,21 +9,26 @@ srcdir=${srcdir:-$PWD}
|
||||
SSHD=${SSHD:-/usr/sbin/sshd}
|
||||
|
||||
cmd="./ssh2${EXEEXT}"
|
||||
srcdir=`cd $srcdir; pwd`
|
||||
srcdir=`cd "$srcdir"; pwd`
|
||||
|
||||
PRIVKEY=$srcdir/etc/user
|
||||
export PRIVKEY
|
||||
PUBKEY=$srcdir/etc/user.pub
|
||||
export PUBKEY
|
||||
|
||||
chmod go-r $srcdir/etc/host*
|
||||
$SSHD -f /dev/null -h $srcdir/etc/host \
|
||||
if test -n "$DEBUG"; then
|
||||
libssh2_sshd_params="-d -d"
|
||||
fi
|
||||
|
||||
chmod go-rwx "$srcdir"/etc/host*
|
||||
$SSHD -f /dev/null -h "$srcdir"/etc/host \
|
||||
-o 'Port 4711' \
|
||||
-o 'Protocol 2' \
|
||||
-o "AuthorizedKeysFile $srcdir/etc/user.pub" \
|
||||
-o 'UsePrivilegeSeparation no' \
|
||||
-o 'StrictModes no' \
|
||||
-D &
|
||||
-D \
|
||||
$libssh2_sshd_params &
|
||||
sshdpid=$!
|
||||
|
||||
trap "kill ${sshdpid}; echo signal killing sshd; exit 1;" EXIT
|
||||
|
@@ -1,3 +1,3 @@
|
||||
# End Target
|
||||
# End Project
|
||||
|
||||
# End Target
|
||||
# End Project
|
||||
|
||||
|
@@ -1,145 +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"
|
||||
|
||||
# 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"
|
||||
|
||||
|
@@ -125,7 +125,7 @@ else
|
||||
DS = \\
|
||||
endif
|
||||
|
||||
vpath %.c ../../example/simple
|
||||
vpath %.c ../../example
|
||||
|
||||
.PRECIOUS: $(OBJDIR)/%.o $(OBJDIR)/%.rc $(OBJDIR)/%.res
|
||||
|
||||
|
Reference in New Issue
Block a user