Update libssh

This commit is contained in:
Nicolas Viennot 2013-11-06 19:40:47 -05:00
parent 92bf230b8a
commit 2535b531bb
41 changed files with 615 additions and 278 deletions

View File

@ -71,6 +71,13 @@ if (WITH_GSSAPI)
find_package(GSSAPI) find_package(GSSAPI)
endif (WITH_GSSAPI) endif (WITH_GSSAPI)
if (WITH_NACL)
find_package(NaCl)
if (NOT NACL_FOUND)
set(WITH_NACL OFF)
endif (NOT NACL_FOUND)
endif (WITH_NACL)
# config.h checks # config.h checks
include(ConfigureChecks.cmake) include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
@ -125,6 +132,7 @@ message(STATUS "********** ${PROJECT_NAME} build options : **********")
message(STATUS "zlib support: ${WITH_ZLIB}") message(STATUS "zlib support: ${WITH_ZLIB}")
message(STATUS "libgcrypt support: ${WITH_GCRYPT}") message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
message(STATUS "libnacl support: ${WITH_NACL}")
message(STATUS "SSH-1 support: ${WITH_SSH1}") message(STATUS "SSH-1 support: ${WITH_SSH1}")
message(STATUS "SFTP support: ${WITH_SFTP}") message(STATUS "SFTP support: ${WITH_SFTP}")
message(STATUS "Server support : ${WITH_SERVER}") message(STATUS "Server support : ${WITH_SERVER}")

View File

@ -50,6 +50,7 @@ check_include_file(argp.h HAVE_ARGP_H)
check_include_file(pty.h HAVE_PTY_H) check_include_file(pty.h HAVE_PTY_H)
check_include_file(termios.h HAVE_TERMIOS_H) check_include_file(termios.h HAVE_TERMIOS_H)
check_include_file(unistd.h HAVE_UNISTD_H) check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(util.h HAVE_UTIL_H)
if (WIN32) if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H) check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
@ -93,6 +94,7 @@ endif (NOT WITH_GCRYPT)
# FUNCTIONS # FUNCTIONS
check_function_exists(isblank HAVE_ISBLANK)
check_function_exists(strncpy HAVE_STRNCPY) check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(vsnprintf HAVE_VSNPRINTF) check_function_exists(vsnprintf HAVE_VSNPRINTF)
check_function_exists(snprintf HAVE_SNPRINTF) check_function_exists(snprintf HAVE_SNPRINTF)

View File

@ -13,7 +13,7 @@ option(WITH_TESTING "Build with unit tests" OFF)
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF) option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
option(WITH_BENCHMARKS "Build benchmarks tools" OFF) option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
option(WITH_EXAMPLES "Build examples" ON) option(WITH_EXAMPLES "Build examples" ON)
option(WITH_NACL "Build with libnacl (curve25519" ON)
if (WITH_ZLIB) if (WITH_ZLIB)
set(WITH_LIBZ ON) set(WITH_LIBZ ON)
else (WITH_ZLIB) else (WITH_ZLIB)
@ -27,3 +27,7 @@ endif(WITH_BENCHMARKS)
if (WITH_TESTING) if (WITH_TESTING)
set(WITH_STATIC_LIB ON) set(WITH_STATIC_LIB ON)
endif (WITH_TESTING) endif (WITH_TESTING)
if (WITH_NACL)
set(WITH_NACL ON)
endif (WITH_NACL)

View File

