Compare commits
32 Commits
libssh2-1.
...
libssh2-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c8cc30c996 | ||
![]() |
acd9bd6104 | ||
![]() |
2ea40e63e8 | ||
![]() |
f4f2298ef3 | ||
![]() |
cc4f9d5679 | ||
![]() |
fed0759720 | ||
![]() |
a46ef85a56 | ||
![]() |
626f91da07 | ||
![]() |
bf097e37b0 | ||
![]() |
a1c996cef1 | ||
![]() |
8fc16beda9 | ||
![]() |
9a42fac055 | ||
![]() |
7194a9bd7b | ||
![]() |
7e53949e66 | ||
![]() |
5672e8f4cf | ||
![]() |
4449905ea5 | ||
![]() |
8e0cddd01f | ||
![]() |
796a5195d3 | ||
![]() |
15aadb930d | ||
![]() |
f28264c6a3 | ||
![]() |
179d2197dd | ||
![]() |
aa8f2cbf33 | ||
![]() |
e07342443f | ||
![]() |
4774d500e7 | ||
![]() |
1403847429 | ||
![]() |
0d824e5702 | ||
![]() |
9836b0889f | ||
![]() |
e394987911 | ||
![]() |
e95c7de453 | ||
![]() |
effbb72192 | ||
![]() |
0ebe6f44bd | ||
![]() |
b3ade9a63e |
@@ -1,30 +1,28 @@
|
||||
libssh2 1.4.0
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o Added libssh2_session_supported_algs()
|
||||
o Added libssh2_session_banner_get()
|
||||
o Added libssh2_sftp_get_channel()
|
||||
o libssh2.h: bump the default window size to 256K
|
||||
libssh2 1.4.1
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o sftp-seek: clear EOF flag
|
||||
o userauth: Provide more informations if ssh pub key extraction fails
|
||||
o ssh2_exec: skip error outputs for EAGAIN
|
||||
o LIBSSH2_SFTP_PACKET_MAXLEN: increase to 80000
|
||||
o knownhost_check(): Don't dereference ext if NULL is passed
|
||||
o knownhost_add: Avoid dereferencing uninitialized memory on error path
|
||||
o OpenSSL EVP: fix threaded use of structs
|
||||
o _libssh2_channel_read: react on errors from receive_window_adjust
|
||||
o sftp_read: cap the read ahead maximum amount
|
||||
o _libssh2_channel_read: fix non-blocking window adjusting
|
||||
o build error with gcrypt backend
|
||||
o always do "forced" window updates to avoid corner case stalls
|
||||
o aes: the init function fails when OpenSSL has AES support
|
||||
o transport_send: Finish in-progress key exchange before sending data
|
||||
o channel_write: acknowledge transport errors
|
||||
o examples/x11.c: Make sure sizeof passed to read operation is correct
|
||||
o examples/x11.c:,Fix suspicious sizeof usage
|
||||
o sftp_packet_add: verify the packet before accepting it
|
||||
o SFTP: preserve the original error code more
|
||||
o sftp_packet_read: adjust window size as necessary
|
||||
o Use safer snprintf rather then sprintf in several places
|
||||
o Define and use LIBSSH2_INVALID_SOCKET instead of INVALID_SOCKET
|
||||
o sftp_write: cannot return acked data *and* EAGAIN
|
||||
o sftp_read: avoid data *and* EAGAIN
|
||||
o libssh2.h: Add missing prototype for libssh2_session_banner_set()
|
||||
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Gellule Xg, Jernej Kovacic, Peter Krempa, Vincent Torri, Kamil Dudka,
|
||||
Peter Stuge, Guenter Knauf, John Engstrom, Alexander Lamaison,
|
||||
Mikhail Gusarov
|
||||
Armen Babakhanian, Paul Howarth, Matthew Booth, Steven Dake, Peter Stuge,
|
||||
Matt Lawson, Tom Weber, Alexander Lamaison
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
||||
|
@@ -220,7 +220,8 @@ AC_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibi
|
||||
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])
|
||||
AC_CHECK_HEADERS([sys/un.h], [have_sys_un_h=yes], [have_sys_un_h=no])
|
||||
AM_CONDITIONAL([HAVE_SYS_UN_H], test "x$have_sys_un_h" = xyes)
|
||||
|
||||
case $host in
|
||||
*-*-cygwin* | *-*-cegcc*)
|
||||
|
1
example/.gitignore
vendored
1
example/.gitignore
vendored
@@ -33,4 +33,5 @@ test-sftp_nonblock
|
||||
test-sftp_write
|
||||
test-sftp_write_nonblock
|
||||
test-ssh2_echo
|
||||
tcpip-forward
|
||||
x11
|
||||
|
@@ -7,7 +7,11 @@ 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 sftp_write_sliding \
|
||||
sftpdir sftpdir_nonblock ssh2_exec ssh2_agent ssh2_echo sftp_append \
|
||||
subsystem_netconf x11
|
||||
subsystem_netconf tcpip-forward
|
||||
|
||||
if HAVE_SYS_UN_H
|
||||
noinst_PROGRAMS += x11
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/example
|
||||
LDADD = $(top_builddir)/src/libssh2.la
|
||||
|
@@ -61,7 +61,8 @@ static int netconf_write(LIBSSH2_CHANNEL *channel, const char *buf, size_t len)
|
||||
static int netconf_read_until(LIBSSH2_CHANNEL *channel, const char *endtag,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
ssize_t len, rd = 0;
|
||||
ssize_t len;
|
||||
size_t rd = 0;
|
||||
char *endreply = NULL, *specialsequence = NULL;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
@@ -71,7 +72,7 @@ static int netconf_read_until(LIBSSH2_CHANNEL *channel, const char *endtag,
|
||||
if (LIBSSH2_ERROR_EAGAIN == len)
|
||||
continue;
|
||||
else if (len < 0) {
|
||||
fprintf(stderr, "libssh2_channel_read: %d", (int)len);
|
||||
fprintf(stderr, "libssh2_channel_read: %d\n", (int)len);
|
||||
return -1;
|
||||
}
|
||||
rd += len;
|
||||
@@ -85,7 +86,12 @@ static int netconf_read_until(LIBSSH2_CHANNEL *channel, const char *endtag,
|
||||
if (endreply)
|
||||
specialsequence = strstr(endreply, "]]>]]>");
|
||||
|
||||
} while (!endreply || !specialsequence);
|
||||
} while (!specialsequence && rd < buflen);
|
||||
|
||||
if (!specialsequence) {
|
||||
fprintf(stderr, "%s: ]]>]]> not found! read buffer too small?\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* discard the special sequence so that only XML is returned */
|
||||
rd = specialsequence - buf;
|
||||
|
292
example/tcpip-forward.c
Normal file
292
example/tcpip-forward.c
Normal file
@@ -0,0 +1,292 @@
|
||||
#include "libssh2_config.h"
|
||||
#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>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#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 *remote_listenhost = "localhost"; /* resolved by the server */
|
||||
unsigned int remote_wantport = 2222;
|
||||
unsigned int remote_listenport;
|
||||
|
||||
const char *local_destip = "127.0.0.1";
|
||||
unsigned int local_destport = 22;
|
||||
|
||||
enum {
|
||||
AUTH_NONE = 0,
|
||||
AUTH_PASSWORD,
|
||||
AUTH_PUBLICKEY
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc, sock = -1, forwardsock = -1, i, auth = AUTH_NONE;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sinlen = sizeof(sin);
|
||||
const char *fingerprint;
|
||||
char *userauthlist;
|
||||
LIBSSH2_SESSION *session;
|
||||
LIBSSH2_LISTENER *listener = NULL;
|
||||
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)
|
||||
remote_listenhost = argv[4];
|
||||
if (argc > 5)
|
||||
remote_wantport = atoi(argv[5]);
|
||||
if (argc > 6)
|
||||
local_destip = argv[6];
|
||||
if (argc > 7)
|
||||
local_destport = atoi(argv[7]);
|
||||
|
||||
rc = libssh2_init (0);
|
||||
if (rc != 0) {
|
||||
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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_handshake(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;
|
||||
}
|
||||
|
||||
printf("Asking server to listen on remote %s:%d\n", remote_listenhost,
|
||||
remote_wantport);
|
||||
|
||||
listener = libssh2_channel_forward_listen_ex(session, remote_listenhost,
|
||||
remote_wantport, &remote_listenport, 1);
|
||||
if (!listener) {
|
||||
fprintf(stderr, "Could not start the tcpip-forward listener!\n"
|
||||
"(Note that this can be a problem at the server!"
|
||||
" Please review the server logs.)\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
printf("Server is listening on %s:%d\n", remote_listenhost,
|
||||
remote_listenport);
|
||||
|
||||
printf("Waiting for remote connection\n");
|
||||
channel = libssh2_channel_forward_accept(listener);
|
||||
if (!channel) {
|
||||
fprintf(stderr, "Could not accept connection!\n"
|
||||
"(Note that this can be a problem at the server!"
|
||||
" Please review the server logs.)\n");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
printf("Accepted remote connection. Connecting to local server %s:%d\n",
|
||||
local_destip, local_destport);
|
||||
forwardsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(local_destport);
|
||||
if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(local_destip))) {
|
||||
perror("inet_addr");
|
||||
goto shutdown;
|
||||
}
|
||||
if (-1 == connect(forwardsock, (struct sockaddr *)&sin, sinlen)) {
|
||||
perror("connect");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
printf("Forwarding connection from remote %s:%d to local %s:%d\n",
|
||||
remote_listenhost, remote_listenport, local_destip, local_destport);
|
||||
|
||||
/* 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 local server at %s:%d disconnected!\n",
|
||||
local_destip, local_destport);
|
||||
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 remote client at %s:%d disconnected!\n",
|
||||
remote_listenhost, remote_listenport);
|
||||
goto shutdown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shutdown:
|
||||
#ifdef WIN32
|
||||
closesocket(forwardsock);
|
||||
#else
|
||||
close(forwardsock);
|
||||
#endif
|
||||
if (channel)
|
||||
libssh2_channel_free(channel);
|
||||
if (listener)
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
libssh2_session_disconnect(session, "Client disconnecting normally");
|
||||
libssh2_session_free(session);
|
||||
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
|
||||
libssh2_exit();
|
||||
|
||||
return 0;
|
||||
}
|
@@ -79,7 +79,12 @@ static int _raw_mode(void)
|
||||
rc = tcgetattr(fileno(stdin), &tio);
|
||||
if (rc != -1) {
|
||||
_saved_tio = tio;
|
||||
cfmakeraw(&tio);
|
||||
/* do the equivalent of cfmakeraw() manually, to build on Solaris */
|
||||
tio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
||||
tio.c_oflag &= ~OPOST;
|
||||
tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
tio.c_cflag &= ~(CSIZE|PARENB);
|
||||
tio.c_cflag |= CS8;
|
||||
rc = tcsetattr(fileno(stdin), TCSADRAIN, &tio);
|
||||
}
|
||||
return rc;
|
||||
@@ -203,7 +208,7 @@ static int x11_send_receive(LIBSSH2_CHANNEL *channel, int sock)
|
||||
|
||||
rc = libssh2_poll(fds, nfds, 0);
|
||||
if (rc >0) {
|
||||
rc = libssh2_channel_read(channel, buf,sizeof(buf));
|
||||
rc = libssh2_channel_read(channel, buf, bufsize);
|
||||
rc = write(sock, buf, rc);
|
||||
}
|
||||
|
||||
@@ -212,7 +217,7 @@ static int x11_send_receive(LIBSSH2_CHANNEL *channel, int sock)
|
||||
memset((void *)buf,0,bufsize);
|
||||
|
||||
/* Data in sock*/
|
||||
rc = read(sock, buf,sizeof(buf));
|
||||
rc = read(sock, buf, bufsize);
|
||||
if (rc > 0)
|
||||
rc = libssh2_channel_write(channel,buf, rc);
|
||||
else
|
||||
|
@@ -135,9 +135,10 @@ typedef long long libssh2_int64_t;
|
||||
|
||||
#ifdef WIN32
|
||||
typedef SOCKET libssh2_socket_t;
|
||||
#define LIBSSH2_INVALID_SOCKET INVALID_SOCKET
|
||||
#else /* !WIN32 */
|
||||
typedef int libssh2_socket_t;
|
||||
#define INVALID_SOCKET -1
|
||||
#define LIBSSH2_INVALID_SOCKET -1
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* Part of every banner, user specified or not */
|
||||
@@ -466,6 +467,8 @@ LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session);
|
||||
|
||||
LIBSSH2_API void *libssh2_session_callback_set(LIBSSH2_SESSION *session,
|
||||
int cbtype, void *callback);
|
||||
LIBSSH2_API int libssh2_session_banner_set(LIBSSH2_SESSION *session,
|
||||
const char *banner);
|
||||
LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session,
|
||||
const char *banner);
|
||||
|
||||
|
@@ -566,7 +566,7 @@ $(DEVLDIR)/readme.txt: Makefile.netware
|
||||
@echo Creating $@
|
||||
@echo $(DL)This is a development distribution for NetWare platform.$(DL) > $@
|
||||
@echo $(DL)libssh2 version $(LIBSSH2_VERSION_STR)$(DL) >> $@
|
||||
@echo $(DL)Please download the complete libssh package for$(DL) >> $@
|
||||
@echo $(DL)Please download the complete libssh2 package for$(DL) >> $@
|
||||
@echo $(DL)any further documentation:$(DL) >> $@
|
||||
@echo $(DL)$(WWWURL)$(DL) >> $@
|
||||
|
||||
|
@@ -338,7 +338,7 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||
static int
|
||||
agent_disconnect_pageant(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
agent->fd = INVALID_SOCKET;
|
||||
agent->fd = LIBSSH2_INVALID_SOCKET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -771,7 +771,7 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent,
|
||||
LIBSSH2_API int
|
||||
libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
|
||||
{
|
||||
if (agent->ops && agent->fd != INVALID_SOCKET)
|
||||
if (agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET)
|
||||
return agent->ops->disconnect(agent);
|
||||
return 0;
|
||||
}
|
||||
@@ -785,7 +785,7 @@ libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
|
||||
LIBSSH2_API void
|
||||
libssh2_agent_free(LIBSSH2_AGENT *agent) {
|
||||
/* Allow connection freeing when the socket has lost its connection */
|
||||
if (agent->fd != INVALID_SOCKET) {
|
||||
if (agent->fd != LIBSSH2_INVALID_SOCKET) {
|
||||
libssh2_agent_disconnect(agent);
|
||||
}
|
||||
agent_free_identities(agent);
|
||||
|
@@ -1418,7 +1418,7 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
|
||||
|
||||
rc = _libssh2_channel_receive_window_adjust(channel,
|
||||
channel->flush_refund_bytes,
|
||||
0, NULL);
|
||||
1, NULL);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN)
|
||||
return rc;
|
||||
}
|
||||
@@ -1898,7 +1898,7 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
|
||||
if(buflen > recv_window) {
|
||||
BLOCK_ADJUST(rc, channel->session,
|
||||
_libssh2_channel_receive_window_adjust(channel, buflen,
|
||||
0, NULL));
|
||||
1, NULL));
|
||||
}
|
||||
|
||||
BLOCK_ADJUST(rc, channel->session,
|
||||
@@ -2008,6 +2008,9 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
rc = _libssh2_transport_read(session);
|
||||
while (rc > 0);
|
||||
|
||||
if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
|
||||
return rc;
|
||||
|
||||
if(channel->local.window_size <= 0)
|
||||
/* there's no room for data so we stop */
|
||||
return (rc==LIBSSH2_ERROR_EAGAIN?rc:0);
|
||||
|
@@ -74,5 +74,5 @@ void
|
||||
_libssh2_init_if_needed(void)
|
||||
{
|
||||
if (_libssh2_initialized == 0)
|
||||
libssh2_init (0);
|
||||
(void)libssh2_init (0);
|
||||
}
|
||||
|
@@ -997,10 +997,10 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
|
||||
if(nlen <= buflen)
|
||||
if(node->comment)
|
||||
sprintf(buf, "|1|%s|%s%s %s %s\n", saltalloc, namealloc,
|
||||
snprintf(buf, buflen, "|1|%s|%s%s %s %s\n", saltalloc, namealloc,
|
||||
keytype, node->key, node->comment);
|
||||
else
|
||||
sprintf(buf, "|1|%s|%s%s %s\n", saltalloc, namealloc,
|
||||
snprintf(buf, buflen, "|1|%s|%s%s %s\n", saltalloc, namealloc,
|
||||
keytype, node->key);
|
||||
else
|
||||
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||
@@ -1016,10 +1016,10 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
if(nlen <= buflen)
|
||||
/* these types have the plain name */
|
||||
if(node->comment)
|
||||
sprintf(buf, "%s%s %s %s\n", node->name, keytype, node->key,
|
||||
snprintf(buf, buflen, "%s%s %s %s\n", node->name, keytype, node->key,
|
||||
node->comment);
|
||||
else
|
||||
sprintf(buf, "%s%s %s\n", node->name, keytype, node->key);
|
||||
snprintf(buf, buflen, "%s%s %s\n", node->name, keytype, node->key);
|
||||
else
|
||||
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||
"Known-host write buffer too small");
|
||||
|
@@ -581,7 +581,7 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
{
|
||||
return _libssh_error(session, LIBSSH2_ERROR_FILE,
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key file: "
|
||||
"Method unimplemented in libgcrypt backend");
|
||||
}
|
||||
|
@@ -201,7 +201,7 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
return ret == 1 ? 0 : 1;
|
||||
}
|
||||
|
||||
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
|
||||
#if LIBSSH2_AES_CTR
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/evp.h>
|
||||
@@ -217,6 +217,10 @@ static int
|
||||
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc) /* init key */
|
||||
{
|
||||
/*
|
||||
* variable "c" is leaked from this scope, but is later freed
|
||||
* in aes_ctr_cleanup
|
||||
*/
|
||||
aes_ctr_ctx *c = malloc(sizeof(*c));
|
||||
const EVP_CIPHER *aes_cipher;
|
||||
(void) enc;
|
||||
@@ -358,6 +362,8 @@ void _libssh2_init_aes_ctr(void)
|
||||
_libssh2_EVP_aes_256_ctr();
|
||||
}
|
||||
|
||||
#else
|
||||
void _libssh2_init_aes_ctr(void) {}
|
||||
#endif /* LIBSSH2_AES_CTR */
|
||||
|
||||
/* TODO: Optionally call a passphrase callback specified by the
|
||||
|
@@ -148,15 +148,9 @@ void libssh2_md5(const unsigned char *message, unsigned long len, unsigned char
|
||||
#define _libssh2_cipher_aes256 EVP_aes_256_cbc
|
||||
#define _libssh2_cipher_aes192 EVP_aes_192_cbc
|
||||
#define _libssh2_cipher_aes128 EVP_aes_128_cbc
|
||||
#ifdef HAVE_EVP_AES_128_CTR
|
||||
#define _libssh2_cipher_aes128ctr EVP_aes_128_ctr
|
||||
#define _libssh2_cipher_aes192ctr EVP_aes_192_ctr
|
||||
#define _libssh2_cipher_aes256ctr EVP_aes_256_ctr
|
||||
#else
|
||||
#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
|
||||
#endif
|
||||
#define _libssh2_cipher_blowfish EVP_bf_cbc
|
||||
#define _libssh2_cipher_arcfour EVP_rc4
|
||||
#define _libssh2_cipher_cast5 EVP_cast5_cbc
|
||||
|
@@ -661,7 +661,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
rc = _libssh2_channel_receive_window_adjust(session->
|
||||
packAdd_channelp,
|
||||
datalen - 13,
|
||||
0, NULL);
|
||||
1, NULL);
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN)
|
||||
return rc;
|
||||
|
||||
|
@@ -294,8 +294,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sprintf() is fine here since we allocated a large enough buffer */
|
||||
sprintf((char *)session->scpRecv_command, "scp -%sf ", sb?"p":"");
|
||||
snprintf((char *)session->scpRecv_command,
|
||||
session->scpRecv_command_len, "scp -%sf ", sb?"p":"");
|
||||
|
||||
cmd_len = strlen((char *)session->scpRecv_command);
|
||||
|
||||
@@ -796,8 +796,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf((char *)session->scpSend_command, "scp -%st ",
|
||||
(mtime || atime)?"p":"");
|
||||
snprintf((char *)session->scpSend_command, session->scpSend_command_len,
|
||||
"scp -%st ", (mtime || atime)?"p":"");
|
||||
|
||||
cmd_len = strlen((char *)session->scpSend_command);
|
||||
|
||||
|
@@ -675,7 +675,7 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
||||
if (session->startup_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"session_startup for socket %d", sock);
|
||||
if (INVALID_SOCKET == sock) {
|
||||
if (LIBSSH2_INVALID_SOCKET == sock) {
|
||||
/* Did we forget something? */
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET,
|
||||
"Bad socket provided");
|
||||
@@ -828,6 +828,7 @@ session_free(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_PACKET *pkg;
|
||||
LIBSSH2_CHANNEL *ch;
|
||||
LIBSSH2_LISTENER *l;
|
||||
int packets_left = 0;
|
||||
|
||||
if (session->free_state == libssh2_NB_state_idle) {
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource",
|
||||
@@ -1018,6 +1019,9 @@ session_free(LIBSSH2_SESSION *session)
|
||||
|
||||
/* Cleanup all remaining packets */
|
||||
while ((pkg = _libssh2_list_first(&session->packets))) {
|
||||
packets_left++;
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"packet left with id %d", pkg->data[0]);
|
||||
/* unlink the node */
|
||||
_libssh2_list_remove(&pkg->node);
|
||||
|
||||
@@ -1025,6 +1029,8 @@ session_free(LIBSSH2_SESSION *session)
|
||||
LIBSSH2_FREE(session, pkg->data);
|
||||
LIBSSH2_FREE(session, pkg);
|
||||
}
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||
"Extra packets left %d", packets_left);
|
||||
|
||||
if(session->socket_prev_blockstate)
|
||||
/* if the socket was previously blocking, put it back so */
|
||||
|
1059
src/sftp.c
1059
src/sftp.c
File diff suppressed because it is too large
Load Diff
10
src/sftp.h
10
src/sftp.h
@@ -1,7 +1,7 @@
|
||||
#ifndef _LIBSSH2_SFTP_H
|
||||
#define _LIBSSH2_SFTP_H
|
||||
/*
|
||||
* Copyright (C) 2010, 2011 by Daniel Stenberg
|
||||
* Copyright (C) 2010 - 2012 by Daniel Stenberg
|
||||
* Author: Daniel Stenberg <daniel@haxx.se>
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@@ -158,9 +158,15 @@ struct _LIBSSH2_SFTP
|
||||
size_t open_packet_sent;
|
||||
uint32_t open_request_id;
|
||||
|
||||
/* State variables used in libssh2_sftp_read() */
|
||||
/* State variable used in sftp_read() */
|
||||
libssh2_nonblocking_states read_state;
|
||||
|
||||
/* State variable used in sftp_packet_read() */
|
||||
libssh2_nonblocking_states packet_state;
|
||||
|
||||
/* State variable used in sftp_write() */
|
||||
libssh2_nonblocking_states write_state;
|
||||
|
||||
/* State variables used in libssh2_sftp_readdir() */
|
||||
libssh2_nonblocking_states readdir_state;
|
||||
unsigned char *readdir_packet;
|
||||
|
@@ -296,7 +296,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||
* is done!
|
||||
*/
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
|
||||
" key re-exchange");
|
||||
" key re-exchange from _libssh2_transport_read");
|
||||
rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -687,6 +687,24 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
|
||||
const unsigned char *orgdata = data;
|
||||
size_t orgdata_len = data_len;
|
||||
|
||||
/*
|
||||
* If the last read operation was interrupted in the middle of a key
|
||||
* exchange, we must complete that key exchange before continuing to write
|
||||
* further data.
|
||||
*
|
||||
* See the similar block in _libssh2_transport_read for more details.
|
||||
*/
|
||||
if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
|
||||
!(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
|
||||
/* Don't write any new packets if we're still in the middle of a key
|
||||
* exchange. */
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
|
||||
" key re-exchange from _libssh2_transport_send");
|
||||
rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
debugdump(session, "libssh2_transport_write plain", data, data_len);
|
||||
if(data2)
|
||||
debugdump(session, "libssh2_transport_write plain2", data2, data2_len);
|
||||
|
Reference in New Issue
Block a user