Compare commits

...

11 Commits

Author SHA1 Message Date
Andreas Schneider
0588cbf9d4 Bump version to 0.7.5
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2017-04-13 16:33:04 +02:00
Andreas Schneider
a7cce77550 buffer: Validate the length before before memory allocation
Check if the size the other party sent is a valid size in the
transmitted buffer.

Thanks to Alex Gaynor for finding and reporting the issue.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 68b7ca6e92)
2017-04-13 16:28:18 +02:00
Andreas Schneider
5e63b40cde buffer: Create ssh_buffer_validate_length()
This functions allows if a given length can be obtained from the buffer.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c165c396de)
2017-04-13 16:27:33 +02:00
Alex Hermann
7b8b5eb4ea config: Only use first occurence of each parameter
ssh_config's manpage says:
"For each parameter, the first obtained value will be used."

Make libssh adhere to this rule.

BUG: https://red.libssh.org/issues/256

Signed-off-by: Alex Hermann <alex@hexla.nl>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 5f202d7ffa)
2017-04-13 16:10:10 +02:00
Alex Hermann
8dc3d883b8 config: Don't expand Host variable
Tokens are not allowed (according to the manpage).
Expansion was introduced by a wrong fix for #127.

This commit reverts part of 6eea08a9ef

Signed-off-by: Alex Hermann <alex@hexla.nl>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c3a8b5009f)
2017-04-13 16:10:09 +02:00
Alex Hermann
24a3f7020c config: Support expansion in the HostName variable
BUG: https://red.libssh.org/issues/127

The original "fix" for 127 was expanding the wrong variable: Host instead
of HostName.

Signed-off-by: Alex Hermann <alex@hexla.nl>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9ef7e90821)
2017-04-13 16:10:07 +02:00
Yanis Kurganov
f74d5d5df4 session: Add SSH1 support in ssh_send_debug()
Signed-off-by: Yanis Kurganov <ykurganov@ptsecurity.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 38cb19268a)
2017-04-11 17:40:58 +02:00
Yanis Kurganov
7a21187fb9 session: Add SSH1 support in ssh_send_ignore()
Signed-off-by: Yanis Kurganov <ykurganov@ptsecurity.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 72fdb4867e)
2017-04-11 17:40:57 +02:00
Max Bachmann
439d3039e3 messages: Utilize the message queue for SSH_REQUEST_GLOBAL.
Signed-off-by: Max Bachmann <mabahltm@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3ec8babfaf)
2017-04-11 09:55:46 +02:00
Andreas Schneider
61cbf160a0 cmake: Fix GCRYPT_ROOT_DIR and check correct paths
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 462c7726c3)
2017-04-11 09:55:05 +02:00
Andreas Schneider
ce029c0735 pki: Use byte mode for fopen()
BUG: https://red.libssh.org/issues/251

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit de369b46b1)
2017-02-03 13:19:24 +01:00
10 changed files with 110 additions and 30 deletions

View File

@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0") set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "7") set(APPLICATION_VERSION_MINOR "7")
set(APPLICATION_VERSION_PATCH "4") set(APPLICATION_VERSION_PATCH "5")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}") set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
# Increment AGE. Set REVISION to 0 # Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes: # If the source code was changed, but there were no interface changes:
# Increment REVISION. # Increment REVISION.
set(LIBRARY_VERSION "4.4.1") set(LIBRARY_VERSION "4.4.2")
set(LIBRARY_SOVERSION "4") set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked

View File

@@ -1,5 +1,12 @@
ChangeLog ChangeLog
========== ==========
version 0.7.5 (released 2017-04-13)
* Fixed a memory allocation issue with buffers
* Fixed PKI on Windows
* Fixed some SSHv1 functions
* Fixed config hostname expansion
version 0.7.4 (released 2017-02-03) version 0.7.4 (released 2017-02-03)
* Added id_ed25519 to the default identity list * Added id_ed25519 to the default identity list
* Fixed sftp EOF packet handling * Fixed sftp EOF packet handling

View File