@ -26,3 +26,7 @@ endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
if (CMAKE_SYSTEM_NAME MATCHES "OS2") if (CMAKE_SYSTEM_NAME MATCHES "OS2")
set(OS2 TRUE) set(OS2 TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OS2") endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
set (OSX TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "Darwin")

View File

@ -20,6 +20,9 @@
/* Define to 1 if you have the <pty.h> header file. */ /* Define to 1 if you have the <pty.h> header file. */
#cmakedefine HAVE_PTY_H 1 #cmakedefine HAVE_PTY_H 1
/* Define to 1 if you have the <util.h> header file. */
#cmakedefine HAVE_UTIL_H 1
/* Define to 1 if you have the <termios.h> header file. */ /* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H 1 #cmakedefine HAVE_TERMIOS_H 1
@ -79,6 +82,9 @@
/* Define to 1 if you have the `_vsnprintf_s' function. */ /* Define to 1 if you have the `_vsnprintf_s' function. */
#cmakedefine HAVE__VSNPRINTF_S 1 #cmakedefine HAVE__VSNPRINTF_S 1
/* Define to 1 if you have the `isblank' function. */
#cmakedefine HAVE_ISBLANK 1
/* Define to 1 if you have the `strncpy' function. */ /* Define to 1 if you have the `strncpy' function. */
#cmakedefine HAVE_STRNCPY 1 #cmakedefine HAVE_STRNCPY 1
@ -123,7 +129,6 @@
/* Define to 1 if you have the `pthread' library (-lpthread). */ /* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine HAVE_PTHREAD 1 #cmakedefine HAVE_PTHREAD 1
/**************************** OPTIONS ****************************/ /**************************** OPTIONS ****************************/
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1 #cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
@ -155,6 +160,9 @@
/* Define to 1 if you want to enable calltrace debug output */ /* Define to 1 if you want to enable calltrace debug output */
#cmakedefine DEBUG_CALLTRACE 1 #cmakedefine DEBUG_CALLTRACE 1
/* Define to 1 if you want to enable NaCl support */
#cmakedefine WITH_NACL 1
/*************************** ENDIAN *****************************/ /*************************** ENDIAN *****************************/
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most

View File

@ -1628,7 +1628,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator # undefined via #undef or recursively expanded use the := operator
# instead of the = operator. # instead of the = operator.
PREDEFINED = PREDEFINED = WITH_SERVER WITH_SFTP WITH_PCAP
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded. # this tag can be used to specify a list of macro names that should be expanded.

View File

@ -19,7 +19,7 @@ the interesting functions as you go.
The libssh library provides: The libssh library provides:
- <strong>Key Exchange Methods</strong>: <i>ecdh-sha2-nistp256</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1 - <strong>Key Exchange Methods</strong>: <i>curve25519-sha256@libssh.org, ecdh-sha2-nistp256</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
- <strong>Hostkey Types</strong>: <i>ecdsa-sha2-nistp256</i>, ssh-dss, ssh-rsa - <strong>Hostkey Types</strong>: <i>ecdsa-sha2-nistp256</i>, ssh-dss, ssh-rsa
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, des-cbc-ssh1, blowfish-cbc, none - <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, des-cbc-ssh1, blowfish-cbc, none
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none - <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
@ -184,6 +184,8 @@ It was later modified and expanded by the following RFCs.
Authentication and Key Exchange for the Secure Shell (SSH) Protocol Authentication and Key Exchange for the Secure Shell (SSH) Protocol
- <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>, - <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
The Secure Shell (SSH) Public Key File Format The Secure Shell (SSH) Public Key File Format
- <a href="http://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
AES Galois Counter Mode for the Secure Shell Transport Layer Protocol
- <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>, - <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
@ -203,6 +205,12 @@ do the same in libssh.
@subsection main-rfc-extensions Secure Shell Extensions @subsection main-rfc-extensions Secure Shell Extensions
The libssh project has an extension to support Curve25519 which is also supported by
the OpenSSH project.
- <a href="" target="_blank">curve25519-sha256@libssh.org</a>,
Curve25519-SHA256 for ECDH KEX
The OpenSSH project has defined some extensions to the protocol. We support some of The OpenSSH project has defined some extensions to the protocol. We support some of
them like the statvfs calls in SFTP or the ssh-agent. them like the statvfs calls in SFTP or the ssh-agent.

View File

@ -210,52 +210,63 @@ results to come.
Synchronous read is done with sftp_read(). Synchronous read is done with sftp_read().
The following example prints the contents of remote file "/etc/profile". For Files are normally transferred in chunks. A good chunk size is 16 KB. The following
each 1024 bytes of information read, it waits until the end of the read operation: example transfers the remote file "/etc/profile" in 16 KB chunks. For each chunk we
request, sftp_read blocks till the data has been received:
@code @code
// Good chunk size
#define MAX_XFER_BUF_SIZE 16384
int sftp_read_sync(ssh_session session, sftp_session sftp) int sftp_read_sync(ssh_session session, sftp_session sftp)
{ {
int access_type; int access_type;
sftp_file file; sftp_file file;
char buffer[1024]; char buffer[MAX_XFER_BUF_SIZE];
int nbytes, rc; int nbytes, nwritten, rc;
int fd;
access_type = O_RDONLY; access_type = O_RDONLY;
file = sftp_open(sftp, "/etc/profile", file = sftp_open(sftp, "/etc/profile",
access_type, 0); access_type, 0);
if (file == NULL) if (file == NULL) {
{ fprintf(stderr, "Can't open file for reading: %s\n",
fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
ssh_get_error(session));
return SSH_ERROR;
}
nbytes = sftp_read(file, buffer, sizeof(buffer));
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != nbytes)
{
sftp_close(file);
return SSH_ERROR; return SSH_ERROR;
}
nbytes = sftp_read(file, buffer, sizeof(buffer));
} }
if (nbytes < 0) fd = open("/path/to/profile", O_CREAT);
{ if (fd < 0) {
fprintf(stderr, "Error while reading file: %s\n", fprintf(stderr, "Can't open file for writing: %s\n",
ssh_get_error(session)); strerror(errno));
sftp_close(file); return SSH_ERROR;
return SSH_ERROR; }
for (;;) {
nbytes = sftp_read(file, buffer, sizeof(buffer));
if (nbytes == 0) {
break; // EOF
} else if (nbytes < 0) {
fprintf(stderr, "Error while reading file: %s\n",
ssh_get_error(session));
sftp_close(file);
return SSH_ERROR;
}
nwritten = write(fd, buf, nbytes);
if (nwritten != nbytes) {
fprintf(stderr, "Error writing: %s\n",
strerror(errno));
sftp_close(file);
return SSH_ERROR;
}
} }
rc = sftp_close(file); rc = sftp_close(file);
if (rc != SSH_OK) if (rc != SSH_OK) {
{ fprintf(stderr, "Can't close the read file: %s\n",
fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
ssh_get_error(session)); return rc;
return rc;
} }
return SSH_OK; return SSH_OK;
@ -274,11 +285,14 @@ The example below reads a very big file in asynchronous, nonblocking, mode. Each
time the data are not ready yet, a counter is incrementer. time the data are not ready yet, a counter is incrementer.
@code @code
// Good chunk size
#define MAX_XFER_BUF_SIZE 16384
int sftp_read_async(ssh_session session, sftp_session sftp) int sftp_read_async(ssh_session session, sftp_session sftp)
{ {
int access_type; int access_type;
sftp_file file; sftp_file file;
char buffer[1024]; char buffer[MAX_XFER_BUF_SIZE];
int async_request; int async_request;
int nbytes; int nbytes;
long counter; long counter;
@ -287,8 +301,7 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
access_type = O_RDONLY; access_type = O_RDONLY;
file = sftp_open(sftp, "some_very_big_file", file = sftp_open(sftp, "some_very_big_file",
access_type, 0); access_type, 0);
if (file == NULL) if (file == NULL) {
{
fprintf(stderr, "Can't open file for reading: %s\n", fprintf(stderr, "Can't open file for reading: %s\n",
ssh_get_error(session)); ssh_get_error(session));
return SSH_ERROR; return SSH_ERROR;
@ -298,27 +311,31 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
async_request = sftp_async_read_begin(file, sizeof(buffer)); async_request = sftp_async_read_begin(file, sizeof(buffer));
counter = 0L; counter = 0L;
usleep(10000); usleep(10000);
if (async_request >= 0) if (async_request >= 0) {
nbytes = sftp_async_read(file, buffer, sizeof(buffer), nbytes = sftp_async_read(file, buffer, sizeof(buffer),
async_request); async_request);
else nbytes = -1; } else {
while (nbytes > 0 || nbytes == SSH_AGAIN) nbytes = -1;
{
if (nbytes > 0)
{
write(1, buffer, nbytes);
async_request = sftp_async_read_begin(file, sizeof(buffer));
}
else counter++;
usleep(10000);
if (async_request >= 0)
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
async_request);
else nbytes = -1;
} }
if (nbytes < 0) while (nbytes > 0 || nbytes == SSH_AGAIN) {
{ if (nbytes > 0) {
write(1, buffer, nbytes);
async_request = sftp_async_read_begin(file, sizeof(buffer));
} else {
counter++;
}
usleep(10000);
if (async_request >= 0) {
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
async_request);
} else {
nbytes = -1;
}
}
if (nbytes < 0) {
fprintf(stderr, "Error while reading file: %s\n", fprintf(stderr, "Error while reading file: %s\n",
ssh_get_error(session)); ssh_get_error(session));
sftp_close(file); sftp_close(file);
@ -328,8 +345,7 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
printf("The counter has reached value: %ld\n", counter); printf("The counter has reached value: %ld\n", counter);
rc = sftp_close(file); rc = sftp_close(file);
if (rc != SSH_OK) if (rc != SSH_OK) {
{
fprintf(stderr, "Can't close the read file: %s\n", fprintf(stderr, "Can't close the read file: %s\n",
ssh_get_error(session)); ssh_get_error(session));
return rc; return rc;

View File

@ -11,9 +11,9 @@ include_directories(
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
) )
if (BSD OR SOLARIS) if (BSD OR SOLARIS OR OSX)
find_package(Argp) find_package(Argp)
endif (BSD OR SOLARIS) endif (BSD OR SOLARIS OR OSX)
if (UNIX AND NOT WIN32) if (UNIX AND NOT WIN32)
add_executable(libssh_scp libssh_scp.c ${examples_SRCS}) add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
@ -28,7 +28,7 @@ if (UNIX AND NOT WIN32)
if (WITH_SERVER) if (WITH_SERVER)
if (HAVE_LIBUTIL) if (HAVE_LIBUTIL)
add_executable(samplesshd-tty samplesshd-tty.c) add_executable(samplesshd-tty samplesshd-tty.c)
target_link_libraries(samplesshd-tty ${LIBSSH_SHARED_LIBRARY} util) target_link_libraries(samplesshd-tty ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES} util)
endif (HAVE_LIBUTIL) endif (HAVE_LIBUTIL)
endif (WITH_SERVER) endif (WITH_SERVER)

View File

@ -34,14 +34,26 @@ int verify_knownhost(ssh_session session){
int state; int state;
char buf[10]; char buf[10];
unsigned char *hash = NULL; unsigned char *hash = NULL;
int hlen; size_t hlen;
ssh_key srv_pubkey;
int rc;
state=ssh_is_server_known(session); state=ssh_is_server_known(session);
hlen = ssh_get_pubkey_hash(session, &hash); rc = ssh_get_publickey(session, &srv_pubkey);
if (hlen < 0) { if (rc < 0) {
return -1; return -1;
} }
rc = ssh_get_publickey_hash(srv_pubkey,
SSH_PUBLICKEY_HASH_SHA1,
&hash,
&hlen);
ssh_key_free(srv_pubkey);
if (rc < 0) {
return -1;
}
switch(state){ switch(state){
case SSH_SERVER_KNOWN_OK: case SSH_SERVER_KNOWN_OK:
break; /* ok */ break; /* ok */

View File

@ -25,8 +25,12 @@ clients must be made or how a client should react.
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <poll.h> #include <poll.h>
#ifdef HAVE_PTY_H
#include <pty.h> #include <pty.h>
#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#define SSHD_USER "libssh" #define SSHD_USER "libssh"
#define SSHD_PASSWORD "libssh" #define SSHD_PASSWORD "libssh"

View File

@ -166,7 +166,7 @@ typedef struct ssh_callbacks_struct *ssh_callbacks;
* @param user User that wants to authenticate * @param user User that wants to authenticate
* @param password Password used for authentication * @param password Password used for authentication
* @param userdata Userdata to be passed to the callback function. * @param userdata Userdata to be passed to the callback function.
* @returns SSH_AUTH_OK Authentication is accepted. * @returns SSH_AUTH_SUCCESS Authentication is accepted.
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
* @returns SSH_AUTH_DENIED Authentication failed. * @returns SSH_AUTH_DENIED Authentication failed.
*/ */
@ -179,7 +179,7 @@ typedef int (*ssh_auth_password_callback) (ssh_session session, const char *user
* @param session Current session handler * @param session Current session handler
* @param user User that wants to authenticate * @param user User that wants to authenticate
* @param userdata Userdata to be passed to the callback function. * @param userdata Userdata to be passed to the callback function.
* @returns SSH_AUTH_OK Authentication is accepted. * @returns SSH_AUTH_SUCCESS Authentication is accepted.
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
* @returns SSH_AUTH_DENIED Authentication failed. * @returns SSH_AUTH_DENIED Authentication failed.
*/ */
@ -191,7 +191,7 @@ typedef int (*ssh_auth_none_callback) (ssh_session session, const char *user, vo
* @param user Username of the user (can be spoofed) * @param user Username of the user (can be spoofed)
* @param principal Authenticated principal of the user, including realm. * @param principal Authenticated principal of the user, including realm.
* @param userdata Userdata to be passed to the callback function. * @param userdata Userdata to be passed to the callback function.
* @returns SSH_AUTH_OK Authentication is accepted. * @returns SSH_AUTH_SUCCESS Authentication is accepted.
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
* @returns SSH_AUTH_DENIED Authentication failed. * @returns SSH_AUTH_DENIED Authentication failed.
* @warning Implementations should verify that parameter user matches in some way the principal. * @warning Implementations should verify that parameter user matches in some way the principal.
@ -209,7 +209,7 @@ typedef int (*ssh_auth_gssapi_mic_callback) (ssh_session session, const char *us
* SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be * SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be
* replied with a SSH_AUTH_DENIED. * replied with a SSH_AUTH_DENIED.
* @param userdata Userdata to be passed to the callback function. * @param userdata Userdata to be passed to the callback function.
* @returns SSH_AUTH_OK Authentication is accepted. * @returns SSH_AUTH_SUCCESS Authentication is accepted.
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
* @returns SSH_AUTH_DENIED Authentication failed. * @returns SSH_AUTH_DENIED Authentication failed.
*/ */

View File

@ -26,15 +26,23 @@
#ifdef WITH_NACL #ifdef WITH_NACL
#define HAVE_CURVE25519
#include <nacl/crypto_scalarmult_curve25519.h> #include <nacl/crypto_scalarmult_curve25519.h>
#define CURVE25519_PUBKEY_SIZE crypto_scalarmult_curve25519_BYTES #define CURVE25519_PUBKEY_SIZE crypto_scalarmult_curve25519_BYTES
#define CURVE25519_PRIVKEY_SIZE crypto_scalarmult_curve25519_SCALARBYTES #define CURVE25519_PRIVKEY_SIZE crypto_scalarmult_curve25519_SCALARBYTES
#define crypto_scalarmult_base crypto_scalarmult_curve25519_base
#define crypto_scalarmult crypto_scalarmult_curve25519
#else
#define CURVE25519_PUBKEY_SIZE 32
#define CURVE25519_PRIVKEY_SIZE 32
int crypto_scalarmult_base(unsigned char *q, const unsigned char *n);
int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
#endif /* WITH_NACL */
#define HAVE_CURVE25519
typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE]; typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE];
typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE]; typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
#endif /* WITH_NACL */
int ssh_client_curve25519_init(ssh_session session); int ssh_client_curve25519_init(ssh_session session);
int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet); int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet);

View File

@ -38,6 +38,11 @@ typedef SHA_CTX* SHACTX;
typedef SHA256_CTX* SHA256CTX; typedef SHA256_CTX* SHA256CTX;
typedef MD5_CTX* MD5CTX; typedef MD5_CTX* MD5CTX;
typedef HMAC_CTX* HMACCTX; typedef HMAC_CTX* HMACCTX;
#ifdef HAVE_ECC
typedef EVP_MD_CTX *EVPCTX;
#else
typedef void *EVPCTX;
#endif
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
#ifdef MD5_DIGEST_LEN #ifdef MD5_DIGEST_LEN

View File

@ -29,6 +29,7 @@
typedef gcry_md_hd_t SHACTX; typedef gcry_md_hd_t SHACTX;
typedef gcry_md_hd_t MD5CTX; typedef gcry_md_hd_t MD5CTX;
typedef gcry_md_hd_t HMACCTX; typedef gcry_md_hd_t HMACCTX;
typedef void *EVPCTX;
#define SHA_DIGEST_LENGTH 20 #define SHA_DIGEST_LENGTH 20
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
#define MD5_DIGEST_LEN 16 #define MD5_DIGEST_LEN 16

View File

@ -208,10 +208,14 @@ enum ssh_publickey_state_e {
SSH_PUBLICKEY_STATE_WRONG=2 SSH_PUBLICKEY_STATE_WRONG=2
}; };
/* status flags */ /* Status flags */
/** Socket is closed */
#define SSH_CLOSED 0x01 #define SSH_CLOSED 0x01
/** Reading to socket won't block */
#define SSH_READ_PENDING 0x02 #define SSH_READ_PENDING 0x02
/** Session was closed due to an error */
#define SSH_CLOSED_ERROR 0x04 #define SSH_CLOSED_ERROR 0x04
/** Output buffer not empty */
#define SSH_WRITE_PENDING 0x08 #define SSH_WRITE_PENDING 0x08
enum ssh_server_known_e { enum ssh_server_known_e {
@ -408,8 +412,20 @@ LIBSSH_API socket_t ssh_get_fd(ssh_session session);
LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len); LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len);
LIBSSH_API char *ssh_get_issue_banner(ssh_session session); LIBSSH_API char *ssh_get_issue_banner(ssh_session session);
LIBSSH_API int ssh_get_openssh_version(ssh_session session); LIBSSH_API int ssh_get_openssh_version(ssh_session session);
LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key); LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key);
LIBSSH_API int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash);
enum ssh_publickey_hash_type {
SSH_PUBLICKEY_HASH_SHA1,
SSH_PUBLICKEY_HASH_MD5
};
LIBSSH_API int ssh_get_publickey_hash(const ssh_key key,
enum ssh_publickey_hash_type type,
unsigned char **hash,
size_t *hlen);
SSH_DEPRECATED LIBSSH_API int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash);
LIBSSH_API int ssh_get_random(void *where,int len,int strong); LIBSSH_API int ssh_get_random(void *where,int len,int strong);
LIBSSH_API int ssh_get_version(ssh_session session); LIBSSH_API int ssh_get_version(ssh_session session);
LIBSSH_API int ssh_get_status(ssh_session session); LIBSSH_API int ssh_get_status(ssh_session session);

View File

@ -60,6 +60,7 @@ struct ssh_key_struct {
struct ssh_signature_struct { struct ssh_signature_struct {
enum ssh_keytypes_e type; enum ssh_keytypes_e type;
const char *type_c;
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_sexp_t dsa_sig; gcry_sexp_t dsa_sig;
gcry_sexp_t rsa_sig; gcry_sexp_t rsa_sig;

View File

@ -67,7 +67,9 @@
# define strcasecmp _stricmp # define strcasecmp _stricmp
# define strncasecmp _strnicmp # define strncasecmp _strnicmp
# define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r') # if ! defined(HAVE_ISBLANK)
# define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
# endif
# define usleep(X) Sleep(((X)+1000)/1000) # define usleep(X) Sleep(((X)+1000)/1000)
@ -153,6 +155,16 @@ int gettimeofday(struct timeval *__p, void *__t);
#include <sys/time.h> #include <sys/time.h>
#endif #endif
/*
* get rid of deprecacy warnings on OSX when using OpenSSL
*/
#if defined(__APPLE__)
#ifdef MAC_OS_X_VERSION_MIN_REQUIRED
#undef MAC_OS_X_VERSION_MIN_REQUIRED
#endif
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
#endif
/* forward declarations */ /* forward declarations */
struct ssh_common_struct; struct ssh_common_struct;
struct ssh_kex_struct; struct ssh_kex_struct;
@ -252,7 +264,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
/** Overwrite the buffer with '\0' */ /** Overwrite the buffer with '\0' */
# define BURN_BUFFER(x, size) do { \ # define BURN_BUFFER(x, size) do { \
if ((x) != NULL) \ if ((x) != NULL) \
memset((x), '\0', (size))); __asm__ volatile("" : : "r"(&(x)) : "memory"); \ memset((x), '\0', (size)); __asm__ volatile("" : : "r"(&(x)) : "memory"); \
} while(0) } while(0)
#else /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */ #else /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
/** Overwrite a string with '\0' */ /** Overwrite a string with '\0' */
@ -263,7 +275,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
/** Overwrite the buffer with '\0' */ /** Overwrite the buffer with '\0' */
# define BURN_BUFFER(x, size) do { \ # define BURN_BUFFER(x, size) do { \
if ((x) != NULL) \ if ((x) != NULL) \
memset((x), '\0', (size))); __asm__ volatile("" : : "r"(&(x)) : "memory"); \ memset((x), '\0', (size)); __asm__ volatile("" : : "r"(&(x)) : "memory"); \
} while(0) } while(0)
#endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */ #endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */

