1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-08-08 19:02:07 +03:00

Use string_buf in sftp_init().

This commit is contained in:
Michael Buckley
2018-12-07 15:10:07 -08:00
parent c02d9b7b73
commit 41fbd4476a
4 changed files with 50 additions and 80 deletions

View File

@@ -97,12 +97,12 @@ struct _LIBSSH2_SFTP_ATTRIBUTES {
/* If flags & ATTR_* bit is set, then the value in this struct will be /* If flags & ATTR_* bit is set, then the value in this struct will be
* meaningful Otherwise it should be ignored * meaningful Otherwise it should be ignored
*/ */
unsigned long flags; uint32_t flags;
libssh2_uint64_t filesize; libssh2_uint64_t filesize;
unsigned long uid, gid; uint32_t uid, gid;
unsigned long permissions; uint32_t permissions;
unsigned long atime, mtime; uint32_t atime, mtime;
}; };
struct _LIBSSH2_SFTP_STATVFS { struct _LIBSSH2_SFTP_STATVFS {

View File

@@ -744,6 +744,19 @@ int _libssh2_get_u32(struct string_buf *buf, uint32_t *out)
return 0; return 0;
} }
int _libssh2_get_u64(struct string_buf *buf, uint64_t *out)
{
if (!_libssh2_check_length(buf, 8)) {
return -1;
}
unsigned char *p = buf->dataptr;
*out = _libssh2_ntohu64(p);
buf->dataptr += 8;
buf->offset -= 8;
return 0;
}
int _libssh2_match_string(struct string_buf *buf, const char *match) int _libssh2_match_string(struct string_buf *buf, const char *match)
{ {
unsigned char *out; unsigned char *out;

View File

@@ -91,6 +91,7 @@ void _libssh2_explicit_zero(void *buf, size_t size);
struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session); struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session);
void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf); void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf);
int _libssh2_get_u32(struct string_buf *buf, uint32_t *out); int _libssh2_get_u32(struct string_buf *buf, uint32_t *out);
int _libssh2_get_u64(struct string_buf *buf, uint64_t *out);
int _libssh2_match_string(struct string_buf *buf, const char *match); int _libssh2_match_string(struct string_buf *buf, const char *match);
int _libssh2_get_c_string(struct string_buf *buf, unsigned char **outbuf); int _libssh2_get_c_string(struct string_buf *buf, unsigned char **outbuf);
int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf); int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf);

View File

@@ -670,66 +670,43 @@ sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
static int static int
sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p, size_t data_len) sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p, size_t data_len)
{ {
const unsigned char *s = p; struct string_buf buf;
buf.data = (unsigned char *)p;
buf.dataptr = buf.data;
buf.len = data_len;
buf.offset = 0;
if (data_len >= 4) { if (_libssh2_get_u32(&buf, &(attrs->flags)) != 0) {
memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
attrs->flags = _libssh2_ntohu32(s);
s += 4;
data_len -= 4;
}
else {
return LIBSSH2_ERROR_BUFFER_TOO_SMALL; return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
} }
if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
if (data_len >= 8) { if (_libssh2_get_u64(&buf, &(attrs->filesize)) != 0) {
attrs->filesize = _libssh2_ntohu64(s);
s += 8;
data_len -= 8;
}
else {
return LIBSSH2_ERROR_BUFFER_TOO_SMALL; return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
} }
} }
if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
if (data_len >= 8) { if (_libssh2_get_u32(&buf, &(attrs->uid)) != 0 ||
attrs->uid = _libssh2_ntohu32(s); _libssh2_get_u32(&buf, &(attrs->gid)) != 0) {
s += 4;
attrs->gid = _libssh2_ntohu32(s);
s += 4;
data_len -= 8;
}
else {
return LIBSSH2_ERROR_BUFFER_TOO_SMALL; return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
} }
} }
if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
if (data_len >= 4) { if (_libssh2_get_u32(&buf, &(attrs->permissions)) != 0) {
attrs->permissions = _libssh2_ntohu32(s);
s += 4;
data_len -= 4;
}
else {
return LIBSSH2_ERROR_BUFFER_TOO_SMALL; return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
} }
} }
if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
if (data_len >= 8) { if (_libssh2_get_u32(&buf, &(attrs->atime)) != 0 ||
attrs->atime = _libssh2_ntohu32(s); _libssh2_get_u32(&buf, &(attrs->mtime)) != 0) {
s += 4;
attrs->mtime = _libssh2_ntohu32(s);
s += 4;
}
else {
return LIBSSH2_ERROR_BUFFER_TOO_SMALL; return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
} }
} }
return (s - p); return (buf.dataptr - buf.data);
} }
/* ************ /* ************
@@ -768,7 +745,7 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
*/ */
static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
{ {
unsigned char *data, *s; unsigned char *data;
size_t data_len; size_t data_len;
ssize_t rc; ssize_t rc;
LIBSSH2_SFTP *sftp_handle; LIBSSH2_SFTP *sftp_handle;
@@ -917,9 +894,18 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
goto sftp_init_error; goto sftp_init_error;
} }
s = data + 1; struct string_buf buf;
sftp_handle->version = _libssh2_ntohu32(s); buf.data = data;
s += 4; buf.dataptr = buf.data + 1;
buf.len = data_len;
buf.offset = 1;
if (_libssh2_get_u32(&buf, &(sftp_handle->version)) != 0) {
LIBSSH2_FREE(session, data);
rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
goto sftp_init_error;
}
if(sftp_handle->version > LIBSSH2_SFTP_VERSION) { if(sftp_handle->version > LIBSSH2_SFTP_VERSION) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Truncating remote SFTP version from %lu", "Truncating remote SFTP version from %lu",
@@ -929,50 +915,20 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Enabling SFTP version %lu compatibility", "Enabling SFTP version %lu compatibility",
sftp_handle->version); sftp_handle->version);
while(s < (data + data_len)) { while (buf.offset < buf.len) {
size_t extname_len, extdata_len; unsigned char *extname, *extdata;
if( s + 4 <= data + data_len ) { if (_libssh2_get_c_string(&buf, &extname) < 0) {
extname_len = _libssh2_ntohu32(s);
s += 4;
}
else {
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short when extracting extname_len"); "Data too short when extracting extname");
goto sftp_init_error; goto sftp_init_error;
} }
if(s + extname_len <= data + data_len) { if (_libssh2_get_c_string(&buf, &extdata) < 0) {
/* the extension name starts here */
s += extname_len;
}
else {
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short for extname"); "Data too short when extracting extdata");
goto sftp_init_error;
}
if( s + 4 <= data + data_len ) {
extdata_len = _libssh2_ntohu32(s);
s += 4;
}
else {
LIBSSH2_FREE(session, data);
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short when extracting extdata_len");
goto sftp_init_error;
}
if(s + extdata_len <= data + data_len) {
/* TODO: Actually process extensions */
s += extdata_len;
}
else {
LIBSSH2_FREE(session, data);
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short for extdata");
goto sftp_init_error; goto sftp_init_error;
} }
} }