Compare commits
24 Commits
RELEASE.0.
...
RELEASE.0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2427c1b803 | ||
![]() |
159120f844 | ||
![]() |
fc1563a41d | ||
![]() |
c6bbe0d42f | ||
![]() |
a05bf84ecf | ||
![]() |
2c5c54e999 | ||
![]() |
5f2864c0b4 | ||
![]() |
4675d1242b | ||
![]() |
b59f2ccc1b | ||
![]() |
b25446d0a5 | ||
![]() |
064c6cde3a | ||
![]() |
2c5a8480b0 | ||
![]() |
87d61a39e8 | ||
![]() |
0e878271db | ||
![]() |
bc16411dd3 | ||
![]() |
096ef86627 | ||
![]() |
2b414db02e | ||
![]() |
5f7470700e | ||
![]() |
bfc2f5039e | ||
![]() |
a3735795dd | ||
![]() |
a891971a63 | ||
![]() |
d4677dba5b | ||
![]() |
d1ae5a501f | ||
![]() |
72c4c38e37 |
@@ -42,7 +42,7 @@ dist:
|
|||||||
ln -s . $(DISTLIB)
|
ln -s . $(DISTLIB)
|
||||||
tar -zcf $(DISTLIB).tar.gz \
|
tar -zcf $(DISTLIB).tar.gz \
|
||||||
$(DISTLIB)/configure $(DISTLIB)/Makefile.in $(DISTLIB)/ssh2_sample.c \
|
$(DISTLIB)/configure $(DISTLIB)/Makefile.in $(DISTLIB)/ssh2_sample.c \
|
||||||
$(DISTLIB)/LICENSE $(DISTLIB)/README $(DISTLIB)/TODO $(DISTLIB)/INSTALL \
|
$(DISTLIB)/LICENSE $(DISTLIB)/README $(DISTLIB)/INSTALL \
|
||||||
$(DISTLIB)/mkinstalldirs $(DISTLIB)/install-sh $(DISTLIB)/config.sub $(DISTLIB)/config.guess \
|
$(DISTLIB)/mkinstalldirs $(DISTLIB)/install-sh $(DISTLIB)/config.sub $(DISTLIB)/config.guess \
|
||||||
$(DISTLIB)/src/*.c $(DISTLIB)/src/Makefile.in \
|
$(DISTLIB)/src/*.c $(DISTLIB)/src/Makefile.in \
|
||||||
$(DISTLIB)/include/libssh2.h $(DISTLIB)/include/libssh2_priv.h $(DISTLIB)/include/libssh2_sftp.h \
|
$(DISTLIB)/include/libssh2.h $(DISTLIB)/include/libssh2_priv.h $(DISTLIB)/include/libssh2_sftp.h \
|
||||||
|
17
README
17
README
@@ -1,6 +1,23 @@
|
|||||||
libssh2 - SSH2 library
|
libssh2 - SSH2 library
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
Version 0.6
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Added LIBSSH2_FLAG_SIGPIPE to enable/disable SIGPIPE generated by send()/recv() calls. Default off.
|
||||||
|
|
||||||
|
Added libssh2_session_flag() to set optional session flags.
|
||||||
|
|
||||||
|
Collapsed exchanging_keys/newkeys/authenticated flags into single state attribute.
|
||||||
|
|
||||||
|
Fix zlib compression issue when internal buffer state misses partial sync.
|
||||||
|
|
||||||
|
Fix segfault when libssh2_session_methods() is called prior to session_startup().
|
||||||
|
|
||||||
|
Fixed client to server channel windowing. Pervent send queue overruns.
|
||||||
|
|
||||||
|
Swapped banner send/receive order (send first, then wait for response).
|
||||||
|
|
||||||
Version 0.5
|
Version 0.5
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
# AC_PREREQ(2.57)
|
# AC_PREREQ(2.57)
|
||||||
AC_INIT(libssh2,0.5,sarag@libssh2.org)
|
AC_INIT(libssh2,0.6,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])
|
||||||
|
|
||||||
|
@@ -58,7 +58,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _MSC_VER < 1300
|
#if defined(LIBSSH2_WIN32) && _MSC_VER < 1300
|
||||||
typedef unsigned __int64 libssh2_uint64_t;
|
typedef unsigned __int64 libssh2_uint64_t;
|
||||||
typedef __int64 libssh2_int64_t;
|
typedef __int64 libssh2_int64_t;
|
||||||
#else
|
#else
|
||||||
@@ -66,8 +66,8 @@ 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.5"
|
#define LIBSSH2_VERSION "0.6"
|
||||||
#define LIBSSH2_APINO 200412301450
|
#define LIBSSH2_APINO 200502091118
|
||||||
|
|
||||||
/* Part of every banner, user specified or not */
|
/* Part of every banner, user specified or not */
|
||||||
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
|
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
|
||||||
@@ -76,51 +76,6 @@ typedef long long libssh2_int64_t;
|
|||||||
#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER
|
#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER
|
||||||
#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n"
|
#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n"
|
||||||
|
|
||||||
/* Capabilities */
|
|
||||||
#define LIBSSH2_KEX_DH_GROUP1
|
|
||||||
#define LIBSSH2_KEX_DH_GROUP14
|
|
||||||
#define LIBSSH2_KEX_DH_GROUP_EXCHANGE
|
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_RSA
|
|
||||||
#define LIBSSH2_HOSTKEY_RSA
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_DSA
|
|
||||||
#define LIBSSH2_HOSTKEY_DSA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_AES
|
|
||||||
#define LIBSSH2_CRYPT_AES256_CBC
|
|
||||||
#define LIBSSH2_CRYPT_RIJNDAEL_CBC_LYSATOR_LIU_SE
|
|
||||||
#define LIBSSH2_CRYPT_AES192_CBC
|
|
||||||
#define LIBSSH2_CRYPT_AES128_CBC
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_BLOWFISH
|
|
||||||
#define LIBSSH2_CRYPT_BLOWFISH_CBC
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_RC4
|
|
||||||
#define LIBSSH2_CRYPT_ARCFOUR
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_CAST
|
|
||||||
#define LIBSSH2_CRYPT_CAST128_CBC
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_DES
|
|
||||||
#define LIBSSH2_CRYPT_3DES_CBC
|
|
||||||
#endif
|
|
||||||
/* LIBSSH2_CRYPT_NONE already defined (or not) by ./configure */
|
|
||||||
|
|
||||||
#ifdef LIBSSH2_HAVE_ZLIB
|
|
||||||
#define LIBSSH2_COMP_ZLIB
|
|
||||||
#endif
|
|
||||||
#define LIBSSH2_COMP_NONE
|
|
||||||
|
|
||||||
#define LIBSSH2_MAC_SHA1
|
|
||||||
#define LIBSSH2_MAC_SHA1_96
|
|
||||||
#ifndef OPENSSL_NO_RIPEMD
|
|
||||||
#define LIBSSH2_MAC_RIPEMD160
|
|
||||||
#define LIBSSH2_MAC_RIPEMD160_OPENSSH_COM
|
|
||||||
#endif
|
|
||||||
/* LIBSSH2_MAC_NONE already defined (or not) by ./configure */
|
|
||||||
|
|
||||||
/* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 */
|
/* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 */
|
||||||
#define LIBSSH2_DH_GEX_MINGROUP 1024
|
#define LIBSSH2_DH_GEX_MINGROUP 1024
|
||||||
#define LIBSSH2_DH_GEX_OPTGROUP 1536
|
#define LIBSSH2_DH_GEX_OPTGROUP 1536
|
||||||
@@ -180,6 +135,9 @@ typedef long long libssh2_int64_t;
|
|||||||
#define LIBSSH2_METHOD_LANG_CS 8
|
#define LIBSSH2_METHOD_LANG_CS 8
|
||||||
#define LIBSSH2_METHOD_LANG_SC 9
|
#define LIBSSH2_METHOD_LANG_SC 9
|
||||||
|
|
||||||
|
/* session.flags bits */
|
||||||
|
#define LIBSSH2_FLAG_SIGPIPE 0x00000001
|
||||||
|
|
||||||
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
|
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
|
||||||
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
|
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
|
||||||
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
|
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
|
||||||
@@ -259,6 +217,8 @@ LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method
|
|||||||
LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type);
|
LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type);
|
||||||
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf);
|
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf);
|
||||||
|
|
||||||
|
LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value);
|
||||||
|
|
||||||
/* Userauth API */
|
/* Userauth API */
|
||||||
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len);
|
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len);
|
||||||
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
|
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
|
||||||
|
@@ -180,9 +180,8 @@ struct _LIBSSH2_SESSION {
|
|||||||
char *kex_prefs;
|
char *kex_prefs;
|
||||||
char *hostkey_prefs;
|
char *hostkey_prefs;
|
||||||
|
|
||||||
int exchanging_keys;
|
int state;
|
||||||
int newkeys;
|
int flags;
|
||||||
int authenticated;
|
|
||||||
|
|
||||||
/* Agreed Key Exchange Method */
|
/* Agreed Key Exchange Method */
|
||||||
LIBSSH2_KEX_METHOD *kex;
|
LIBSSH2_KEX_METHOD *kex;
|
||||||
@@ -233,6 +232,21 @@ struct _LIBSSH2_SESSION {
|
|||||||
int err_code;
|
int err_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* session.state bits */
|
||||||
|
#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
|
||||||
|
#define LIBSSH2_STATE_NEWKEYS 0x00000002
|
||||||
|
#define LIBSSH2_STATE_AUTHENTICATED 0x00000004
|
||||||
|
|
||||||
|
/* session.flag helpers */
|
||||||
|
#ifdef MSG_NOSIGNAL
|
||||||
|
#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
|
||||||
|
#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
|
||||||
|
#else
|
||||||
|
/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */
|
||||||
|
#define LIBSSH2_SOCKET_SEND_FLAGS(session) 0
|
||||||
|
#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */
|
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */
|
||||||
|
|
||||||
struct _LIBSSH2_KEX_METHOD {
|
struct _LIBSSH2_KEX_METHOD {
|
||||||
|
@@ -902,7 +902,7 @@ LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id
|
|||||||
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_EOF_SENT, "EOF has already been sight, data might be ignored", 0);
|
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_EOF_SENT, "EOF has already been sight, data might be ignored", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel->blocking && channel->local.window_size_initial && (channel->local.window_size <= 0)) {
|
if (channel->blocking && (channel->local.window_size <= 0)) {
|
||||||
/* twiddle our thumbs until there's window space available */
|
/* twiddle our thumbs until there's window space available */
|
||||||
if (libssh2_packet_read(session, 1) < 0) {
|
if (libssh2_packet_read(session, 1) < 0) {
|
||||||
/* Error occured, disconnect? */
|
/* Error occured, disconnect? */
|
||||||
@@ -925,7 +925,7 @@ LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id
|
|||||||
|
|
||||||
/* Don't exceed the remote end's limits */
|
/* Don't exceed the remote end's limits */
|
||||||
/* REMEMBER local means local as the SOURCE of the data */
|
/* REMEMBER local means local as the SOURCE of the data */
|
||||||
if (channel->local.window_size_initial && (buflen > channel->local.window_size)) {
|
if (buflen > channel->local.window_size) {
|
||||||
buflen = channel->local.window_size;
|
buflen = channel->local.window_size;
|
||||||
}
|
}
|
||||||
if (buflen > channel->local.packet_size) {
|
if (buflen > channel->local.packet_size) {
|
||||||
|
48
src/comp.c
48
src/comp.c
@@ -136,12 +136,12 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
|
|||||||
z_stream *strm = *abstract;
|
z_stream *strm = *abstract;
|
||||||
/* A short-term alloc of a full data chunk is better than a series of reallocs */
|
/* A short-term alloc of a full data chunk is better than a series of reallocs */
|
||||||
char *out;
|
char *out;
|
||||||
int out_maxlen = compress ? src_len : (2 * src_len);
|
int out_maxlen = compress ? (src_len + 4) : (2 * src_len);
|
||||||
int limiter = 0;
|
int limiter = 0;
|
||||||
|
|
||||||
/* In practice they never come smaller than this */
|
/* In practice they never come smaller than this */
|
||||||
if (out_maxlen < 21) {
|
if (out_maxlen < 25) {
|
||||||
out_maxlen = 21;
|
out_maxlen = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_maxlen > payload_limit) {
|
if (out_maxlen > payload_limit) {
|
||||||
@@ -172,11 +172,11 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
|
|||||||
if (strm->avail_in) {
|
if (strm->avail_in) {
|
||||||
unsigned long out_ofs = out_maxlen - strm->avail_out;
|
unsigned long out_ofs = out_maxlen - strm->avail_out;
|
||||||
|
|
||||||
out_maxlen += compress ? strm->avail_in : (2 * strm->avail_in);
|
out_maxlen += compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||||
|
|
||||||
if ((out_maxlen > payload_limit) && !compress && limiter++) {
|
if ((out_maxlen > payload_limit) && !compress && limiter++) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
|
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
|
||||||
LIBSSH2_FREE(session, strm->next_out);
|
LIBSSH2_FREE(session, out);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +186,43 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
strm->next_out = out + out_ofs;
|
strm->next_out = out + out_ofs;
|
||||||
strm->avail_out += compress ? strm->avail_in : (2 * strm->avail_in);
|
strm->avail_out += compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||||
|
} else while (!strm->avail_out) {
|
||||||
|
/* Done with input, might be a byte or two in internal buffer during compress
|
||||||
|
* Or potentially many bytes if it's a decompress
|
||||||
|
*/
|
||||||
|
int grow_size = compress ? 8 : 1024;
|
||||||
|
|
||||||
|
if (out_maxlen >= payload_limit) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
|
||||||
|
LIBSSH2_FREE(session, out);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grow_size > (payload_limit - out_maxlen)) {
|
||||||
|
grow_size = payload_limit - out_maxlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_maxlen += grow_size;
|
||||||
|
strm->avail_out = grow_size;
|
||||||
|
|
||||||
|
out = LIBSSH2_REALLOC(session, out, out_maxlen);
|
||||||
|
if (!out) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to expand final compress/decompress buffer", 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strm->next_out = out + out_maxlen - grow_size;
|
||||||
|
|
||||||
|
if (compress) {
|
||||||
|
status = deflate(strm, Z_PARTIAL_FLUSH);
|
||||||
|
} else {
|
||||||
|
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||||
|
}
|
||||||
|
if (status != Z_OK) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0);
|
||||||
|
LIBSSH2_FREE(session, strm->next_out);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -392,11 +392,9 @@ static int libssh2_hostkey_method_ssh_dss_sign(LIBSSH2_SESSION *session, unsigne
|
|||||||
DSA_SIG *sig;
|
DSA_SIG *sig;
|
||||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||||
SHA_CTX ctx;
|
SHA_CTX ctx;
|
||||||
int r_len, s_len, rs_pad;
|
|
||||||
|
|
||||||
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
|
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
|
||||||
*signature_len = 2 * SHA_DIGEST_LENGTH;
|
*signature_len = 2 * SHA_DIGEST_LENGTH;
|
||||||
memset(*signature, 0, 2 * SHA_DIGEST_LENGTH);
|
|
||||||
|
|
||||||
if (!(*signature)) {
|
if (!(*signature)) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -412,17 +410,8 @@ static int libssh2_hostkey_method_ssh_dss_sign(LIBSSH2_SESSION *session, unsigne
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
r_len = BN_num_bytes(sig->r);
|
BN_bn2bin(sig->r, *signature);
|
||||||
s_len = BN_num_bytes(sig->s);
|
BN_bn2bin(sig->s, *signature + SHA_DIGEST_LENGTH);
|
||||||
rs_pad = (2 * SHA_DIGEST_LENGTH) - (r_len + s_len);
|
|
||||||
if (rs_pad < 0) {
|
|
||||||
DSA_SIG_free(sig);
|
|
||||||
LIBSSH2_FREE(session, *signature);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BN_bn2bin(sig->r, *signature + rs_pad);
|
|
||||||
BN_bn2bin(sig->s, *signature + rs_pad + r_len);
|
|
||||||
|
|
||||||
DSA_SIG_free(sig);
|
DSA_SIG_free(sig);
|
||||||
|
|
||||||
|
@@ -263,7 +263,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
|
|||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
/* The first key exchange has been performed, switch to active crypt/comp/mac mode */
|
/* The first key exchange has been performed, switch to active crypt/comp/mac mode */
|
||||||
session->newkeys = 1;
|
session->state |= LIBSSH2_STATE_NEWKEYS;
|
||||||
|
|
||||||
/* This will actually end up being just packet_type(1) for this packet type anyway */
|
/* This will actually end up being just packet_type(1) for this packet type anyway */
|
||||||
LIBSSH2_FREE(session, tmp);
|
LIBSSH2_FREE(session, tmp);
|
||||||
@@ -1145,7 +1145,7 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
|
|||||||
unsigned long data_len;
|
unsigned long data_len;
|
||||||
|
|
||||||
/* Prevent loop in packet_add() */
|
/* Prevent loop in packet_add() */
|
||||||
session->exchanging_keys = 1;
|
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||||
|
|
||||||
if (reexchange) {
|
if (reexchange) {
|
||||||
session->kex = NULL;
|
session->kex = NULL;
|
||||||
@@ -1191,7 +1191,7 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
|
|||||||
session->remote.kexinit = NULL;
|
session->remote.kexinit = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->exchanging_keys = 0;
|
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -49,7 +49,7 @@ unsigned long libssh2_ntohu32(const unsigned char *buf)
|
|||||||
* Note: Some 32-bit platforms have issues with bitops on long longs
|
* Note: Some 32-bit platforms have issues with bitops on long longs
|
||||||
* Work around this by doing expensive (but safer) arithmetic ops with optimization defying parentheses
|
* Work around this by doing expensive (but safer) arithmetic ops with optimization defying parentheses
|
||||||
*/
|
*/
|
||||||
unsigned long long libssh2_ntohu64(const unsigned char *buf)
|
libssh2_uint64_t libssh2_ntohu64(const unsigned char *buf)
|
||||||
{
|
{
|
||||||
unsigned long msl, lsl;
|
unsigned long msl, lsl;
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ void libssh2_htonu32(unsigned char *buf, unsigned long value)
|
|||||||
|
|
||||||
/* {{{ libssh2_htonu64
|
/* {{{ libssh2_htonu64
|
||||||
*/
|
*/
|
||||||
void libssh2_htonu64(unsigned char *buf, unsigned long long value)
|
void libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
|
||||||
{
|
{
|
||||||
unsigned long msl = (value / 65536) / 65536;
|
unsigned long msl = (value / 65536) / 65536;
|
||||||
|
|
||||||
|
31
src/packet.c
31
src/packet.c
@@ -475,6 +475,19 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SSH_MSG_CHANNEL_WINDOW_ADJUST:
|
||||||
|
{
|
||||||
|
LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data + 1));
|
||||||
|
unsigned long bytestoadd = libssh2_ntohu32(data + 5);
|
||||||
|
|
||||||
|
if (channel && bytestoadd) {
|
||||||
|
channel->local.window_size += bytestoadd;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
|
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
|
||||||
@@ -497,7 +510,7 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
|
|||||||
packet->prev = NULL;
|
packet->prev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data[0] == SSH_MSG_KEXINIT && !session->exchanging_keys) {
|
if (data[0] == SSH_MSG_KEXINIT && !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) {
|
||||||
/* Remote wants new keys
|
/* Remote wants new keys
|
||||||
* Well, it's already in the brigade,
|
* Well, it's already in the brigade,
|
||||||
* let's just call back into ourselves
|
* let's just call back into ourselves
|
||||||
@@ -521,7 +534,7 @@ static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, s
|
|||||||
while (bytes_read < count) {
|
while (bytes_read < count) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = recv(session->socket_fd, buf + bytes_read, count - bytes_read, 0);
|
ret = recv(session->socket_fd, buf + bytes_read, count - bytes_read, LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
switch (WSAGetLastError()) {
|
switch (WSAGetLastError()) {
|
||||||
@@ -578,7 +591,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
|
|||||||
ioctlsocket(session->socket_fd, FIONBIO, &non_block);
|
ioctlsocket(session->socket_fd, FIONBIO, &non_block);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (session->newkeys) {
|
if (session->state & LIBSSH2_STATE_NEWKEYS) {
|
||||||
/* Temporary Buffer
|
/* Temporary Buffer
|
||||||
* The largest blocksize (currently) is 32, the largest MAC (currently) is 20
|
* The largest blocksize (currently) is 32, the largest MAC (currently) is 20
|
||||||
*/
|
*/
|
||||||
@@ -598,7 +611,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
|
|||||||
if (should_block) {
|
if (should_block) {
|
||||||
read_len = libssh2_blocking_read(session, block, blocksize);
|
read_len = libssh2_blocking_read(session, block, blocksize);
|
||||||
} else {
|
} else {
|
||||||
read_len = recv(session->socket_fd, block, 1, 0);
|
read_len = recv(session->socket_fd, block, 1, LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||||
if (read_len <= 0) {
|
if (read_len <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -723,7 +736,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
|
|||||||
if (should_block) {
|
if (should_block) {
|
||||||
buf_len = libssh2_blocking_read(session, buf, 5);
|
buf_len = libssh2_blocking_read(session, buf, 5);
|
||||||
} else {
|
} else {
|
||||||
buf_len = recv(session->socket_fd, buf, 1, 0);
|
buf_len = recv(session->socket_fd, buf, 1, LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||||
if (buf_len <= 0) {
|
if (buf_len <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -841,14 +854,14 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
|
|||||||
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)
|
||||||
{
|
{
|
||||||
unsigned long packet_length = data_len + 1;
|
unsigned long packet_length = data_len + 1;
|
||||||
unsigned long block_size = (session->newkeys) ? session->local.crypt->blocksize : 8;
|
unsigned long block_size = (session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->blocksize : 8;
|
||||||
/* At this point packet_length doesn't include the packet_len field itself */
|
/* At this point packet_length doesn't include the packet_len field itself */
|
||||||
unsigned long padding_length;
|
unsigned long padding_length;
|
||||||
int free_data = 0;
|
int free_data = 0;
|
||||||
unsigned char buf[246]; /* 6 byte header plus max padding size(240) */
|
unsigned char buf[246]; /* 6 byte header plus max padding size(240) */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (session->newkeys &&
|
if ((session->state & LIBSSH2_STATE_NEWKEYS) &&
|
||||||
strcmp(session->local.comp->name, "none")) {
|
strcmp(session->local.comp->name, "none")) {
|
||||||
|
|
||||||
if (session->local.comp->comp(session, 1, &data, &data_len, LIBSSH2_PACKET_MAXCOMP, &free_data, data, data_len, &session->local.comp_abstract)) {
|
if (session->local.comp->comp(session, 1, &data, &data_len, LIBSSH2_PACKET_MAXCOMP, &free_data, data, data_len, &session->local.comp_abstract)) {
|
||||||
@@ -881,7 +894,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
|
|||||||
buf[5 + i] = '\0';
|
buf[5 + i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->newkeys) {
|
if (session->state & LIBSSH2_STATE_NEWKEYS) {
|
||||||
/* Encryption is in effect */
|
/* Encryption is in effect */
|
||||||
unsigned char *encbuf, *s;
|
unsigned char *encbuf, *s;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -923,7 +936,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
|
|||||||
session->local.seqno++;
|
session->local.seqno++;
|
||||||
|
|
||||||
/* Send It */
|
/* Send It */
|
||||||
ret = ((4 + packet_length + session->local.mac->mac_len) == send(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len, 0)) ? 0 : -1;
|
ret = ((4 + packet_length + session->local.mac->mac_len) == send(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len, LIBSSH2_SOCKET_SEND_FLAGS(session))) ? 0 : -1;
|
||||||
|
|
||||||
/* Cleanup environment */
|
/* Cleanup environment */
|
||||||
LIBSSH2_FREE(session, encbuf);
|
LIBSSH2_FREE(session, encbuf);
|
||||||
|
@@ -347,6 +347,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, char
|
|||||||
|
|
||||||
/* Allocate a channel */
|
/* Allocate a channel */
|
||||||
if ((channel = libssh2_channel_open_session(session)) == NULL) {
|
if ((channel = libssh2_channel_open_session(session)) == NULL) {
|
||||||
|
/* previous call set libssh2_session_last_error(), pass it through */
|
||||||
LIBSSH2_FREE(session, command);
|
LIBSSH2_FREE(session, command);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -355,6 +356,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, char
|
|||||||
|
|
||||||
/* Request SCP for the desired file */
|
/* Request SCP for the desired file */
|
||||||
if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) {
|
if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) {
|
||||||
|
/* previous call set libssh2_session_last_error(), pass it through */
|
||||||
LIBSSH2_FREE(session, command);
|
LIBSSH2_FREE(session, command);
|
||||||
libssh2_channel_free(channel);
|
libssh2_channel_free(channel);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -81,7 +81,7 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
|
|||||||
char c = '\0';
|
char c = '\0';
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = recv(session->socket_fd, &c, 1, 0);
|
ret = recv(session->socket_fd, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session));
|
||||||
|
|
||||||
if ((ret < 0) && (ret != EAGAIN)) {
|
if ((ret < 0) && (ret != EAGAIN)) {
|
||||||
/* Some kinda error, but don't break for non-blocking issues */
|
/* Some kinda error, but don't break for non-blocking issues */
|
||||||
@@ -126,7 +126,7 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
|
|||||||
banner = session->local.banner;
|
banner = session->local.banner;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (send(session->socket_fd, banner, banner_len, 0) == banner_len) ? 0 : 1;
|
return (send(session->socket_fd, banner, banner_len, LIBSSH2_SOCKET_SEND_FLAGS(session)) == banner_len) ? 0 : 1;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
@@ -254,18 +254,18 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
|
|||||||
session->socket_fd = socket;
|
session->socket_fd = socket;
|
||||||
|
|
||||||
/* TODO: Liveness check */
|
/* TODO: Liveness check */
|
||||||
if (libssh2_banner_receive(session)) {
|
|
||||||
/* Unable to receive banner from remote */
|
|
||||||
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE, "Timeout waiting for banner", 0);
|
|
||||||
return LIBSSH2_ERROR_BANNER_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (libssh2_banner_send(session)) {
|
if (libssh2_banner_send(session)) {
|
||||||
/* Unable to send banner? */
|
/* Unable to send banner? */
|
||||||
libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND, "Error sending banner to remote host", 0);
|
libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND, "Error sending banner to remote host", 0);
|
||||||
return LIBSSH2_ERROR_BANNER_SEND;
|
return LIBSSH2_ERROR_BANNER_SEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (libssh2_banner_receive(session)) {
|
||||||
|
/* Unable to receive banner from remote */
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE, "Timeout waiting for banner", 0);
|
||||||
|
return LIBSSH2_ERROR_BANNER_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (libssh2_kex_exchange(session, 0)) {
|
if (libssh2_kex_exchange(session, 0)) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, "Unable to exchange encryption keys", 0);
|
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, "Unable to exchange encryption keys", 0);
|
||||||
return LIBSSH2_ERROR_KEX_FAILURE;
|
return LIBSSH2_ERROR_KEX_FAILURE;
|
||||||
@@ -325,7 +325,7 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
|
|||||||
libssh2_channel_forward_cancel(session->listeners);
|
libssh2_channel_forward_cancel(session->listeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->newkeys) {
|
if (session->state & LIBSSH2_STATE_NEWKEYS) {
|
||||||
/* hostkey */
|
/* hostkey */
|
||||||
if (session->hostkey && session->hostkey->dtor) {
|
if (session->hostkey && session->hostkey->dtor) {
|
||||||
session->hostkey->dtor(session, &session->server_hostkey_abstract);
|
session->hostkey->dtor(session, &session->server_hostkey_abstract);
|
||||||
@@ -488,46 +488,52 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
|
|||||||
*/
|
*/
|
||||||
LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type)
|
LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type)
|
||||||
{
|
{
|
||||||
char *methodlist = NULL;
|
/* All methods have char *name as their first element */
|
||||||
|
LIBSSH2_KEX_METHOD *method = NULL;
|
||||||
|
|
||||||
switch(method_type) {
|
switch(method_type) {
|
||||||
case LIBSSH2_METHOD_KEX:
|
case LIBSSH2_METHOD_KEX:
|
||||||
methodlist = session->kex->name;
|
method = session->kex;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_HOSTKEY:
|
case LIBSSH2_METHOD_HOSTKEY:
|
||||||
methodlist = session->hostkey->name;
|
method = (LIBSSH2_KEX_METHOD*)session->hostkey;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_CRYPT_CS:
|
case LIBSSH2_METHOD_CRYPT_CS:
|
||||||
methodlist = session->local.crypt->name;
|
method = (LIBSSH2_KEX_METHOD*)session->local.crypt;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_CRYPT_SC:
|
case LIBSSH2_METHOD_CRYPT_SC:
|
||||||
methodlist = session->remote.crypt->name;
|
method = (LIBSSH2_KEX_METHOD*)session->remote.crypt;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_MAC_CS:
|
case LIBSSH2_METHOD_MAC_CS:
|
||||||
methodlist = session->local.mac->name;
|
method = (LIBSSH2_KEX_METHOD*)session->local.mac;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_MAC_SC:
|
case LIBSSH2_METHOD_MAC_SC:
|
||||||
methodlist = session->remote.mac->name;
|
method = (LIBSSH2_KEX_METHOD*)session->remote.mac;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_COMP_CS:
|
case LIBSSH2_METHOD_COMP_CS:
|
||||||
methodlist = session->local.comp->name;
|
method = (LIBSSH2_KEX_METHOD*)session->local.comp;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_COMP_SC:
|
case LIBSSH2_METHOD_COMP_SC:
|
||||||
methodlist = session->remote.comp->name;
|
method = (LIBSSH2_KEX_METHOD*)session->remote.comp;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_LANG_CS:
|
case LIBSSH2_METHOD_LANG_CS:
|
||||||
methodlist = "";
|
return "";
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_METHOD_LANG_SC:
|
case LIBSSH2_METHOD_LANG_SC:
|
||||||
methodlist = "";
|
return "";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0);
|
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0);
|
||||||
methodlist = NULL;
|
return NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(methodlist);
|
if (!method) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, "No method negotiated", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method->name;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
@@ -594,3 +600,19 @@ LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errm
|
|||||||
return session->err_code;
|
return session->err_code;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ libssh2_session_flag
|
||||||
|
* Set/Get session flags
|
||||||
|
* Passing flag==0 will avoid changing session->flags while still returning its current value
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value)
|
||||||
|
{
|
||||||
|
if (value) {
|
||||||
|
session->flags |= flag;
|
||||||
|
} else {
|
||||||
|
session->flags &= ~flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return session->flags;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
@@ -80,7 +80,7 @@ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username
|
|||||||
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
|
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
|
||||||
/* Wow, who'dve thought... */
|
/* Wow, who'dve thought... */
|
||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
session->authenticated = 1;
|
session->state |= LIBSSH2_STATE_AUTHENTICATED;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username
|
|||||||
*/
|
*/
|
||||||
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session)
|
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
return session->authenticated;
|
return session->state & LIBSSH2_STATE_AUTHENTICATED;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, char *use
|
|||||||
while (1) {
|
while (1) {
|
||||||
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
|
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
|
||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
session->authenticated = 1;
|
session->state |= LIBSSH2_STATE_AUTHENTICATED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,7 +389,7 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
|
|||||||
LIBSSH2_FREE(session, packet);
|
LIBSSH2_FREE(session, packet);
|
||||||
LIBSSH2_FREE(session, method);
|
LIBSSH2_FREE(session, method);
|
||||||
LIBSSH2_FREE(session, pubkeydata);
|
LIBSSH2_FREE(session, pubkeydata);
|
||||||
session->authenticated = 1;
|
session->state |= LIBSSH2_STATE_AUTHENTICATED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
|
|||||||
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
|
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
|
||||||
/* We are us and we've proved it. */
|
/* We are us and we've proved it. */
|
||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
session->authenticated = 1;
|
session->state |= LIBSSH2_STATE_AUTHENTICATED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
test/Makefile
Normal file
19
test/Makefile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
LIBS = -L../src -lssh2
|
||||||
|
CFLAGS = -c -I../include
|
||||||
|
CC = gcc -Wall -g
|
||||||
|
OBJS = main.o util.o methods.o auth.o forward.o
|
||||||
|
|
||||||
|
all: libssh2-test
|
||||||
|
|
||||||
|
libssh2-test: $(OBJS)
|
||||||
|
$(CC) -o libssh2-test $(OBJS) $(LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
main.o: main.c libssh2-test.h
|
||||||
|
util.o: util.c libssh2-test.h
|
||||||
|
methods.o: methods.c libssh2-test.h
|
||||||
|
auth.o: auth.c libssh2-test.h
|
||||||
|
forward.o: forward.c libssh2-test.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) libssh2-test
|
58
test/README
Normal file
58
test/README
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
This directory contains some code meant to test libssh2's protocol compliance
|
||||||
|
against other implementations, as well as providing a body of example code.
|
||||||
|
The following tests are done:
|
||||||
|
|
||||||
|
* methods.c:
|
||||||
|
|
||||||
|
Tries a connection + authentication with every possible key exchange,
|
||||||
|
hostkey, encryption, mac and compression method (see
|
||||||
|
libssh2_session_method_pref()).
|
||||||
|
|
||||||
|
The first connection is done with methods that are required to be supported
|
||||||
|
by server implementations according to the standard: key exchange method
|
||||||
|
"diffie-hellman-group1-sha1", hostkey method "ssh-dss", encryption method
|
||||||
|
"3des-cbc", mac method "hmac-sha1" and no compression.
|
||||||
|
|
||||||
|
Then every method is tried in turn, with all the other methods set to these
|
||||||
|
"known good" methods. Hence, the test will report exactly which method of
|
||||||
|
which method type failed to initialize a connection. A total of 26 tests
|
||||||
|
is performed.
|
||||||
|
|
||||||
|
|
||||||
|
* auth.c:
|
||||||
|
|
||||||
|
This test tries to authenticate with username+pasword, and public/private
|
||||||
|
key + passphrase. In addition, the hostkey is retrieved in both MD5 and SHA1
|
||||||
|
formats, and sanity-checked.
|
||||||
|
|
||||||
|
|
||||||
|
* forward.c:
|
||||||
|
|
||||||
|
This test tries to make the remote host listen on a port, then requests a
|
||||||
|
tunnel through the remote host to that port, accepting the connection
|
||||||
|
locally. A block of data is then sent through the tunnel, and this data is
|
||||||
|
then compared to the original when received.
|
||||||
|
|
||||||
|
This is tried four times: one each for every combination of the remote
|
||||||
|
host's bind address provided or not, and bind port provided or not.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
If you want to add a test, you will need to do the following:
|
||||||
|
|
||||||
|
* create a new source file, and add it to the Makefile
|
||||||
|
* call your main function (runtest_yourtest) from main() in main.c
|
||||||
|
* at the top of your source file, put:
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
#include "libssh2-test.h"
|
||||||
|
|
||||||
|
extern struct authdefs auth;
|
||||||
|
|
||||||
|
* call init_test("description of your test", number_of_steps)
|
||||||
|
* use new_socket() to get a connected socket, and log_line() to log
|
||||||
|
errors if your test fails.
|
||||||
|
* before every step in your test, call increase_progress()
|
||||||
|
* after every step, if it was successful, call step_successful()
|
||||||
|
* after your test, print a "\n".
|
||||||
|
|
215
test/auth.c
Normal file
215
test/auth.c
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* auth.c -- test authentication methods
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
#include "libssh2-test.h"
|
||||||
|
|
||||||
|
extern struct authdefs auth;
|
||||||
|
|
||||||
|
|
||||||
|
static int auth_publickey(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(libssh2_userauth_publickey_fromfile(session, auth.username,
|
||||||
|
auth.pubkey, auth.privkey, auth.passphrase))
|
||||||
|
{
|
||||||
|
log_line(ERROR, "Public key authentication failed\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!libssh2_userauth_authenticated(session))
|
||||||
|
{
|
||||||
|
log_line(ERROR, "Public key authentication succeeded, but authentication not set\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int auth_password(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(libssh2_userauth_password(session, auth.username, auth.password))
|
||||||
|
{
|
||||||
|
log_line(ERROR, "Password authentication failed\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!libssh2_userauth_authenticated(session))
|
||||||
|
{
|
||||||
|
log_line(ERROR, "Password authentication succeeded, but authentication not set\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void all_auth(void)
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session;
|
||||||
|
int sock, size, res, sum, i;
|
||||||
|
unsigned char *hash;
|
||||||
|
char *errmsg, *_authlist, *authlist, *authmethod, *sep;
|
||||||
|
|
||||||
|
authlist = NULL;
|
||||||
|
authmethod = "";
|
||||||
|
while(authmethod)
|
||||||
|
{
|
||||||
|
sock = new_socket();
|
||||||
|
if(sock == -1)
|
||||||
|
{
|
||||||
|
log_line(ERROR, "new_socket() failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session = libssh2_session_init();
|
||||||
|
|
||||||
|
res = libssh2_session_startup(session, sock);
|
||||||
|
if(res)
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "session_startup() failed: %s\n", errmsg);
|
||||||
|
close(sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!authlist)
|
||||||
|
{
|
||||||
|
_authlist = libssh2_userauth_list(session, auth.username, strlen(auth.username));
|
||||||
|
if(_authlist == NULL)
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "userauth_list() failed: %s\n", errmsg);
|
||||||
|
libssh2_session_disconnect(session, "All done.");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
close(sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
authlist = strdup(_authlist);
|
||||||
|
authmethod = authlist;
|
||||||
|
|
||||||
|
/* only need to check hostkey hashes once... might as well do that here */
|
||||||
|
increase_progress();
|
||||||
|
hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||||
|
if(hash)
|
||||||
|
{
|
||||||
|
sum = 0;
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
sum += hash[i];
|
||||||
|
if(sum > 0)
|
||||||
|
step_successful();
|
||||||
|
else
|
||||||
|
log_line(ERROR, "MD5 hostkey hash invalid\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_line(ERROR, "MD5 hostkey hash failed\n");
|
||||||
|
|
||||||
|
increase_progress();
|
||||||
|
hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||||
|
if(hash)
|
||||||
|
{
|
||||||
|
sum = 0;
|
||||||
|
for(i = 0; i < 20; i++)
|
||||||
|
sum += hash[i];
|
||||||
|
if(sum > 0)
|
||||||
|
step_successful();
|
||||||
|
else
|
||||||
|
log_line(ERROR, "SHA1 hostkey hash invalid\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_line(ERROR, "SHA1 hostkey hash failed\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (sep = strchr(authmethod, ',')) )
|
||||||
|
*sep++ = '\0';
|
||||||
|
|
||||||
|
if(!strcasecmp(authmethod, "publickey"))
|
||||||
|
{
|
||||||
|
increase_progress();
|
||||||
|
if(auth_publickey(session))
|
||||||
|
step_successful();
|
||||||
|
}
|
||||||
|
else if(!strcasecmp(authmethod, "password"))
|
||||||
|
{
|
||||||
|
increase_progress();
|
||||||
|
if(auth_password(session))
|
||||||
|
step_successful();
|
||||||
|
}
|
||||||
|
else if(!strcasecmp(authmethod, "keyboard-interactive"))
|
||||||
|
{
|
||||||
|
/* no idea how to test this */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_line(DEBUG, "Unknown authentication method %s\n", authmethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
authmethod = sep;
|
||||||
|
|
||||||
|
libssh2_session_disconnect(session, "All done.");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(authlist);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void runtest_auth(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
init_test("authentication", 4);
|
||||||
|
|
||||||
|
all_auth();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
272
test/forward.c
Normal file
272
test/forward.c
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* forward.c -- ssh2 port forwarding test
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||||
|
* 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 <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wordexp.h>
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
#include "libssh2-test.h"
|
||||||
|
|
||||||
|
struct authdefs auth;
|
||||||
|
extern struct addrinfo *cur_ai;
|
||||||
|
|
||||||
|
#define LISTEN_PORT 22617
|
||||||
|
#define TESTBUF_SIZE 10
|
||||||
|
|
||||||
|
|
||||||
|
static int loopback(LIBSSH2_SESSION *session, int hostbind, int portbind)
|
||||||
|
{
|
||||||
|
LIBSSH2_CHANNEL *inbound, *outbound;
|
||||||
|
LIBSSH2_LISTENER *listener;
|
||||||
|
int listen_port, size, i, res;
|
||||||
|
char paramstr[64], ipstr[128], *errmsg, *host, *sendbuf, *recvbuf;
|
||||||
|
|
||||||
|
snprintf(paramstr, 64, "(%shost bind, %sport bind)", hostbind ? "" : "no ", portbind ? "" : "no ");
|
||||||
|
|
||||||
|
host = NULL;
|
||||||
|
if(hostbind)
|
||||||
|
{
|
||||||
|
if(getnameinfo(cur_ai->ai_addr, cur_ai->ai_addrlen, ipstr, sizeof(ipstr), NULL, 0, NI_NUMERICHOST))
|
||||||
|
{
|
||||||
|
log_line(ERROR, "getnameinfo() failed\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
host = ipstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
listen_port = 0;
|
||||||
|
if(portbind)
|
||||||
|
listen_port = LISTEN_PORT;
|
||||||
|
|
||||||
|
listener = libssh2_channel_forward_listen_ex(session, host, listen_port, &listen_port, 2);
|
||||||
|
if(!listener)
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "Listen failed %s: %s\n", paramstr, errmsg);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
outbound = libssh2_channel_direct_tcpip(session, auth.hostname, listen_port);
|
||||||
|
if(!outbound)
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "Outbound channel setup failed %s: %s\n", paramstr, errmsg);
|
||||||
|
|
||||||
|
libssh2_channel_forward_cancel(listener);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inbound = libssh2_channel_forward_accept(listener);
|
||||||
|
if(!inbound)
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "Forwarding channel accept failed %s: %s\n", paramstr, errmsg);
|
||||||
|
|
||||||
|
libssh2_channel_free(outbound);
|
||||||
|
libssh2_channel_forward_cancel(listener);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendbuf = malloc(TESTBUF_SIZE);
|
||||||
|
if(!sendbuf)
|
||||||
|
{
|
||||||
|
log_line(ERROR, "sendbuf malloc failed\n");
|
||||||
|
|
||||||
|
libssh2_channel_free(inbound);
|
||||||
|
libssh2_channel_free(outbound);
|
||||||
|
libssh2_channel_forward_cancel(listener);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < TESTBUF_SIZE; i++)
|
||||||
|
sendbuf[i] = (char) random;
|
||||||
|
|
||||||
|
res = libssh2_channel_write(outbound, sendbuf, TESTBUF_SIZE);
|
||||||
|
if(res != TESTBUF_SIZE)
|
||||||
|
{
|
||||||
|
if(res == -1)
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
else
|
||||||
|
errmsg = NULL;
|
||||||
|
log_line(ERROR, "Unable to send %d bytes across tunnel %s%s%s\n",
|
||||||
|
TESTBUF_SIZE, paramstr, errmsg ? ": " : "", errmsg ? errmsg : "");
|
||||||
|
|
||||||
|
free(sendbuf);
|
||||||
|
libssh2_channel_free(inbound);
|
||||||
|
libssh2_channel_free(outbound);
|
||||||
|
libssh2_channel_forward_cancel(listener);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
recvbuf = malloc(TESTBUF_SIZE);
|
||||||
|
if(!recvbuf)
|
||||||
|
{
|
||||||
|
log_line(ERROR, "recvbuf malloc failed\n");
|
||||||
|
|
||||||
|
free(sendbuf);
|
||||||
|
libssh2_channel_free(inbound);
|
||||||
|
libssh2_channel_free(outbound);
|
||||||
|
libssh2_channel_forward_cancel(listener);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = libssh2_channel_read(inbound, recvbuf, TESTBUF_SIZE);
|
||||||
|
if(res != TESTBUF_SIZE)
|
||||||
|
{
|
||||||
|
if(res == -1)
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
else
|
||||||
|
errmsg = NULL;
|
||||||
|
log_line(ERROR, "Unable to receive %d bytes across tunnel %s%s%s\n",
|
||||||
|
TESTBUF_SIZE, paramstr, errmsg ? ": " : "", errmsg ? errmsg : "");
|
||||||
|
|
||||||
|
free(sendbuf);
|
||||||
|
free(recvbuf);
|
||||||
|
libssh2_channel_free(inbound);
|
||||||
|
libssh2_channel_free(outbound);
|
||||||
|
libssh2_channel_forward_cancel(listener);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = 1;
|
||||||
|
for(i = 0; i < TESTBUF_SIZE; i++)
|
||||||
|
{
|
||||||
|
if(recvbuf[i] != sendbuf[i])
|
||||||
|
{
|
||||||
|
log_line(ERROR, "Received data did not match sent data %s\n", paramstr);
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sendbuf);
|
||||||
|
free(recvbuf);
|
||||||
|
libssh2_channel_free(inbound);
|
||||||
|
libssh2_channel_free(outbound);
|
||||||
|
libssh2_channel_forward_cancel(listener);
|
||||||
|
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void all_forward(void)
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session;
|
||||||
|
int sock, res, size;
|
||||||
|
char *errmsg;
|
||||||
|
|
||||||
|
sock = new_socket();
|
||||||
|
if(sock == -1)
|
||||||
|
{
|
||||||
|
log_line(ERROR, "Unable to open a socket\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session = libssh2_session_init();
|
||||||
|
|
||||||
|
res = libssh2_session_startup(session, sock);
|
||||||
|
if(res)
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "Session startup failed: %s\n", errmsg);
|
||||||
|
close(sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(libssh2_userauth_password(session, auth.username, auth.password))
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "Authentication failed%s%s\n", errmsg[0] ? ": " : "", errmsg);
|
||||||
|
libssh2_session_disconnect(session, "All done.");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
close(sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
increase_progress();
|
||||||
|
if(loopback(session, 1, 1))
|
||||||
|
step_successful();
|
||||||
|
|
||||||
|
increase_progress();
|
||||||
|
if(loopback(session, 1, 0))
|
||||||
|
step_successful();
|
||||||
|
|
||||||
|
increase_progress();
|
||||||
|
if(loopback(session, 0, 1))
|
||||||
|
step_successful();
|
||||||
|
|
||||||
|
increase_progress();
|
||||||
|
if(loopback(session, 0, 0))
|
||||||
|
step_successful();
|
||||||
|
|
||||||
|
libssh2_session_disconnect(session, "All done.");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
close(sock);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void runtest_forward(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
init_test("TCP port forwarding/tunneling", 4);
|
||||||
|
|
||||||
|
all_forward();
|
||||||
|
|
||||||
|
}
|
102
test/libssh2-test.h
Normal file
102
test/libssh2-test.h
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* prototest.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBSSH2_TEST_H
|
||||||
|
#define LIBSSH2_TEST_H 1
|
||||||
|
|
||||||
|
#define MAX_LOGLINE_LEN 256
|
||||||
|
|
||||||
|
|
||||||
|
void log_line(int priority, char *format, ...);
|
||||||
|
void init_test(char *msg, int num_items);
|
||||||
|
void increase_progress(void);
|
||||||
|
void step_successful(void);
|
||||||
|
void output_testresults(void);
|
||||||
|
int new_socket(void);
|
||||||
|
void runtest_methods(void);
|
||||||
|
void runtest_auth(void);
|
||||||
|
void runtest_forward(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct authdefs {
|
||||||
|
char *hostname;
|
||||||
|
char *port;
|
||||||
|
char *username;
|
||||||
|
char *password;
|
||||||
|
char *privkey;
|
||||||
|
char *pubkey;
|
||||||
|
char *passphrase;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct methodlist {
|
||||||
|
int method_type;
|
||||||
|
char *description;
|
||||||
|
char **list;
|
||||||
|
int cursor;
|
||||||
|
int done;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct logentry {
|
||||||
|
int priority;
|
||||||
|
char *logline;
|
||||||
|
struct logentry *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct logresults {
|
||||||
|
char *description;
|
||||||
|
int num_steps;
|
||||||
|
int success_steps;
|
||||||
|
int progress;
|
||||||
|
struct logentry *log;
|
||||||
|
struct logresults *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ERROR,
|
||||||
|
WARNING,
|
||||||
|
NORMAL,
|
||||||
|
DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
174
test/main.c
Normal file
174
test/main.c
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* main.c -- ssh2 protocol compliance tester for libssh2
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||||
|
* 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 <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wordexp.h>
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
#include "libssh2-test.h"
|
||||||
|
|
||||||
|
struct authdefs auth;
|
||||||
|
char *progress_message;
|
||||||
|
int progress, progress_max;
|
||||||
|
struct addrinfo *hostai = NULL, *cur_ai = NULL;
|
||||||
|
|
||||||
|
extern struct logresults *testlogs;
|
||||||
|
extern struct logentry *logfile;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cleanup(void)
|
||||||
|
{
|
||||||
|
struct logresults *test, *nexttest;
|
||||||
|
struct logentry *logfile, *nextlog;
|
||||||
|
|
||||||
|
if(hostai)
|
||||||
|
freeaddrinfo(hostai);
|
||||||
|
|
||||||
|
test = testlogs;
|
||||||
|
while(test)
|
||||||
|
{
|
||||||
|
logfile = test->log;
|
||||||
|
while(logfile)
|
||||||
|
{
|
||||||
|
nextlog = logfile->next;
|
||||||
|
free(logfile->logline);
|
||||||
|
free(logfile);
|
||||||
|
|
||||||
|
logfile = nextlog;
|
||||||
|
}
|
||||||
|
nexttest = test->next;
|
||||||
|
free(test);
|
||||||
|
|
||||||
|
test = nexttest;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(auth.hostname);
|
||||||
|
free(auth.port);
|
||||||
|
free(auth.username);
|
||||||
|
free(auth.password);
|
||||||
|
free(auth.privkey);
|
||||||
|
free(auth.pubkey);
|
||||||
|
free(auth.passphrase);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *get_interactive(char *prompt, int size, char *default_value)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
if( !(str = malloc(size)) )
|
||||||
|
{
|
||||||
|
log_line(ERROR, "unable to malloc %d bytes for %s\n", size, prompt);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s [%s]: ", prompt, default_value);
|
||||||
|
fgets(str, size, stdin);
|
||||||
|
if(str[strlen(str)-1] == '\n')
|
||||||
|
str[strlen(str)-1] = 0;
|
||||||
|
if(!str[0])
|
||||||
|
strncpy(str, default_value, size);
|
||||||
|
|
||||||
|
return(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *resolve_tilde(char *path)
|
||||||
|
{
|
||||||
|
wordexp_t we;
|
||||||
|
|
||||||
|
if( (wordexp(path, &we, 0)) == 0 && we.we_wordc == 1)
|
||||||
|
{
|
||||||
|
free(path);
|
||||||
|
path = strdup(we.we_wordv[0]);
|
||||||
|
wordfree(&we);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void get_auth(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
auth.hostname = get_interactive("hostname", 64, "localhost");
|
||||||
|
auth.port = get_interactive("port", 6, "22");
|
||||||
|
// auth.username = get_interactive("username", 20, getenv("USER"));
|
||||||
|
// auth.password = get_interactive("password", 20, "");
|
||||||
|
auth.username = get_interactive("username", 20, "bert2");
|
||||||
|
auth.password = get_interactive("password", 20, "blinko");
|
||||||
|
|
||||||
|
auth.privkey = resolve_tilde(get_interactive("private key filename", 128, "~/.ssh/id_dsa"));
|
||||||
|
auth.pubkey = resolve_tilde(get_interactive("public key filename", 128, "~/.ssh/id_dsa.pub"));
|
||||||
|
auth.passphrase = get_interactive("passphrase", 256, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
get_auth();
|
||||||
|
if(!strlen(auth.username) || !strlen(auth.password))
|
||||||
|
{
|
||||||
|
printf("Not enough authentication info to continue.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
runtest_methods();
|
||||||
|
runtest_auth();
|
||||||
|
runtest_forward();
|
||||||
|
|
||||||
|
output_testresults();
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
214
test/methods.c
Normal file
214
test/methods.c
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* methods.c -- test all available key exchange, hostkey, encryption, mac
|
||||||
|
* and compression methods
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
#include "libssh2-test.h"
|
||||||
|
|
||||||
|
extern struct authdefs auth;
|
||||||
|
|
||||||
|
|
||||||
|
static char *kex_methods[] = {
|
||||||
|
"diffie-hellman-group1-sha1",
|
||||||
|
"diffie-hellman-group14-sha1",
|
||||||
|
"diffie-hellman-group-exchange-sha1",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *hostkey_methods[] = {
|
||||||
|
"ssh-dss",
|
||||||
|
"ssh-rsa",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *crypt_methods[] = {
|
||||||
|
"3des-cbc",
|
||||||
|
"aes256-cbc",
|
||||||
|
"aes192-cbc",
|
||||||
|
"aes128-cbc",
|
||||||
|
"blowfish-cbc",
|
||||||
|
"arcfour",
|
||||||
|
"cast128-cbc",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *mac_methods[] = {
|
||||||
|
"hmac-sha1",
|
||||||
|
"hmac-sha1-96",
|
||||||
|
"hmac-md5",
|
||||||
|
"hmac-md5-96",
|
||||||
|
"hmac-ripemd160",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *compression_methods[] = {
|
||||||
|
"none",
|
||||||
|
"zlib",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct methodlist methods[] = {
|
||||||
|
{ LIBSSH2_METHOD_KEX, "kex", kex_methods, 0, 0 },
|
||||||
|
{ LIBSSH2_METHOD_HOSTKEY, "hostkey", hostkey_methods, 0, 0 },
|
||||||
|
{ LIBSSH2_METHOD_CRYPT_CS, "crypt (cs)", crypt_methods, 0, 0 },
|
||||||
|
{ LIBSSH2_METHOD_CRYPT_SC, "crypt (sc)", crypt_methods, 0, 0 },
|
||||||
|
{ LIBSSH2_METHOD_MAC_CS, "MAC (cs)", mac_methods, 0, 0 },
|
||||||
|
{ LIBSSH2_METHOD_MAC_SC, "MAC (sc)", mac_methods, 0, 0 },
|
||||||
|
{ LIBSSH2_METHOD_COMP_CS, "compression (cs)", compression_methods, 0, 0 },
|
||||||
|
{ LIBSSH2_METHOD_COMP_SC, "compression (sc)", compression_methods, 0, 0 },
|
||||||
|
{ 0, NULL, NULL, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
static void dump_methods(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
|
||||||
|
printf(" Key exchange methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_KEX));
|
||||||
|
printf(" Hostkey methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_HOSTKEY));
|
||||||
|
printf(" Crypt C->S methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_CS));
|
||||||
|
printf(" Crypt S->C methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_SC));
|
||||||
|
printf(" MAC C->S methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_MAC_CS));
|
||||||
|
printf(" MAC S->C methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_MAC_SC));
|
||||||
|
printf("Compression C->S methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_COMP_CS));
|
||||||
|
printf("Compression S->C methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_COMP_SC));
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static void cycle_methods(void)
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session;
|
||||||
|
int sock, size, res, method_type, method, i, methods_set;
|
||||||
|
char *errmsg;
|
||||||
|
|
||||||
|
method_type = 0;
|
||||||
|
method = 0;
|
||||||
|
while(methods[method_type].description)
|
||||||
|
{
|
||||||
|
while(methods[method_type].list[method])
|
||||||
|
{
|
||||||
|
increase_progress();
|
||||||
|
sock = new_socket();
|
||||||
|
if(sock == -1)
|
||||||
|
{
|
||||||
|
log_line(ERROR, "new_socket() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session = libssh2_session_init();
|
||||||
|
|
||||||
|
methods_set = 1;
|
||||||
|
for(i = 0; methods[i].description; i++)
|
||||||
|
{
|
||||||
|
res = libssh2_session_method_pref(session, methods[i].method_type,
|
||||||
|
methods[i].list[ i == method_type ? method : 0 ]);
|
||||||
|
if(res != 0)
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "%s method set to '%s' failed: %s\n",
|
||||||
|
methods[i].description,
|
||||||
|
methods[i].list[ i == method_type ? method : 0 ], errmsg);
|
||||||
|
|
||||||
|
methods_set = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(methods_set)
|
||||||
|
{
|
||||||
|
res = libssh2_session_startup(session, sock);
|
||||||
|
if(res == 0)
|
||||||
|
{
|
||||||
|
if(libssh2_userauth_password(session, auth.username, auth.password))
|
||||||
|
{
|
||||||
|
log_line(ERROR, "Authentication failed\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
step_successful();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||||
|
log_line(ERROR, "Session startup for %s method %s failed: %s\n",
|
||||||
|
methods[method_type].description, methods[method_type].list[method], errmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
libssh2_session_disconnect(session, "All done.");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
method++;
|
||||||
|
}
|
||||||
|
method_type++;
|
||||||
|
method = 1;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void runtest_methods(void)
|
||||||
|
{
|
||||||
|
int i, j, num_steps;
|
||||||
|
|
||||||
|
num_steps = 0;
|
||||||
|
for(i = 0; methods[i].description; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; methods[i].list[j]; j++)
|
||||||
|
;
|
||||||
|
num_steps += j - 1;
|
||||||
|
}
|
||||||
|
num_steps++;
|
||||||
|
|
||||||
|
init_test("kex/hostkey/crypt/mac/compression methods", num_steps);
|
||||||
|
|
||||||
|
cycle_methods();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
222
test/util.c
Normal file
222
test/util.c
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* util.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
#include "libssh2-test.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern struct addrinfo *hostai, *cur_ai;
|
||||||
|
struct logresults *testlogs = NULL, *cur_testlog;
|
||||||
|
struct logentry *logfile = NULL, *cur_logentry;
|
||||||
|
|
||||||
|
extern struct authdefs auth;
|
||||||
|
extern char *progress_message;
|
||||||
|
extern int progress, progress_max;
|
||||||
|
|
||||||
|
|
||||||
|
struct loglevel {
|
||||||
|
int priority;
|
||||||
|
char *descr;
|
||||||
|
} loglevels[] = {
|
||||||
|
{ ERROR, "ERROR" },
|
||||||
|
{ WARNING, "WARNING" },
|
||||||
|
{ NORMAL, "NORMAL" },
|
||||||
|
{ DEBUG, "DEBUG" }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void log_line(int priority, char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
struct logentry *entry;
|
||||||
|
char line[MAX_LOGLINE_LEN];
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf(line, MAX_LOGLINE_LEN, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
entry = malloc(sizeof(struct logentry));
|
||||||
|
entry->priority = priority;
|
||||||
|
entry->logline = malloc(strlen(line)+1);
|
||||||
|
strcpy(entry->logline, line);
|
||||||
|
entry->next = NULL;
|
||||||
|
|
||||||
|
if(!cur_testlog->log)
|
||||||
|
cur_testlog->log = entry;
|
||||||
|
else
|
||||||
|
cur_logentry->next = entry;
|
||||||
|
|
||||||
|
cur_logentry = entry;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void init_test(char *msg, int num_items)
|
||||||
|
{
|
||||||
|
struct logresults *newtest;
|
||||||
|
|
||||||
|
newtest = malloc(sizeof(struct logresults));
|
||||||
|
newtest->description = msg;
|
||||||
|
newtest->num_steps = num_items;
|
||||||
|
newtest->success_steps = 0;
|
||||||
|
newtest->progress = 0;
|
||||||
|
newtest->log = NULL;
|
||||||
|
newtest->next = NULL;
|
||||||
|
|
||||||
|
if(!testlogs)
|
||||||
|
testlogs = newtest;
|
||||||
|
else
|
||||||
|
cur_testlog->next = newtest;
|
||||||
|
|
||||||
|
cur_testlog = newtest;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void increase_progress(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
cur_testlog->progress++;
|
||||||
|
|
||||||
|
printf("Testing %s... %3d/%d\r", cur_testlog->description, cur_testlog->progress, cur_testlog->num_steps);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void step_successful(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
cur_testlog->success_steps++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void output_testresults(void)
|
||||||
|
{
|
||||||
|
struct logresults *test;
|
||||||
|
struct logentry *logfile;
|
||||||
|
int total_steps, total_success;
|
||||||
|
|
||||||
|
printf("\nTest results\n============\n");
|
||||||
|
|
||||||
|
total_steps = 0;
|
||||||
|
total_success = 0;
|
||||||
|
test = testlogs;
|
||||||
|
while(test)
|
||||||
|
{
|
||||||
|
total_steps += test->num_steps;
|
||||||
|
total_success += test->success_steps;
|
||||||
|
printf("Test: %s (%d/%d)\n", test->description, test->success_steps, test->num_steps);
|
||||||
|
logfile = test->log;
|
||||||
|
while(logfile)
|
||||||
|
{
|
||||||
|
printf(" %s", logfile->logline);
|
||||||
|
logfile = logfile->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
test = test->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%d/%d steps successful\n", total_success, total_steps);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int new_socket(void)
|
||||||
|
{
|
||||||
|
int sock, res;
|
||||||
|
struct addrinfo hints, *ai;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = PF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
if(!hostai)
|
||||||
|
{
|
||||||
|
res = getaddrinfo(auth.hostname, auth.port, &hints, &hostai);
|
||||||
|
if(res)
|
||||||
|
{
|
||||||
|
printf("unable to resolve %s: %s\n", auth.hostname, gai_strerror(res));
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sock = 0;
|
||||||
|
ai = hostai;
|
||||||
|
while(ai)
|
||||||
|
{
|
||||||
|
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||||
|
if(sock > 0)
|
||||||
|
{
|
||||||
|
res = connect(sock, ai->ai_addr, ai->ai_addrlen);
|
||||||
|
if(res == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
sock = 0;
|
||||||
|
}
|
||||||
|
ai = ai->ai_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!sock)
|
||||||
|
{
|
||||||
|
printf("unable to connect: %s\n", strerror(errno));
|
||||||
|
close(sock);
|
||||||
|
sock = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_ai = ai;
|
||||||
|
|
||||||
|
return(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@@ -7,3 +7,6 @@
|
|||||||
Debug
|
Debug
|
||||||
Release
|
Release
|
||||||
*.exp
|
*.exp
|
||||||
|
*.ncb
|
||||||
|
*.opt
|
||||||
|
*.plg
|
||||||
|
156
win32/libssh2.dsp
Normal file
156
win32/libssh2.dsp
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
# 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) 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 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "libssh2 - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE "libssh2 - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "libssh2 - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "libssh2___Win32_Release"
|
||||||
|
# PROP BASE Intermediate_Dir "libssh2___Win32_Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# 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 "..\include" /I "..\win32" /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
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "libssh2 - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# 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 "..\include" /I "..\win32" /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\libssh2d.lib"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "libssh2 - Win32 Release"
|
||||||
|
# Name "libssh2 - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\channel.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\comp.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\crypt.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\hostkey.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\kex.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\mac.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\misc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\packet.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\scp.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\session.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\sftp.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\userauth.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\libssh2.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\libssh2_config.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\libssh2_priv.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\libssh2_sftp.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
41
win32/libssh2.dsw
Normal file
41
win32/libssh2.dsw
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "libssh2"=.\libssh2.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "ssh2_sample"=.\ssh2_sample.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
@@ -1,4 +1,6 @@
|
|||||||
#define WIN32
|
#ifndef WIN32
|
||||||
|
#define WIN32
|
||||||
|
#endif
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <mswsock.h>
|
#include <mswsock.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
@@ -29,3 +31,8 @@ static inline int usleep(int udelay)
|
|||||||
|
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
|
|
||||||
|
/* Compile in zlib support */
|
||||||
|
#define LIBSSH2_HAVE_ZLIB 1
|
||||||
|
|
||||||
|
/* Enable newer diffie-hellman-group-exchange-sha1 syntax */
|
||||||
|
#define LIBSSH2_DH_GEX_NEW 1
|
||||||
|
102
win32/ssh2_sample.dsp
Normal file
102
win32/ssh2_sample.dsp
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="ssh2_sample" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=ssh2_sample - 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 "ssh2_sample.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 "ssh2_sample.mak" CFG="ssh2_sample - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "ssh2_sample - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "ssh2_sample - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "ssh2_sample - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "ssh2_sample___Win32_Release"
|
||||||
|
# PROP BASE Intermediate_Dir "ssh2_sample___Win32_Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\include" /I "..\win32" /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBSSH2_LIBRARY" /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
|
||||||
|
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 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 /subsystem:console /machine:I386
|
||||||
|
# ADD 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libeay32.lib ssleay32.lib ws2_32.lib zlib.lib libssh2.lib /nologo /subsystem:console /machine:I386 /libpath:"Release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "ssh2_sample - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "ssh2_sample___Win32_Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "ssh2_sample___Win32_Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# 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 "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\win32" /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBSSH2_LIBRARY" /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
|
||||||
|
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 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 /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libeay32.lib ssleay32.lib ws2_32.lib zlib.lib libssh2d.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept /libpath:"Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "ssh2_sample - Win32 Release"
|
||||||
|
# Name "ssh2_sample - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\ssh2_sample.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
Reference in New Issue
Block a user