diff --git a/libssh/CMakeLists.txt b/libssh/CMakeLists.txt index 2c5c7232..5998bc50 100644 --- a/libssh/CMakeLists.txt +++ b/libssh/CMakeLists.txt @@ -71,6 +71,13 @@ if (WITH_GSSAPI) find_package(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 include(ConfigureChecks.cmake) 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 "libgcrypt support: ${WITH_GCRYPT}") +message(STATUS "libnacl support: ${WITH_NACL}") message(STATUS "SSH-1 support: ${WITH_SSH1}") message(STATUS "SFTP support: ${WITH_SFTP}") message(STATUS "Server support : ${WITH_SERVER}") diff --git a/libssh/ConfigureChecks.cmake b/libssh/ConfigureChecks.cmake index e5233eeb..472fe79e 100644 --- a/libssh/ConfigureChecks.cmake +++ b/libssh/ConfigureChecks.cmake @@ -50,6 +50,7 @@ check_include_file(argp.h HAVE_ARGP_H) check_include_file(pty.h HAVE_PTY_H) check_include_file(termios.h HAVE_TERMIOS_H) check_include_file(unistd.h HAVE_UNISTD_H) +check_include_file(util.h HAVE_UTIL_H) if (WIN32) check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H) diff --git a/libssh/DefineOptions.cmake b/libssh/DefineOptions.cmake index 756b948a..ab7819a5 100644 --- a/libssh/DefineOptions.cmake +++ b/libssh/DefineOptions.cmake @@ -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_BENCHMARKS "Build benchmarks tools" OFF) option(WITH_EXAMPLES "Build examples" ON) - +option(WITH_NACL "Build with libnacl (curve25519" ON) if (WITH_ZLIB) set(WITH_LIBZ ON) else (WITH_ZLIB) @@ -27,3 +27,7 @@ endif(WITH_BENCHMARKS) if (WITH_TESTING) set(WITH_STATIC_LIB ON) endif (WITH_TESTING) + +if (WITH_NACL) + set(WITH_NACL ON) +endif (WITH_NACL) \ No newline at end of file diff --git a/libssh/cmake/Modules/DefinePlatformDefaults.cmake b/libssh/cmake/Modules/DefinePlatformDefaults.cmake index 502d936b..77f8a461 100644 --- a/libssh/cmake/Modules/DefinePlatformDefaults.cmake +++ b/libssh/cmake/Modules/DefinePlatformDefaults.cmake @@ -26,3 +26,7 @@ endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") if (CMAKE_SYSTEM_NAME MATCHES "OS2") set(OS2 TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "OS2") + +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + set (OSX TRUE) +endif (CMAKE_SYSTEM_NAME MATCHES "Darwin") diff --git a/libssh/config.h.cmake b/libssh/config.h.cmake index 1835e070..7e8cb6a8 100644 --- a/libssh/config.h.cmake +++ b/libssh/config.h.cmake @@ -20,6 +20,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTY_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIL_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_TERMIOS_H 1 @@ -126,7 +129,6 @@ /* Define to 1 if you have the `pthread' library (-lpthread). */ #cmakedefine HAVE_PTHREAD 1 - /**************************** OPTIONS ****************************/ #cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1 @@ -158,6 +160,9 @@ /* Define to 1 if you want to enable calltrace debug output */ #cmakedefine DEBUG_CALLTRACE 1 +/* Define to 1 if you want to enable NaCl support */ +#cmakedefine WITH_NACL 1 + /*************************** ENDIAN *****************************/ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most diff --git a/libssh/doc/mainpage.dox b/libssh/doc/mainpage.dox index 5fb695a6..70f774ad 100644 --- a/libssh/doc/mainpage.dox +++ b/libssh/doc/mainpage.dox @@ -19,7 +19,7 @@ the interesting functions as you go. The libssh library provides: - - Key Exchange Methods: ecdh-sha2-nistp256, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1 + - Key Exchange Methods: curve25519-sha256@libssh.org, ecdh-sha2-nistp256, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1 - Hostkey Types: ecdsa-sha2-nistp256, ssh-dss, ssh-rsa - Ciphers: aes256-ctr, aes192-ctr, aes128-ctr, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, des-cbc-ssh1, blowfish-cbc, none - Compression Schemes: zlib, zlib@openssh.com, 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 - RFC 4716, The Secure Shell (SSH) Public Key File Format + - RFC 5647, + AES Galois Counter Mode for the Secure Shell Transport Layer Protocol - RFC 5656, 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 +The libssh project has an extension to support Curve25519 which is also supported by +the OpenSSH project. + + - curve25519-sha256@libssh.org, + Curve25519-SHA256 for ECDH KEX + 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. diff --git a/libssh/examples/CMakeLists.txt b/libssh/examples/CMakeLists.txt index fc1c9341..c155e097 100644 --- a/libssh/examples/CMakeLists.txt +++ b/libssh/examples/CMakeLists.txt @@ -11,9 +11,9 @@ include_directories( ${CMAKE_BINARY_DIR} ) -if (BSD OR SOLARIS) +if (BSD OR SOLARIS OR OSX) find_package(Argp) -endif (BSD OR SOLARIS) +endif (BSD OR SOLARIS OR OSX) if (UNIX AND NOT WIN32) add_executable(libssh_scp libssh_scp.c ${examples_SRCS}) @@ -28,7 +28,7 @@ if (UNIX AND NOT WIN32) if (WITH_SERVER) if (HAVE_LIBUTIL) 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 (WITH_SERVER) diff --git a/libssh/examples/knownhosts.c b/libssh/examples/knownhosts.c index 37c0ba4e..5097cd93 100644 --- a/libssh/examples/knownhosts.c +++ b/libssh/examples/knownhosts.c @@ -34,14 +34,26 @@ int verify_knownhost(ssh_session session){ int state; char buf[10]; unsigned char *hash = NULL; - int hlen; + size_t hlen; + ssh_key srv_pubkey; + int rc; state=ssh_is_server_known(session); - hlen = ssh_get_pubkey_hash(session, &hash); - if (hlen < 0) { - return -1; + rc = ssh_get_publickey(session, &srv_pubkey); + if (rc < 0) { + 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){ case SSH_SERVER_KNOWN_OK: break; /* ok */ diff --git a/libssh/examples/samplesshd-tty.c b/libssh/examples/samplesshd-tty.c index 7ed70d3d..83b75648 100644 --- a/libssh/examples/samplesshd-tty.c +++ b/libssh/examples/samplesshd-tty.c @@ -25,8 +25,12 @@ clients must be made or how a client should react. #include #include #include +#ifdef HAVE_PTY_H #include - +#endif +#ifdef HAVE_UTIL_H +#include +#endif #define SSHD_USER "libssh" #define SSHD_PASSWORD "libssh" diff --git a/libssh/include/libssh/curve25519.h b/libssh/include/libssh/curve25519.h index 004210cb..35e25be0 100644 --- a/libssh/include/libssh/curve25519.h +++ b/libssh/include/libssh/curve25519.h @@ -26,15 +26,23 @@ #ifdef WITH_NACL -#define HAVE_CURVE25519 #include #define CURVE25519_PUBKEY_SIZE crypto_scalarmult_curve25519_BYTES #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_privkey[CURVE25519_PRIVKEY_SIZE]; -#endif /* WITH_NACL */ int ssh_client_curve25519_init(ssh_session session); int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet); diff --git a/libssh/include/libssh/libssh.h b/libssh/include/libssh/libssh.h index a451620e..3833adcd 100644 --- a/libssh/include/libssh/libssh.h +++ b/libssh/include/libssh/libssh.h @@ -208,10 +208,14 @@ enum ssh_publickey_state_e { SSH_PUBLICKEY_STATE_WRONG=2 }; -/* status flags */ +/* Status flags */ +/** Socket is closed */ #define SSH_CLOSED 0x01 +/** Reading to socket won't block */ #define SSH_READ_PENDING 0x02 +/** Session was closed due to an error */ #define SSH_CLOSED_ERROR 0x04 +/** Output buffer not empty */ #define SSH_WRITE_PENDING 0x08 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_issue_banner(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_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_version(ssh_session session); LIBSSH_API int ssh_get_status(ssh_session session); diff --git a/libssh/include/libssh/priv.h b/libssh/include/libssh/priv.h index 364f8e97..d8176d90 100644 --- a/libssh/include/libssh/priv.h +++ b/libssh/include/libssh/priv.h @@ -155,6 +155,16 @@ int gettimeofday(struct timeval *__p, void *__t); #include #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 */ struct ssh_common_struct; struct ssh_kex_struct; @@ -254,7 +264,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len); /** Overwrite the buffer with '\0' */ # define BURN_BUFFER(x, size) do { \ if ((x) != NULL) \ - memset((x), '\0', (size))); __asm__ volatile("" : : "r"(&(x)) : "memory"); \ + memset((x), '\0', (size)); __asm__ volatile("" : : "r"(&(x)) : "memory"); \ } while(0) #else /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */ /** Overwrite a string with '\0' */ @@ -265,7 +275,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len); /** Overwrite the buffer with '\0' */ # define BURN_BUFFER(x, size) do { \ if ((x) != NULL) \ - memset((x), '\0', (size))); __asm__ volatile("" : : "r"(&(x)) : "memory"); \ + memset((x), '\0', (size)); __asm__ volatile("" : : "r"(&(x)) : "memory"); \ } while(0) #endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */ diff --git a/libssh/src/CMakeLists.txt b/libssh/src/CMakeLists.txt index b4046805..83435d0c 100644 --- a/libssh/src/CMakeLists.txt +++ b/libssh/src/CMakeLists.txt @@ -115,6 +115,7 @@ set(libssh_SRCS client.c config.c connect.c + curve25519.c dh.c ecdh.c error.c @@ -204,12 +205,12 @@ if (WITH_GSSAPI AND GSSAPI_FOUND) ) endif (WITH_GSSAPI AND GSSAPI_FOUND) -if (WITH_NACL) +if (NOT WITH_NACL) set(libssh_SRCS ${libssh_SRCS} - curve25519.c + curve25519_ref.c ) -endif (WITH_NACL) +endif (NOT WITH_NACL) include_directories( ${LIBSSH_PUBLIC_INCLUDE_DIRS} diff --git a/libssh/src/channels.c b/libssh/src/channels.c index a006ab36..f7bcded2 100644 --- a/libssh/src/channels.c +++ b/libssh/src/channels.c @@ -3348,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). * * @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 - * (including attempts to send exit status via SSH-v1 session). + * @return SSH_OK on success, SSH_ERROR if an error occurred. + * (including attempts to send exit status via SSH-v1 session). */ int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status) { ssh_buffer buffer = NULL; diff --git a/libssh/src/client.c b/libssh/src/client.c index 49bb544e..1fb963d7 100644 --- a/libssh/src/client.c +++ b/libssh/src/client.c @@ -533,7 +533,7 @@ pending: if (timeout == 0) { 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); if (ret == SSH_ERROR || !ssh_connect_termination(session)) { ssh_set_error(session, SSH_FATAL, @@ -550,7 +550,7 @@ pending: 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)){ return SSH_AGAIN; } diff --git a/libssh/src/curve25519.c b/libssh/src/curve25519.c index 653beee0..153fbcd9 100644 --- a/libssh/src/curve25519.c +++ b/libssh/src/curve25519.c @@ -26,7 +26,10 @@ #include "libssh/curve25519.h" #ifdef HAVE_CURVE25519 +#ifdef WITH_NACL #include "nacl/crypto_scalarmult_curve25519.h" +#endif + #include "libssh/ssh2.h" #include "libssh/buffer.h" #include "libssh/priv.h" @@ -53,7 +56,7 @@ int ssh_client_curve25519_init(ssh_session session){ 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); client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE); if (client_pubkey == NULL) { @@ -81,10 +84,10 @@ static int ssh_curve25519_build_k(ssh_session session) { } 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); else - crypto_scalarmult_curve25519(k, session->next_crypto->curve25519_privkey, + crypto_scalarmult(k, session->next_crypto->curve25519_privkey, session->next_crypto->curve25519_server_pubkey); 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){ 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); 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){ 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); return SSH_ERROR; } @@ -195,7 +198,7 @@ int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){ 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); q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE); diff --git a/libssh/src/dh.c b/libssh/src/dh.c index f96a94a3..5ebbc91e 100644 --- a/libssh/src/dh.c +++ b/libssh/src/dh.c @@ -239,63 +239,6 @@ void ssh_print_bignum(const char *which, bignum num) { 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) { session->next_crypto->x = bignum_new(); if (session->next_crypto->x == NULL) { @@ -1047,25 +990,7 @@ error: */ /** - * @brief Allocates a buffer with the MD5 hash of the server public key. - * - * 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() + * @deprecated Use ssh_get_publickey_hash() */ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) { ssh_string pubkey; @@ -1142,6 +1067,164 @@ int ssh_get_publickey(ssh_session session, ssh_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: */ diff --git a/libssh/src/log.c b/libssh/src/log.c index fba5fdc4..4552b969 100644 --- a/libssh/src/log.c +++ b/libssh/src/log.c @@ -65,7 +65,7 @@ static int current_timestring(int hires, char *buf, size_t len) if (hires) { 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 { strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm); snprintf(buf, len, "%s", tbuf); diff --git a/libssh/src/messages.c b/libssh/src/messages.c index c5783a68..2c99311d 100644 --- a/libssh/src/messages.c +++ b/libssh/src/messages.c @@ -309,10 +309,8 @@ static int ssh_execute_server_callbacks(ssh_session session, ssh_message msg){ if (session->server_callbacks != NULL){ rc = ssh_execute_server_request(session, msg); - } - - /* This one is in fact a client callback... */ - else if (session->common.callbacks != NULL) { + } else if (session->common.callbacks != NULL) { + /* This one is in fact a client callback... */ rc = ssh_execute_client_request(session, msg); } diff --git a/libssh/src/options.c b/libssh/src/options.c index 46dc0b4b..e02ad4df 100644 --- a/libssh/src/options.c +++ b/libssh/src/options.c @@ -1254,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. * - * @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 * following: diff --git a/libssh/src/pki_crypto.c b/libssh/src/pki_crypto.c index 04fea74e..e87d7ace 100644 --- a/libssh/src/pki_crypto.c +++ b/libssh/src/pki_crypto.c @@ -25,6 +25,8 @@ #ifndef _PKI_CRYPTO_H #define _PKI_CRYPTO_H +#include "libssh/priv.h" + #include #include #include @@ -37,8 +39,6 @@ #include #endif - -#include "libssh/priv.h" #include "libssh/libssh.h" #include "libssh/buffer.h" #include "libssh/session.h" diff --git a/libssh/src/server.c b/libssh/src/server.c index b31371fe..8629c8ba 100644 --- a/libssh/src/server.c +++ b/libssh/src/server.c @@ -1221,38 +1221,45 @@ int ssh_execute_message_callbacks(ssh_session session){ return SSH_OK; } - int ssh_send_keepalive(ssh_session session) { - /* TODO check the reply and all that */ struct ssh_string_struct *req; - int reply = 1; - int rc = SSH_ERROR; + int rc; + + rc = buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST); + if (rc < 0) { + goto err; + } req = ssh_string_from_char("keepalive@openssh.com"); if (req == NULL) { - ssh_set_error_oom(session); - goto out; + goto err; } - if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 || - 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 out; + rc = buffer_add_ssh_string(session->out_buffer, req); + ssh_string_free(req); + if (rc < 0) { + goto err; } - if (packet_send(session) == SSH_ERROR) - goto out; + rc = buffer_add_u8(session->out_buffer, 1); + if (rc < 0) { + goto err; + } + + if (packet_send(session) == SSH_ERROR) { + goto err; + } ssh_handle_packets(session, 0); SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive"); - rc = SSH_OK; + return SSH_OK; -out: - ssh_string_free(req); - return rc; +err: + ssh_set_error_oom(session); + buffer_reinit(session->out_buffer); + return SSH_ERROR; } /** @} */ diff --git a/libssh/src/session.c b/libssh/src/session.c index fe11b416..d4b3643f 100644 --- a/libssh/src/session.c +++ b/libssh/src/session.c @@ -273,7 +273,7 @@ void ssh_free(ssh_session session) { } /* burn connection, it could hang sensitive datas */ - ZERO_STRUCTP(session); + BURN_BUFFER(session, sizeof(struct ssh_session_struct)); SAFE_FREE(session); } diff --git a/libssh/src/socket.c b/libssh/src/socket.c index 0dbbe2bc..c76ef5ae 100644 --- a/libssh/src/socket.c +++ b/libssh/src/socket.c @@ -695,11 +695,11 @@ int ssh_socket_buffered_write_bytes(ssh_socket s){ int ssh_socket_get_status(ssh_socket s) { int r = 0; - if (s->read_wontblock) { - r |= SSH_READ_PENDING; + if (buffer_get_len(s->in_buffer) > 0) { + r |= SSH_READ_PENDING; } - if (s->write_wontblock) { + if (buffer_get_len(s->out_buffer) > 0) { r |= SSH_WRITE_PENDING; } diff --git a/libssh/src/wrapper.c b/libssh/src/wrapper.c index dc2e7db1..51688753 100644 --- a/libssh/src/wrapper.c +++ b/libssh/src/wrapper.c @@ -158,7 +158,7 @@ void crypto_free(struct ssh_crypto_struct *crypto){ SAFE_FREE(crypto->kex_methods[i]); } - memset(crypto,0,sizeof(*crypto)); + BURN_BUFFER(crypto, sizeof(struct ssh_crypto_struct)); SAFE_FREE(crypto); } @@ -319,10 +319,11 @@ int crypt_set_algorithms_server(ssh_session session){ if(strcmp(method,"zlib@openssh.com") == 0){ SSH_LOG(SSH_LOG_PACKET,"enabling C->S delayed compression"); - if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) - session->next_crypto->do_compress_in=1; - else - 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]; @@ -333,10 +334,11 @@ int crypt_set_algorithms_server(ssh_session session){ if(strcmp(method,"zlib@openssh.com") == 0){ SSH_LOG(SSH_LOG_PACKET,"enabling S->C delayed compression\n"); - if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) - session->next_crypto->do_compress_out=1; - else - 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];