View File

@ -53,6 +53,9 @@ void sha1(unsigned char *digest,int len,unsigned char *hash);
void sha256(unsigned char *digest, int len, unsigned char *hash); void sha256(unsigned char *digest, int len, unsigned char *hash);
void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen); void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen);
EVPCTX evp_init(int nid);
void evp_update(EVPCTX ctx, const void *data, unsigned long len);
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen);
ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type); ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type);
void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len); void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len);

View File

@ -115,6 +115,7 @@ set(libssh_SRCS
client.c client.c
config.c config.c
connect.c connect.c
curve25519.c
dh.c dh.c
ecdh.c ecdh.c
error.c error.c
@ -204,12 +205,12 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
) )
endif (WITH_GSSAPI AND GSSAPI_FOUND) endif (WITH_GSSAPI AND GSSAPI_FOUND)
if (WITH_NACL) if (NOT WITH_NACL)
set(libssh_SRCS set(libssh_SRCS
${libssh_SRCS} ${libssh_SRCS}
curve25519.c curve25519_ref.c
) )
endif (WITH_NACL) endif (NOT WITH_NACL)
include_directories( include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS} ${LIBSSH_PUBLIC_INCLUDE_DIRS}

View File

@ -355,7 +355,7 @@ int ssh_userauth_list(ssh_session session, const char *username)
* later. * later.
* *
* @note Most server implementations do not permit changing the username during * @note Most server implementations do not permit changing the username during
* authentication. The username should only be set with ssh_optoins_set() only * authentication. The username should only be set with ssh_options_set() only
* before you connect to the server. * before you connect to the server.
*/ */
int ssh_userauth_none(ssh_session session, const char *username) { int ssh_userauth_none(ssh_session session, const char *username) {
@ -478,7 +478,7 @@ fail:
* later. * later.
* *
* @note Most server implementations do not permit changing the username during * @note Most server implementations do not permit changing the username during
* authentication. The username should only be set with ssh_optoins_set() only * authentication. The username should only be set with ssh_options_set() only
* before you connect to the server. * before you connect to the server.
*/ */
int ssh_userauth_try_publickey(ssh_session session, int ssh_userauth_try_publickey(ssh_session session,
@ -640,7 +640,7 @@ fail:
* later. * later.
* *
* @note Most server implementations do not permit changing the username during * @note Most server implementations do not permit changing the username during
* authentication. The username should only be set with ssh_optoins_set() only * authentication. The username should only be set with ssh_options_set() only
* before you connect to the server. * before you connect to the server.
*/ */
int ssh_userauth_publickey(ssh_session session, int ssh_userauth_publickey(ssh_session session,
@ -961,7 +961,7 @@ struct ssh_agent_state_struct {
* later. * later.
* *
* @note Most server implementations do not permit changing the username during * @note Most server implementations do not permit changing the username during
* authentication. The username should only be set with ssh_optoins_set() only * authentication. The username should only be set with ssh_options_set() only
* before you connect to the server. * before you connect to the server.
*/ */
int ssh_userauth_agent(ssh_session session, int ssh_userauth_agent(ssh_session session,
@ -1083,7 +1083,7 @@ struct ssh_auth_auto_state_struct {
* later. * later.
* *
* @note Most server implementations do not permit changing the username during * @note Most server implementations do not permit changing the username during
* authentication. The username should only be set with ssh_optoins_set() only * authentication. The username should only be set with ssh_options_set() only
* before you connect to the server. * before you connect to the server.
*/ */
int ssh_userauth_publickey_auto(ssh_session session, int ssh_userauth_publickey_auto(ssh_session session,
@ -1297,7 +1297,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
* later. * later.
* *
* @note Most server implementations do not permit changing the username during * @note Most server implementations do not permit changing the username during
* authentication. The username should only be set with ssh_optoins_set() only * authentication. The username should only be set with ssh_options_set() only
* before you connect to the server. * before you connect to the server.
* *
* @see ssh_userauth_none() * @see ssh_userauth_none()

View File

@ -454,8 +454,7 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
#else #else
close(fd); close(fd);
#endif #endif
if (session->socket) ssh_socket_free(session->socket);
ssh_socket_close(session->socket);
} }
return rc; return rc;
} }

View File

@ -2089,7 +2089,7 @@ SSH_PACKET_CALLBACK(ssh_request_denied){
static int ssh_global_request_termination(void *s){ static int ssh_global_request_termination(void *s){
ssh_session session = (ssh_session) s; ssh_session session = (ssh_session) s;
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING || if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING ||
session->session_state != SSH_SESSION_STATE_ERROR) session->session_state == SSH_SESSION_STATE_ERROR)
return 1; return 1;
else else
return 0; return 0;
@ -2117,43 +2117,66 @@ static int ssh_global_request_termination(void *s){
static int global_request(ssh_session session, const char *request, static int global_request(ssh_session session, const char *request,
ssh_buffer buffer, int reply) { ssh_buffer buffer, int reply) {
ssh_string req = NULL; ssh_string req = NULL;
int rc = SSH_ERROR; int rc;
if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE) switch (session->global_req_state) {
case SSH_CHANNEL_REQ_STATE_NONE:
break;
default:
goto pending; goto pending;
}
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST);
if (rc < 0) {
goto error;
}
req = ssh_string_from_char(request); req = ssh_string_from_char(request);
if (req == NULL) { if (req == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
goto error; rc = SSH_ERROR;
goto error;
} }
if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 || rc = buffer_add_ssh_string(session->out_buffer, req);
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
ssh_set_error_oom(session);
goto error;
}
ssh_string_free(req); ssh_string_free(req);
req=NULL; if (rc < 0) {
ssh_set_error_oom(session);
rc = SSH_ERROR;
goto error;
}
rc = buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1);
if (rc < 0) {
ssh_set_error_oom(session);
rc = SSH_ERROR;
goto error;
}
if (buffer != NULL) { if (buffer != NULL) {
if (buffer_add_data(session->out_buffer, buffer_get_rest(buffer), rc = buffer_add_data(session->out_buffer,
buffer_get_rest_len(buffer)) < 0) { buffer_get_rest(buffer),
ssh_set_error_oom(session); buffer_get_rest_len(buffer));
goto error; if (rc < 0) {
} ssh_set_error_oom(session);
rc = SSH_ERROR;
goto error;
}
} }
session->global_req_state = SSH_CHANNEL_REQ_STATE_PENDING; session->global_req_state = SSH_CHANNEL_REQ_STATE_PENDING;
if (packet_send(session) == SSH_ERROR) { rc = packet_send(session);
return rc; if (rc == SSH_ERROR) {
return rc;
} }
SSH_LOG(SSH_LOG_PACKET, SSH_LOG(SSH_LOG_PACKET,
"Sent a SSH_MSG_GLOBAL_REQUEST %s", request); "Sent a SSH_MSG_GLOBAL_REQUEST %s", request);
if (reply == 0) {
session->global_req_state=SSH_CHANNEL_REQ_STATE_NONE;
return SSH_OK; if (reply == 0) {
session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE;
return SSH_OK;
} }
pending: pending:
rc = ssh_handle_packets_termination(session, rc = ssh_handle_packets_termination(session,
@ -2178,16 +2201,16 @@ pending:
break; break;
case SSH_CHANNEL_REQ_STATE_ERROR: case SSH_CHANNEL_REQ_STATE_ERROR:
case SSH_CHANNEL_REQ_STATE_NONE: case SSH_CHANNEL_REQ_STATE_NONE:
rc=SSH_ERROR; rc = SSH_ERROR;
break; break;
case SSH_CHANNEL_REQ_STATE_PENDING: case SSH_CHANNEL_REQ_STATE_PENDING:
rc=SSH_AGAIN; return SSH_AGAIN;
break;
} }
session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE;
return rc; return rc;
error: error:
ssh_string_free(req); buffer_reinit(session->out_buffer);
return rc; return rc;
} }
@ -3325,17 +3348,18 @@ error:
} }
/** /**
* @brief Send the exit status to the remote process (as described in RFC 4254, section 6.10). * @brief Send the exit status to the remote process
* *
* Sends the exit status to the remote process. * Sends the exit status to the remote process (as described in RFC 4254,
* section 6.10).
* Only SSH-v2 is supported (I'm not sure about SSH-v1). * Only SSH-v2 is supported (I'm not sure about SSH-v1).
* *
* @param[in] channel The channel to send exit status. * @param[in] channel The channel to send exit status.
* *
* @param[in] sig The exit status to send * @param[in] exit_status The exit status to send
* *
* @return SSH_OK on success, SSH_ERROR if an error occurred * @return SSH_OK on success, SSH_ERROR if an error occurred.
* (including attempts to send exit status via SSH-v1 session). * (including attempts to send exit status via SSH-v1 session).
*/ */
int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status) { int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status) {
ssh_buffer buffer = NULL; ssh_buffer buffer = NULL;

View File

@ -105,14 +105,18 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1); ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
} }
#endif #endif
if(buffer[i]=='\r') if(buffer[i]=='\r') {
buffer[i]='\0'; buffer[i]='\0';
if(buffer[i]=='\n'){ }
buffer[i]='\0'; if (buffer[i]=='\n') {
str=strdup(buffer); buffer[i] = '\0';
/* number of bytes read */ str = strdup(buffer);
ret=i+1; if (str == NULL) {
session->serverbanner=str; return SSH_ERROR;
}
/* number of bytes read */
ret = i + 1;
session->serverbanner = str;
session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED; session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED;
SSH_LOG(SSH_LOG_PACKET,"Received banner: %s",str); SSH_LOG(SSH_LOG_PACKET,"Received banner: %s",str);
session->ssh_connection_callback(session); session->ssh_connection_callback(session);
@ -529,7 +533,7 @@ pending:
if (timeout == 0) { if (timeout == 0) {
timeout = 10 * 1000; timeout = 10 * 1000;
} }
SSH_LOG(SSH_LOG_PACKET,"ssh_connect: Actual timeout : %d", timeout); SSH_LOG(SSH_LOG_PACKET,"Actual timeout : %d", timeout);
ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session); ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
if (ret == SSH_ERROR || !ssh_connect_termination(session)) { if (ret == SSH_ERROR || !ssh_connect_termination(session)) {
ssh_set_error(session, SSH_FATAL, ssh_set_error(session, SSH_FATAL,
@ -546,7 +550,7 @@ pending:
session->session_state = SSH_SESSION_STATE_ERROR; session->session_state = SSH_SESSION_STATE_ERROR;
} }
} }
SSH_LOG(SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state); SSH_LOG(SSH_LOG_PACKET,"current state : %d",session->session_state);
if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){ if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
return SSH_AGAIN; return SSH_AGAIN;
} }

