Compare commits
9 Commits
RELEASE.0.
...
RELEASE.0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ace0c8f00b | ||
![]() |
adee5e5653 | ||
![]() |
5f85317efa | ||
![]() |
09b93e4bb6 | ||
![]() |
19cad102f4 | ||
![]() |
4d7726c551 | ||
![]() |
37307a8778 | ||
![]() |
fbcdff2161 | ||
![]() |
c45992da55 |
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -7,7 +7,7 @@ incldir = @prefix@/include
|
|||||||
distdir = @top_srcdir@/dist
|
distdir = @top_srcdir@/dist
|
||||||
|
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
CFLAGS = -c @CFLAGS@ -Iinclude/ -Wall -g
|
CFLAGS = -c @CFLAGS@ -Iinclude/ -Wall
|
||||||
LIBS = -lssh2 -Lsrc/
|
LIBS = -lssh2 -Lsrc/
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
VERSION=@PACKAGE_VERSION@
|
VERSION=@PACKAGE_VERSION@
|
||||||
|
15
README
15
README
@@ -1,6 +1,21 @@
|
|||||||
libssh2 - SSH2 library
|
libssh2 - SSH2 library
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
Version 0.14
|
||||||
|
------------
|
||||||
|
|
||||||
|
Plug leaks in EVP cipher init/shutdown. (Selcuk Gueney)
|
||||||
|
|
||||||
|
Allow socket_fd == 0 in libssh2_session_startup(). (puudeli)
|
||||||
|
|
||||||
|
Swap ordering of packet_add/packet-inspection to avoid inspect after free. (Selcuk)
|
||||||
|
|
||||||
|
Swap KEX_INIT ordering, send our KEX_INIT first.
|
||||||
|
|
||||||
|
Add check for oportunistic KEX_INIT packets. Burn bad guess if necessary.
|
||||||
|
|
||||||
|
Fix OpenSSL detection using pkg-config. (Dan Casey)
|
||||||
|
|
||||||
Version 0.13
|
Version 0.13
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
40
configure.in
40
configure.in
@@ -1,5 +1,5 @@
|
|||||||
# AC_PREREQ(2.57)
|
# AC_PREREQ(2.57)
|
||||||
AC_INIT(libssh2,0.13,sarag@libssh2.org)
|
AC_INIT(libssh2,0.14,sarag@libssh2.org)
|
||||||
AC_CONFIG_SRCDIR([src])
|
AC_CONFIG_SRCDIR([src])
|
||||||
AC_CONFIG_HEADER([include/libssh2_config.h])
|
AC_CONFIG_HEADER([include/libssh2_config.h])
|
||||||
|
|
||||||
@@ -64,15 +64,18 @@ if test "$LIBSSH2_OPENSSL_DIR" = "no" || test "$LIBSSH2_OPENSSL_DIR" = "yes"; th
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
found_openssl=no
|
found_openssl=no
|
||||||
|
pkgcfg_openssl=no
|
||||||
unset OPENSSL_INCDIR
|
unset OPENSSL_INCDIR
|
||||||
unset OPENSSL_LIBDIR
|
unset OPENSSL_INCLINE
|
||||||
|
unset OPENSSL_LIBLINE
|
||||||
|
|
||||||
AC_MSG_CHECKING([for OpenSSL])
|
AC_MSG_CHECKING([for OpenSSL])
|
||||||
|
|
||||||
# Explicit path given, use it rather than pkg-config
|
# Explicit path given, use it rather than pkg-config
|
||||||
if test ! -z "$LIBSSH2_OPENSSL_DIR"; then
|
if test ! -z "$LIBSSH2_OPENSSL_DIR"; then
|
||||||
found_openssl=yes
|
found_openssl=yes
|
||||||
OPENSSL_LIBDIR=$LIBSSH2_OPENSSL_DIR/lib
|
OPENSSL_LIBLINE="-L$LIBSSH2_OPENSSL_DIR/lib -lcrypto"
|
||||||
|
OPENSSL_INCLINE="-I$LIBSSH2_OPENSSL_DIR/include"
|
||||||
OPENSSL_INCDIR=$LIBSSH2_OPENSSL_DIR/include
|
OPENSSL_INCDIR=$LIBSSH2_OPENSSL_DIR/include
|
||||||
AC_MSG_RESULT([Using explicit path $LIBSSH2_OPENSSL_DIR])
|
AC_MSG_RESULT([Using explicit path $LIBSSH2_OPENSSL_DIR])
|
||||||
fi
|
fi
|
||||||
@@ -80,8 +83,9 @@ fi
|
|||||||
# If pkg-config is found try using it
|
# If pkg-config is found try using it
|
||||||
if test "$found_openssl" = "no" && test -x "$PKG_CONFIG" && $PKG_CONFIG --exists openssl; then
|
if test "$found_openssl" = "no" && test -x "$PKG_CONFIG" && $PKG_CONFIG --exists openssl; then
|
||||||
found_openssl=yes
|
found_openssl=yes
|
||||||
OPENSSL_LIBDIR=`$PKG_CONFIG --libs openssl`
|
pkgcfg_openssl=yes
|
||||||
OPENSSL_INCDIR=`$PKG_CONFIG --variable=includedir openssl`
|
OPENSSL_LIBLINE=`$PKG_CONFIG --libs openssl`
|
||||||
|
OPENSSL_INCLINE=`$PKG_CONFIG --variable=includedir openssl`
|
||||||
AC_MSG_RESULT([Using paths from pkg-config])
|
AC_MSG_RESULT([Using paths from pkg-config])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -91,39 +95,43 @@ if test "$found_openssl" = "no"; then
|
|||||||
|
|
||||||
for i in $OPENSSL_SEARCH_PATH; do
|
for i in $OPENSSL_SEARCH_PATH; do
|
||||||
if test -r $i/include/openssl/evp.h; then
|
if test -r $i/include/openssl/evp.h; then
|
||||||
|
OPENSSL_INCLINE="-I$i/include"
|
||||||
OPENSSL_INCDIR=$i/include
|
OPENSSL_INCDIR=$i/include
|
||||||
fi
|
fi
|
||||||
if test -r $i/include/openssl/hmac.h; then
|
if test -r $i/include/openssl/hmac.h; then
|
||||||
|
OPENSSL_INCLINE="-I$i/include"
|
||||||
OPENSSL_INCDIR=$i/include
|
OPENSSL_INCDIR=$i/include
|
||||||
fi
|
fi
|
||||||
if test -r $i/lib/libcrypto.a -o -r $i/lib/libcrypto.$SHLIB_SUFFIX_NAME; then
|
if test -r $i/lib/libcrypto.a -o -r $i/lib/libcrypto.$SHLIB_SUFFIX_NAME; then
|
||||||
OPENSSL_LIBDIR=$i/lib
|
OPENSSL_LIBLINE="-L$i/lib -lcrypto"
|
||||||
fi
|
fi
|
||||||
test -n "$OPENSSL_INCDIR" && test -n "$OPENSSL_LIBDIR" && break
|
test -n "$OPENSSL_INCLINE" && test -n "$OPENSSL_LIBLINE" && break
|
||||||
done
|
done
|
||||||
|
|
||||||
if test -z "$OPENSSL_INCDIR"; then
|
if test -z "$OPENSSL_INCLINE"; then
|
||||||
AC_MSG_ERROR([Cannot find OpenSSL's <evp.h> or <hmac.h>])
|
AC_MSG_ERROR([Cannot find OpenSSL's <evp.h> or <hmac.h>])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -z "$OPENSSL_LIBDIR"; then
|
if test -z "$OPENSSL_LIBLINE"; then
|
||||||
AC_MSG_ERROR([Cannot find OpenSSL's libcrypto])
|
AC_MSG_ERROR([Cannot find OpenSSL's libcrypto])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_RESULT([$OPENSSL_INCDIR $OPENSSL_LIBDIR])
|
AC_MSG_RESULT([$OPENSSL_INCLINE $OPENSSL_LIBLINE])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Confirm required OpenSSL libs
|
# Confirm required OpenSSL libs
|
||||||
#
|
#
|
||||||
if test ! -r $OPENSSL_INCDIR/openssl/bn.h || test ! -r $OPENSSL_INCDIR/openssl/evp.h || \
|
if test ! "$pkgcfg_openssl" = "yes"; then
|
||||||
test ! -r $OPENSSL_INCDIR/openssl/hmac.h || test ! -r $OPENSSL_INCDIR/openssl/pem.h || \
|
if test ! -r $OPENSSL_INCDIR/openssl/bn.h || test ! -r $OPENSSL_INCDIR/openssl/evp.h || \
|
||||||
test ! -r $OPENSSL_INCDIR/openssl/sha.h; then
|
test ! -r $OPENSSL_INCDIR/openssl/hmac.h || test ! -r $OPENSSL_INCDIR/openssl/pem.h || \
|
||||||
AC_MSG_ERROR([Missing one or more of <openssl/bn.h>, <openssl/evp.h>, <openssl/hmac.h>, <openssl/pem.h>, <openssl/sha.h>])
|
test ! -r $OPENSSL_INCDIR/openssl/sha.h; then
|
||||||
|
AC_MSG_ERROR([Missing one or more of <openssl/bn.h>, <openssl/evp.h>, <openssl/hmac.h>, <openssl/pem.h>, <openssl/sha.h>])
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CFLAGS="$CFLAGS -I$OPENSSL_INCDIR"
|
CFLAGS="$CFLAGS $OPENSSL_INCLINE"
|
||||||
LDFLAGS="$LDFLAGS -L$OPENSSL_LIBDIR -lcrypto"
|
LDFLAGS="$LDFLAGS $OPENSSL_LIBLINE"
|
||||||
|
|
||||||
#
|
#
|
||||||
# zlib
|
# zlib
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -71,7 +71,7 @@ typedef unsigned long long libssh2_uint64_t;
|
|||||||
typedef long long libssh2_int64_t;
|
typedef long long libssh2_int64_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LIBSSH2_VERSION "0.13"
|
#define LIBSSH2_VERSION "0.14"
|
||||||
#define LIBSSH2_APINO 200507211326
|
#define LIBSSH2_APINO 200507211326
|
||||||
|
|
||||||
/* Part of every banner, user specified or not */
|
/* Part of every banner, user specified or not */
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -199,6 +199,7 @@ struct _LIBSSH2_SESSION {
|
|||||||
|
|
||||||
/* Agreed Key Exchange Method */
|
/* Agreed Key Exchange Method */
|
||||||
LIBSSH2_KEX_METHOD *kex;
|
LIBSSH2_KEX_METHOD *kex;
|
||||||
|
int burn_optimistic_kexinit:1;
|
||||||
|
|
||||||
unsigned char *session_id;
|
unsigned char *session_id;
|
||||||
unsigned long session_id_len;
|
unsigned long session_id_len;
|
||||||
@@ -462,6 +463,7 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
|
|||||||
int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len);
|
int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len);
|
||||||
#define libssh2_packet_requirev(session, packet_types, data, data_len) \
|
#define libssh2_packet_requirev(session, packet_types, data, data_len) \
|
||||||
libssh2_packet_requirev_ex((session), (packet_types), (data), (data_len), 0, NULL, 0)
|
libssh2_packet_requirev_ex((session), (packet_types), (data), (data_len), 0, NULL, 0)
|
||||||
|
int libssh2_packet_burn(LIBSSH2_SESSION *session);
|
||||||
int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len);
|
int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len);
|
||||||
int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange);
|
int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange);
|
||||||
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session);
|
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -8,7 +8,7 @@ incldir = @prefix@/include
|
|||||||
|
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
LDCC = @LDCC@
|
LDCC = @LDCC@
|
||||||
CFLAGS = -c @CFLAGS@ -Wall -g -I../include/ -fPIC
|
CFLAGS = -c @CFLAGS@ -Wall -I../include/ -fPIC
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
SHLIB_LDFLAGS = @SHLIB_LDFLAGS@
|
SHLIB_LDFLAGS = @SHLIB_LDFLAGS@
|
||||||
LIBS = @LIBS@
|
LIBS = @LIBS@
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
68
src/kex.c
68
src/kex.c
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -118,6 +118,26 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
|
|||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (session->burn_optimistic_kexinit) {
|
||||||
|
/* The first KEX packet to come along will be the guess initially sent by the server
|
||||||
|
* That guess turned out to be wrong so we need to silently ignore it */
|
||||||
|
int burn_type;
|
||||||
|
#ifdef LIBSSH2_DEBUG_KEX
|
||||||
|
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Waiting for badly guessed KEX packet (to be ignored)");
|
||||||
|
#endif
|
||||||
|
burn_type = libssh2_packet_burn(session);
|
||||||
|
if (burn_type <= 0) {
|
||||||
|
/* Failed to receive a packet */
|
||||||
|
ret = -1;
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
session->burn_optimistic_kexinit = 0;
|
||||||
|
|
||||||
|
#ifdef LIBSSH2_DEBUG_KEX
|
||||||
|
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Burnt packet of type: %02x", (unsigned int)burn_type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait for KEX reply */
|
/* Wait for KEX reply */
|
||||||
if (libssh2_packet_require(session, packet_type_reply, &s_packet, &s_packet_len)) {
|
if (libssh2_packet_require(session, packet_type_reply, &s_packet, &s_packet_len)) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Timed out waiting for KEX reply", 0);
|
libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Timed out waiting for KEX reply", 0);
|
||||||
@@ -314,6 +334,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
|
|||||||
/* Calculate IV/Secret/Key for each direction */
|
/* Calculate IV/Secret/Key for each direction */
|
||||||
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
||||||
if (session->local.crypt_abstract) {
|
if (session->local.crypt_abstract) {
|
||||||
|
EVP_CIPHER_CTX_cleanup(session->local.crypt_abstract);
|
||||||
LIBSSH2_FREE(session, session->local.crypt_abstract);
|
LIBSSH2_FREE(session, session->local.crypt_abstract);
|
||||||
session->local.crypt_abstract = NULL;
|
session->local.crypt_abstract = NULL;
|
||||||
}
|
}
|
||||||
@@ -342,6 +363,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
EVP_CIPHER_CTX_init(ctx);
|
||||||
EVP_CipherInit(ctx, cipher, secret, iv, 1);
|
EVP_CipherInit(ctx, cipher, secret, iv, 1);
|
||||||
session->local.crypt_abstract = ctx;
|
session->local.crypt_abstract = ctx;
|
||||||
free_iv = 1;
|
free_iv = 1;
|
||||||
@@ -366,6 +388,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
|
|||||||
|
|
||||||
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
||||||
if (session->remote.crypt_abstract) {
|
if (session->remote.crypt_abstract) {
|
||||||
|
EVP_CIPHER_CTX_cleanup(session->remote.crypt_abstract);
|
||||||
LIBSSH2_FREE(session, session->remote.crypt_abstract);
|
LIBSSH2_FREE(session, session->remote.crypt_abstract);
|
||||||
session->remote.crypt_abstract = NULL;
|
session->remote.crypt_abstract = NULL;
|
||||||
}
|
}
|
||||||
@@ -394,6 +417,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
EVP_CIPHER_CTX_init(ctx);
|
||||||
EVP_CipherInit(ctx, cipher, secret, iv, 0);
|
EVP_CipherInit(ctx, cipher, secret, iv, 0);
|
||||||
session->remote.crypt_abstract = ctx;
|
session->remote.crypt_abstract = ctx;
|
||||||
free_iv = 1;
|
free_iv = 1;
|
||||||
@@ -963,9 +987,9 @@ static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char
|
|||||||
s = session->kex_prefs;
|
s = session->kex_prefs;
|
||||||
|
|
||||||
while (s && *s) {
|
while (s && *s) {
|
||||||
unsigned char *p = strchr(s, ',');
|
unsigned char *q, *p = strchr(s, ',');
|
||||||
int method_len = (p ? (p - s) : strlen(s));
|
int method_len = (p ? (p - s) : strlen(s));
|
||||||
if (libssh2_kex_agree_instr(kex, kex_len, s, method_len)) {
|
if ((q = libssh2_kex_agree_instr(kex, kex_len, s, method_len))) {
|
||||||
LIBSSH2_KEX_METHOD *method = (LIBSSH2_KEX_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)kexp);
|
LIBSSH2_KEX_METHOD *method = (LIBSSH2_KEX_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)kexp);
|
||||||
|
|
||||||
if (!method) {
|
if (!method) {
|
||||||
@@ -978,6 +1002,12 @@ static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char
|
|||||||
*/
|
*/
|
||||||
if (libssh2_kex_agree_hostkey(session, method->flags, hostkey, hostkey_len) == 0) {
|
if (libssh2_kex_agree_hostkey(session, method->flags, hostkey, hostkey_len) == 0) {
|
||||||
session->kex = method;
|
session->kex = method;
|
||||||
|
if (session->burn_optimistic_kexinit && (kex == q)) {
|
||||||
|
/* Server sent an optimistic packet,
|
||||||
|
* and client agrees with preference
|
||||||
|
* cancel burning the first KEX_INIT packet that comes in */
|
||||||
|
session->burn_optimistic_kexinit = 0;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -995,6 +1025,12 @@ static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char
|
|||||||
*/
|
*/
|
||||||
if (libssh2_kex_agree_hostkey(session, (*kexp)->flags, hostkey, hostkey_len) == 0) {
|
if (libssh2_kex_agree_hostkey(session, (*kexp)->flags, hostkey, hostkey_len) == 0) {
|
||||||
session->kex = *kexp;
|
session->kex = *kexp;
|
||||||
|
if (session->burn_optimistic_kexinit && (kex == s)) {
|
||||||
|
/* Server sent an optimistic packet,
|
||||||
|
* and client agrees with preference
|
||||||
|
* cancel burning the first KEX_INIT packet that comes in */
|
||||||
|
session->burn_optimistic_kexinit = 0;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1170,6 +1206,12 @@ static int libssh2_kex_agree_methods(LIBSSH2_SESSION *session, unsigned char *da
|
|||||||
lang_cs_len = libssh2_ntohu32(s); lang_cs = s + 4; s += 4 + lang_cs_len;
|
lang_cs_len = libssh2_ntohu32(s); lang_cs = s + 4; s += 4 + lang_cs_len;
|
||||||
lang_sc_len = libssh2_ntohu32(s); lang_sc = s + 4; s += 4 + lang_sc_len;
|
lang_sc_len = libssh2_ntohu32(s); lang_sc = s + 4; s += 4 + lang_sc_len;
|
||||||
|
|
||||||
|
/* If the server sent an optimistic packet, assume that it guessed wrong.
|
||||||
|
* If the guess is determined to be right (by libssh2_kex_agree_kex_hostkey)
|
||||||
|
* This flag will be reset to zero so that it's not ignored */
|
||||||
|
session->burn_optimistic_kexinit = *(s++);
|
||||||
|
/* Next uint32 in packet is all zeros (reserved) */
|
||||||
|
|
||||||
if (libssh2_kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
|
if (libssh2_kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1244,7 +1286,23 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!session->kex || !session->hostkey) {
|
if (!session->kex || !session->hostkey) {
|
||||||
|
/* Preserve in case of failure */
|
||||||
|
unsigned char *oldlocal = session->local.kexinit;
|
||||||
|
unsigned long oldlocal_len = session->local.kexinit_len;
|
||||||
|
|
||||||
|
session->local.kexinit = NULL;
|
||||||
|
if (libssh2_kexinit(session)) {
|
||||||
|
session->local.kexinit = oldlocal;
|
||||||
|
session->local.kexinit_len = oldlocal_len;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (libssh2_packet_require(session, SSH_MSG_KEXINIT, &data, &data_len)) {
|
if (libssh2_packet_require(session, SSH_MSG_KEXINIT, &data, &data_len)) {
|
||||||
|
if (session->local.kexinit) {
|
||||||
|
LIBSSH2_FREE(session, session->local.kexinit);
|
||||||
|
}
|
||||||
|
session->local.kexinit = oldlocal;
|
||||||
|
session->local.kexinit_len = oldlocal_len;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1254,10 +1312,6 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
|
|||||||
session->remote.kexinit = data;
|
session->remote.kexinit = data;
|
||||||
session->remote.kexinit_len = data_len;
|
session->remote.kexinit_len = data_len;
|
||||||
|
|
||||||
if (libssh2_kexinit(session)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (libssh2_kex_agree_methods(session, data, data_len)) {
|
if (libssh2_kex_agree_methods(session, data, data_len)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
56
src/packet.c
56
src/packet.c
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -640,9 +640,9 @@ static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, s
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
switch (WSAGetLastError()) {
|
switch (WSAGetLastError()) {
|
||||||
case WSAEWOULDBLOCK: errno = EAGAIN; break;
|
case WSAEWOULDBLOCK: errno = EAGAIN; break;
|
||||||
|
case WSAENOTSOCK: errno = EBADF; break;
|
||||||
case WSAENOTCONN:
|
case WSAENOTCONN:
|
||||||
case WSAENOTSOCK:
|
case WSAECONNABORTED: errno = ENOTCONN; break;
|
||||||
case WSAECONNABORTED: errno = EBADF; break;
|
|
||||||
case WSAEINTR: errno = EINTR; break;
|
case WSAEINTR: errno = EINTR; break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -680,7 +680,7 @@ static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, s
|
|||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((errno == EBADF) || (errno == EIO)) {
|
if ((errno == EBADF) || (errno == EIO) || (errno == ENOTCONN)) {
|
||||||
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
|
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -862,9 +862,9 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet_type = payload[0];
|
||||||
libssh2_packet_add(session, payload, payload_len, macstate);
|
libssh2_packet_add(session, payload, payload_len, macstate);
|
||||||
|
|
||||||
packet_type = payload[0];
|
|
||||||
} else { /* No cipher active */
|
} else { /* No cipher active */
|
||||||
unsigned char *payload;
|
unsigned char *payload;
|
||||||
unsigned char buf[24];
|
unsigned char buf[24];
|
||||||
@@ -911,11 +911,11 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet_type = payload[0];
|
||||||
|
|
||||||
/* MACs don't exist in non-encrypted mode */
|
/* MACs don't exist in non-encrypted mode */
|
||||||
libssh2_packet_add(session, payload, payload_len, LIBSSH2_MAC_CONFIRMED);
|
libssh2_packet_add(session, payload, payload_len, LIBSSH2_MAC_CONFIRMED);
|
||||||
session->remote.seqno++;
|
session->remote.seqno++;
|
||||||
|
|
||||||
packet_type = payload[0];
|
|
||||||
}
|
}
|
||||||
return packet_type;
|
return packet_type;
|
||||||
}
|
}
|
||||||
@@ -1017,6 +1017,48 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ libssh2_packet_burn
|
||||||
|
* Loops libssh2_packet_read() until any packet is available and promptly discards it
|
||||||
|
* Used during KEX exchange to discard badly guessed KEX_INIT packets
|
||||||
|
*/
|
||||||
|
int libssh2_packet_burn(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
unsigned long data_len;
|
||||||
|
char all_packets[255];
|
||||||
|
int i;
|
||||||
|
for(i = 1; i < 256; i++) all_packets[i - 1] = i;
|
||||||
|
|
||||||
|
if (libssh2_packet_askv_ex(session, all_packets, &data, &data_len, 0, NULL, 0, 0) == 0) {
|
||||||
|
i = data[0];
|
||||||
|
/* A packet was available in the packet brigade, burn it */
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LIBSSH2_DEBUG_TRANSPORT
|
||||||
|
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking until packet becomes available to burn");
|
||||||
|
#endif
|
||||||
|
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
||||||
|
int ret = libssh2_packet_read(session, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ret == 0) continue;
|
||||||
|
|
||||||
|
/* Be lazy, let packet_ask pull it out of the brigade */
|
||||||
|
if (0 == libssh2_packet_ask_ex(session, ret, &data, &data_len, 0, NULL, 0, 0)) {
|
||||||
|
/* Smoke 'em if you got 'em */
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only reached if the socket died */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ libssh2_packet_requirev
|
/* {{{ libssh2_packet_requirev
|
||||||
* Loops libssh2_packet_read() until one of a list of packet types requested is available
|
* Loops libssh2_packet_read() until one of a list of packet types requested is available
|
||||||
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
|
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -103,9 +103,28 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
|
|||||||
|
|
||||||
ret = recv(session->socket_fd, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session));
|
ret = recv(session->socket_fd, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||||
|
|
||||||
if ((ret < 0) && (ret != EAGAIN)) {
|
if (ret < 0) {
|
||||||
/* Some kinda error, but don't break for non-blocking issues */
|
#ifdef WIN32
|
||||||
return 1;
|
switch (WSAGetLastError()) {
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
errno = EAGAIN;
|
||||||
|
break;
|
||||||
|
case WSAENOTSOCK:
|
||||||
|
errno = EBADF;
|
||||||
|
break;
|
||||||
|
case WSAENOTCONN:
|
||||||
|
case WSAECONNABORTED:
|
||||||
|
errno = ENOTCONN;
|
||||||
|
break;
|
||||||
|
case WSAEINTR:
|
||||||
|
errno = EINTR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
|
if (errno != EAGAIN) {
|
||||||
|
/* Some kinda error, but don't break for non-blocking issues */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret <= 0) continue;
|
if (ret <= 0) continue;
|
||||||
@@ -298,9 +317,9 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
|
|||||||
#ifdef LIBSSH2_DEBUG_TRANSPORT
|
#ifdef LIBSSH2_DEBUG_TRANSPORT
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "session_startup for socket %d", socket);
|
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "session_startup for socket %d", socket);
|
||||||
#endif
|
#endif
|
||||||
if (socket <= 0) {
|
if (socket < 0) {
|
||||||
/* Did we forget something? */
|
/* Did we forget something? */
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE, "No socket provided", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE, "Bad socket provided", 0);
|
||||||
return LIBSSH2_ERROR_SOCKET_NONE;
|
return LIBSSH2_ERROR_SOCKET_NONE;
|
||||||
}
|
}
|
||||||
session->socket_fd = socket;
|
session->socket_fd = socket;
|
||||||
@@ -394,6 +413,7 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
|
|||||||
if (session->local.crypt) {
|
if (session->local.crypt) {
|
||||||
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
||||||
if (session->local.crypt_abstract) {
|
if (session->local.crypt_abstract) {
|
||||||
|
EVP_CIPHER_CTX_cleanup(session->local.crypt_abstract);
|
||||||
LIBSSH2_FREE(session, session->local.crypt_abstract);
|
LIBSSH2_FREE(session, session->local.crypt_abstract);
|
||||||
session->local.crypt_abstract = NULL;
|
session->local.crypt_abstract = NULL;
|
||||||
}
|
}
|
||||||
@@ -415,6 +435,7 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
|
|||||||
if (session->remote.crypt) {
|
if (session->remote.crypt) {
|
||||||
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
|
||||||
if (session->remote.crypt_abstract) {
|
if (session->remote.crypt_abstract) {
|
||||||
|
EVP_CIPHER_CTX_cleanup(session->remote.crypt_abstract);
|
||||||
LIBSSH2_FREE(session, session->remote.crypt_abstract);
|
LIBSSH2_FREE(session, session->remote.crypt_abstract);
|
||||||
session->remote.crypt_abstract = NULL;
|
session->remote.crypt_abstract = NULL;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
Reference in New Issue
Block a user