Sean Peterson's key re-exchange fix. See his long explanation on:
http://daniel.haxx.se/projects/libssh2/mail/libssh2-devel-archive-2008-06/0002.shtml
Этот коммит содержится в:
родитель
903307113e
Коммит
99afc66665
3
NEWS
3
NEWS
@ -1,6 +1,9 @@
|
||||
Version 0.19 ( )
|
||||
-------------------------------
|
||||
|
||||
- Sean Peterson fixed a key re-exchange bug:
|
||||
http://daniel.haxx.se/projects/libssh2/mail/libssh2-devel-archive-2008-06/0002.shtml
|
||||
|
||||
- Mike Protts filed the bug report #1908724 that identified and fixed a problem
|
||||
with SFTP stat on files >4GB in size. Previously it used 32bit math only.
|
||||
|
||||
|
10
src/kex.c
10
src/kex.c
@ -1680,6 +1680,8 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
|
||||
int rc = 0;
|
||||
int retcode;
|
||||
|
||||
session->state |= LIBSSH2_STATE_KEX_ACTIVE;
|
||||
|
||||
if (key_state->state == libssh2_NB_state_idle) {
|
||||
/* Prevent loop in packet_add() */
|
||||
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||
@ -1711,11 +1713,14 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
|
||||
if (key_state->state == libssh2_NB_state_sent) {
|
||||
retcode = libssh2_kexinit(session);
|
||||
if (retcode == PACKET_EAGAIN) {
|
||||
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||
return PACKET_EAGAIN;
|
||||
} else if (retcode) {
|
||||
session->local.kexinit = key_state->oldlocal;
|
||||
session->local.kexinit_len = key_state->oldlocal_len;
|
||||
key_state->state = libssh2_NB_state_idle;
|
||||
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1729,6 +1734,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
|
||||
&key_state->data_len, 0, NULL, 0,
|
||||
&key_state->req_state);
|
||||
if (retcode == PACKET_EAGAIN) {
|
||||
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||
return PACKET_EAGAIN;
|
||||
} else if (retcode) {
|
||||
if (session->local.kexinit) {
|
||||
@ -1737,6 +1743,8 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
|
||||
session->local.kexinit = key_state->oldlocal;
|
||||
session->local.kexinit_len = key_state->oldlocal_len;
|
||||
key_state->state = libssh2_NB_state_idle;
|
||||
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1763,6 +1771,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
|
||||
session->kex->exchange_keys(session,
|
||||
&key_state->key_state_low);
|
||||
if (retcode == PACKET_EAGAIN) {
|
||||
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||
return PACKET_EAGAIN;
|
||||
} else if (retcode) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
|
||||
@ -1782,6 +1791,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
|
||||
session->remote.kexinit = NULL;
|
||||
}
|
||||
|
||||
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||
|
||||
key_state->state = libssh2_NB_state_idle;
|
||||
|
@ -833,6 +833,7 @@ struct _LIBSSH2_SESSION
|
||||
#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
|
||||
#define LIBSSH2_STATE_NEWKEYS 0x00000002
|
||||
#define LIBSSH2_STATE_AUTHENTICATED 0x00000004
|
||||
#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008
|
||||
|
||||
/* session.flag helpers */
|
||||
#ifdef MSG_NOSIGNAL
|
||||
|
22
src/packet.c
22
src/packet.c
@ -914,11 +914,31 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||
|
||||
session->packAdd_state = libssh2_NB_state_sent2;
|
||||
}
|
||||
|
||||
/*
|
||||
* The KEXINIT message has been added to the queue.
|
||||
* The packAdd and readPack states need to be reset
|
||||
* because libssh2_kex_exchange (eventually) calls upon
|
||||
* libssh2_packet_read to read the rest of the key exchange
|
||||
* conversation.
|
||||
*/
|
||||
session->readPack_state = libssh2_NB_state_idle;
|
||||
session->packet.total_num = 0;
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
session->fullpacket_state = libssh2_NB_state_idle;
|
||||
|
||||
/*
|
||||
* Also, don't use packAdd_key_state for key re-exchange,
|
||||
* as it will be wiped out in the middle of the exchange.
|
||||
* How about re-using the startup_key_state?
|
||||
*/
|
||||
memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t));
|
||||
|
||||
/*
|
||||
* If there was a key reexchange failure, let's just hope we didn't
|
||||
* send NEWKEYS yet, otherwise remote will drop us like a rock
|
||||
*/
|
||||
rc = libssh2_kex_exchange(session, 1, &session->packAdd_key_state);
|
||||
rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
|
391
src/sshentry.c
Обычный файл
391
src/sshentry.c
Обычный файл
@ -0,0 +1,391 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libssh2_priv.h"
|
||||
|
||||
static int
|
||||
ssh_host_parse_hostnames (LIBSSH2_SESSION * session,
|
||||
LIBSSH2_KNOWNHOSTS * s,
|
||||
char *line,
|
||||
char *end
|
||||
);
|
||||
|
||||
static int
|
||||
ssh_host_parse_key (LIBSSH2_SESSION * session,
|
||||
LIBSSH2_KNOWNHOSTS * s,
|
||||
char *line,
|
||||
int is_base64_encoded
|
||||
);
|
||||
|
||||
/* Returns zero if successful, > zero for malformed data, < 0 not supported. */
|
||||
LIBSSH2_API int
|
||||
libssh2_new_host_entry(LIBSSH2_SESSION * session,
|
||||
LIBSSH2_KNOWNHOSTS ** s,
|
||||
char *line)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
LIBSSH2_KNOWNHOSTS *t = NULL;
|
||||
int i;
|
||||
|
||||
if (line == NULL || *line == 0)
|
||||
return 1;
|
||||
if (s == NULL)
|
||||
return 2;
|
||||
|
||||
tmp = strchr (line, ' ');
|
||||
if (tmp == NULL)
|
||||
return 3;
|
||||
|
||||
|
||||
t = (LIBSSH2_KNOWNHOSTS *)
|
||||
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_KNOWNHOSTS));
|
||||
|
||||
t->hostname_line = NULL;
|
||||
t->hostnames = NULL;
|
||||
t->hostnames_size = t->bits = t->exponent = -1;
|
||||
t->modulus = NULL;
|
||||
t->modulus_length = -1;
|
||||
t->ssh_version = -1;
|
||||
t->md5 = NULL;
|
||||
|
||||
i = ssh_host_parse_hostnames (session, t, line, tmp);
|
||||
if (i != 0) {
|
||||
libssh2_free_host_entry (session, t);
|
||||
return ((i > 0) ? 4 : -1);
|
||||
}
|
||||
|
||||
line = tmp + 1;
|
||||
tmp = strchr (line, ' ');
|
||||
if (tmp != NULL)
|
||||
tmp = strchr (tmp + 1, ' ');
|
||||
|
||||
i = ssh_host_parse_key (session, t, line, tmp == NULL ? 1 : 0);
|
||||
if (i != 0) {
|
||||
libssh2_free_host_entry (session, t);
|
||||
return ((i > 0) ? 5 : -2);
|
||||
}
|
||||
|
||||
*s = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_host_parse_hostnames(LIBSSH2_SESSION * session,
|
||||
LIBSSH2_KNOWNHOSTS * s,
|
||||
char *line,
|
||||
char *end)
|
||||
{
|
||||
char *start;
|
||||
char *comma = NULL;
|
||||
int i;
|
||||
|
||||
/* TODO: we don't handle the hashed name format because the hashing
|
||||
* mechanism isnt defined (at least based on the man page)
|
||||
*/
|
||||
if (*line == '|')
|
||||
return -1;
|
||||
if (line == end || *line == ' ')
|
||||
return 1;
|
||||
|
||||
s->hostname_line = (char *) LIBSSH2_ALLOC (session, (end - line) + 1);
|
||||
strncpy (s->hostname_line, line, (end - line) + 1);
|
||||
start = end = s->hostname_line + (end - line);
|
||||
*end = 0;
|
||||
|
||||
s->hostnames_size = 1;
|
||||
comma = s->hostname_line;
|
||||
while ((comma = strchr (comma, ',')) != NULL) {
|
||||
comma++;
|
||||
if (*comma == ',' || *comma == 0) {
|
||||
LIBSSH2_FREE (session, s->hostname_line);
|
||||
s->hostname_line = NULL;
|
||||
return 2;
|
||||
}
|
||||
s->hostnames_size++;
|
||||
}
|
||||
s->hostnames = (char **) LIBSSH2_ALLOC
|
||||
(session, sizeof (char *) * s->hostnames_size);
|
||||
|
||||
start = comma = s->hostname_line;
|
||||
i = 0;
|
||||
while ((comma = strchr (comma, ',')) != NULL) {
|
||||
*comma = 0;
|
||||
s->hostnames[i] = start;
|
||||
|
||||
comma++;
|
||||
start = comma;
|
||||
i++;
|
||||
}
|
||||
s->hostnames[i] = start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns the number of bytes read or -1. */
|
||||
static int
|
||||
ssh_proto_str_read(LIBSSH2_SESSION * session,
|
||||
char *line,
|
||||
char **val,
|
||||
char *end
|
||||
)
|
||||
{
|
||||
unsigned int len;
|
||||
|
||||
if (line + 4 > end)
|
||||
return -1;
|
||||
len = (line[0] << 24) + (line[1] << 16) + (line[2] << 8) + line[3];
|
||||
if (line + 4 + len > end)
|
||||
return -1;
|
||||
|
||||
*val = LIBSSH2_ALLOC (session, len);
|
||||
memcpy (*val, line + 4, len);
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_host_parse_key(LIBSSH2_SESSION * session,
|
||||
LIBSSH2_KNOWNHOSTS * s,
|
||||
char *line,
|
||||
int is_base64_encoded)
|
||||
{
|
||||
int i, j;
|
||||
char *tmp, *tmp2;
|
||||
/* workaround for the MD5 stuff */
|
||||
libssh2_md5_ctx ctx;
|
||||
|
||||
/* the bits, exponent, modulus format */
|
||||
if (is_base64_encoded == 0) {
|
||||
s->ssh_version = 1;
|
||||
s->key_type = 0;
|
||||
if (!isdigit (*line))
|
||||
return -1;
|
||||
if (sscanf (line, "%hu %hu ", &(s->bits), &(s->exponent)) != 2)
|
||||
return -2;
|
||||
/* TODO:
|
||||
* There's probably an acceptable range...
|
||||
*/
|
||||
if (s->bits <= 0 || s->exponent <= 0)
|
||||
return 1;
|
||||
|
||||
line = strchr (line, ' ');
|
||||
if (line == NULL)
|
||||
return -3;
|
||||
line++;
|
||||
line = strchr (line, ' ');
|
||||
if (line == NULL)
|
||||
return -4;
|
||||
line++;
|
||||
/* TODO:
|
||||
* figure out what format modulus is in since its not clear
|
||||
* from the man page
|
||||
*/
|
||||
return -5;
|
||||
}
|
||||
else {
|
||||
s->ssh_version = 2;
|
||||
/* we only handle the rsa type */
|
||||
if (strstr (line, "ssh-rsa") != line)
|
||||
return -6;
|
||||
s->key_type = 0;
|
||||
line += 7;
|
||||
if (*line != ' ')
|
||||
return 2;
|
||||
line++;
|
||||
i = 0;
|
||||
while (*line) {
|
||||
if ((line[i] >= 0x30 && line[i] <= 0x39) ||
|
||||
(line[i] >= 0x41 && line[i] <= 0x5a) ||
|
||||
(line[i] >= 0x61 && line[i] <= 0x7a) ||
|
||||
(line[i] == '+') || (line[i] == '/') || (line[i] == '='))
|
||||
i++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
return 3;
|
||||
tmp = LIBSSH2_ALLOC (session, sizeof (char) * (i + 5));
|
||||
strncpy (tmp, line, i);
|
||||
/* this should hopefully avoid any issues with reading
|
||||
* past the array if its malformed */
|
||||
tmp[i] = tmp[i + 1] = tmp[i + 2] = tmp[i + 3] = tmp[i + 4] = 0;
|
||||
/*
|
||||
i = j = Curl_base64_decode (tmp, (unsigned char **) &tmp2);
|
||||
*/
|
||||
|
||||
/* FIXME:
|
||||
* Must use a base64 decoder implementation in order to decode stuff.
|
||||
*/
|
||||
{
|
||||
/* TODO: rework the api interface instead of making a local instance */
|
||||
i = libssh2_base64_decode(session, &tmp2, (unsigned int *)&j,
|
||||
tmp, strlen(tmp));
|
||||
LIBSSH2_FREE(session, tmp);
|
||||
if (i != 0)
|
||||
return 4;
|
||||
|
||||
}
|
||||
|
||||
/* printf("Decode Size: %d\n", i); */
|
||||
/* free (tmp); */
|
||||
|
||||
|
||||
#if LIBSSH2_MD5
|
||||
s->md5 = LIBSSH2_ALLOC (session, 16);
|
||||
|
||||
libssh2_md5_init (&ctx);
|
||||
libssh2_md5_update (ctx, tmp2, j);
|
||||
libssh2_md5_final (ctx, s->md5);
|
||||
/*
|
||||
MD5_Init (ctx);
|
||||
MD5_Update (ctx, tmp2, j);
|
||||
MD5_Final (s->md5, ctx);
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
line = tmp2;
|
||||
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
|
||||
if (i < 0) {
|
||||
LIBSSH2_FREE (session, tmp2);
|
||||
return 5;
|
||||
}
|
||||
/* TODO: verify that its ssh-rsa -- its the only one
|
||||
* supported
|
||||
*/
|
||||
if (!(i == 11 && tmp[0] == 's' && tmp[1] == 's' &&
|
||||
tmp[2] == 'h' && tmp[3] == '-' && tmp[4] == 'r' &&
|
||||
tmp[5] == 's' && tmp[6] == 'a')) {
|
||||
free (tmp);
|
||||
free (tmp2);
|
||||
return 8;
|
||||
}
|
||||
|
||||
LIBSSH2_FREE (session, tmp);
|
||||
line += i;
|
||||
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
|
||||
if (i < 0) {
|
||||
LIBSSH2_FREE (session, tmp2);
|
||||
return 6;
|
||||
}
|
||||
/* TODO: verify that the exponent is valid */
|
||||
if (i == 5)
|
||||
s->exponent = (unsigned short) ((unsigned char) *tmp);
|
||||
else {
|
||||
LIBSSH2_FREE (session, tmp);
|
||||
LIBSSH2_FREE (session, tmp2);
|
||||
return 9;
|
||||
}
|
||||
|
||||
LIBSSH2_FREE (session, tmp);
|
||||
line += i;
|
||||
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
|
||||
if (i < 0) {
|
||||
LIBSSH2_FREE (session, tmp2);
|
||||
return 7;
|
||||
}
|
||||
|
||||
/* TODO: the modulus may need to be converted to
|
||||
* big integer format
|
||||
*/
|
||||
s->modulus_length = i - 4;
|
||||
s->modulus = tmp;
|
||||
|
||||
s->bits = (s->modulus_length - 1) * 8;
|
||||
|
||||
LIBSSH2_FREE (session, tmp2);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LIBSSH2_API void
|
||||
libssh2_free_host_entry(LIBSSH2_SESSION * session, LIBSSH2_KNOWNHOSTS * s)
|
||||
{
|
||||
/* int i; */
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
if (s->hostname_line != NULL) {
|
||||
LIBSSH2_FREE (session, s->hostname_line);
|
||||
s->hostname_line = NULL;
|
||||
}
|
||||
/*
|
||||
for (i=0; i < s->hostnames_size; i++) {
|
||||
if (s->hostnames[i] != NULL) {
|
||||
free(s->hostnames[i]);
|
||||
s->hostnames[i] = NULL;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (s->hostnames != NULL && s->hostnames_size > 0) {
|
||||
LIBSSH2_FREE (session, s->hostnames);
|
||||
s->hostnames = NULL;
|
||||
}
|
||||
s->hostnames_size = s->bits = s->exponent = -1;
|
||||
|
||||
if (s->modulus != NULL) {
|
||||
LIBSSH2_FREE (session, s->modulus);
|
||||
s->modulus = NULL;
|
||||
}
|
||||
s->modulus_length = -1;
|
||||
s->ssh_version = -1;
|
||||
|
||||
if (s->md5 != NULL) {
|
||||
LIBSSH2_FREE (session, s->md5);
|
||||
s->md5 = NULL;
|
||||
}
|
||||
|
||||
LIBSSH2_FREE (session, s);
|
||||
}
|
||||
|
||||
#ifdef SSH_HOSTNAME_TESTS
|
||||
int
|
||||
ssh_unit_tests (int argc, char **argv)
|
||||
{
|
||||
char *l[] = {
|
||||
"closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net",
|
||||
"cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
|
||||
" cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
|
||||
"",
|
||||
",",
|
||||
"f, ",
|
||||
"cvs.example.net ssh-rsa AAAA1234.....=",
|
||||
"192.168.30.118 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwWVqxKm2Biwilakq9Ex8/tzHVQjRrzEkwlrWTDneptodVgqAzXUFQSa6Oj9AwzdDPhKe71vTv7RhXYg0ZvB1a5dIkzgCdoF/mIuTb80LvK7f0NxCaAHWODuHbwlJeMmjHV0WFsjsdOf690fPqeinD/8jfBQB950M1K3Qesib9H75gsnawF06MzZ52nC1HHi8mG2tGy2PMyP+mJs7KN1v4T+nobZ10ePe1dMqYXMdro/PB0JQmuGL7bBR5GRDEkK6nFcp2HsvuzXSeWZJcmWDdo+1n0cNg2th5VEIxrrFG5iy0CA2AXVPMqkf3VrAXGXV66dJTGtBqZ5GoxJCxDgW6w==",
|
||||
"|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsaAAAA1234.....="
|
||||
};
|
||||
int s;
|
||||
int cases = sizeof (l) / sizeof (char *);
|
||||
|
||||
if (argc == 2) {
|
||||
s = atoi (argv[1]);
|
||||
if (s >= 0 && s < cases) {
|
||||
LIBSSH2_KNOWNHOSTS *x = NULL;
|
||||
printf ("%d\n", s = new_ssh_host_entry (&x, l[s]));
|
||||
libssh2_free_host_entry (x);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Returns 0 for a match, non-zero otherwise. */
|
||||
LIBSSH2_API int
|
||||
libssh2_host_entry_match(LIBSSH2_KNOWNHOSTS * x, char *host)
|
||||
{
|
||||
/* TODO: Add pattern matching and/or DNS matching against
|
||||
* to entries found in x
|
||||
*/
|
||||
int i;
|
||||
if (host == NULL || x == NULL)
|
||||
return -1;
|
||||
|
||||
/* FIXME: this should use a case-insensitive compare as dns hostnames
|
||||
* are generally case insensitive anyways
|
||||
*/
|
||||
for (i = 0; i < x->hostnames_size; i++)
|
||||
if (!strcmp (x->hostnames[i], host))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
@ -269,6 +269,40 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
|
||||
int blocksize;
|
||||
int encrypted = 1;
|
||||
|
||||
int status;
|
||||
|
||||
/*
|
||||
* All channels, systems, subsystems, etc eventually make it down here
|
||||
* when looking for more incoming data. If a key exchange is going on
|
||||
* (LIBSSH2_STATE_EXCHANGING_KEYS bit is set) then the remote end
|
||||
* will ONLY send key exchange related traffic. In non-blocking mode,
|
||||
* there is a chance to break out of the kex_exchange function with an
|
||||
* EAGAIN status, and never come back to it. If LIBSSH2_STATE_EXCHANGING_KEYS
|
||||
* is active, then we must redirect to the key exchange. However,
|
||||
* if kex_exchange is active (as in it is the one that calls this execution
|
||||
* of packet_read, then don't redirect, as that would be an infinite loop!
|
||||
*/
|
||||
|
||||
if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
|
||||
!(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
|
||||
|
||||
/* Whoever wants a packet won't get anything until the key re-exchange
|
||||
* is done!
|
||||
*/
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the"
|
||||
" key re-exchange");
|
||||
status = libssh2_kex_exchange(session, 1, &session->startup_key_state);
|
||||
if (status == PACKET_EAGAIN) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block exchanging encryption keys", 0);
|
||||
return PACKET_EAGAIN;
|
||||
} else if (status) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
|
||||
"Unable to exchange encryption keys",0);
|
||||
return LIBSSH2_ERROR_KEX_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* =============================== NOTE ===============================
|
||||
* I know this is very ugly and not a really good use of "goto", but
|
||||
@ -527,8 +561,21 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
|
||||
libssh2_packet_read_point1:
|
||||
rc = fullpacket(session, encrypted);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
session->readPack_encrypted = encrypted;
|
||||
session->readPack_state = libssh2_NB_state_jump1;
|
||||
|
||||
if (session->packAdd_state != libssh2_NB_state_idle)
|
||||
{
|
||||
/* fullpacket only returns PACKET_EAGAIN if
|
||||
* libssh2_packet_add returns PACKET_EAGAIN. If that
|
||||
* returns PACKET_EAGAIN but the packAdd_state is idle,
|
||||
* then the packet has been added to the brigade, but some
|
||||
* immediate action that was taken based on the packet
|
||||
* type (such as key re-exchange) is not yet complete.
|
||||
* Clear the way for a new packet to be read in.
|
||||
*/
|
||||
session->readPack_encrypted = encrypted;
|
||||
session->readPack_state = libssh2_NB_state_jump1;
|
||||
}
|
||||
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user