View File

@ -436,6 +436,7 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
*/ */
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd, int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
fd_set *readfds, struct timeval *timeout) { fd_set *readfds, struct timeval *timeout) {
fd_set origfds;
socket_t fd; socket_t fd;
int i,j; int i,j;
int rc; int rc;
@ -449,9 +450,11 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
ssh_event_add_session(event, channels[i]->session); ssh_event_add_session(event, channels[i]->session);
} }
FD_ZERO(&origfds);
for (fd = 0; fd < maxfd ; fd++) { for (fd = 0; fd < maxfd ; fd++) {
if (FD_ISSET(fd, readfds)) { if (FD_ISSET(fd, readfds)) {
ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds); ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
FD_SET(fd, &origfds);
} }
} }
outchannels[0] = NULL; outchannels[0] = NULL;
@ -485,13 +488,17 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
/* since there's nothing, let's fire the polling */ /* since there's nothing, let's fire the polling */
rc = ssh_event_dopoll(event,tm); rc = ssh_event_dopoll(event,tm);
if (rc == SSH_ERROR){ if (rc == SSH_ERROR){
ssh_event_free(event); goto out;
return SSH_ERROR;
} }
tm = ssh_timeout_update(&ts, base_tm); tm = ssh_timeout_update(&ts, base_tm);
firstround=0; firstround=0;
} while (1); } while (1);
out: out:
for (fd = 0; fd < maxfd; fd++) {
if (FD_ISSET(fd, &origfds)) {
ssh_event_remove_fd(event, fd);
}
}
ssh_event_free(event); ssh_event_free(event);
return SSH_OK; return SSH_OK;
} }

