_libssh2_transport_write: remade to send without malloc
Этот коммит содержится в:
родитель
3a391f6cf2
Коммит
5ede32a826
184
src/comp.c
184
src/comp.c
@ -53,7 +53,30 @@
|
|||||||
* Minimalist compression: Absolutely none
|
* Minimalist compression: Absolutely none
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
comp_method_none_comp(LIBSSH2_SESSION * session,
|
comp_method_none_comp(LIBSSH2_SESSION *session,
|
||||||
|
unsigned char *dest,
|
||||||
|
size_t *dest_len,
|
||||||
|
const unsigned char *src,
|
||||||
|
size_t src_len,
|
||||||
|
void **abstract)
|
||||||
|
{
|
||||||
|
(void) session;
|
||||||
|
(void) abstract;
|
||||||
|
(void) dest;
|
||||||
|
(void) dest_len;
|
||||||
|
(void) src;
|
||||||
|
(void) src_len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* comp_method_none_decomp
|
||||||
|
*
|
||||||
|
* Minimalist decompression: Absolutely none
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
comp_method_none_decomp(LIBSSH2_SESSION * session,
|
||||||
int compress,
|
int compress,
|
||||||
unsigned char **dest,
|
unsigned char **dest,
|
||||||
size_t *dest_len,
|
size_t *dest_len,
|
||||||
@ -81,7 +104,7 @@ static const LIBSSH2_COMP_METHOD comp_method_none = {
|
|||||||
0, /* not really compressing */
|
0, /* not really compressing */
|
||||||
NULL,
|
NULL,
|
||||||
comp_method_none_comp,
|
comp_method_none_comp,
|
||||||
comp_method_none_comp,
|
comp_method_none_decomp,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -154,141 +177,35 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
|
|||||||
/*
|
/*
|
||||||
* libssh2_comp_method_zlib_comp
|
* libssh2_comp_method_zlib_comp
|
||||||
*
|
*
|
||||||
* Compresses source to destination. Without any allocation.
|
* Compresses source to destination. Without allocation.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
comp_method_zlib_comp(LIBSSH2_SESSION * session,
|
comp_method_zlib_comp(LIBSSH2_SESSION *session,
|
||||||
int compress,
|
unsigned char *dest,
|
||||||
unsigned char **dest,
|
|
||||||
|
/* dest_len is a pointer to allow this function to
|
||||||
|
update it with the final actual size used */
|
||||||
size_t *dest_len,
|
size_t *dest_len,
|
||||||
size_t payload_limit,
|
|
||||||
int *free_dest,
|
|
||||||
const unsigned char *src,
|
const unsigned char *src,
|
||||||
size_t src_len, void **abstract)
|
size_t src_len,
|
||||||
|
void **abstract)
|
||||||
{
|
{
|
||||||
z_stream *strm = *abstract;
|
z_stream *strm = *abstract;
|
||||||
/* A short-term alloc of a full data chunk is better than a series of
|
int out_maxlen = *dest_len;
|
||||||
reallocs */
|
int status;
|
||||||
char *out;
|
|
||||||
int out_maxlen = compress ? (src_len + 4) : (2 * src_len);
|
|
||||||
int limiter = 0;
|
|
||||||
|
|
||||||
/* If strm is null, then we have not yet been initialized. */
|
|
||||||
if (strm == NULL) {
|
|
||||||
*dest = (unsigned char *) src;
|
|
||||||
*dest_len = src_len;
|
|
||||||
|
|
||||||
*free_dest = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In practice they never come smaller than this */
|
|
||||||
if (out_maxlen < 25) {
|
|
||||||
out_maxlen = 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out_maxlen > (int) payload_limit) {
|
|
||||||
out_maxlen = payload_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
strm->next_in = (unsigned char *) src;
|
strm->next_in = (unsigned char *) src;
|
||||||
strm->avail_in = src_len;
|
strm->avail_in = src_len;
|
||||||
strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
|
strm->next_out = dest;
|
||||||
out = (char *) strm->next_out;
|
|
||||||
strm->avail_out = out_maxlen;
|
strm->avail_out = out_maxlen;
|
||||||
if (!strm->next_out) {
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
|
||||||
"Unable to allocate compression/decompression "
|
|
||||||
"buffer");
|
|
||||||
}
|
|
||||||
while (strm->avail_in) {
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (compress) {
|
status = deflate(strm, Z_PARTIAL_FLUSH);
|
||||||
status = deflate(strm, Z_PARTIAL_FLUSH);
|
|
||||||
} else {
|
|
||||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
|
||||||
}
|
|
||||||
if (status != Z_OK) {
|
|
||||||
LIBSSH2_FREE(session, out);
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
|
||||||
"compress/decompression failure");
|
|
||||||
}
|
|
||||||
if (strm->avail_in) {
|
|
||||||
size_t out_ofs = out_maxlen - strm->avail_out;
|
|
||||||
char *newout;
|
|
||||||
|
|
||||||
out_maxlen +=
|
if (status != Z_OK)
|
||||||
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
||||||
|
"compression failure");
|
||||||
|
|
||||||
if ((out_maxlen > (int) payload_limit) && !compress && limiter++) {
|
|
||||||
LIBSSH2_FREE(session, out);
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
|
||||||
"Excessive growth in decompression phase");
|
|
||||||
}
|
|
||||||
|
|
||||||
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
|
|
||||||
if (!newout) {
|
|
||||||
LIBSSH2_FREE(session, out);
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
|
||||||
"Unable to expand compress/"
|
|
||||||
"decompression buffer");
|
|
||||||
}
|
|
||||||
out = newout;
|
|
||||||
strm->next_out = (unsigned char *) out + out_ofs;
|
|
||||||
strm->avail_out +=
|
|
||||||
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
|
||||||
} else
|
|
||||||
while (!strm->avail_out) {
|
|
||||||
/* Done with input, might be a byte or two in internal buffer
|
|
||||||
* during compress. Or potentially many bytes if it's a
|
|
||||||
* decompress
|
|
||||||
*/
|
|
||||||
int grow_size = compress ? 8 : 1024;
|
|
||||||
char *newout;
|
|
||||||
|
|
||||||
if (out_maxlen >= (int) payload_limit) {
|
|
||||||
LIBSSH2_FREE(session, out);
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
|
||||||
"Excessive growth in decompression "
|
|
||||||
"phase");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grow_size > (int) (payload_limit - out_maxlen)) {
|
|
||||||
grow_size = payload_limit - out_maxlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_maxlen += grow_size;
|
|
||||||
strm->avail_out = grow_size;
|
|
||||||
|
|
||||||
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
|
|
||||||
if (!newout) {
|
|
||||||
LIBSSH2_FREE(session, out);
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
|
||||||
"Unable to expand final compress/"
|
|
||||||
"decompress buffer");
|
|
||||||
}
|
|
||||||
out = newout;
|
|
||||||
strm->next_out = (unsigned char *) out + out_maxlen -
|
|
||||||
grow_size;
|
|
||||||
|
|
||||||
if (compress) {
|
|
||||||
status = deflate(strm, Z_PARTIAL_FLUSH);
|
|
||||||
} else {
|
|
||||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
|
||||||
}
|
|
||||||
if (status != Z_OK) {
|
|
||||||
LIBSSH2_FREE(session, out);
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
|
||||||
"compress/decompression failure");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*dest = (unsigned char *) out;
|
|
||||||
*dest_len = out_maxlen - strm->avail_out;
|
*dest_len = out_maxlen - strm->avail_out;
|
||||||
*free_dest = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +355,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session,
|
|||||||
* All done, no more compression for you
|
* All done, no more compression for you
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
comp_method_zlib_dtor(LIBSSH2_SESSION * session, int compress,
|
comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compress,
|
||||||
void **abstract)
|
void **abstract)
|
||||||
{
|
{
|
||||||
z_stream *strm = *abstract;
|
z_stream *strm = *abstract;
|
||||||
@ -470,10 +387,8 @@ static const LIBSSH2_COMP_METHOD comp_method_zlib = {
|
|||||||
};
|
};
|
||||||
#endif /* LIBSSH2_HAVE_ZLIB */
|
#endif /* LIBSSH2_HAVE_ZLIB */
|
||||||
|
|
||||||
/* ***********************
|
/* If compression is enabled by the API, then this array is used which then
|
||||||
* Compression Methods *
|
may allow compression if zlib is available at build time */
|
||||||
*********************** */
|
|
||||||
|
|
||||||
static const LIBSSH2_COMP_METHOD *comp_methods[] = {
|
static const LIBSSH2_COMP_METHOD *comp_methods[] = {
|
||||||
#ifdef LIBSSH2_HAVE_ZLIB
|
#ifdef LIBSSH2_HAVE_ZLIB
|
||||||
&comp_method_zlib,
|
&comp_method_zlib,
|
||||||
@ -482,8 +397,17 @@ static const LIBSSH2_COMP_METHOD *comp_methods[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* If compression is disabled by the API, then this array is used */
|
||||||
|
static const LIBSSH2_COMP_METHOD *no_comp_methods[] = {
|
||||||
|
&comp_method_none,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
const LIBSSH2_COMP_METHOD **
|
const LIBSSH2_COMP_METHOD **
|
||||||
_libssh2_comp_methods(void)
|
_libssh2_comp_methods(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
return comp_methods;
|
if(session->flag.compress)
|
||||||
|
return comp_methods;
|
||||||
|
else
|
||||||
|
return no_comp_methods;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __LIBSSH2_COMP_H
|
#ifndef __LIBSSH2_COMP_H
|
||||||
#define __LIBSSH2_COMP_H
|
#define __LIBSSH2_COMP_H
|
||||||
|
|
||||||
/* Copyright (C) 2009 by Daniel Stenberg
|
/* Copyright (C) 2009-2010 by Daniel Stenberg
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
* with or without modification, are permitted provided
|
* with or without modification, are permitted provided
|
||||||
@ -40,6 +40,6 @@
|
|||||||
|
|
||||||
#include "libssh2_priv.h"
|
#include "libssh2_priv.h"
|
||||||
|
|
||||||
const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(void);
|
const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session);
|
||||||
|
|
||||||
#endif /* __LIBSSH2_COMP_H */
|
#endif /* __LIBSSH2_COMP_H */
|
||||||
|
21
src/kex.c
21
src/kex.c
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||||
|
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@ -1043,10 +1044,10 @@ static int kexinit(LIBSSH2_SESSION * session)
|
|||||||
_libssh2_mac_methods());
|
_libssh2_mac_methods());
|
||||||
comp_cs_len =
|
comp_cs_len =
|
||||||
LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs,
|
LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs,
|
||||||
_libssh2_comp_methods());
|
_libssh2_comp_methods(session));
|
||||||
comp_sc_len =
|
comp_sc_len =
|
||||||
LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs,
|
LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs,
|
||||||
_libssh2_comp_methods());
|
_libssh2_comp_methods(session));
|
||||||
lang_cs_len =
|
lang_cs_len =
|
||||||
LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
|
LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
|
||||||
lang_sc_len =
|
lang_sc_len =
|
||||||
@ -1083,9 +1084,9 @@ static int kexinit(LIBSSH2_SESSION * session)
|
|||||||
LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs,
|
LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs,
|
||||||
_libssh2_mac_methods());
|
_libssh2_mac_methods());
|
||||||
LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs,
|
LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs,
|
||||||
_libssh2_comp_methods());
|
_libssh2_comp_methods(session));
|
||||||
LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs,
|
LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs,
|
||||||
_libssh2_comp_methods());
|
_libssh2_comp_methods(session));
|
||||||
LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs,
|
LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs,
|
||||||
NULL);
|
NULL);
|
||||||
LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs,
|
LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs,
|
||||||
@ -1487,11 +1488,11 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
|
|||||||
/* kex_agree_comp
|
/* kex_agree_comp
|
||||||
* Agree on a compression scheme
|
* Agree on a compression scheme
|
||||||
*/
|
*/
|
||||||
static int kex_agree_comp(LIBSSH2_SESSION * session,
|
static int kex_agree_comp(LIBSSH2_SESSION *session,
|
||||||
libssh2_endpoint_data * endpoint, unsigned char *comp,
|
libssh2_endpoint_data *endpoint, unsigned char *comp,
|
||||||
unsigned long comp_len)
|
unsigned long comp_len)
|
||||||
{
|
{
|
||||||
const LIBSSH2_COMP_METHOD **compp = _libssh2_comp_methods();
|
const LIBSSH2_COMP_METHOD **compp = _libssh2_comp_methods(session);
|
||||||
unsigned char *s;
|
unsigned char *s;
|
||||||
(void) session;
|
(void) session;
|
||||||
|
|
||||||
@ -1827,12 +1828,14 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
|
|||||||
|
|
||||||
case LIBSSH2_METHOD_COMP_CS:
|
case LIBSSH2_METHOD_COMP_CS:
|
||||||
prefvar = &session->local.comp_prefs;
|
prefvar = &session->local.comp_prefs;
|
||||||
mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods();
|
mlist = (const LIBSSH2_COMMON_METHOD **)
|
||||||
|
_libssh2_comp_methods(session);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LIBSSH2_METHOD_COMP_SC:
|
case LIBSSH2_METHOD_COMP_SC:
|
||||||
prefvar = &session->remote.comp_prefs;
|
prefvar = &session->remote.comp_prefs;
|
||||||
mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods();
|
mlist = (const LIBSSH2_COMMON_METHOD **)
|
||||||
|
_libssh2_comp_methods(session);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LIBSSH2_METHOD_LANG_CS:
|
case LIBSSH2_METHOD_LANG_CS:
|
||||||
|
@ -492,8 +492,8 @@ struct transportpacket
|
|||||||
are currently writing decrypted data */
|
are currently writing decrypted data */
|
||||||
|
|
||||||
/* ------------- for outgoing data --------------- */
|
/* ------------- for outgoing data --------------- */
|
||||||
unsigned char *outbuf; /* pointer to a LIBSSH2_ALLOC() area for the
|
unsigned char outbuf[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */
|
||||||
outgoing data */
|
|
||||||
int ototal_num; /* size of outbuf in number of bytes */
|
int ototal_num; /* size of outbuf in number of bytes */
|
||||||
unsigned char *odata; /* original pointer to the data we stored in
|
unsigned char *odata; /* original pointer to the data we stored in
|
||||||
outbuf */
|
outbuf */
|
||||||
@ -1009,12 +1009,14 @@ struct _LIBSSH2_COMP_METHOD
|
|||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
int compress; /* 1 if it does compress, 0 if it doesn't */
|
int compress; /* 1 if it does compress, 0 if it doesn't */
|
||||||
int (*init) (LIBSSH2_SESSION * session, int compress, void **abstract);
|
int (*init) (LIBSSH2_SESSION *session, int compress, void **abstract);
|
||||||
int (*comp) (LIBSSH2_SESSION * session, int compress, unsigned char **dest,
|
int (*comp) (LIBSSH2_SESSION *session,
|
||||||
size_t *dest_len, size_t payload_limit,
|
unsigned char *dest,
|
||||||
int *free_dest, const unsigned char *src,
|
size_t *dest_len,
|
||||||
size_t src_len, void **abstract);
|
const unsigned char *src,
|
||||||
int (*decomp) (LIBSSH2_SESSION * session, int compress,
|
size_t src_len,
|
||||||
|
void **abstract);
|
||||||
|
int (*decomp) (LIBSSH2_SESSION *session, int compress,
|
||||||
unsigned char **dest,
|
unsigned char **dest,
|
||||||
size_t *dest_len, size_t payload_limit,
|
size_t *dest_len, size_t payload_limit,
|
||||||
int *free_dest, const unsigned char *src,
|
int *free_dest, const unsigned char *src,
|
||||||
|
@ -980,11 +980,6 @@ session_free(LIBSSH2_SESSION *session)
|
|||||||
LIBSSH2_FREE(session, pkg);
|
LIBSSH2_FREE(session, pkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup remaining outgoing packet buffer */
|
|
||||||
if (p->outbuf) {
|
|
||||||
LIBSSH2_FREE(session, p->outbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(session->socket_prev_blockstate)
|
if(session->socket_prev_blockstate)
|
||||||
/* if the socket was previously blocking, put it back so */
|
/* if the socket was previously blocking, put it back so */
|
||||||
session_nonblock(session->socket_fd, 0);
|
session_nonblock(session->socket_fd, 0);
|
||||||
|
@ -200,13 +200,13 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
|||||||
size_t data_len;
|
size_t data_len;
|
||||||
int free_payload = 1;
|
int free_payload = 1;
|
||||||
|
|
||||||
rc = session->remote.comp->comp(session, 0,
|
rc = session->remote.comp->decomp(session, 0,
|
||||||
&data, &data_len,
|
&data, &data_len,
|
||||||
LIBSSH2_PACKET_MAXDECOMP,
|
LIBSSH2_PACKET_MAXDECOMP,
|
||||||
&free_payload,
|
&free_payload,
|
||||||
p->payload,
|
p->payload,
|
||||||
session->fullpacket_payload_len,
|
session->fullpacket_payload_len,
|
||||||
&session->remote.comp_abstract);
|
&session->remote.comp_abstract);
|
||||||
if(rc) {
|
if(rc) {
|
||||||
LIBSSH2_FREE(session, p->payload);
|
LIBSSH2_FREE(session, p->payload);
|
||||||
return rc;
|
return rc;
|
||||||
@ -605,7 +605,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
ssize_t length;
|
ssize_t length;
|
||||||
struct transportpacket *p = &session->packet;
|
struct transportpacket *p = &session->packet;
|
||||||
|
|
||||||
if (!p->outbuf) {
|
if (!p->olen) {
|
||||||
*ret = 0;
|
*ret = 0;
|
||||||
return LIBSSH2_ERROR_NONE;
|
return LIBSSH2_ERROR_NONE;
|
||||||
}
|
}
|
||||||
@ -642,8 +642,6 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
|
|
||||||
if (rc == length) {
|
if (rc == length) {
|
||||||
/* the remainder of the package was sent */
|
/* the remainder of the package was sent */
|
||||||
LIBSSH2_FREE(session, p->outbuf);
|
|
||||||
p->outbuf = NULL;
|
|
||||||
p->ototal_num = 0;
|
p->ototal_num = 0;
|
||||||
}
|
}
|
||||||
else if (rc < 0) {
|
else if (rc < 0) {
|
||||||
@ -673,10 +671,6 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
* then be called with the same argument set (same data pointer and same
|
* then be called with the same argument set (same data pointer and same
|
||||||
* data_len) until ERROR_NONE or failure is returned.
|
* data_len) until ERROR_NONE or failure is returned.
|
||||||
*
|
*
|
||||||
* NOTE: this function does not verify that 'data_len' is less than ~35000
|
|
||||||
* which is what all implementations should support at least as packet size.
|
|
||||||
* (RFC4253 section 6.1)
|
|
||||||
*
|
|
||||||
* This function DOES not call _libssh2_error() on any errors.
|
* This function DOES not call _libssh2_error() on any errors.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -689,7 +683,6 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
int padding_length;
|
int padding_length;
|
||||||
int packet_length;
|
int packet_length;
|
||||||
int total_length;
|
int total_length;
|
||||||
int free_data = 0;
|
|
||||||
#ifdef RANDOM_PADDING
|
#ifdef RANDOM_PADDING
|
||||||
int rand_max;
|
int rand_max;
|
||||||
int seed = data[0]; /* FIXME: make this random */
|
int seed = data[0]; /* FIXME: make this random */
|
||||||
@ -702,6 +695,11 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
unsigned char *orgdata = data;
|
unsigned char *orgdata = data;
|
||||||
size_t orgdata_len = data_len;
|
size_t orgdata_len = data_len;
|
||||||
|
|
||||||
|
if(data_len >= MAX_SSH_PACKET_LEN)
|
||||||
|
/* too large packet, return error for this until we make this function
|
||||||
|
split it up and send multiple SSH packets */
|
||||||
|
return LIBSSH2_ERROR_INVAL;
|
||||||
|
|
||||||
debugdump(session, "libssh2_transport_write plain", data, data_len);
|
debugdump(session, "libssh2_transport_write plain", data, data_len);
|
||||||
|
|
||||||
/* FIRST, check if we have a pending write to complete */
|
/* FIRST, check if we have a pending write to complete */
|
||||||
@ -717,15 +715,21 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
|
|
||||||
encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
|
encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
|
||||||
|
|
||||||
/* check if we should compress */
|
|
||||||
if (encrypted && session->local.comp->compress) {
|
if (encrypted && session->local.comp->compress) {
|
||||||
rc = session->local.comp->comp(session, 1, &data, &data_len,
|
/* compress directly to the target buffer */
|
||||||
LIBSSH2_PACKET_MAXCOMP,
|
rc = session->local.comp->comp(session,
|
||||||
&free_data, data, data_len,
|
data, &data_len,
|
||||||
|
&p->outbuf[5], MAX_SSH_PACKET_LEN-5,
|
||||||
&session->local.comp_abstract);
|
&session->local.comp_abstract);
|
||||||
if(rc)
|
if(rc)
|
||||||
return rc; /* compression failure */
|
return rc; /* compression failure */
|
||||||
|
|
||||||
|
data = p->outbuf;
|
||||||
|
/* data_len is already updated by the compression function */
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
/* copy the payload data */
|
||||||
|
memcpy(&p->outbuf[5], data, data_len);
|
||||||
|
|
||||||
/* RFC4253 says: Note that the length of the concatenation of
|
/* RFC4253 says: Note that the length of the concatenation of
|
||||||
'packet_length', 'padding_length', 'payload', and 'random padding'
|
'packet_length', 'padding_length', 'payload', and 'random padding'
|
||||||
@ -766,26 +770,14 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
total_length =
|
total_length =
|
||||||
packet_length + (encrypted ? session->local.mac->mac_len : 0);
|
packet_length + (encrypted ? session->local.mac->mac_len : 0);
|
||||||
|
|
||||||
/* allocate memory to store the outgoing packet in, in case we can't
|
|
||||||
send the whole one and thus need to keep it after this function
|
|
||||||
returns. */
|
|
||||||
p->outbuf = LIBSSH2_ALLOC(session, total_length);
|
|
||||||
if (!p->outbuf) {
|
|
||||||
return LIBSSH2_ERROR_ALLOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store packet_length, which is the size of the whole packet except
|
/* store packet_length, which is the size of the whole packet except
|
||||||
the MAC and the packet_length field itself */
|
the MAC and the packet_length field itself */
|
||||||
_libssh2_htonu32(p->outbuf, packet_length - 4);
|
_libssh2_htonu32(p->outbuf, packet_length - 4);
|
||||||
/* store padding_length */
|
/* store padding_length */
|
||||||
p->outbuf[4] = padding_length;
|
p->outbuf[4] = padding_length;
|
||||||
/* copy the payload data */
|
|
||||||
memcpy(p->outbuf + 5, data, data_len);
|
|
||||||
/* fill the padding area with random junk */
|
/* fill the padding area with random junk */
|
||||||
_libssh2_random(p->outbuf + 5 + data_len, padding_length);
|
_libssh2_random(p->outbuf + 5 + data_len, padding_length);
|
||||||
if (free_data) {
|
|
||||||
LIBSSH2_FREE(session, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
/* Calculate MAC hash. Put the output at index packet_length,
|
/* Calculate MAC hash. Put the output at index packet_length,
|
||||||
@ -837,8 +829,6 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
/* the whole thing got sent away */
|
/* the whole thing got sent away */
|
||||||
p->odata = NULL;
|
p->odata = NULL;
|
||||||
p->olen = 0;
|
p->olen = 0;
|
||||||
LIBSSH2_FREE(session, p->outbuf);
|
|
||||||
p->outbuf = NULL;
|
|
||||||
|
|
||||||
return LIBSSH2_ERROR_NONE; /* all is good */
|
return LIBSSH2_ERROR_NONE; /* all is good */
|
||||||
}
|
}
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user