@@ -35,6 +35,8 @@ find_path(GCRYPT_INCLUDE_DIR
gcrypt.h gcrypt.h
HINTS HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS} ${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
) )
find_library(GCRYPT_LIBRARY find_library(GCRYPT_LIBRARY
@@ -44,6 +46,8 @@ find_library(GCRYPT_LIBRARY
libgcrypt-11 libgcrypt-11
HINTS HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS} ${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
) )
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY}) set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})

View File

@@ -53,6 +53,8 @@ int buffer_add_u32(ssh_buffer buffer, uint32_t data);
int buffer_add_u64(ssh_buffer buffer, uint64_t data); int buffer_add_u64(ssh_buffer buffer, uint64_t data);
int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len); int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len);
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
const char *format, const char *format,
int argc, int argc,

View File

@@ -79,7 +79,7 @@
/* libssh version */ /* libssh version */
#define LIBSSH_VERSION_MAJOR 0 #define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 7 #define LIBSSH_VERSION_MINOR 7
#define LIBSSH_VERSION_MICRO 4 #define LIBSSH_VERSION_MICRO 5
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \ #define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \ LIBSSH_VERSION_MINOR, \

View File

@@ -563,11 +563,14 @@ uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
* @returns 0 if there is not enough data in buffer, len otherwise. * @returns 0 if there is not enough data in buffer, len otherwise.
*/ */
uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len){ uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len){
int rc;
/* /*
* Check for a integer overflow first, then check if not enough data is in * Check for a integer overflow first, then check if not enough data is in
* the buffer. * the buffer.
*/ */
if (buffer->pos + len < len || buffer->pos + len > buffer->used) { rc = ssh_buffer_validate_length(buffer, len);
if (rc != SSH_OK) {
return 0; return 0;
} }
memcpy(data,buffer->data+buffer->pos,len); memcpy(data,buffer->data+buffer->pos,len);
@@ -617,6 +620,24 @@ int buffer_get_u64(struct ssh_buffer_struct *buffer, uint64_t *data){
return buffer_get_data(buffer,data,sizeof(uint64_t)); return buffer_get_data(buffer,data,sizeof(uint64_t));
} }
/**
* @brief Valdiates that the given length can be obtained from the buffer.
*
* @param[in] buffer The buffer to read from.
*
* @param[in] len The length to be checked.
*
* @return SSH_OK if the length is valid, SSH_ERROR otherwise.
*/
int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len)
{
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return SSH_ERROR;
}
return SSH_OK;
}
/** /**
* @internal * @internal
* *
@@ -630,13 +651,15 @@ struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer
uint32_t stringlen; uint32_t stringlen;
uint32_t hostlen; uint32_t hostlen;
struct ssh_string_struct *str = NULL; struct ssh_string_struct *str = NULL;
int rc;
if (buffer_get_u32(buffer, &stringlen) == 0) { if (buffer_get_u32(buffer, &stringlen) == 0) {
return NULL; return NULL;
} }
hostlen = ntohl(stringlen); hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */ /* verify if there is enough space in buffer to get it */
if (buffer->pos + hostlen < hostlen || buffer->pos + hostlen > buffer->used) { rc = ssh_buffer_validate_length(buffer, hostlen);
if (rc != SSH_OK) {
return NULL; /* it is indeed */ return NULL; /* it is indeed */
} }
str = ssh_string_new(hostlen); str = ssh_string_new(hostlen);
@@ -867,11 +890,13 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
char **cstring; char **cstring;
void **data; void **data;
} o; } o;
size_t len, rlen; size_t len, rlen, max_len;
uint32_t u32len; uint32_t u32len;
va_list ap_copy; va_list ap_copy;
int count; int count;
max_len = ssh_buffer_get_len(buffer);
/* copy the argument list in case a rollback is needed */ /* copy the argument list in case a rollback is needed */
va_copy(ap_copy, ap); va_copy(ap_copy, ap);
@@ -921,10 +946,16 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
break; break;
} }
len = ntohl(u32len); len = ntohl(u32len);
if (len > UINT_MAX - 1){ if (len > max_len - 1) {
rc = SSH_ERROR; rc = SSH_ERROR;
break; break;
} }
rc = ssh_buffer_validate_length(buffer, len);
if (rc != SSH_OK) {
break;
}
*o.cstring = malloc(len + 1); *o.cstring = malloc(len + 1);
if (*o.cstring == NULL){ if (*o.cstring == NULL){
rc = SSH_ERROR; rc = SSH_ERROR;
@@ -942,6 +973,15 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
break; break;
case 'P': case 'P':
len = va_arg(ap, size_t); len = va_arg(ap, size_t);
if (len > max_len - 1) {
rc = SSH_ERROR;
break;
}
rc = ssh_buffer_validate_length(buffer, len);
if (rc != SSH_OK) {
break;
}
o.data = va_arg(ap, void **); o.data = va_arg(ap, void **);
count++; count++;

View File

@@ -50,6 +50,8 @@ enum ssh_config_opcode_e {
SOC_GSSAPISERVERIDENTITY, SOC_GSSAPISERVERIDENTITY,
SOC_GSSAPICLIENTIDENTITY, SOC_GSSAPICLIENTIDENTITY,
SOC_GSSAPIDELEGATECREDENTIALS, SOC_GSSAPIDELEGATECREDENTIALS,
SOC_END /* Keep this one last in the list */
}; };
struct ssh_config_keyword_table_s { struct ssh_config_keyword_table_s {
@@ -185,7 +187,7 @@ static int ssh_config_get_yesno(char **str, int notfound) {
} }
static int ssh_config_parse_line(ssh_session session, const char *line, static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing) { unsigned int count, int *parsing, int seen[]) {
enum ssh_config_opcode_e opcode; enum ssh_config_opcode_e opcode;
const char *p; const char *p;
char *s, *x; char *s, *x;
@@ -216,6 +218,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
} }
opcode = ssh_config_get_opcode(keyword); opcode = ssh_config_get_opcode(keyword);
if (*parsing == 1 && opcode != SOC_HOST) {
if (seen[opcode] == 0) {
return 0;
}
seen[opcode] = 1;
}
switch (opcode) { switch (opcode) {
case SOC_HOST: { case SOC_HOST: {
@@ -227,18 +235,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
p != NULL && p[0] != '\0'; p != NULL && p[0] != '\0';
p = ssh_config_get_str_tok(&s, NULL)) { p = ssh_config_get_str_tok(&s, NULL)) {
if (ok >= 0) { if (ok >= 0) {
char *z = ssh_path_expand_escape(session, p); ok = match_hostname(lowerhost, p, strlen(p));
if (z == NULL) {
z = strdup(p);
}
ok = match_hostname(lowerhost, z, strlen(z));
if (ok < 0) { if (ok < 0) {
*parsing = 0; *parsing = 0;
} else if (ok > 0) { } else if (ok > 0) {
*parsing = 1; *parsing = 1;
} }
free(z);
} }
} }
SAFE_FREE(lowerhost); SAFE_FREE(lowerhost);
@@ -247,7 +249,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
case SOC_HOSTNAME: case SOC_HOSTNAME:
p = ssh_config_get_str_tok(&s, NULL); p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) { if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_HOST, p); char *z = ssh_path_expand_escape(session, p);
if (z == NULL) {
z = strdup(p);
}
ssh_options_set(session, SSH_OPTIONS_HOST, z);
free(z);
} }
break; break;
case SOC_PORT: case SOC_PORT:
@@ -384,6 +391,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
unsigned int count = 0; unsigned int count = 0;
FILE *f; FILE *f;
int parsing; int parsing;
int seen[SOC_END - SOC_UNSUPPORTED] = {0};
if ((f = fopen(filename, "r")) == NULL) { if ((f = fopen(filename, "r")) == NULL) {
return 0; return 0;
@@ -394,7 +402,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
parsing = 1; parsing = 1;
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
count++; count++;
if (ssh_config_parse_line(session, line, count, &parsing) < 0) { if (ssh_config_parse_line(session, line, count, &parsing, seen) < 0) {
fclose(f); fclose(f);
return -1; return -1;
} }

View File

@@ -1355,7 +1355,8 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
msg->global_request.bind_port); msg->global_request.bind_port);
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
} else { } else {
ssh_message_reply_default(msg); ssh_message_queue(session, msg);
return rc;
} }
} else if (strcmp(request, "cancel-tcpip-forward") == 0) { } else if (strcmp(request, "cancel-tcpip-forward") == 0) {
r = ssh_buffer_unpack(packet, "sd", r = ssh_buffer_unpack(packet, "sd",
@@ -1374,7 +1375,8 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) { if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
} else { } else {
ssh_message_reply_default(msg); ssh_message_queue(session, msg);
return rc;
} }
} else { } else {
SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply); SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s %d", request, want_reply);