View File

@ -26,7 +26,10 @@
#include "libssh/curve25519.h" #include "libssh/curve25519.h"
#ifdef HAVE_CURVE25519 #ifdef HAVE_CURVE25519
#ifdef WITH_NACL
#include "nacl/crypto_scalarmult_curve25519.h" #include "nacl/crypto_scalarmult_curve25519.h"
#endif
#include "libssh/ssh2.h" #include "libssh/ssh2.h"
#include "libssh/buffer.h" #include "libssh/buffer.h"
#include "libssh/priv.h" #include "libssh/priv.h"
@ -53,7 +56,7 @@ int ssh_client_curve25519_init(ssh_session session){
return SSH_ERROR; return SSH_ERROR;
} }
crypto_scalarmult_curve25519_base(session->next_crypto->curve25519_client_pubkey, crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
session->next_crypto->curve25519_privkey); session->next_crypto->curve25519_privkey);
client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE); client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE);
if (client_pubkey == NULL) { if (client_pubkey == NULL) {
@ -81,10 +84,10 @@ static int ssh_curve25519_build_k(ssh_session session) {
} }
if (session->server) if (session->server)
crypto_scalarmult_curve25519(k, session->next_crypto->curve25519_privkey, crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
session->next_crypto->curve25519_client_pubkey); session->next_crypto->curve25519_client_pubkey);
else else
crypto_scalarmult_curve25519(k, session->next_crypto->curve25519_privkey, crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
session->next_crypto->curve25519_server_pubkey); session->next_crypto->curve25519_server_pubkey);
BN_bin2bn(k, CURVE25519_PUBKEY_SIZE, session->next_crypto->k); BN_bin2bn(k, CURVE25519_PUBKEY_SIZE, session->next_crypto->k);
@ -125,7 +128,7 @@ int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet){
} }
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){ if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d", ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
ssh_string_len(q_s_string)); (int)ssh_string_len(q_s_string));
ssh_string_free(q_s_string); ssh_string_free(q_s_string);
goto error; goto error;
} }
@ -179,7 +182,7 @@ int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){
} }
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){ if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d", ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
ssh_string_len(q_c_string)); (int)ssh_string_len(q_c_string));
ssh_string_free(q_c_string); ssh_string_free(q_c_string);
return SSH_ERROR; return SSH_ERROR;
} }
@ -195,7 +198,7 @@ int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){
return SSH_ERROR; return SSH_ERROR;
} }
crypto_scalarmult_curve25519_base(session->next_crypto->curve25519_server_pubkey, crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
session->next_crypto->curve25519_privkey); session->next_crypto->curve25519_privkey);
q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE); q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);

View File

@ -239,63 +239,6 @@ void ssh_print_bignum(const char *which, bignum num) {
SAFE_FREE(hex); SAFE_FREE(hex);
} }
/**
* @brief Convert a buffer into a colon separated hex string.
* The caller has to free the memory.
*
* @param what What should be converted to a hex string.
*
* @param len Length of the buffer to convert.
*
* @return The hex string or NULL on error.
*
* @see ssh_string_free_char()
*/
char *ssh_get_hexa(const unsigned char *what, size_t len) {
const char h[] = "0123456789abcdef";
char *hexa;
size_t i;
size_t hlen = len * 3;
if (len > (UINT_MAX - 1) / 3) {
return NULL;
}
hexa = malloc(hlen + 1);
if (hexa == NULL) {
return NULL;
}
for (i = 0; i < len; i++) {
hexa[i * 3] = h[(what[i] >> 4) & 0xF];
hexa[i * 3 + 1] = h[what[i] & 0xF];
hexa[i * 3 + 2] = ':';
}
hexa[hlen - 1] = '\0';
return hexa;
}
/**
* @brief Print a buffer as colon separated hex string.
*
* @param descr Description printed in front of the hex string.
*
* @param what What should be converted to a hex string.
*
* @param len Length of the buffer to convert.
*/
void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
char *hexa = ssh_get_hexa(what, len);
if (hexa == NULL) {
return;
}
printf("%s: %s\n", descr, hexa);
free(hexa);
}
int dh_generate_x(ssh_session session) { int dh_generate_x(ssh_session session) {
session->next_crypto->x = bignum_new(); session->next_crypto->x = bignum_new();
if (session->next_crypto->x == NULL) { if (session->next_crypto->x == NULL) {
@ -1047,25 +990,7 @@ error:
*/ */
/** /**
* @brief Allocates a buffer with the MD5 hash of the server public key. * @deprecated Use ssh_get_publickey_hash()
*
* This function allows you to get a MD5 hash of the public key. You can then
* print this hash in a human-readable form to the user so that he is able to
* verify it. Use ssh_get_hexa() or ssh_print_hexa() to display it.
*
* @param[in] session The SSH session to use.
*
* @param[in] hash The buffer to allocate.
*
* @return The bytes allocated or < 0 on error.
*
* @warning It is very important that you verify at some moment that the hash
* matches a known server. If you don't do it, cryptography wont help
* you at making things secure
*
* @see ssh_is_server_known()
* @see ssh_get_hexa()
* @see ssh_print_hexa()
*/ */
int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) { int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
ssh_string pubkey; ssh_string pubkey;
@ -1142,6 +1067,164 @@ int ssh_get_publickey(ssh_session session, ssh_key *key)
key); key);
} }
/**
* @brief Allocates a buffer with the hash of the public key.
*
* This function allows you to get a hash of the public key. You can then
* print this hash in a human-readable form to the user so that he is able to
* verify it. Use ssh_get_hexa() or ssh_print_hexa() to display it.
*
* @param[in] key The public key to create the hash for.
*
* @param[in] type The type of the hash you want.
*
* @param[in] hash A pointer to store the allocated buffer. It can be
* freed using ssh_clean_pubkey_hash().
*
* @param[in] hlen The length of the hash.
*
* @return 0 on success, -1 if an error occured.
*
* @warning It is very important that you verify at some moment that the hash
* matches a known server. If you don't do it, cryptography wont help
* you at making things secure.
* OpenSSH uses SHA1 to print public key digests.
*
* @see ssh_is_server_known()
* @see ssh_get_hexa()
* @see ssh_print_hexa()
* @see ssh_clean_pubkey_hash()
*/
int ssh_get_publickey_hash(const ssh_key key,
enum ssh_publickey_hash_type type,
unsigned char **hash,
size_t *hlen)
{
ssh_string blob;
unsigned char *h;
int rc;
rc = ssh_pki_export_pubkey_blob(key, &blob);
if (rc < 0) {
return rc;
}
switch (type) {
case SSH_PUBLICKEY_HASH_SHA1:
{
SHACTX ctx;
h = malloc(SHA_DIGEST_LEN);
if (h == NULL) {
rc = -1;
goto out;
}
ctx = sha1_init();
if (ctx == NULL) {
free(h);
rc = -1;
goto out;
}
sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
sha1_final(h, ctx);
*hlen = SHA_DIGEST_LEN;
}
break;
case SSH_PUBLICKEY_HASH_MD5:
{
MD5CTX ctx;
h = malloc(MD5_DIGEST_LEN);
if (h == NULL) {
rc = -1;
goto out;
}
ctx = md5_init();
if (ctx == NULL) {
free(h);
rc = -1;
goto out;
}
md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
md5_final(h, ctx);
*hlen = MD5_DIGEST_LEN;
}
break;
default:
rc = -1;
goto out;
}
*hash = h;
rc = 0;
out:
ssh_string_free(blob);
return rc;
}
/**
* @brief Convert a buffer into a colon separated hex string.
* The caller has to free the memory.
*
* @param what What should be converted to a hex string.
*
* @param len Length of the buffer to convert.
*
* @return The hex string or NULL on error.
*
* @see ssh_string_free_char()
*/
char *ssh_get_hexa(const unsigned char *what, size_t len) {
const char h[] = "0123456789abcdef";
char *hexa;
size_t i;
size_t hlen = len * 3;
if (len > (UINT_MAX - 1) / 3) {
return NULL;
}
hexa = malloc(hlen + 1);
if (hexa == NULL) {
return NULL;
}
for (i = 0; i < len; i++) {
hexa[i * 3] = h[(what[i] >> 4) & 0xF];
hexa[i * 3 + 1] = h[what[i] & 0xF];
hexa[i * 3 + 2] = ':';
}
hexa[hlen - 1] = '\0';
return hexa;
}
/**
* @brief Print a buffer as colon separated hex string.
*
* @param descr Description printed in front of the hex string.
*
* @param what What should be converted to a hex string.
*
* @param len Length of the buffer to convert.
*/
void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
char *hexa = ssh_get_hexa(what, len);
if (hexa == NULL) {
return;
}
printf("%s: %s\n", descr, hexa);
free(hexa);
}
/** @} */ /** @} */
/* vim: set ts=4 sw=4 et cindent: */ /* vim: set ts=4 sw=4 et cindent: */

View File