View File

@@ -955,7 +955,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
return SSH_ERROR; return SSH_ERROR;
} }
file = fopen(filename, "r"); file = fopen(filename, "rb");
if (file == NULL) { if (file == NULL) {
ssh_pki_log("Error opening %s: %s", ssh_pki_log("Error opening %s: %s",
filename, strerror(errno)); filename, strerror(errno));
@@ -1233,7 +1233,7 @@ int ssh_pki_export_pubkey_file(const ssh_key key,
return SSH_ERROR; return SSH_ERROR;
} }
fp = fopen(filename, "w+"); fp = fopen(filename, "wb+");
if (fp == NULL) { if (fp == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }

View File

@@ -31,6 +31,9 @@
#include "libssh/crypto.h" #include "libssh/crypto.h"
#include "libssh/server.h" #include "libssh/server.h"
#include "libssh/socket.h" #include "libssh/socket.h"
#ifdef WITH_SSH1
#include "libssh/ssh1.h"
#endif /* WITH_SSH1 */
#include "libssh/ssh2.h" #include "libssh/ssh2.h"
#include "libssh/agent.h" #include "libssh/agent.h"
#include "libssh/packet.h" #include "libssh/packet.h"
@@ -830,13 +833,17 @@ void ssh_socket_exception_callback(int code, int errno_code, void *user){
* @return SSH_OK on success, SSH_ERROR otherwise. * @return SSH_OK on success, SSH_ERROR otherwise.
*/ */
int ssh_send_ignore (ssh_session session, const char *data) { int ssh_send_ignore (ssh_session session, const char *data) {
#ifdef WITH_SSH1
const int type = session->version == 1 ? SSH_MSG_IGNORE : SSH2_MSG_IGNORE;
#else /* WITH_SSH1 */
const int type = SSH2_MSG_IGNORE;
#endif /* WITH_SSH1 */
int rc; int rc;
if (ssh_socket_is_open(session->socket)) { if (ssh_socket_is_open(session->socket)) {
rc = ssh_buffer_pack(session->out_buffer, rc = ssh_buffer_pack(session->out_buffer,
"bs", "bs",
SSH2_MSG_IGNORE, type,
data); data);
if (rc != SSH_OK){ if (rc != SSH_OK){
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -868,12 +875,22 @@ int ssh_send_debug (ssh_session session, const char *message, int always_display
int rc; int rc;
if (ssh_socket_is_open(session->socket)) { if (ssh_socket_is_open(session->socket)) {
#ifdef WITH_SSH1
if (session->version == 1) {
rc = ssh_buffer_pack(session->out_buffer,
"bs",
SSH_MSG_DEBUG,
message);
} else
#endif /* WITH_SSH1 */
{
rc = ssh_buffer_pack(session->out_buffer, rc = ssh_buffer_pack(session->out_buffer,
"bbsd", "bbsd",
SSH2_MSG_DEBUG, SSH2_MSG_DEBUG,
always_display != 0 ? 1 : 0, always_display != 0 ? 1 : 0,
message, message,
0); /* empty language tag */ 0); /* empty language tag */
}
if (rc != SSH_OK) { if (rc != SSH_OK) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
goto error; goto error;