@ -123,6 +123,30 @@ void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned
EVP_DigestUpdate(&md, digest, len); EVP_DigestUpdate(&md, digest, len);
EVP_DigestFinal(&md, hash, hlen); EVP_DigestFinal(&md, hash, hlen);
} }
EVPCTX evp_init(int nid)
{
const EVP_MD *evp_md = nid_to_evpmd(nid);
EVPCTX ctx = malloc(sizeof(EVP_MD_CTX));
if (ctx == NULL) {
return NULL;
}
EVP_DigestInit(ctx, evp_md);
return ctx;
}
void evp_update(EVPCTX ctx, const void *data, unsigned long len)
{
EVP_DigestUpdate(ctx, data, len);
}
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
{
EVP_DigestFinal(ctx, md, mdlen);
}
#endif #endif
SHA256CTX sha256_init(void){ SHA256CTX sha256_init(void){

View File

@ -65,7 +65,7 @@ static int current_timestring(int hires, char *buf, size_t len)
if (hires) { if (hires) {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm); strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s.%06ld", tbuf, tv.tv_usec); snprintf(buf, len, "%s.%06ld", tbuf, (long)tv.tv_usec);
} else { } else {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm); strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s", tbuf); snprintf(buf, len, "%s", tbuf);

View File

@ -120,10 +120,18 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
msg->auth_request.username, msg->auth_request.pubkey, msg->auth_request.username, msg->auth_request.pubkey,
msg->auth_request.signature_state, msg->auth_request.signature_state,
session->server_callbacks->userdata); session->server_callbacks->userdata);
if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL){ if (msg->auth_request.signature_state != SSH_PUBLICKEY_STATE_NONE) {
if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL) {
ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL); ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL);
} else { } else {
ssh_message_reply_default(msg); ssh_message_reply_default(msg);
}
} else {
if (rc == SSH_AUTH_SUCCESS) {
ssh_message_auth_reply_pk_ok_simple(msg);
} else {
ssh_message_reply_default(msg);
}
} }
return SSH_OK; return SSH_OK;
@ -301,10 +309,8 @@ static int ssh_execute_server_callbacks(ssh_session session, ssh_message msg){
if (session->server_callbacks != NULL){ if (session->server_callbacks != NULL){
rc = ssh_execute_server_request(session, msg); rc = ssh_execute_server_request(session, msg);
} } else if (session->common.callbacks != NULL) {
/* This one is in fact a client callback... */
/* This one is in fact a client callback... */
if (session->common.callbacks != NULL) {
rc = ssh_execute_client_request(session, msg); rc = ssh_execute_client_request(session, msg);
} }

View File

@ -856,6 +856,11 @@ int ssh_options_get_port(ssh_session session, unsigned int* port_target) {
* It may include "%s" which will be replaced by the * It may include "%s" which will be replaced by the
* user home directory. * user home directory.
* *
* - SSH_OPTIONS_PROXYCOMMAND:
* Get the proxycommand necessary to log into the
* remote host. When not explicitly set, it will be read
* from the ~/.ssh/config file.
*
* @param value The value to get into. As a char**, space will be * @param value The value to get into. As a char**, space will be
* allocated by the function for the value, it is * allocated by the function for the value, it is
* your responsibility to free the memory using * your responsibility to free the memory using
@ -894,6 +899,10 @@ int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value)
src = ssh_iterator_value(char *, it); src = ssh_iterator_value(char *, it);
break; break;
} }
case SSH_OPTIONS_PROXYCOMMAND: {
src = session->opts.ProxyCommand;
break;
}
default: default:
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return SSH_ERROR; return SSH_ERROR;
@ -1245,7 +1254,7 @@ static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo,
/** /**
* @brief This function can set all possible ssh bind options. * @brief This function can set all possible ssh bind options.
* *
* @param session An allocated ssh option structure. * @param sshbind An allocated ssh bind structure.
* *
* @param type The option type to set. This could be one of the * @param type The option type to set. This could be one of the
* following: * following:

View File

@ -1118,7 +1118,7 @@ int ssh_pki_export_signature_blob(const ssh_signature sig,
return SSH_ERROR; return SSH_ERROR;
} }
str = ssh_string_from_char(ssh_key_type_to_char(sig->type)); str = ssh_string_from_char(sig->type_c);
if (str == NULL) { if (str == NULL) {
ssh_buffer_free(buf); ssh_buffer_free(buf);
return SSH_ERROR; return SSH_ERROR;
@ -1271,11 +1271,9 @@ ssh_string ssh_pki_do_sign(ssh_session session,
struct ssh_crypto_struct *crypto = struct ssh_crypto_struct *crypto =
session->current_crypto ? session->current_crypto : session->current_crypto ? session->current_crypto :
session->next_crypto; session->next_crypto;
unsigned char hash[SHA_DIGEST_LEN] = {0};
ssh_signature sig; ssh_signature sig;
ssh_string sig_blob; ssh_string sig_blob;
ssh_string session_id; ssh_string session_id;
SHACTX ctx;
int rc; int rc;
if (privkey == NULL || !ssh_key_is_private(privkey)) { if (privkey == NULL || !ssh_key_is_private(privkey)) {
@ -1287,24 +1285,46 @@ ssh_string ssh_pki_do_sign(ssh_session session,
return NULL; return NULL;
} }
ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); ssh_string_fill(session_id, crypto->session_id, crypto->digest_len);
/* TODO: change when supporting ECDSA keys */
ctx = sha1_init();
if (ctx == NULL) {
ssh_string_free(session_id);
return NULL;
}
sha1_update(ctx, session_id, ssh_string_len(session_id) + 4); if (privkey->type == SSH_KEYTYPE_ECDSA) {
ssh_string_free(session_id); #ifdef HAVE_ECC
unsigned char ehash[EVP_DIGEST_LEN] = {0};
uint32_t elen;
EVPCTX ctx;
sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf)); ctx = evp_init(privkey->ecdsa_nid);
sha1_final(hash, ctx); if (ctx == NULL) {
ssh_string_free(session_id);
return NULL;
}
evp_update(ctx, session_id, ssh_string_len(session_id) + 4);
evp_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
evp_final(ctx, ehash, &elen);
sig = pki_do_sign(privkey, ehash, elen);
#endif
} else {
unsigned char hash[SHA_DIGEST_LEN] = {0};
SHACTX ctx;
ctx = sha1_init();
if (ctx == NULL) {
ssh_string_free(session_id);
return NULL;
}
sha1_update(ctx, session_id, ssh_string_len(session_id) + 4);
sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
sha1_final(hash, ctx);
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN); ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
#endif #endif
sig = pki_do_sign(privkey, hash, SHA_DIGEST_LEN); sig = pki_do_sign(privkey, hash, SHA_DIGEST_LEN);
}
ssh_string_free(session_id);
if (sig == NULL) { if (sig == NULL) {
return NULL; return NULL;
} }

View File

@ -25,6 +25,8 @@
#ifndef _PKI_CRYPTO_H #ifndef _PKI_CRYPTO_H
#define _PKI_CRYPTO_H #define _PKI_CRYPTO_H
#include "libssh/priv.h"
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/err.h> #include <openssl/err.h>
@ -37,8 +39,6 @@
#include <openssl/ecdsa.h> #include <openssl/ecdsa.h>
#endif #endif
#include "libssh/priv.h"
#include "libssh/libssh.h" #include "libssh/libssh.h"
#include "libssh/buffer.h" #include "libssh/buffer.h"
#include "libssh/session.h" #include "libssh/session.h"
@ -1018,36 +1018,52 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
break; break;
case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
{
ssh_buffer b;
int rc;
b = ssh_buffer_new();
if (b == NULL) {
return NULL;
}
r = make_bignum_string(sig->ecdsa_sig->r); r = make_bignum_string(sig->ecdsa_sig->r);
if (r == NULL) { if (r == NULL) {
ssh_buffer_free(b);
return NULL; return NULL;
} }
rc = buffer_add_ssh_string(b, r);
ssh_string_free(r);
if (rc < 0) {
ssh_buffer_free(b);
return NULL;
}
s = make_bignum_string(sig->ecdsa_sig->s); s = make_bignum_string(sig->ecdsa_sig->s);
if (s == NULL) { if (s == NULL) {
ssh_string_free(r); ssh_buffer_free(b);
return NULL; return NULL;
} }
rc = buffer_add_ssh_string(b, s);
memcpy(buffer,
((char *)ssh_string_data(r)) + ssh_string_len(r) - 20,
20);
memcpy(buffer + 20,
((char *)ssh_string_data(s)) + ssh_string_len(s) - 20,
20);
ssh_string_free(r);
ssh_string_free(s); ssh_string_free(s);
if (rc < 0) {
sig_blob = ssh_string_new(40); ssh_buffer_free(b);
if (sig_blob == NULL) {
return NULL; return NULL;
} }
ssh_string_fill(sig_blob, buffer, 40); sig_blob = ssh_string_new(buffer_get_rest_len(b));
if (sig_blob == NULL) {
ssh_buffer_free(b);
return NULL;
}
ssh_string_fill(sig_blob, buffer_get_rest(b), buffer_get_rest_len(b));
ssh_buffer_free(b);
break; break;
}
#endif #endif
case SSH_KEYTYPE_UNKNOWN: case SSH_KEYTYPE_UNKNOWN:
ssh_pki_log("Unknown signature key type: %d", sig->type); ssh_pki_log("Unknown signature key type: %s", sig->type_c);
return NULL; return NULL;
} }
@ -1070,6 +1086,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
} }
sig->type = type; sig->type = type;
sig->type_c = ssh_key_type_to_char(type);
len = ssh_string_len(sig_blob); len = ssh_string_len(sig_blob);
@ -1309,6 +1326,7 @@ ssh_signature pki_do_sign(const ssh_key privkey,
} }
sig->type = privkey->type; sig->type = privkey->type;
sig->type_c = privkey->type_c;
switch(privkey->type) { switch(privkey->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:
@ -1368,6 +1386,7 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
return NULL; return NULL;
} }
sig->type = key->type; sig->type = key->type;
sig->type_c = key->type_c;
switch(key->type) { switch(key->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:

View File

@ -450,7 +450,11 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
if (ctx->polls_allocated > 0) { if (ctx->polls_allocated > 0) {
while (ctx->polls_used > 0){ while (ctx->polls_used > 0){
ssh_poll_handle p = ctx->pollptrs[0]; ssh_poll_handle p = ctx->pollptrs[0];
ssh_poll_ctx_remove(ctx, p); /*
* The free function calls ssh_poll_ctx_remove() and decrements
* ctx->polls_used
*/
ssh_poll_free(p);
} }
SAFE_FREE(ctx->pollptrs); SAFE_FREE(ctx->pollptrs);

View File

@ -814,7 +814,7 @@ int ssh_scp_integer_mode(const char *mode){
*/ */
char *ssh_scp_string_mode(int mode){ char *ssh_scp_string_mode(int mode){
char buffer[16]; char buffer[16];
snprintf(buffer,sizeof(buffer),"%.4o",mode); snprintf(buffer,sizeof(buffer),"%.4d",mode);
return strdup(buffer); return strdup(buffer);
} }

View File

@ -1221,38 +1221,45 @@ int ssh_execute_message_callbacks(ssh_session session){
return SSH_OK; return SSH_OK;
} }
int ssh_send_keepalive(ssh_session session) int ssh_send_keepalive(ssh_session session)
{ {
/* TODO check the reply and all that */
struct ssh_string_struct *req; struct ssh_string_struct *req;
int reply = 1; int rc;
int rc = SSH_ERROR;
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST);
if (rc < 0) {
goto err;
}
req = ssh_string_from_char("keepalive@openssh.com"); req = ssh_string_from_char("keepalive@openssh.com");
if (req == NULL) { if (req == NULL) {
ssh_set_error_oom(session); goto err;
goto out;
} }
if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 || rc = buffer_add_ssh_string(session->out_buffer, req);
buffer_add_ssh_string(session->out_buffer, req) < 0 || ssh_string_free(req);
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) { if (rc < 0) {
ssh_set_error_oom(session); goto err;
goto out;
} }
if (packet_send(session) == SSH_ERROR) rc = buffer_add_u8(session->out_buffer, 1);
goto out; if (rc < 0) {
goto err;
}
if (packet_send(session) == SSH_ERROR) {
goto err;
}
ssh_handle_packets(session, 0); ssh_handle_packets(session, 0);
SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive"); SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive");
rc = SSH_OK; return SSH_OK;
out: err:
ssh_string_free(req); ssh_set_error_oom(session);
return rc; buffer_reinit(session->out_buffer);
return SSH_ERROR;
} }
/** @} */ /** @} */

View File

@ -273,7 +273,7 @@ void ssh_free(ssh_session session) {
} }
/* burn connection, it could hang sensitive datas */ /* burn connection, it could hang sensitive datas */
ZERO_STRUCTP(session); BURN_BUFFER(session, sizeof(struct ssh_session_struct));
SAFE_FREE(session); SAFE_FREE(session);
} }

View File

@ -695,11 +695,11 @@ int ssh_socket_buffered_write_bytes(ssh_socket s){
int ssh_socket_get_status(ssh_socket s) { int ssh_socket_get_status(ssh_socket s) {
int r = 0; int r = 0;
if (s->read_wontblock) { if (buffer_get_len(s->in_buffer) > 0) {
r |= SSH_READ_PENDING; r |= SSH_READ_PENDING;
} }
if (s->write_wontblock) { if (buffer_get_len(s->out_buffer) > 0) {
r |= SSH_WRITE_PENDING; r |= SSH_WRITE_PENDING;
} }

View File

@ -158,7 +158,7 @@ void crypto_free(struct ssh_crypto_struct *crypto){
SAFE_FREE(crypto->kex_methods[i]); SAFE_FREE(crypto->kex_methods[i]);
} }
memset(crypto,0,sizeof(*crypto)); BURN_BUFFER(crypto, sizeof(struct ssh_crypto_struct));
SAFE_FREE(crypto); SAFE_FREE(crypto);
} }
@ -317,8 +317,13 @@ int crypt_set_algorithms_server(ssh_session session){
session->next_crypto->do_compress_in=1; session->next_crypto->do_compress_in=1;
} }
if(strcmp(method,"zlib@openssh.com") == 0){ if(strcmp(method,"zlib@openssh.com") == 0){
SSH_LOG(SSH_LOG_PACKET,"enabling C->S compression"); SSH_LOG(SSH_LOG_PACKET,"enabling C->S delayed compression");
session->next_crypto->delayed_compress_in=1;
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
session->next_crypto->do_compress_in = 1;
} else {
session->next_crypto->delayed_compress_in = 1;
}
} }
method = session->next_crypto->kex_methods[SSH_COMP_S_C]; method = session->next_crypto->kex_methods[SSH_COMP_S_C];
@ -328,7 +333,12 @@ int crypt_set_algorithms_server(ssh_session session){
} }
if(strcmp(method,"zlib@openssh.com") == 0){ if(strcmp(method,"zlib@openssh.com") == 0){
SSH_LOG(SSH_LOG_PACKET,"enabling S->C delayed compression\n"); SSH_LOG(SSH_LOG_PACKET,"enabling S->C delayed compression\n");
session->next_crypto->delayed_compress_out=1;
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
session->next_crypto->do_compress_out = 1;
} else {
session->next_crypto->delayed_compress_out = 1;
}
} }
method = session->next_crypto->kex_methods[SSH_HOSTKEYS]; method = session->next_crypto->kex_methods[SSH_HOSTKEYS];

View File

@ -6,7 +6,10 @@ add_cmocka_test(torture_connect torture_connect.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_knownhosts torture_knownhosts.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_knownhosts torture_knownhosts.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_proxycommand torture_proxycommand.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_proxycommand torture_proxycommand.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_session torture_session.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_session torture_session.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_forward torture_forward.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_request_env torture_request_env.c ${TORTURE_LIBRARY})
if (WITH_SFTP) if (WITH_SFTP)
add_cmocka_test(torture_sftp_static torture_sftp_static.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_sftp_static torture_sftp_static.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_sftp_dir torture_sftp_dir.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_sftp_dir torture_sftp_dir.c ${TORTURE_LIBRARY})
add_cmocka_test(torture_sftp_read torture_sftp_read.c ${TORTURE_LIBRARY})
endif (WITH_SFTP) endif (WITH_SFTP)

View File

@ -13,4 +13,6 @@ if (UNIX AND NOT WIN32)
add_cmocka_test(torture_pki torture_pki.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_pki torture_pki.c ${TORTURE_LIBRARY})
# requires pthread # requires pthread
add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY})
# requires /dev/null
add_cmocka_test(torture_channel torture_channel.c ${TORTURE_LIBRARY})
endif (UNIX AND NOT WIN32) endif (UNIX AND NOT WIN32)