1
1

re-indented the source code with this script:

indent \
--braces-on-if-line \
--braces-after-struct-decl-line \
--space-after-cast \
--line-length 79 \
--comment-line-length 79 \
--cuddle-else \
--no-tabs \
--tab-size 8 \
--indent-level 4 \
--no-space-after-for \
--space-after-if \
--space-after-while \
--no-space-after-function-call-names \
*.[ch]
Этот коммит содержится в:
Daniel Stenberg 2007-08-06 20:48:04 +00:00
родитель 4c3dd3ea9f
Коммит 210459db4b
20 изменённых файлов: 6378 добавлений и 4497 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -47,15 +47,15 @@
/* {{{ libssh2_comp_method_none_comp /* {{{ libssh2_comp_method_none_comp
* Minimalist compression: Absolutely none * Minimalist compression: Absolutely none
*/ */
static int libssh2_comp_method_none_comp(LIBSSH2_SESSION *session, static int
libssh2_comp_method_none_comp(LIBSSH2_SESSION * session,
int compress, int compress,
unsigned char **dest, unsigned char **dest,
unsigned long *dest_len, unsigned long *dest_len,
unsigned long payload_limit, unsigned long payload_limit,
int *free_dest, int *free_dest,
const unsigned char *src, const unsigned char *src,
unsigned long src_len, unsigned long src_len, void **abstract)
void **abstract)
{ {
(void) session; (void) session;
(void) compress; (void) compress;
@ -68,6 +68,7 @@ static int libssh2_comp_method_none_comp(LIBSSH2_SESSION *session,
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_COMP_METHOD libssh2_comp_method_none = { static const LIBSSH2_COMP_METHOD libssh2_comp_method_none = {
@ -87,32 +88,39 @@ static const LIBSSH2_COMP_METHOD libssh2_comp_method_none = {
* Deal... * Deal...
*/ */
static voidpf libssh2_comp_method_zlib_alloc(voidpf opaque, uInt items, uInt size) static voidpf
libssh2_comp_method_zlib_alloc(voidpf opaque, uInt items, uInt size)
{ {
LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque; LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
return (voidpf) LIBSSH2_ALLOC(session, items * size); return (voidpf) LIBSSH2_ALLOC(session, items * size);
} }
static void libssh2_comp_method_zlib_free(voidpf opaque, voidpf address) static void
libssh2_comp_method_zlib_free(voidpf opaque, voidpf address)
{ {
LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque; LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
LIBSSH2_FREE(session, address); LIBSSH2_FREE(session, address);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_comp_method_zlib_init /* {{{ libssh2_comp_method_zlib_init
* All your bandwidth are belong to us (so save some) * All your bandwidth are belong to us (so save some)
*/ */
static int libssh2_comp_method_zlib_init(LIBSSH2_SESSION *session, int compress, void **abstract) static int
libssh2_comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
void **abstract)
{ {
z_stream *strm; z_stream *strm;
int status; int status;
strm = LIBSSH2_ALLOC(session, sizeof(z_stream)); strm = LIBSSH2_ALLOC(session, sizeof(z_stream));
if (!strm) { if (!strm) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for zlib compression/decompression", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for zlib compression/decompression",
0);
return -1; return -1;
} }
memset(strm, 0, sizeof(z_stream)); memset(strm, 0, sizeof(z_stream));
@ -136,20 +144,21 @@ static int libssh2_comp_method_zlib_init(LIBSSH2_SESSION *session, int compress,
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_comp_method_zlib_comp /* {{{ libssh2_comp_method_zlib_comp
* zlib, a compression standard for all occasions * zlib, a compression standard for all occasions
*/ */
static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, static int
libssh2_comp_method_zlib_comp(LIBSSH2_SESSION * session,
int compress, int compress,
unsigned char **dest, unsigned char **dest,
unsigned long *dest_len, unsigned long *dest_len,
unsigned long payload_limit, unsigned long payload_limit,
int *free_dest, int *free_dest,
const unsigned char *src, const unsigned char *src,
unsigned long src_len, unsigned long src_len, void **abstract)
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 /* A short-term alloc of a full data chunk is better than a series of
@ -173,7 +182,9 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
out = (char *) strm->next_out; out = (char *) strm->next_out;
strm->avail_out = out_maxlen; strm->avail_out = out_maxlen;
if (!strm->next_out) { if (!strm->next_out) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate compression/decompression buffer", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate compression/decompression buffer",
0);
return -1; return -1;
} }
while (strm->avail_in) { while (strm->avail_in) {
@ -185,7 +196,8 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
status = inflate(strm, Z_PARTIAL_FLUSH); status = inflate(strm, Z_PARTIAL_FLUSH);
} }
if (status != Z_OK) { if (status != Z_OK) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0); libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure", 0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, out);
return -1; return -1;
} }
@ -193,10 +205,10 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
unsigned long out_ofs = out_maxlen - strm->avail_out; unsigned long out_ofs = out_maxlen - strm->avail_out;
char *newout; char *newout;
out_maxlen += compress ? (strm->avail_in + 4) : (2 * strm->avail_in); out_maxlen +=
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
if ((out_maxlen > (int)payload_limit) && if ((out_maxlen > (int) payload_limit) && !compress && limiter++) {
!compress && limiter++) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase", 0); "Excessive growth in decompression phase", 0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, out);
@ -205,14 +217,18 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
newout = LIBSSH2_REALLOC(session, out, out_maxlen); newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) { if (!newout) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to expand compress/decompression buffer", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand compress/decompression buffer",
0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, out);
return -1; return -1;
} }
out = newout; out = newout;
strm->next_out = (unsigned char *) out + out_ofs; strm->next_out = (unsigned char *) out + out_ofs;
strm->avail_out += compress ? (strm->avail_in + 4) : (2 * strm->avail_in); strm->avail_out +=
} else while (!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 /* Done with input, might be a byte or two in internal buffer during compress
* Or potentially many bytes if it's a decompress * Or potentially many bytes if it's a decompress
*/ */
@ -220,7 +236,9 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
char *newout; char *newout;
if (out_maxlen >= (int) payload_limit) { if (out_maxlen >= (int) payload_limit) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0); libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase",
0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, out);
return -1; return -1;
} }
@ -234,7 +252,9 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
newout = LIBSSH2_REALLOC(session, out, out_maxlen); newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) { if (!newout) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to expand final compress/decompress buffer", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand final compress/decompress buffer",
0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, out);
return -1; return -1;
} }
@ -248,7 +268,8 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
status = inflate(strm, Z_PARTIAL_FLUSH); status = inflate(strm, Z_PARTIAL_FLUSH);
} }
if (status != Z_OK) { if (status != Z_OK) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0); libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure", 0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, out);
return -1; return -1;
} }
@ -261,12 +282,15 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_comp_method_zlib_dtor /* {{{ libssh2_comp_method_zlib_dtor
* All done, no more compression for you * All done, no more compression for you
*/ */
static int libssh2_comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compress, void **abstract) static int
libssh2_comp_method_zlib_dtor(LIBSSH2_SESSION * session, int compress,
void **abstract)
{ {
z_stream *strm = *abstract; z_stream *strm = *abstract;
@ -286,6 +310,7 @@ static int libssh2_comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compress,
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_COMP_METHOD libssh2_comp_method_zlib = { static const LIBSSH2_COMP_METHOD libssh2_comp_method_zlib = {
@ -308,7 +333,8 @@ static const LIBSSH2_COMP_METHOD *_libssh2_comp_methods[] = {
NULL NULL
}; };
const LIBSSH2_COMP_METHOD **libssh2_comp_methods(void) { const LIBSSH2_COMP_METHOD **
libssh2_comp_methods(void)
{
return _libssh2_comp_methods; return _libssh2_comp_methods;
} }

Просмотреть файл

@ -41,11 +41,14 @@
/* {{{ libssh2_crypt_none_crypt /* {{{ libssh2_crypt_none_crypt
* Minimalist cipher: VERY secure *wink* * Minimalist cipher: VERY secure *wink*
*/ */
static int libssh2_crypt_none_crypt(LIBSSH2_SESSION *session, unsigned char *buf, void **abstract) static int
libssh2_crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf,
void **abstract)
{ {
/* Do nothing to the data! */ /* Do nothing to the data! */
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = { static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = {
@ -60,13 +63,15 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = {
}; };
#endif /* LIBSSH2_CRYPT_NONE */ #endif /* LIBSSH2_CRYPT_NONE */
struct crypt_ctx { struct crypt_ctx
{
int encrypt; int encrypt;
_libssh2_cipher_type(algo); _libssh2_cipher_type(algo);
_libssh2_cipher_ctx h; _libssh2_cipher_ctx h;
}; };
static int _libssh2_init (LIBSSH2_SESSION *session, static int
_libssh2_init(LIBSSH2_SESSION * session,
const LIBSSH2_CRYPT_METHOD * method, const LIBSSH2_CRYPT_METHOD * method,
unsigned char *iv, int *free_iv, unsigned char *iv, int *free_iv,
unsigned char *secret, int *free_secret, unsigned char *secret, int *free_secret,
@ -79,8 +84,7 @@ static int _libssh2_init (LIBSSH2_SESSION *session,
} }
ctx->encrypt = encrypt; ctx->encrypt = encrypt;
ctx->algo = method->algo; ctx->algo = method->algo;
if (_libssh2_cipher_init (&ctx->h, ctx->algo, iv, secret, encrypt)) if (_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
{
LIBSSH2_FREE(session, ctx); LIBSSH2_FREE(session, ctx);
return -1; return -1;
} }
@ -90,15 +94,17 @@ static int _libssh2_init (LIBSSH2_SESSION *session,
return 0; return 0;
} }
static int _libssh2_encrypt(LIBSSH2_SESSION *session, unsigned char *block, void **abstract) static int
_libssh2_encrypt(LIBSSH2_SESSION * session, unsigned char *block,
void **abstract)
{ {
struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract; struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
(void) session; (void) session;
return _libssh2_cipher_crypt(&cctx->h, cctx->algo, return _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block);
cctx->encrypt, block);
} }
static int _libssh2_dtor(LIBSSH2_SESSION *session, void **abstract) static int
_libssh2_dtor(LIBSSH2_SESSION * session, void **abstract)
{ {
struct crypt_ctx **cctx = (struct crypt_ctx **) abstract; struct crypt_ctx **cctx = (struct crypt_ctx **) abstract;
if (cctx && *cctx) { if (cctx && *cctx) {
@ -147,7 +153,8 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
}; };
/* rijndael-cbc@lysator.liu.se == aes256-cbc */ /* rijndael-cbc@lysator.liu.se == aes256-cbc */
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_rijndael_cbc_lysator_liu_se = { static const LIBSSH2_CRYPT_METHOD
libssh2_crypt_method_rijndael_cbc_lysator_liu_se = {
"rijndael-cbc@lysator.liu.se", "rijndael-cbc@lysator.liu.se",
16, /* blocksize */ 16, /* blocksize */
16, /* initial value length */ 16, /* initial value length */
@ -242,6 +249,8 @@ static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
}; };
/* Expose to kex.c */ /* Expose to kex.c */
const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void) { const LIBSSH2_CRYPT_METHOD **
libssh2_crypt_methods(void)
{
return _libssh2_crypt_methods; return _libssh2_crypt_methods;
} }

Просмотреть файл

@ -47,7 +47,8 @@
* ssh-rsa * * ssh-rsa *
*********** */ *********** */
static int libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION *session, void **abstract); static int libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session,
void **abstract);
/* {{{ libssh2_hostkey_method_ssh_rsa_init /* {{{ libssh2_hostkey_method_ssh_rsa_init
* Initialize the server hostkey working area with e/n pair * Initialize the server hostkey working area with e/n pair
@ -81,9 +82,12 @@ libssh2_hostkey_method_ssh_rsa_init(LIBSSH2_SESSION *session,
e_len = libssh2_ntohu32(s); e_len = libssh2_ntohu32(s);
s += 4; s += 4;
e = s; s += e_len; e = s;
n_len = libssh2_ntohu32(s); s += 4; s += e_len;
n = s; s += n_len; n_len = libssh2_ntohu32(s);
s += 4;
n = s;
s += n_len;
if (_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0, if (_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0,
NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0))
@ -93,13 +97,17 @@ libssh2_hostkey_method_ssh_rsa_init(LIBSSH2_SESSION *session,
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_rsa_initPEM /* {{{ libssh2_hostkey_method_ssh_rsa_initPEM
* Load a Private Key from a PEM file * Load a Private Key from a PEM file
*/ */
static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session, static int
const char *privkeyfile, unsigned const char *passphrase, void **abstract) libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
const char *privkeyfile,
unsigned const char *passphrase,
void **abstract)
{ {
libssh2_rsa_ctx *rsactx; libssh2_rsa_ctx *rsactx;
FILE *fp; FILE *fp;
@ -125,32 +133,40 @@ static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session,
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_rsa_sign /* {{{ libssh2_hostkey_method_ssh_rsa_sign
* Verify signature created by remote * Verify signature created by remote
*/ */
static int libssh2_hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION *session, static int
libssh2_hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session,
const unsigned char *sig, const unsigned char *sig,
unsigned long sig_len, unsigned long sig_len,
const unsigned char *m, const unsigned char *m,
unsigned long m_len, unsigned long m_len, void **abstract)
void **abstract)
{ {
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
(void) session; (void) session;
/* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */ /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */
sig += 15; sig_len -= 15; sig += 15;
sig_len -= 15;
return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len); return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_rsa_signv /* {{{ libssh2_hostkey_method_ssh_rsa_signv
* Construct a signature from an array of vectors * Construct a signature from an array of vectors
*/ */
static int libssh2_hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION *session, unsigned char **signature, unsigned long *signature_len, static int
unsigned long veccount, const struct iovec datavec[], void **abstract) libssh2_hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session,
unsigned char **signature,
unsigned long *signature_len,
unsigned long veccount,
const struct iovec datavec[],
void **abstract)
{ {
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
int ret; int ret;
@ -172,13 +188,14 @@ static int libssh2_hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION *session, unsign
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_rsa_dtor /* {{{ libssh2_hostkey_method_ssh_rsa_dtor
* Shutdown the hostkey * Shutdown the hostkey
*/ */
static int libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION *session, static int
void **abstract) libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session, void **abstract)
{ {
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
(void) session; (void) session;
@ -189,6 +206,7 @@ static int libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION *session,
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_rsa = { static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_rsa = {
@ -208,7 +226,8 @@ static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_rsa = {
* ssh-dss * * ssh-dss *
*********** */ *********** */
static int libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION *session, void **abstract); static int libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session,
void **abstract);
/* {{{ libssh2_hostkey_method_ssh_dss_init /* {{{ libssh2_hostkey_method_ssh_dss_init
* Initialize the server hostkey working area with p/q/g/y set * Initialize the server hostkey working area with p/q/g/y set
@ -230,33 +249,44 @@ libssh2_hostkey_method_ssh_dss_init(LIBSSH2_SESSION *session,
} }
s = hostkey_data; s = hostkey_data;
len = libssh2_ntohu32(s); s += 4; len = libssh2_ntohu32(s);
s += 4;
if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) { if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) {
return -1; return -1;
} s += 7; }
s += 7;
p_len = libssh2_ntohu32(s); s += 4; p_len = libssh2_ntohu32(s);
p = s; s += p_len; s += 4;
q_len = libssh2_ntohu32(s); s += 4; p = s;
q = s; s += q_len; s += p_len;
g_len = libssh2_ntohu32(s); s += 4; q_len = libssh2_ntohu32(s);
g = s; s += g_len; s += 4;
y_len = libssh2_ntohu32(s); s += 4; q = s;
y = s; s += y_len; s += q_len;
g_len = libssh2_ntohu32(s);
s += 4;
g = s;
s += g_len;
y_len = libssh2_ntohu32(s);
s += 4;
y = s;
s += y_len;
_libssh2_dsa_new(&dsactx, p, p_len, q, q_len, g, g_len, _libssh2_dsa_new(&dsactx, p, p_len, q, q_len, g, g_len, y, y_len, NULL, 0);
y, y_len, NULL, 0);
*abstract = dsactx; *abstract = dsactx;
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_dss_initPEM /* {{{ libssh2_hostkey_method_ssh_dss_initPEM
* Load a Private Key from a PEM file * Load a Private Key from a PEM file
*/ */
static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session, static int
libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
const char *privkeyfile, const char *privkeyfile,
unsigned const char *passphrase, unsigned const char *passphrase,
void **abstract) void **abstract)
@ -285,31 +315,44 @@ static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session,
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_dss_sign /* {{{ libssh2_hostkey_method_ssh_dss_sign
* Verify signature created by remote * Verify signature created by remote
*/ */
static int libssh2_hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION *session, const unsigned char *sig, unsigned long sig_len, static int
const unsigned char *m, unsigned long m_len, void **abstract) libssh2_hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session,
const unsigned char *sig,
unsigned long sig_len,
const unsigned char *m,
unsigned long m_len, void **abstract)
{ {
libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
/* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */ /* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */
sig += 15; sig_len -= 15; sig += 15;
sig_len -= 15;
if (sig_len != 40) { if (sig_len != 40) {
libssh2_error(session, LIBSSH2_ERROR_PROTO, "Invalid DSS signature length", 0); libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Invalid DSS signature length", 0);
return -1; return -1;
} }
return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len); return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_dss_signv /* {{{ libssh2_hostkey_method_ssh_dss_signv
* Construct a signature from an array of vectors * Construct a signature from an array of vectors
*/ */
static int libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION *session, unsigned char **signature, unsigned long *signature_len, static int
unsigned long veccount, const struct iovec datavec[], void **abstract) libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session,
unsigned char **signature,
unsigned long *signature_len,
unsigned long veccount,
const struct iovec datavec[],
void **abstract)
{ {
libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
unsigned char hash[SHA_DIGEST_LENGTH]; unsigned char hash[SHA_DIGEST_LENGTH];
@ -330,22 +373,21 @@ static int libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION *session, unsign
} }
libssh2_sha1_final(ctx, hash); libssh2_sha1_final(ctx, hash);
if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) {
*signature))
{
LIBSSH2_FREE(session, *signature); LIBSSH2_FREE(session, *signature);
return -1; return -1;
} }
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_hostkey_method_ssh_dss_dtor /* {{{ libssh2_hostkey_method_ssh_dss_dtor
* Shutdown the hostkey method * Shutdown the hostkey method
*/ */
static int libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION *session, static int
void **abstract) libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session, void **abstract)
{ {
libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
(void) session; (void) session;
@ -356,6 +398,7 @@ static int libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION *session,
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_dss = { static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_dss = {
@ -380,7 +423,8 @@ static const LIBSSH2_HOSTKEY_METHOD *_libssh2_hostkey_methods[] = {
NULL NULL
}; };
const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void) const LIBSSH2_HOSTKEY_METHOD **
libssh2_hostkey_methods(void)
{ {
return _libssh2_hostkey_methods; return _libssh2_hostkey_methods;
} }
@ -391,7 +435,8 @@ const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void)
* Length of buffer is determined by hash type * Length of buffer is determined by hash type
* i.e. MD5 == 16, SHA1 == 20 * i.e. MD5 == 16, SHA1 == 20
*/ */
LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type) LIBSSH2_API const char *
libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
{ {
switch (hash_type) { switch (hash_type) {
#if LIBSSH2_MD5 #if LIBSSH2_MD5
@ -406,6 +451,5 @@ LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_
return NULL; return NULL;
} }
} }
/* }}} */ /* }}} */

738
src/kex.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -38,7 +38,8 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include <string.h> #include <string.h>
int _libssh2_rsa_new(libssh2_rsa_ctx **rsa, int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata, const unsigned char *edata,
unsigned long elen, unsigned long elen,
const unsigned char *ndata, const unsigned char *ndata,
@ -53,8 +54,7 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
unsigned long e1len, unsigned long e1len,
const unsigned char *e2data, const unsigned char *e2data,
unsigned long e2len, unsigned long e2len,
const unsigned char *coeffdata, const unsigned char *coeffdata, unsigned long coefflen)
unsigned long coefflen)
{ {
int rc; int rc;
(void) e1data; (void) e1data;
@ -72,8 +72,7 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))", rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))",
nlen, ndata, elen, edata); nlen, ndata, elen, edata);
} }
if (rc) if (rc) {
{
*rsa = NULL; *rsa = NULL;
return -1; return -1;
} }
@ -81,11 +80,11 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
return 0; return 0;
} }
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa, int
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig, const unsigned char *sig,
unsigned long sig_len, unsigned long sig_len,
const unsigned char *m, const unsigned char *m, unsigned long m_len)
unsigned long m_len)
{ {
unsigned char hash[SHA_DIGEST_LENGTH]; unsigned char hash[SHA_DIGEST_LENGTH];
gcry_sexp_t s_sig, s_hash; gcry_sexp_t s_sig, s_hash;
@ -100,8 +99,7 @@ int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
return -1; return -1;
} }
rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s %b)))", rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig);
sig_len, sig);
if (rc != 0) { if (rc != 0) {
gcry_sexp_release(s_hash); gcry_sexp_release(s_hash);
return -1; return -1;
@ -114,7 +112,8 @@ int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
return (rc == 0) ? 0 : -1; return (rc == 0) ? 0 : -1;
} }
int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx, int
_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
const unsigned char *p, const unsigned char *p,
unsigned long p_len, unsigned long p_len,
const unsigned char *q, const unsigned char *q,
@ -123,8 +122,7 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
unsigned long g_len, unsigned long g_len,
const unsigned char *y, const unsigned char *y,
unsigned long y_len, unsigned long y_len,
const unsigned char *x, const unsigned char *x, unsigned long x_len)
unsigned long x_len)
{ {
int rc; int rc;
@ -147,10 +145,10 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
return 0; return 0;
} }
int _libssh2_rsa_new_private (libssh2_rsa_ctx **rsa, int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase)
unsigned const char *passphrase)
{ {
char *data, *save_data; char *data, *save_data;
unsigned int datalen; unsigned int datalen;
@ -230,8 +228,7 @@ int _libssh2_rsa_new_private (libssh2_rsa_ctx **rsa,
} }
if (_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen, if (_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen,
q, qlen, e1, e1len, e2, e2len, q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) {
coeff, coefflen)) {
ret = -1; ret = -1;
goto fail; goto fail;
} }
@ -243,10 +240,10 @@ fail:
return ret; return ret;
} }
int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa, int
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase)
unsigned const char *passphrase)
{ {
char *data, *save_data; char *data, *save_data;
unsigned int datalen; unsigned int datalen;
@ -313,8 +310,7 @@ int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa,
goto fail; goto fail;
} }
if (_libssh2_dsa_new (dsa, p, plen, q, qlen, if (_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) {
g, glen, y, ylen, x, xlen)) {
ret = -1; ret = -1;
goto fail; goto fail;
} }
@ -326,12 +322,12 @@ fail:
return ret; return ret;
} }
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session, int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_dsa_ctx * rsactx, libssh2_dsa_ctx * rsactx,
const unsigned char *hash, const unsigned char *hash,
unsigned long hash_len, unsigned long hash_len,
unsigned char **signature, unsigned char **signature, unsigned long *signature_len)
unsigned long *signature_len)
{ {
gcry_sexp_t sig_sexp; gcry_sexp_t sig_sexp;
gcry_sexp_t data; gcry_sexp_t data;
@ -379,10 +375,10 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session,
return rc; return rc;
} }
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx, int
_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash, const unsigned char *hash,
unsigned long hash_len, unsigned long hash_len, unsigned char *sig)
unsigned char *sig)
{ {
unsigned char zhash[SHA_DIGEST_LENGTH + 1]; unsigned char zhash[SHA_DIGEST_LENGTH + 1];
gcry_sexp_t sig_sexp; gcry_sexp_t sig_sexp;
@ -398,8 +394,7 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx,
memcpy(zhash + 1, hash, hash_len); memcpy(zhash + 1, hash, hash_len);
zhash[0] = 0; zhash[0] = 0;
if (gcry_sexp_build (&data, NULL, "(data (value %b))", if (gcry_sexp_build(&data, NULL, "(data (value %b))", hash_len + 1, zhash)) {
hash_len + 1, zhash)) {
return -1; return -1;
} }
@ -476,10 +471,10 @@ out:
return ret; return ret;
} }
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx *dsactx, int
_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
const unsigned char *sig, const unsigned char *sig,
const unsigned char *m, const unsigned char *m, unsigned long m_len)
unsigned long m_len)
{ {
unsigned char hash[SHA_DIGEST_LENGTH + 1]; unsigned char hash[SHA_DIGEST_LENGTH + 1];
gcry_sexp_t s_sig, s_hash; gcry_sexp_t s_sig, s_hash;
@ -506,11 +501,10 @@ int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx *dsactx,
return (rc == 0) ? 0 : -1; return (rc == 0) ? 0 : -1;
} }
int _libssh2_cipher_init (_libssh2_cipher_ctx *h, int
_libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
unsigned char *iv, unsigned char *iv, unsigned char *secret, int encrypt)
unsigned char *secret,
int encrypt)
{ {
int mode = 0, ret; int mode = 0, ret;
int keylen = gcry_cipher_get_algo_keylen(algo); int keylen = gcry_cipher_get_algo_keylen(algo);
@ -544,10 +538,10 @@ int _libssh2_cipher_init (_libssh2_cipher_ctx *h,
return 0; return 0;
} }
int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx, int
_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
int encrypt, int encrypt, unsigned char *block)
unsigned char *block)
{ {
size_t blklen = gcry_cipher_get_algo_blklen(algo); size_t blklen = gcry_cipher_get_algo_blklen(algo);
int ret; int ret;
@ -557,11 +551,9 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx,
} }
if (encrypt) { if (encrypt) {
ret = gcry_cipher_encrypt (*ctx, block, blklen, ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen);
block, blklen);
} else { } else {
ret = gcry_cipher_decrypt (*ctx, block, blklen, ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen);
block, blklen);
} }
return ret; return ret;
} }

Просмотреть файл

@ -108,17 +108,14 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
unsigned long e1len, unsigned long e1len,
const unsigned char *e2data, const unsigned char *e2data,
unsigned long e2len, unsigned long e2len,
const unsigned char *coeffdata, const unsigned char *coeffdata, unsigned long coefflen);
unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase);
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig, const unsigned char *sig,
unsigned long sig_len, unsigned long sig_len,
const unsigned char *m, const unsigned char *m, unsigned long m_len);
unsigned long m_len);
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx, libssh2_rsa_ctx * rsactx,
const unsigned char *hash, const unsigned char *hash,
@ -139,20 +136,16 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsa,
unsigned long glen, unsigned long glen,
const unsigned char *ydata, const unsigned char *ydata,
unsigned long ylen, unsigned long ylen,
const unsigned char *x, const unsigned char *x, unsigned long x_len);
unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase);
unsigned const char *passphrase);
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsa, int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsa,
const unsigned char *sig, const unsigned char *sig,
const unsigned char *m, const unsigned char *m, unsigned long m_len);
unsigned long m_len);
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash, const unsigned char *hash,
unsigned long hash_len, unsigned long hash_len, unsigned char *sig);
unsigned char *sig);
#define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx) #define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx)
@ -170,13 +163,11 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx,
int _libssh2_cipher_init(_libssh2_cipher_ctx * h, int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
unsigned char *iv, unsigned char *iv,
unsigned char *secret, unsigned char *secret, int encrypt);
int encrypt);
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
int encrypt, int encrypt, unsigned char *block);
unsigned char *block);
#define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx)) #define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx))

Просмотреть файл

@ -127,7 +127,8 @@ typedef struct _LIBSSH2_CHANNEL_BRIGADE LIBSSH2_CHANNEL_BRIGADE;
typedef int libssh2pack_t; typedef int libssh2pack_t;
typedef enum { typedef enum
{
libssh2_NB_state_idle = 0, libssh2_NB_state_idle = 0,
libssh2_NB_state_allocated, libssh2_NB_state_allocated,
libssh2_NB_state_created, libssh2_NB_state_created,
@ -144,16 +145,19 @@ typedef enum {
libssh2_NB_state_jump3 libssh2_NB_state_jump3
} libssh2_nonblocking_states; } libssh2_nonblocking_states;
typedef struct packet_require_state_t { typedef struct packet_require_state_t
{
libssh2_nonblocking_states state; libssh2_nonblocking_states state;
time_t start; time_t start;
} packet_require_state_t; } packet_require_state_t;
typedef struct packet_requirev_state_t { typedef struct packet_requirev_state_t
{
time_t start; time_t start;
} packet_requirev_state_t; } packet_requirev_state_t;
typedef struct kmdhgGPsha1kex_state_t { typedef struct kmdhgGPsha1kex_state_t
{
libssh2_nonblocking_states state; libssh2_nonblocking_states state;
unsigned char *e_packet; unsigned char *e_packet;
unsigned char *s_packet; unsigned char *s_packet;
@ -180,7 +184,8 @@ typedef struct kmdhgGPsha1kex_state_t {
libssh2_nonblocking_states burn_state; libssh2_nonblocking_states burn_state;
} kmdhgGPsha1kex_state_t; } kmdhgGPsha1kex_state_t;
typedef struct key_exchange_state_low_t { typedef struct key_exchange_state_low_t
{
libssh2_nonblocking_states state; libssh2_nonblocking_states state;
packet_require_state_t req_state; packet_require_state_t req_state;
kmdhgGPsha1kex_state_t exchange_state; kmdhgGPsha1kex_state_t exchange_state;
@ -192,7 +197,8 @@ typedef struct key_exchange_state_low_t {
unsigned long data_len; unsigned long data_len;
} key_exchange_state_low_t; } key_exchange_state_low_t;
typedef struct key_exchange_state_t { typedef struct key_exchange_state_t
{
libssh2_nonblocking_states state; libssh2_nonblocking_states state;
packet_require_state_t req_state; packet_require_state_t req_state;
key_exchange_state_low_t key_state_low; key_exchange_state_low_t key_state_low;
@ -204,7 +210,8 @@ typedef struct key_exchange_state_t {
#define FwdNotReq "Forward not requested" #define FwdNotReq "Forward not requested"
typedef struct packet_queue_listener_state_t { typedef struct packet_queue_listener_state_t
{
libssh2_nonblocking_states state; libssh2_nonblocking_states state;
unsigned char packet[17 + (sizeof(FwdNotReq) - 1)]; unsigned char packet[17 + (sizeof(FwdNotReq) - 1)];
unsigned char *host; unsigned char *host;
@ -220,7 +227,8 @@ typedef struct packet_queue_listener_state_t {
#define X11FwdUnAvil "X11 Forward Unavailable" #define X11FwdUnAvil "X11 Forward Unavailable"
typedef struct packet_x11_open_state_t { typedef struct packet_x11_open_state_t
{
libssh2_nonblocking_states state; libssh2_nonblocking_states state;
unsigned char packet[17 + (sizeof(X11FwdUnAvil) - 1)]; unsigned char packet[17 + (sizeof(X11FwdUnAvil) - 1)];
unsigned char *shost; unsigned char *shost;
@ -231,7 +239,8 @@ typedef struct packet_x11_open_state_t {
uint32_t shost_len; uint32_t shost_len;
} packet_x11_open_state_t; } packet_x11_open_state_t;
struct _LIBSSH2_PACKET { struct _LIBSSH2_PACKET
{
unsigned char type; unsigned char type;
/* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */ /* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */
@ -250,11 +259,13 @@ struct _LIBSSH2_PACKET {
LIBSSH2_PACKET *next, *prev; LIBSSH2_PACKET *next, *prev;
}; };
struct _LIBSSH2_PACKET_BRIGADE { struct _LIBSSH2_PACKET_BRIGADE
{
LIBSSH2_PACKET *head, *tail; LIBSSH2_PACKET *head, *tail;
}; };
typedef struct _libssh2_channel_data { typedef struct _libssh2_channel_data
{
/* Identifier */ /* Identifier */
unsigned long id; unsigned long id;
@ -265,7 +276,8 @@ typedef struct _libssh2_channel_data {
char close, eof, extended_data_ignore_mode; char close, eof, extended_data_ignore_mode;
} libssh2_channel_data; } libssh2_channel_data;
struct _LIBSSH2_CHANNEL { struct _LIBSSH2_CHANNEL
{
unsigned char *channel_type; unsigned char *channel_type;
unsigned channel_type_len; unsigned channel_type_len;
@ -355,11 +367,13 @@ struct _LIBSSH2_CHANNEL {
libssh2_nonblocking_states extData2_state; libssh2_nonblocking_states extData2_state;
}; };
struct _LIBSSH2_CHANNEL_BRIGADE { struct _LIBSSH2_CHANNEL_BRIGADE
{
LIBSSH2_CHANNEL *head, *tail; LIBSSH2_CHANNEL *head, *tail;
}; };
struct _LIBSSH2_LISTENER { struct _LIBSSH2_LISTENER
{
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
char *host; char *host;
@ -377,7 +391,8 @@ struct _LIBSSH2_LISTENER {
size_t chanFwdCncl_data_len; size_t chanFwdCncl_data_len;
}; };
typedef struct _libssh2_endpoint_data { typedef struct _libssh2_endpoint_data
{
unsigned char *banner; unsigned char *banner;
unsigned char *kexinit; unsigned char *kexinit;
@ -402,7 +417,8 @@ typedef struct _libssh2_endpoint_data {
#define PACKETBUFSIZE 4096 #define PACKETBUFSIZE 4096
struct transportpacket { struct transportpacket
{
/* ------------- for incoming data --------------- */ /* ------------- for incoming data --------------- */
unsigned char buf[PACKETBUFSIZE]; unsigned char buf[PACKETBUFSIZE];
unsigned char init[5]; /* first 5 bytes of the incoming data stream, unsigned char init[5]; /* first 5 bytes of the incoming data stream,
@ -437,7 +453,8 @@ struct transportpacket {
unsigned long osent; /* number of bytes already sent */ unsigned long osent; /* number of bytes already sent */
}; };
struct _LIBSSH2_PUBLICKEY { struct _LIBSSH2_PUBLICKEY
{
LIBSSH2_CHANNEL *channel; LIBSSH2_CHANNEL *channel;
unsigned long version; unsigned long version;
@ -464,7 +481,8 @@ struct _LIBSSH2_PUBLICKEY {
unsigned long listFetch_data_len; unsigned long listFetch_data_len;
}; };
struct _LIBSSH2_SFTP_HANDLE { struct _LIBSSH2_SFTP_HANDLE
{
LIBSSH2_SFTP *sftp; LIBSSH2_SFTP *sftp;
LIBSSH2_SFTP_HANDLE *prev, *next; LIBSSH2_SFTP_HANDLE *prev, *next;
@ -473,11 +491,14 @@ struct _LIBSSH2_SFTP_HANDLE {
char handle_type; char handle_type;
union _libssh2_sftp_handle_data { union _libssh2_sftp_handle_data
struct _libssh2_sftp_handle_file_data { {
struct _libssh2_sftp_handle_file_data
{
libssh2_uint64_t offset; libssh2_uint64_t offset;
} file; } file;
struct _libssh2_sftp_handle_dir_data { struct _libssh2_sftp_handle_dir_data
{
unsigned long names_left; unsigned long names_left;
void *names_packet; void *names_packet;
char *next_name; char *next_name;
@ -490,7 +511,8 @@ struct _LIBSSH2_SFTP_HANDLE {
unsigned char *close_packet; unsigned char *close_packet;
}; };
struct _LIBSSH2_SFTP { struct _LIBSSH2_SFTP
{
LIBSSH2_CHANNEL *channel; LIBSSH2_CHANNEL *channel;
unsigned long request_id, version; unsigned long request_id, version;
@ -570,7 +592,8 @@ struct _LIBSSH2_SFTP {
#define LIBSSH2_SCP_RESPONSE_BUFLEN 256 #define LIBSSH2_SCP_RESPONSE_BUFLEN 256
struct _LIBSSH2_SESSION { struct _LIBSSH2_SESSION
{
/* Memory management callbacks */ /* Memory management callbacks */
void *abstract; void *abstract;
LIBSSH2_ALLOC_FUNC((*alloc)); LIBSSH2_ALLOC_FUNC((*alloc));
@ -823,28 +846,40 @@ struct _LIBSSH2_SESSION {
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */ /* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */
struct _LIBSSH2_KEX_METHOD { struct _LIBSSH2_KEX_METHOD
{
const char *name; const char *name;
/* Key exchange, populates session->* and returns 0 on success, non-0 on error */ /* Key exchange, populates session->* and returns 0 on success, non-0 on error */
int (*exchange_keys)(LIBSSH2_SESSION *session, key_exchange_state_low_t *key_state); int (*exchange_keys) (LIBSSH2_SESSION * session,
key_exchange_state_low_t * key_state);
long flags; long flags;
}; };
struct _LIBSSH2_HOSTKEY_METHOD { struct _LIBSSH2_HOSTKEY_METHOD
{
const char *name; const char *name;
unsigned long hash_len; unsigned long hash_len;
int (*init)(LIBSSH2_SESSION *session, const unsigned char *hostkey_data, unsigned long hostkey_data_len, void **abstract); int (*init) (LIBSSH2_SESSION * session, const unsigned char *hostkey_data,
int (*initPEM)(LIBSSH2_SESSION *session, const char *privkeyfile, unsigned const char *passphrase, void **abstract); unsigned long hostkey_data_len, void **abstract);
int (*sig_verify)(LIBSSH2_SESSION *session, const unsigned char *sig, unsigned long sig_len, const unsigned char *m, unsigned long m_len, void **abstract); int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile,
int (*signv)(LIBSSH2_SESSION *session, unsigned char **signature, unsigned long *signature_len, unsigned long veccount, const struct iovec datavec[], void **abstract); unsigned const char *passphrase, void **abstract);
int (*encrypt)(LIBSSH2_SESSION *session, unsigned char **dst, unsigned long *dst_len, const unsigned char *src, unsigned long src_len, void **abstract); int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig,
unsigned long sig_len, const unsigned char *m,
unsigned long m_len, void **abstract);
int (*signv) (LIBSSH2_SESSION * session, unsigned char **signature,
unsigned long *signature_len, unsigned long veccount,
const struct iovec datavec[], void **abstract);
int (*encrypt) (LIBSSH2_SESSION * session, unsigned char **dst,
unsigned long *dst_len, const unsigned char *src,
unsigned long src_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, void **abstract); int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
}; };
struct _LIBSSH2_CRYPT_METHOD { struct _LIBSSH2_CRYPT_METHOD
{
const char *name; const char *name;
int blocksize; int blocksize;
@ -855,23 +890,31 @@ struct _LIBSSH2_CRYPT_METHOD {
long flags; long flags;
int (*init)(LIBSSH2_SESSION *session, const LIBSSH2_CRYPT_METHOD *method, unsigned char *iv, int *free_iv, unsigned char *secret, int *free_secret, int encrypt, void **abstract); int (*init) (LIBSSH2_SESSION * session,
int (*crypt)(LIBSSH2_SESSION *session, unsigned char *block, void **abstract); const LIBSSH2_CRYPT_METHOD * method, unsigned char *iv,
int *free_iv, unsigned char *secret, int *free_secret,
int encrypt, void **abstract);
int (*crypt) (LIBSSH2_SESSION * session, unsigned char *block,
void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, void **abstract); int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
_libssh2_cipher_type(algo); _libssh2_cipher_type(algo);
}; };
struct _LIBSSH2_COMP_METHOD { struct _LIBSSH2_COMP_METHOD
{
const char *name; const char *name;
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, unsigned long *dest_len, unsigned long payload_limit, int *free_dest, int (*comp) (LIBSSH2_SESSION * session, int compress, unsigned char **dest,
const unsigned char *src, unsigned long src_len, void **abstract); unsigned long *dest_len, unsigned long payload_limit,
int *free_dest, const unsigned char *src,
unsigned long src_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract); int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
}; };
struct _LIBSSH2_MAC_METHOD { struct _LIBSSH2_MAC_METHOD
{
const char *name; const char *name;
/* The length of a given MAC packet */ /* The length of a given MAC packet */
@ -881,8 +924,12 @@ struct _LIBSSH2_MAC_METHOD {
int key_len; int key_len;
/* Message Authentication Code Hashing algo */ /* Message Authentication Code Hashing algo */
int (*init)(LIBSSH2_SESSION *session, unsigned char *key, int *free_key, void **abstract); int (*init) (LIBSSH2_SESSION * session, unsigned char *key, int *free_key,
int (*hash)(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, const unsigned char *packet, unsigned long packet_len, const unsigned char *addtl, unsigned long addtl_len, void **abstract); void **abstract);
int (*hash) (LIBSSH2_SESSION * session, unsigned char *buf,
unsigned long seqno, const unsigned char *packet,
unsigned long packet_len, const unsigned char *addtl,
unsigned long addtl_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, void **abstract); int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
}; };
@ -895,7 +942,8 @@ struct _LIBSSH2_MAC_METHOD {
#define LIBSSH2_DBG_ERROR 7 #define LIBSSH2_DBG_ERROR 7
#define LIBSSH2_DBG_PUBLICKEY 8 #define LIBSSH2_DBG_PUBLICKEY 8
#ifdef LIBSSH2DEBUG #ifdef LIBSSH2DEBUG
void _libssh2_debug(LIBSSH2_SESSION *session, int context, const char *format, ...); void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
...);
#else #else
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
/* C99 style */ /* C99 style */
@ -905,8 +953,10 @@ void _libssh2_debug(LIBSSH2_SESSION *session, int context, const char *format, .
#define _libssh2_debug(x,y,z,...) do {} while (0) #define _libssh2_debug(x,y,z,...) do {} while (0)
#else #else
/* no gcc and not C99, do static and hopefully inline */ /* no gcc and not C99, do static and hopefully inline */
static inline void _libssh2_debug(LIBSSH2_SESSION *session, int context, static inline void
const char *format, ...) {} _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
{
}
#endif #endif
#endif #endif
@ -1037,16 +1087,38 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type,
const unsigned char *match_buf, const unsigned char *match_buf,
unsigned long match_len, int poll_socket); unsigned long match_len, int poll_socket);
int libssh2_packet_askv_ex(LIBSSH2_SESSION *session, const unsigned char *packet_types, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket); int libssh2_packet_askv_ex(LIBSSH2_SESSION * session,
int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, packet_require_state_t *state); const unsigned char *packet_types,
int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, const unsigned char *packet_types, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, packet_requirev_state_t *state); unsigned char **data, unsigned long *data_len,
int libssh2_packet_burn(LIBSSH2_SESSION *session, libssh2_nonblocking_states *state); unsigned long match_ofs,
int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len); const unsigned char *match_buf,
int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, size_t datalen, int macstate); unsigned long match_len, int poll_socket);
int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange, key_exchange_state_t *state); int libssh2_packet_require_ex(LIBSSH2_SESSION * session,
unsigned char packet_type, unsigned char **data,
unsigned long *data_len, unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len,
packet_require_state_t * state);
int libssh2_packet_requirev_ex(LIBSSH2_SESSION * session,
const unsigned char *packet_types,
unsigned char **data, unsigned long *data_len,
unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len,
packet_requirev_state_t * state);
int libssh2_packet_burn(LIBSSH2_SESSION * session,
libssh2_nonblocking_states * state);
int libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len);
int libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate);
int libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_exchange_state_t * state);
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION * session); unsigned long libssh2_channel_nextid(LIBSSH2_SESSION * session);
LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id); LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION * session,
unsigned long libssh2_channel_packet_data_len(LIBSSH2_CHANNEL *channel, int stream_id); unsigned long channel_id);
unsigned long libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,
int stream_id);
/* this is the lib-internal set blocking function */ /* this is the lib-internal set blocking function */
int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking); int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
@ -1064,8 +1136,7 @@ const LIBSSH2_MAC_METHOD **libssh2_mac_methods(void);
int _libssh2_pem_parse(LIBSSH2_SESSION * session, int _libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin, const char *headerbegin,
const char *headerend, const char *headerend,
FILE *fp, FILE * fp, char **data, unsigned int *datalen);
char **data, unsigned int *datalen);
int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen); int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen);
int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
unsigned char **i, unsigned int *ilen); unsigned char **i, unsigned int *ilen);

Просмотреть файл

@ -41,12 +41,15 @@
/* {{{ libssh2_mac_none_MAC /* {{{ libssh2_mac_none_MAC
* Minimalist MAC: No MAC * Minimalist MAC: No MAC
*/ */
static int libssh2_mac_none_MAC(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, static int
const unsigned char *packet, unsigned long packet_len, libssh2_mac_none_MAC(LIBSSH2_SESSION * session, unsigned char *buf,
const unsigned char *addtl, unsigned long addtl_len, void **abstract) unsigned long seqno, const unsigned char *packet,
unsigned long packet_len, const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
{ {
return 0; return 0;
} }
/* }}} */ /* }}} */
@ -63,7 +66,9 @@ static LIBSSH2_MAC_METHOD libssh2_mac_method_none = {
/* {{{ libssh2_mac_method_common_init /* {{{ libssh2_mac_method_common_init
* Initialize simple mac methods * Initialize simple mac methods
*/ */
static int libssh2_mac_method_common_init(LIBSSH2_SESSION *session, unsigned char *key, int *free_key, void **abstract) static int
libssh2_mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key,
int *free_key, void **abstract)
{ {
*abstract = key; *abstract = key;
*free_key = 0; *free_key = 0;
@ -71,12 +76,14 @@ static int libssh2_mac_method_common_init(LIBSSH2_SESSION *session, unsigned cha
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_mac_method_common_dtor /* {{{ libssh2_mac_method_common_dtor
* Cleanup simple mac methods * Cleanup simple mac methods
*/ */
static int libssh2_mac_method_common_dtor(LIBSSH2_SESSION *session, void **abstract) static int
libssh2_mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract)
{ {
if (*abstract) { if (*abstract) {
LIBSSH2_FREE(session, *abstract); LIBSSH2_FREE(session, *abstract);
@ -85,14 +92,19 @@ static int libssh2_mac_method_common_dtor(LIBSSH2_SESSION *session, void **abstr
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_mac_method_hmac_sha1_hash /* {{{ libssh2_mac_method_hmac_sha1_hash
* Calculate hash using full sha1 value * Calculate hash using full sha1 value
*/ */
static int libssh2_mac_method_hmac_sha1_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, static int
const unsigned char *packet, unsigned long packet_len, libssh2_mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session,
const unsigned char *addtl, unsigned long addtl_len, void **abstract) unsigned char *buf, unsigned long seqno,
const unsigned char *packet,
unsigned long packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
{ {
libssh2_hmac_ctx ctx; libssh2_hmac_ctx ctx;
unsigned char seqno_buf[4]; unsigned char seqno_buf[4];
@ -111,6 +123,7 @@ static int libssh2_mac_method_hmac_sha1_hash(LIBSSH2_SESSION *session, unsigned
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1 = { static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1 = {
@ -125,17 +138,23 @@ static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1 = {
/* {{{ libssh2_mac_method_hmac_sha1_96_hash /* {{{ libssh2_mac_method_hmac_sha1_96_hash
* Calculate hash using first 96 bits of sha1 value * Calculate hash using first 96 bits of sha1 value
*/ */
static int libssh2_mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, static int
const unsigned char *packet, unsigned long packet_len, libssh2_mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session,
const unsigned char *addtl, unsigned long addtl_len, void **abstract) unsigned char *buf, unsigned long seqno,
const unsigned char *packet,
unsigned long packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
{ {
unsigned char temp[SHA_DIGEST_LENGTH]; unsigned char temp[SHA_DIGEST_LENGTH];
libssh2_mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len, addtl, addtl_len, abstract); libssh2_mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len,
addtl, addtl_len, abstract);
memcpy(buf, (char *) temp, 96 / 8); memcpy(buf, (char *) temp, 96 / 8);
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1_96 = { static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1_96 = {
@ -150,9 +169,13 @@ static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1_96 = {
/* {{{ libssh2_mac_method_hmac_md5_hash /* {{{ libssh2_mac_method_hmac_md5_hash
* Calculate hash using full md5 value * Calculate hash using full md5 value
*/ */
static int libssh2_mac_method_hmac_md5_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, static int
const unsigned char *packet, unsigned long packet_len, libssh2_mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf,
const unsigned char *addtl, unsigned long addtl_len, void **abstract) unsigned long seqno,
const unsigned char *packet,
unsigned long packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
{ {
libssh2_hmac_ctx ctx; libssh2_hmac_ctx ctx;
unsigned char seqno_buf[4]; unsigned char seqno_buf[4];
@ -171,6 +194,7 @@ static int libssh2_mac_method_hmac_md5_hash(LIBSSH2_SESSION *session, unsigned c
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5 = { static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5 = {
@ -185,17 +209,23 @@ static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5 = {
/* {{{ libssh2_mac_method_hmac_md5_96_hash /* {{{ libssh2_mac_method_hmac_md5_96_hash
* Calculate hash using first 96 bits of md5 value * Calculate hash using first 96 bits of md5 value
*/ */
static int libssh2_mac_method_hmac_md5_96_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, static int
const unsigned char *packet, unsigned long packet_len, libssh2_mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session,
const unsigned char *addtl, unsigned long addtl_len, void **abstract) unsigned char *buf, unsigned long seqno,
const unsigned char *packet,
unsigned long packet_len,
const unsigned char *addtl,
unsigned long addtl_len, void **abstract)
{ {
unsigned char temp[MD5_DIGEST_LENGTH]; unsigned char temp[MD5_DIGEST_LENGTH];
libssh2_mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len, addtl, addtl_len, abstract); libssh2_mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len,
addtl, addtl_len, abstract);
memcpy(buf, (char *) temp, 96 / 8); memcpy(buf, (char *) temp, 96 / 8);
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5_96 = { static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5_96 = {
@ -211,9 +241,14 @@ static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5_96 = {
/* {{{ libssh2_mac_method_hmac_ripemd160_hash /* {{{ libssh2_mac_method_hmac_ripemd160_hash
* Calculate hash using ripemd160 value * Calculate hash using ripemd160 value
*/ */
static int libssh2_mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, static int
const unsigned char *packet, unsigned long packet_len, libssh2_mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session,
const unsigned char *addtl, unsigned long addtl_len, void **abstract) unsigned char *buf, unsigned long seqno,
const unsigned char *packet,
unsigned long packet_len,
const unsigned char *addtl,
unsigned long addtl_len,
void **abstract)
{ {
libssh2_hmac_ctx ctx; libssh2_hmac_ctx ctx;
unsigned char seqno_buf[4]; unsigned char seqno_buf[4];
@ -232,6 +267,7 @@ static int libssh2_mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION *session, unsi
return 0; return 0;
} }
/* }}} */ /* }}} */
static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160 = { static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160 = {
@ -268,7 +304,8 @@ static const LIBSSH2_MAC_METHOD *_libssh2_mac_methods[] = {
NULL NULL
}; };
const LIBSSH2_MAC_METHOD **libssh2_mac_methods(void) { const LIBSSH2_MAC_METHOD **
libssh2_mac_methods(void)
{
return _libssh2_mac_methods; return _libssh2_mac_methods;
} }

Просмотреть файл

@ -42,17 +42,20 @@
/* {{{ libssh2_ntohu32 /* {{{ libssh2_ntohu32
*/ */
unsigned long libssh2_ntohu32(const unsigned char *buf) unsigned long
libssh2_ntohu32(const unsigned char *buf)
{ {
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
} }
/* }}} */ /* }}} */
/* {{{ libssh2_ntohu64 /* {{{ libssh2_ntohu64
* Note: Some 32-bit platforms have issues with bitops on long longs * Note: Some 32-bit platforms have issues with bitops on long longs
* Work around this by doing expensive (but safer) arithmetic ops with optimization defying parentheses * Work around this by doing expensive (but safer) arithmetic ops with optimization defying parentheses
*/ */
libssh2_uint64_t libssh2_ntohu64(const unsigned char *buf) libssh2_uint64_t
libssh2_ntohu64(const unsigned char *buf)
{ {
unsigned long msl, lsl; unsigned long msl, lsl;
@ -61,22 +64,26 @@ libssh2_uint64_t libssh2_ntohu64(const unsigned char *buf)
return ((msl * 65536) * 65536) + lsl; return ((msl * 65536) * 65536) + lsl;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_htonu32 /* {{{ libssh2_htonu32
*/ */
void libssh2_htonu32(unsigned char *buf, unsigned long value) void
libssh2_htonu32(unsigned char *buf, unsigned long value)
{ {
buf[0] = (value >> 24) & 0xFF; buf[0] = (value >> 24) & 0xFF;
buf[1] = (value >> 16) & 0xFF; buf[1] = (value >> 16) & 0xFF;
buf[2] = (value >> 8) & 0xFF; buf[2] = (value >> 8) & 0xFF;
buf[3] = value & 0xFF; buf[3] = value & 0xFF;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_htonu64 /* {{{ libssh2_htonu64
*/ */
void libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value) void
libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
{ {
unsigned long msl = (value / 65536) / 65536; unsigned long msl = (value / 65536) / 65536;
@ -90,6 +97,7 @@ void libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
buf[6] = (value >> 8) & 0xFF; buf[6] = (value >> 8) & 0xFF;
buf[7] = value & 0xFF; buf[7] = value & 0xFF;
} }
/* }}} */ /* }}} */
/* Base64 Conversion */ /* Base64 Conversion */
@ -123,14 +131,17 @@ static const short libssh2_base64_reverse_table[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
}; };
/* }}} */ /* }}} */
/* {{{ libssh2_base64_decode /* {{{ libssh2_base64_decode
* Decode a base64 chunk and store it into a newly alloc'd buffer * Decode a base64 chunk and store it into a newly alloc'd buffer
*/ */
LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, unsigned int *datalen, LIBSSH2_API int
const char *src, unsigned int src_len) libssh2_base64_decode(LIBSSH2_SESSION * session, char **data,
unsigned int *datalen, const char *src,
unsigned int src_len)
{ {
unsigned char *s, *d; unsigned char *s, *d;
short v; short v;
@ -143,7 +154,8 @@ LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, uns
} }
for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) { for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
if ((v = libssh2_base64_reverse_table[*s]) < 0) continue; if ((v = libssh2_base64_reverse_table[*s]) < 0)
continue;
switch (i % 4) { switch (i % 4) {
case 0: case 0:
d[len] = v << 2; d[len] = v << 2;
@ -171,17 +183,19 @@ LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, uns
*datalen = len; *datalen = len;
return 0; return 0;
} }
/* }}} */ /* }}} */
#ifdef LIBSSH2DEBUG #ifdef LIBSSH2DEBUG
LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask) LIBSSH2_API int
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
{ {
session->showmask = bitmask; session->showmask = bitmask;
return 0; return 0;
} }
void _libssh2_debug(LIBSSH2_SESSION *session, int context, void
const char *format, ...) _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
{ {
char buffer[1536]; char buffer[1536];
int len; int len;
@ -217,7 +231,8 @@ void _libssh2_debug(LIBSSH2_SESSION *session, int context,
} }
#else #else
LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask) LIBSSH2_API int
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
{ {
(void) session; (void) session;
(void) bitmask; (void) bitmask;

Просмотреть файл

@ -43,7 +43,8 @@
#define EVP_MAX_BLOCK_LENGTH 32 #define EVP_MAX_BLOCK_LENGTH 32
#endif #endif
int _libssh2_rsa_new(libssh2_rsa_ctx **rsa, int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata, const unsigned char *edata,
unsigned long elen, unsigned long elen,
const unsigned char *ndata, const unsigned char *ndata,
@ -58,8 +59,7 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
unsigned long e1len, unsigned long e1len,
const unsigned char *e2data, const unsigned char *e2data,
unsigned long e2len, unsigned long e2len,
const unsigned char *coeffdata, const unsigned char *coeffdata, unsigned long coefflen)
unsigned long coefflen)
{ {
*rsa = RSA_new(); *rsa = RSA_new();
@ -91,11 +91,11 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
return 0; return 0;
} }
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsactx, int
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx,
const unsigned char *sig, const unsigned char *sig,
unsigned long sig_len, unsigned long sig_len,
const unsigned char *m, const unsigned char *m, unsigned long m_len)
unsigned long m_len)
{ {
unsigned char hash[SHA_DIGEST_LENGTH]; unsigned char hash[SHA_DIGEST_LENGTH];
int ret; int ret;
@ -106,7 +106,8 @@ int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsactx,
return (ret == 1) ? 0 : -1; return (ret == 1) ? 0 : -1;
} }
int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx, int
_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
const unsigned char *p, const unsigned char *p,
unsigned long p_len, unsigned long p_len,
const unsigned char *q, const unsigned char *q,
@ -115,8 +116,7 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
unsigned long g_len, unsigned long g_len,
const unsigned char *y, const unsigned char *y,
unsigned long y_len, unsigned long y_len,
const unsigned char *x, const unsigned char *x, unsigned long x_len)
unsigned long x_len)
{ {
*dsactx = DSA_new(); *dsactx = DSA_new();
@ -140,10 +140,10 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
return 0; return 0;
} }
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx *dsactx, int
_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
const unsigned char *sig, const unsigned char *sig,
const unsigned char *m, const unsigned char *m, unsigned long m_len)
unsigned long m_len)
{ {
unsigned char hash[SHA_DIGEST_LENGTH]; unsigned char hash[SHA_DIGEST_LENGTH];
DSA_SIG dsasig; DSA_SIG dsasig;
@ -162,21 +162,20 @@ int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx *dsactx,
return (ret == 1) ? 0 : -1; return (ret == 1) ? 0 : -1;
} }
int _libssh2_cipher_init (_libssh2_cipher_ctx *h, int
_libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
unsigned char *iv, unsigned char *iv, unsigned char *secret, int encrypt)
unsigned char *secret,
int encrypt)
{ {
EVP_CIPHER_CTX_init(h); EVP_CIPHER_CTX_init(h);
EVP_CipherInit(h, algo(), secret, iv, encrypt); EVP_CipherInit(h, algo(), secret, iv, encrypt);
return 0; return 0;
} }
int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx, int
_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
int encrypt, int encrypt, unsigned char *block)
unsigned char *block)
{ {
int blocksize = ctx->cipher->block_size; int blocksize = ctx->cipher->block_size;
unsigned char buf[EVP_MAX_BLOCK_LENGTH]; unsigned char buf[EVP_MAX_BLOCK_LENGTH];
@ -199,8 +198,7 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx,
* calling program * calling program
*/ */
static int static int
passphrase_cb(char *buf, int size, passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
int rwflag, char *passphrase)
{ {
int passphrase_len = strlen(passphrase); int passphrase_len = strlen(passphrase);
(void) rwflag; (void) rwflag;
@ -214,10 +212,10 @@ passphrase_cb(char *buf, int size,
return passphrase_len; return passphrase_len;
} }
int _libssh2_rsa_new_private (libssh2_rsa_ctx **rsa, int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase)
unsigned const char *passphrase)
{ {
(void) session; (void) session;
if (!EVP_get_cipherbyname("des")) { if (!EVP_get_cipherbyname("des")) {
@ -235,10 +233,10 @@ int _libssh2_rsa_new_private (libssh2_rsa_ctx **rsa,
return 0; return 0;
} }
int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa, int
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase)
unsigned const char *passphrase)
{ {
(void) session; (void) session;
if (!EVP_get_cipherbyname("des")) { if (!EVP_get_cipherbyname("des")) {
@ -256,12 +254,12 @@ int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa,
return 0; return 0;
} }
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session, int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx, libssh2_rsa_ctx * rsactx,
const unsigned char *hash, const unsigned char *hash,
unsigned long hash_len, unsigned long hash_len,
unsigned char **signature, unsigned char **signature, unsigned long *signature_len)
unsigned long *signature_len)
{ {
int ret; int ret;
unsigned char *sig; unsigned char *sig;
@ -287,10 +285,10 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session,
return 0; return 0;
} }
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx, int
_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash, const unsigned char *hash,
unsigned long hash_len, unsigned long hash_len, unsigned char *signature)
unsigned char *signature)
{ {
DSA_SIG *sig; DSA_SIG *sig;
int r_len, s_len, rs_pad; int r_len, s_len, rs_pad;

Просмотреть файл

@ -146,17 +146,14 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
unsigned long e1len, unsigned long e1len,
const unsigned char *e2data, const unsigned char *e2data,
unsigned long e2len, unsigned long e2len,
const unsigned char *coeffdata, const unsigned char *coeffdata, unsigned long coefflen);
unsigned long coefflen);
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase);
unsigned const char *passphrase);
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig, const unsigned char *sig,
unsigned long sig_len, unsigned long sig_len,
const unsigned char *m, const unsigned char *m, unsigned long m_len);
unsigned long m_len);
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx, libssh2_rsa_ctx * rsactx,
const unsigned char *hash, const unsigned char *hash,
@ -177,20 +174,16 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsa,
unsigned long glen, unsigned long glen,
const unsigned char *ydata, const unsigned char *ydata,
unsigned long ylen, unsigned long ylen,
const unsigned char *x, const unsigned char *x, unsigned long x_len);
unsigned long x_len);
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE *fp, FILE * fp, unsigned const char *passphrase);
unsigned const char *passphrase);
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
const unsigned char *sig, const unsigned char *sig,
const unsigned char *m, const unsigned char *m, unsigned long m_len);
unsigned long m_len);
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const unsigned char *hash, const unsigned char *hash,
unsigned long hash_len, unsigned long hash_len, unsigned char *sig);
unsigned char *sig);
#define _libssh2_dsa_free(dsactx) DSA_free(dsactx) #define _libssh2_dsa_free(dsactx) DSA_free(dsactx)
@ -208,13 +201,11 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx,
int _libssh2_cipher_init(_libssh2_cipher_ctx * h, int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
unsigned char *iv, unsigned char *iv,
unsigned char *secret, unsigned char *secret, int encrypt);
int encrypt);
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo), _libssh2_cipher_type(algo),
int encrypt, int encrypt, unsigned char *block);
unsigned char *block);
#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx) #define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx)

Просмотреть файл

@ -80,18 +80,27 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
(void) datalen; (void) datalen;
if (listen_state->state == libssh2_NB_state_idle) { if (listen_state->state == libssh2_NB_state_idle) {
listen_state->sender_channel = libssh2_ntohu32(s); s += 4; listen_state->sender_channel = libssh2_ntohu32(s);
s += 4;
listen_state->initial_window_size = libssh2_ntohu32(s); s += 4; listen_state->initial_window_size = libssh2_ntohu32(s);
listen_state->packet_size = libssh2_ntohu32(s); s += 4; s += 4;
listen_state->packet_size = libssh2_ntohu32(s);
s += 4;
listen_state->host_len = libssh2_ntohu32(s); s += 4; listen_state->host_len = libssh2_ntohu32(s);
listen_state->host = s; s += listen_state->host_len; s += 4;
listen_state->port = libssh2_ntohu32(s); s += 4; listen_state->host = s;
s += listen_state->host_len;
listen_state->port = libssh2_ntohu32(s);
s += 4;
listen_state->shost_len = libssh2_ntohu32(s); s += 4; listen_state->shost_len = libssh2_ntohu32(s);
listen_state->shost = s; s += listen_state->shost_len; s += 4;
listen_state->sport = libssh2_ntohu32(s); s += 4; listen_state->shost = s;
s += listen_state->shost_len;
listen_state->sport = libssh2_ntohu32(s);
s += 4;
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Remote received connection from %s:%ld to %s:%ld", "Remote received connection from %s:%ld to %s:%ld",
@ -105,7 +114,9 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
while (listen) { while (listen) {
if ((listen->port == (int) listen_state->port) && if ((listen->port == (int) listen_state->port) &&
(strlen(listen->host) == listen_state->host_len) && (strlen(listen->host) == listen_state->host_len) &&
(memcmp(listen->host, listen_state->host, listen_state->host_len) == 0)) { (memcmp
(listen->host, listen_state->host,
listen_state->host_len) == 0)) {
/* This is our listener */ /* This is our listener */
LIBSSH2_CHANNEL *channel, *last_queued = listen->queue; LIBSSH2_CHANNEL *channel, *last_queued = listen->queue;
@ -135,7 +146,9 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
channel->session = session; channel->session = session;
channel->channel_type_len = sizeof("forwarded-tcpip") - 1; channel->channel_type_len = sizeof("forwarded-tcpip") - 1;
channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type = LIBSSH2_ALLOC(session,
channel->channel_type_len + 1); channel->
channel_type_len +
1);
if (!channel->channel_type) { if (!channel->channel_type) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a channel for new connection", "Unable to allocate a channel for new connection",
@ -149,13 +162,18 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
channel->channel_type_len + 1); channel->channel_type_len + 1);
channel->remote.id = listen_state->sender_channel; channel->remote.id = listen_state->sender_channel;
channel->remote.window_size_initial = LIBSSH2_CHANNEL_WINDOW_DEFAULT; channel->remote.window_size_initial =
channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT; LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT; channel->remote.window_size =
LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.packet_size =
LIBSSH2_CHANNEL_PACKET_DEFAULT;
channel->local.id = libssh2_channel_nextid(session); channel->local.id = libssh2_channel_nextid(session);
channel->local.window_size_initial = listen_state->initial_window_size; channel->local.window_size_initial =
channel->local.window_size = listen_state->initial_window_size; listen_state->initial_window_size;
channel->local.window_size =
listen_state->initial_window_size;
channel->local.packet_size = listen_state->packet_size; channel->local.packet_size = listen_state->packet_size;
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
@ -185,8 +203,7 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
17); 17);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc) {
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel open confirmation", "Unable to send channel open confirmation",
0); 0);
@ -239,8 +256,7 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
rc = libssh2_packet_write(session, listen_state->packet, packet_len); rc = libssh2_packet_write(session, listen_state->packet, packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc) {
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send open failure", 0); "Unable to send open failure", 0);
listen_state->state = libssh2_NB_state_idle; listen_state->state = libssh2_NB_state_idle;
@ -250,6 +266,7 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
return 0; return 0;
} }
} }
/* }}} */ /* }}} */
/* {{{ libssh2_packet_x11_open /* {{{ libssh2_packet_x11_open
@ -271,12 +288,18 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
(void) datalen; (void) datalen;
if (x11open_state->state == libssh2_NB_state_idle) { if (x11open_state->state == libssh2_NB_state_idle) {
x11open_state->sender_channel = libssh2_ntohu32(s); s += 4; x11open_state->sender_channel = libssh2_ntohu32(s);
x11open_state->initial_window_size = libssh2_ntohu32(s); s += 4; s += 4;
x11open_state->packet_size = libssh2_ntohu32(s); s += 4; x11open_state->initial_window_size = libssh2_ntohu32(s);
x11open_state->shost_len = libssh2_ntohu32(s); s += 4; s += 4;
x11open_state->shost = s; s += x11open_state->shost_len; x11open_state->packet_size = libssh2_ntohu32(s);
x11open_state->sport = libssh2_ntohu32(s); s += 4; s += 4;
x11open_state->shost_len = libssh2_ntohu32(s);
s += 4;
x11open_state->shost = s;
s += x11open_state->shost_len;
x11open_state->sport = libssh2_ntohu32(s);
s += 4;
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"X11 Connection Received from %s:%ld on channel %lu", "X11 Connection Received from %s:%ld on channel %lu",
@ -301,7 +324,8 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
channel->session = session; channel->session = session;
channel->channel_type_len = sizeof("x11") - 1; channel->channel_type_len = sizeof("x11") - 1;
channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type = LIBSSH2_ALLOC(session,
channel->channel_type_len + 1); channel->channel_type_len +
1);
if (!channel->channel_type) { if (!channel->channel_type) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a channel for new connection", "Unable to allocate a channel for new connection",
@ -310,15 +334,18 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */ failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
goto x11_exit; goto x11_exit;
} }
memcpy(channel->channel_type, "x11", channel->channel_type_len + 1); memcpy(channel->channel_type, "x11",
channel->channel_type_len + 1);
channel->remote.id = x11open_state->sender_channel; channel->remote.id = x11open_state->sender_channel;
channel->remote.window_size_initial = LIBSSH2_CHANNEL_WINDOW_DEFAULT; channel->remote.window_size_initial =
LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT; channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT; channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
channel->local.id = libssh2_channel_nextid(session); channel->local.id = libssh2_channel_nextid(session);
channel->local.window_size_initial = x11open_state->initial_window_size; channel->local.window_size_initial =
x11open_state->initial_window_size;
channel->local.window_size = x11open_state->initial_window_size; channel->local.window_size = x11open_state->initial_window_size;
channel->local.packet_size = x11open_state->packet_size; channel->local.packet_size = x11open_state->packet_size;
@ -331,10 +358,14 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
channel->remote.packet_size); channel->remote.packet_size);
p = x11open_state->packet; p = x11open_state->packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
libssh2_htonu32(p, channel->remote.id); p += 4; libssh2_htonu32(p, channel->remote.id);
libssh2_htonu32(p, channel->local.id); p += 4; p += 4;
libssh2_htonu32(p, channel->remote.window_size_initial); p += 4; libssh2_htonu32(p, channel->local.id);
libssh2_htonu32(p, channel->remote.packet_size); p += 4; p += 4;
libssh2_htonu32(p, channel->remote.window_size_initial);
p += 4;
libssh2_htonu32(p, channel->remote.packet_size);
p += 4;
x11open_state->state = libssh2_NB_state_created; x11open_state->state = libssh2_NB_state_created;
} }
@ -343,8 +374,7 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
rc = libssh2_packet_write(session, x11open_state->packet, 17); rc = libssh2_packet_write(session, x11open_state->packet, 17);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc) {
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel open confirmation", 0); "Unable to send channel open confirmation", 0);
x11open_state->state = libssh2_NB_state_idle; x11open_state->state = libssh2_NB_state_idle;
@ -366,7 +396,8 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
* Pass control to the callback, they may turn right around and * Pass control to the callback, they may turn right around and
* free the channel, or actually use it * free the channel, or actually use it
*/ */
LIBSSH2_X11_OPEN(channel, (char *)x11open_state->shost, x11open_state->sport); LIBSSH2_X11_OPEN(channel, (char *) x11open_state->shost,
x11open_state->sport);
x11open_state->state = libssh2_NB_state_idle; x11open_state->state = libssh2_NB_state_idle;
return 0; return 0;
@ -378,9 +409,12 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
x11_exit: x11_exit:
p = x11open_state->packet; p = x11open_state->packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
libssh2_htonu32(p, x11open_state->sender_channel); p += 4; libssh2_htonu32(p, x11open_state->sender_channel);
libssh2_htonu32(p, failure_code); p += 4; p += 4;
libssh2_htonu32(p, sizeof(X11FwdUnAvil) - 1); p += 4; libssh2_htonu32(p, failure_code);
p += 4;
libssh2_htonu32(p, sizeof(X11FwdUnAvil) - 1);
p += 4;
memcpy(s, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1); memcpy(s, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1);
p += sizeof(X11FwdUnAvil) - 1; p += sizeof(X11FwdUnAvil) - 1;
libssh2_htonu32(p, 0); libssh2_htonu32(p, 0);
@ -388,8 +422,7 @@ x11_exit:
rc = libssh2_packet_write(session, x11open_state->packet, packet_len); rc = libssh2_packet_write(session, x11open_state->packet, packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc) {
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send open failure", 0); "Unable to send open failure", 0);
x11open_state->state = libssh2_NB_state_idle; x11open_state->state = libssh2_NB_state_idle;
@ -398,12 +431,14 @@ x11_exit:
x11open_state->state = libssh2_NB_state_idle; x11open_state->state = libssh2_NB_state_idle;
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_packet_new /* {{{ libssh2_packet_new
* Create a new packet and attach it to the brigade * Create a new packet and attach it to the brigade
*/ */
int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, int
libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate) size_t datalen, int macstate)
{ {
int rc; int rc;
@ -469,11 +504,9 @@ int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data,
*/ */
if (session->packAdd_state == libssh2_NB_state_jump1) { if (session->packAdd_state == libssh2_NB_state_jump1) {
goto libssh2_packet_add_jump_point1; goto libssh2_packet_add_jump_point1;
} } else if (session->packAdd_state == libssh2_NB_state_jump2) {
else if (session->packAdd_state == libssh2_NB_state_jump2) {
goto libssh2_packet_add_jump_point2; goto libssh2_packet_add_jump_point2;
} } else if (session->packAdd_state == libssh2_NB_state_jump3) {
else if (session->packAdd_state == libssh2_NB_state_jump3) {
goto libssh2_packet_add_jump_point3; goto libssh2_packet_add_jump_point3;
} }
@ -586,7 +619,8 @@ int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data,
session->packAdd_data_head += 9; session->packAdd_data_head += 9;
{ {
session->packAdd_channel = libssh2_channel_locate(session, session->packAdd_channel = libssh2_channel_locate(session,
libssh2_ntohu32(data + 1)); libssh2_ntohu32
(data + 1));
if (!session->packAdd_channel) { if (!session->packAdd_channel) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
@ -606,14 +640,17 @@ int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data,
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"%d bytes received for channel %lu/%lu stream #%lu", "%d bytes received for channel %lu/%lu stream #%lu",
(int)(datalen - session->packAdd_data_head), (int) (datalen -
session->packAdd_data_head),
session->packAdd_channel->local.id, session->packAdd_channel->local.id,
session->packAdd_channel->remote.id, session->packAdd_channel->remote.id,
stream_id); stream_id);
} }
#endif #endif
if ((session->packAdd_channel->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && if ((session->packAdd_channel->remote.
(data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) { extended_data_ignore_mode ==
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE)
&& (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
/* Pretend we didn't receive this */ /* Pretend we didn't receive this */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
@ -623,8 +660,10 @@ int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data,
/* Adjust the window based on the block we just freed */ /* Adjust the window based on the block we just freed */
libssh2_packet_add_jump_point1: libssh2_packet_add_jump_point1:
session->packAdd_state = libssh2_NB_state_jump1; session->packAdd_state = libssh2_NB_state_jump1;
rc = libssh2_channel_receive_window_adjust(session->packAdd_channel, rc = libssh2_channel_receive_window_adjust(session->
datalen - 13, 0); packAdd_channel,
datalen - 13,
0);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@ -636,7 +675,8 @@ libssh2_packet_add_jump_point1:
* REMEMBER! remote means remote as source of data, * REMEMBER! remote means remote as source of data,
* NOT remote window! * NOT remote window!
*/ */
if (session->packAdd_channel->remote.packet_size < (datalen - session->packAdd_data_head)) { if (session->packAdd_channel->remote.packet_size <
(datalen - session->packAdd_data_head)) {
/* /*
* Spec says we MAY ignore bytes sent beyond * Spec says we MAY ignore bytes sent beyond
* packet_size * packet_size
@ -645,7 +685,9 @@ libssh2_packet_add_jump_point1:
LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
"Packet contains more data than we offered to receive, truncating", "Packet contains more data than we offered to receive, truncating",
0); 0);
datalen = session->packAdd_channel->remote.packet_size + session->packAdd_data_head; datalen =
session->packAdd_channel->remote.packet_size +
session->packAdd_data_head;
} }
if (session->packAdd_channel->remote.window_size <= 0) { if (session->packAdd_channel->remote.window_size <= 0) {
/* /*
@ -663,15 +705,19 @@ libssh2_packet_add_jump_point1:
/* Reset EOF status */ /* Reset EOF status */
session->packAdd_channel->remote.eof = 0; session->packAdd_channel->remote.eof = 0;
if ((datalen - session->packAdd_data_head) > session->packAdd_channel->remote.window_size) { if ((datalen - session->packAdd_data_head) >
session->packAdd_channel->remote.window_size) {
libssh2_error(session, libssh2_error(session,
LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
"Remote sent more data than current window allows, truncating", "Remote sent more data than current window allows, truncating",
0); 0);
datalen = session->packAdd_channel->remote.window_size + session->packAdd_data_head; datalen =
session->packAdd_channel->remote.window_size +
session->packAdd_data_head;
} else { } else {
/* Now that we've received it, shrink our window */ /* Now that we've received it, shrink our window */
session->packAdd_channel->remote.window_size -= datalen - session->packAdd_data_head; session->packAdd_channel->remote.window_size -=
datalen - session->packAdd_data_head;
} }
} }
break; break;
@ -679,7 +725,8 @@ libssh2_packet_add_jump_point1:
case SSH_MSG_CHANNEL_EOF: case SSH_MSG_CHANNEL_EOF:
{ {
session->packAdd_channel = libssh2_channel_locate(session, session->packAdd_channel = libssh2_channel_locate(session,
libssh2_ntohu32(data + 1)); libssh2_ntohu32
(data + 1));
if (!session->packAdd_channel) { if (!session->packAdd_channel) {
/* We may have freed already, just quietly ignore this... */ /* We may have freed already, just quietly ignore this... */
@ -704,13 +751,17 @@ libssh2_packet_add_jump_point1:
case SSH_MSG_CHANNEL_REQUEST: case SSH_MSG_CHANNEL_REQUEST:
{ {
if (libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1 if (libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1
&& !memcmp("exit-status", data + 9, sizeof("exit-status") - 1)) { && !memcmp("exit-status", data + 9,
sizeof("exit-status") - 1)) {
/* we've got "exit-status" packet. Set the session value */ /* we've got "exit-status" packet. Set the session value */
session->packAdd_channel = libssh2_channel_locate(session, libssh2_ntohu32(data+1)); session->packAdd_channel =
libssh2_channel_locate(session,
libssh2_ntohu32(data + 1));
if (session->packAdd_channel) { if (session->packAdd_channel) {
session->packAdd_channel->exit_status = libssh2_ntohu32(data + 9 + sizeof("exit-status")); session->packAdd_channel->exit_status =
libssh2_ntohu32(data + 9 + sizeof("exit-status"));
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Exit status %lu received for channel %lu/%lu", "Exit status %lu received for channel %lu/%lu",
session->packAdd_channel->exit_status, session->packAdd_channel->exit_status,
@ -728,7 +779,8 @@ libssh2_packet_add_jump_point1:
case SSH_MSG_CHANNEL_CLOSE: case SSH_MSG_CHANNEL_CLOSE:
{ {
session->packAdd_channel = libssh2_channel_locate(session, session->packAdd_channel = libssh2_channel_locate(session,
libssh2_ntohu32(data + 1)); libssh2_ntohu32
(data + 1));
if (!session->packAdd_channel) { if (!session->packAdd_channel) {
/* We may have freed already, just quietly ignore this... */ /* We may have freed already, just quietly ignore this... */
@ -753,13 +805,17 @@ libssh2_packet_add_jump_point1:
case SSH_MSG_CHANNEL_OPEN: case SSH_MSG_CHANNEL_OPEN:
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip")-1) == libssh2_ntohu32(data + 1)) && ((sizeof("forwarded-tcpip") - 1) == libssh2_ntohu32(data + 1))
(memcmp(data + 5, "forwarded-tcpip", sizeof("forwarded-tcpip") - 1) == 0)) { &&
(memcmp
(data + 5, "forwarded-tcpip",
sizeof("forwarded-tcpip") - 1) == 0)) {
libssh2_packet_add_jump_point2: libssh2_packet_add_jump_point2:
session->packAdd_state = libssh2_NB_state_jump2; session->packAdd_state = libssh2_NB_state_jump2;
rc = libssh2_packet_queue_listener(session, data, datalen, rc = libssh2_packet_queue_listener(session, data, datalen,
&session->packAdd_Qlstn_state); &session->
packAdd_Qlstn_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@ -790,7 +846,8 @@ libssh2_packet_add_jump_point3:
{ {
unsigned long bytestoadd = libssh2_ntohu32(data + 5); unsigned long bytestoadd = libssh2_ntohu32(data + 5);
session->packAdd_channel = libssh2_channel_locate(session, session->packAdd_channel = libssh2_channel_locate(session,
libssh2_ntohu32(data + 1)); libssh2_ntohu32
(data + 1));
if (session->packAdd_channel && bytestoadd) { if (session->packAdd_channel && bytestoadd) {
session->packAdd_channel->local.window_size += bytestoadd; session->packAdd_channel->local.window_size += bytestoadd;
@ -813,7 +870,8 @@ libssh2_packet_add_jump_point3:
} }
if (session->packAdd_state == libssh2_NB_state_sent) { if (session->packAdd_state == libssh2_NB_state_sent) {
session->packAdd_packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); session->packAdd_packet =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!session->packAdd_packet) { if (!session->packAdd_packet) {
_libssh2_debug(session, LIBSSH2_ERROR_ALLOC, _libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for LIBSSH2_PACKET"); "Unable to allocate memory for LIBSSH2_PACKET");
@ -869,14 +927,18 @@ libssh2_packet_add_jump_point3:
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_packet_ask /* {{{ libssh2_packet_ask
* Scan the brigade for a matching packet type, optionally poll the socket for * Scan the brigade for a matching packet type, optionally poll the socket for
* a packet first * a packet first
*/ */
int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, int
unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket) libssh2_packet_ask_ex(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned char **data, unsigned long *data_len,
unsigned long match_ofs, const unsigned char *match_buf,
unsigned long match_len, int poll_socket)
{ {
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = session->packets.head;
@ -896,8 +958,16 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, u
"Looking for packet of type: %d", (int) packet_type); "Looking for packet of type: %d", (int) packet_type);
while (packet) { while (packet) {
if (packet->data[0] == packet_type && (packet->data_len >= (match_ofs + match_len)) && if (packet->data[0] == packet_type
(!match_buf || (memcmp(packet->data + match_ofs, match_buf, match_len) == 0))) { && (packet->data_len >= (match_ofs + match_len)) && (!match_buf
||
(memcmp
(packet->
data +
match_ofs,
match_buf,
match_len)
== 0))) {
*data = packet->data; *data = packet->data;
*data_len = packet->data_len; *data_len = packet->data_len;
@ -921,13 +991,15 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, u
} }
return -1; return -1;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_packet_askv /* {{{ libssh2_packet_askv
* Scan for any of a list of packet types in the brigade, optionally poll the * Scan for any of a list of packet types in the brigade, optionally poll the
* socket for a packet first * socket for a packet first
*/ */
int libssh2_packet_askv_ex(LIBSSH2_SESSION *session, int
libssh2_packet_askv_ex(LIBSSH2_SESSION * session,
const unsigned char *packet_types, const unsigned char *packet_types,
unsigned char **data, unsigned long *data_len, unsigned char **data, unsigned long *data_len,
unsigned long match_ofs, unsigned long match_ofs,
@ -952,6 +1024,7 @@ int libssh2_packet_askv_ex(LIBSSH2_SESSION *session,
return -1; return -1;
} }
/* }}} */ /* }}} */
/* {{{ waitsocket /* {{{ waitsocket
@ -962,7 +1035,8 @@ int libssh2_packet_askv_ex(LIBSSH2_SESSION *session,
* *
* FIXME: convert to use poll on systems that have it. * FIXME: convert to use poll on systems that have it.
*/ */
int libssh2_waitsocket(LIBSSH2_SESSION *session, long seconds) int
libssh2_waitsocket(LIBSSH2_SESSION * session, long seconds)
{ {
struct timeval timeout; struct timeval timeout;
int rc; int rc;
@ -987,42 +1061,48 @@ int libssh2_waitsocket(LIBSSH2_SESSION *session, long seconds)
* Returns negative on error * Returns negative on error
* Returns 0 when it has taken care of the requested packet. * Returns 0 when it has taken care of the requested packet.
*/ */
int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, int
unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, libssh2_packet_require_ex(LIBSSH2_SESSION * session, unsigned char packet_type,
unsigned long match_len, packet_require_state_t *state) unsigned char **data, unsigned long *data_len,
unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len,
packet_require_state_t * state)
{ {
if (state->start == 0) { if (state->start == 0) {
if (libssh2_packet_ask_ex(session, packet_type, data, data_len, match_ofs, match_buf, match_len, 0) == 0) { if (libssh2_packet_ask_ex
(session, packet_type, data, data_len, match_ofs, match_buf,
match_len, 0) == 0) {
/* A packet was available in the packet brigade */ /* A packet was available in the packet brigade */
return 0; return 0;
} }
state->start = time(NULL); state->start = time(NULL);
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "May block until packet of type %d becomes available", (int)packet_type); _libssh2_debug(session, LIBSSH2_DBG_TRANS,
"May block until packet of type %d becomes available",
(int) packet_type);
} }
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
libssh2pack_t ret = libssh2_packet_read(session); libssh2pack_t ret = libssh2_packet_read(session);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if ((ret == 0) && (!session->socket_block)) {
else if ((ret == 0) && (!session->socket_block)) {
/* If we are in non-blocking and there is no data, return that */ /* If we are in non-blocking and there is no data, return that */
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (ret < 0) {
else if (ret < 0) {
state->start = 0; state->start = 0;
/* an error which is not just because of blocking */ /* an error which is not just because of blocking */
return ret; return ret;
} } else if (ret == packet_type) {
else if (ret == packet_type) {
/* Be lazy, let packet_ask pull it out of the brigade */ /* Be lazy, let packet_ask pull it out of the brigade */
ret = libssh2_packet_ask_ex(session, packet_type, data, data_len, match_ofs, match_buf, match_len, 0); ret =
libssh2_packet_ask_ex(session, packet_type, data, data_len,
match_ofs, match_buf, match_len, 0);
state->start = 0; state->start = 0;
return ret; return ret;
} } else if (ret == 0) {
else if (ret == 0) {
/* nothing available, wait until data arrives or we time out */ /* nothing available, wait until data arrives or we time out */
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start); long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
@ -1036,6 +1116,7 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
/* Only reached if the socket died */ /* Only reached if the socket died */
return -1; return -1;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_packet_burn /* {{{ libssh2_packet_burn
@ -1043,7 +1124,9 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
* discards it * discards it
* Used during KEX exchange to discard badly guessed KEX_INIT packets * Used during KEX exchange to discard badly guessed KEX_INIT packets
*/ */
int libssh2_packet_burn(LIBSSH2_SESSION *session, libssh2_nonblocking_states *state) int
libssh2_packet_burn(LIBSSH2_SESSION * session,
libssh2_nonblocking_states * state)
{ {
unsigned char *data; unsigned char *data;
unsigned long data_len; unsigned long data_len;
@ -1056,32 +1139,34 @@ int libssh2_packet_burn(LIBSSH2_SESSION *session, libssh2_nonblocking_states *st
all_packets[i - 1] = i; all_packets[i - 1] = i;
} }
if (libssh2_packet_askv_ex(session, all_packets, &data, &data_len, 0, NULL, 0, 0) == 0) { if (libssh2_packet_askv_ex
(session, all_packets, &data, &data_len, 0, NULL, 0, 0) == 0) {
i = data[0]; i = data[0];
/* A packet was available in the packet brigade, burn it */ /* A packet was available in the packet brigade, burn it */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return i; return i;
} }
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking until packet becomes available to burn"); _libssh2_debug(session, LIBSSH2_DBG_TRANS,
"Blocking until packet becomes available to burn");
*state = libssh2_NB_state_created; *state = libssh2_NB_state_created;
} }
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
if ((ret = libssh2_packet_read(session)) == PACKET_EAGAIN) { if ((ret = libssh2_packet_read(session)) == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (ret < 0) {
else if (ret < 0) {
*state = libssh2_NB_state_idle; *state = libssh2_NB_state_idle;
return ret; return ret;
} } else if (ret == 0) {
else if (ret == 0) {
/* FIXME: this might busyloop */ /* FIXME: this might busyloop */
continue; continue;
} }
/* Be lazy, let packet_ask pull it out of the brigade */ /* Be lazy, let packet_ask pull it out of the brigade */
if (0 == libssh2_packet_ask_ex(session, ret, &data, &data_len, 0, NULL, 0, 0)) { if (0 ==
libssh2_packet_ask_ex(session, ret, &data, &data_len, 0, NULL, 0,
0)) {
/* Smoke 'em if you got 'em */ /* Smoke 'em if you got 'em */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
*state = libssh2_NB_state_idle; *state = libssh2_NB_state_idle;
@ -1092,6 +1177,7 @@ int libssh2_packet_burn(LIBSSH2_SESSION *session, libssh2_nonblocking_states *st
/* Only reached if the socket died */ /* Only reached if the socket died */
return -1; return -1;
} }
/* }}} */ /* }}} */
/* /*
@ -1103,11 +1189,18 @@ int libssh2_packet_burn(LIBSSH2_SESSION *session, libssh2_nonblocking_states *st
* packet_types is a null terminated list of packet_type numbers * packet_types is a null terminated list of packet_type numbers
*/ */
int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, const unsigned char *packet_types, unsigned char **data, int
unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, libssh2_packet_requirev_ex(LIBSSH2_SESSION * session,
unsigned long match_len, packet_requirev_state_t *state) const unsigned char *packet_types,
unsigned char **data, unsigned long *data_len,
unsigned long match_ofs,
const unsigned char *match_buf,
unsigned long match_len,
packet_requirev_state_t * state)
{ {
if (libssh2_packet_askv_ex(session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0) == 0) { if (libssh2_packet_askv_ex
(session, packet_types, data, data_len, match_ofs, match_buf,
match_len, 0) == 0) {
/* One of the packets listed was available in the packet /* One of the packets listed was available in the packet
brigade */ brigade */
state->start = 0; state->start = 0;
@ -1130,15 +1223,16 @@ int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, const unsigned char *pa
if ((left <= 0) || (libssh2_waitsocket(session, left) <= 0)) { if ((left <= 0) || (libssh2_waitsocket(session, left) <= 0)) {
state->start = 0; state->start = 0;
return PACKET_TIMEOUT; return PACKET_TIMEOUT;
} } else if (ret == PACKET_EAGAIN) {
else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
} }
if (strchr((char *) packet_types, ret)) { if (strchr((char *) packet_types, ret)) {
/* Be lazy, let packet_ask pull it out of the brigade */ /* Be lazy, let packet_ask pull it out of the brigade */
return libssh2_packet_askv_ex(session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0); return libssh2_packet_askv_ex(session, packet_types, data,
data_len, match_ofs, match_buf,
match_len, 0);
} }
} }
@ -1146,4 +1240,5 @@ int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, const unsigned char *pa
state->start = 0; state->start = 0;
return -1; return -1;
} }
/* }}} */ /* }}} */

Просмотреть файл

@ -37,18 +37,16 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
static int readline (char *line, int line_size, FILE *fp) static int
{ readline(char *line, int line_size, FILE * fp)
if (!fgets(line, line_size, fp))
{ {
if (!fgets(line, line_size, fp)) {
return -1; return -1;
} }
if (*line && line[strlen(line) - 1] == '\n') if (*line && line[strlen(line) - 1] == '\n') {
{
line[strlen(line) - 1] = '\0'; line[strlen(line) - 1] = '\0';
} }
if (*line && line[strlen(line) - 1] == '\r') if (*line && line[strlen(line) - 1] == '\r') {
{
line[strlen(line) - 1] = '\0'; line[strlen(line) - 1] = '\0';
} }
return 0; return 0;
@ -56,21 +54,19 @@ static int readline (char *line, int line_size, FILE *fp)
#define LINE_SIZE 128 #define LINE_SIZE 128
int _libssh2_pem_parse (LIBSSH2_SESSION *session, int
_libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin, const char *headerbegin,
const char *headerend, const char *headerend,
FILE *fp, FILE * fp, char **data, unsigned int *datalen)
char **data, unsigned int *datalen)
{ {
char line[LINE_SIZE]; char line[LINE_SIZE];
char *b64data = NULL; char *b64data = NULL;
unsigned int b64datalen = 0; unsigned int b64datalen = 0;
int ret; int ret;
do do {
{ if (readline(line, LINE_SIZE, fp)) {
if (readline(line, LINE_SIZE, fp))
{
return -1; return -1;
} }
} }
@ -78,18 +74,14 @@ int _libssh2_pem_parse (LIBSSH2_SESSION *session,
*line = '\0'; *line = '\0';
do do {
{ if (*line) {
if (*line)
{
char *tmp; char *tmp;
size_t linelen; size_t linelen;
linelen = strlen(line); linelen = strlen(line);
tmp = LIBSSH2_REALLOC (session, b64data, tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
b64datalen + linelen); if (!tmp) {
if (!tmp)
{
ret = -1; ret = -1;
goto out; goto out;
} }
@ -98,16 +90,13 @@ int _libssh2_pem_parse (LIBSSH2_SESSION *session,
b64datalen += linelen; b64datalen += linelen;
} }
if (readline(line, LINE_SIZE, fp)) if (readline(line, LINE_SIZE, fp)) {
{
ret = -1; ret = -1;
goto out; goto out;
} }
} while (strcmp(line, headerend) != 0); } while (strcmp(line, headerend) != 0);
if (libssh2_base64_decode(session, data, datalen, if (libssh2_base64_decode(session, data, datalen, b64data, b64datalen)) {
b64data, b64datalen))
{
ret = -1; ret = -1;
goto out; goto out;
} }
@ -120,59 +109,51 @@ out:
return ret; return ret;
} }
static int read_asn1_length (const unsigned char *data, static int
unsigned int datalen, read_asn1_length(const unsigned char *data,
unsigned int *len) unsigned int datalen, unsigned int *len)
{ {
unsigned int lenlen; unsigned int lenlen;
int nextpos; int nextpos;
if (datalen < 1) if (datalen < 1) {
{
return -1; return -1;
} }
*len = data[0]; *len = data[0];
if (*len >= 0x80) if (*len >= 0x80) {
{
lenlen = *len & 0x7F; lenlen = *len & 0x7F;
*len = data[1]; *len = data[1];
if (1 + lenlen > datalen) if (1 + lenlen > datalen) {
{
return -1; return -1;
} }
if (lenlen > 1) if (lenlen > 1) {
{
*len <<= 8; *len <<= 8;
*len |= data[2]; *len |= data[2];
} }
} } else {
else
{
lenlen = 0; lenlen = 0;
} }
nextpos = 1 + lenlen; nextpos = 1 + lenlen;
if (lenlen > 2 || 1 + lenlen + *len > datalen) if (lenlen > 2 || 1 + lenlen + *len > datalen) {
{
return -1; return -1;
} }
return nextpos; return nextpos;
} }
int _libssh2_pem_decode_sequence (unsigned char **data, unsigned int *datalen) int
_libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen)
{ {
unsigned int len; unsigned int len;
int lenlen; int lenlen;
if (*datalen < 1) if (*datalen < 1) {
{
return -1; return -1;
} }
if ((*data)[0] != '\x30') if ((*data)[0] != '\x30') {
{
return -1; return -1;
} }
@ -180,8 +161,7 @@ int _libssh2_pem_decode_sequence (unsigned char **data, unsigned int *datalen)
(*datalen)--; (*datalen)--;
lenlen = read_asn1_length(*data, *datalen, &len); lenlen = read_asn1_length(*data, *datalen, &len);
if (lenlen < 0 || lenlen + len != *datalen) if (lenlen < 0 || lenlen + len != *datalen) {
{
return -1; return -1;
} }
@ -191,19 +171,18 @@ int _libssh2_pem_decode_sequence (unsigned char **data, unsigned int *datalen)
return 0; return 0;
} }
int _libssh2_pem_decode_integer (unsigned char **data, unsigned int *datalen, int
_libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
unsigned char **i, unsigned int *ilen) unsigned char **i, unsigned int *ilen)
{ {
unsigned int len; unsigned int len;
int lenlen; int lenlen;
if (*datalen < 1) if (*datalen < 1) {
{
return -1; return -1;
} }
if ((*data)[0] != '\x02') if ((*data)[0] != '\x02') {
{
return -1; return -1;
} }
@ -211,8 +190,7 @@ int _libssh2_pem_decode_integer (unsigned char **data, unsigned int *datalen,
(*datalen)--; (*datalen)--;
lenlen = read_asn1_length(*data, *datalen, &len); lenlen = read_asn1_length(*data, *datalen, &len);
if (lenlen < 0 || lenlen + len > *datalen) if (lenlen < 0 || lenlen + len > *datalen) {
{
return -1; return -1;
} }

Просмотреть файл

@ -45,16 +45,20 @@
#define LIBSSH2_PUBLICKEY_RESPONSE_VERSION 1 #define LIBSSH2_PUBLICKEY_RESPONSE_VERSION 1
#define LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY 2 #define LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY 2
typedef struct _LIBSSH2_PUBLICKEY_CODE_LIST { typedef struct _LIBSSH2_PUBLICKEY_CODE_LIST
{
int code; int code;
const char *name; const char *name;
int name_len; int name_len;
} LIBSSH2_PUBLICKEY_CODE_LIST; } LIBSSH2_PUBLICKEY_CODE_LIST;
static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_response_codes[] = { static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_response_codes[] = {
{ LIBSSH2_PUBLICKEY_RESPONSE_STATUS, "status", sizeof("status") - 1 }, {LIBSSH2_PUBLICKEY_RESPONSE_STATUS, "status", sizeof("status") - 1}
{ LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1 }, ,
{ LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey", sizeof("publickey") - 1 }, {LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1}
,
{LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey", sizeof("publickey") - 1}
,
{0, NULL, 0} {0, NULL, 0}
}; };
@ -72,15 +76,32 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_response_codes[] = {
#define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX 8 #define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX 8
static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_status_codes[] = { static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_status_codes[] = {
{ LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1 }, {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1}
{ LIBSSH2_PUBLICKEY_ACCESS_DENIED, "access denied", sizeof("access denied") - 1 }, ,
{ LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED, "storage exceeded", sizeof("storage exceeded") - 1 }, {LIBSSH2_PUBLICKEY_ACCESS_DENIED, "access denied",
{ LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED, "version not supported", sizeof("version not supported") - 1 }, sizeof("access denied") - 1}
{ LIBSSH2_PUBLICKEY_KEY_NOT_FOUND, "key not found", sizeof("key not found") - 1 }, ,
{ LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED, "key not supported", sizeof("key not supported") - 1 }, {LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED, "storage exceeded",
{ LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT, "key already present", sizeof("key already present") - 1 }, sizeof("storage exceeded") - 1}
{ LIBSSH2_PUBLICKEY_GENERAL_FAILURE, "general failure", sizeof("general failure") - 1 }, ,
{ LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED, "request not supported", sizeof("request not supported") - 1 }, {LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED, "version not supported",
sizeof("version not supported") - 1}
,
{LIBSSH2_PUBLICKEY_KEY_NOT_FOUND, "key not found",
sizeof("key not found") - 1}
,
{LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED, "key not supported",
sizeof("key not supported") - 1}
,
{LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT, "key already present",
sizeof("key already present") - 1}
,
{LIBSSH2_PUBLICKEY_GENERAL_FAILURE, "general failure",
sizeof("general failure") - 1}
,
{LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED, "request not supported",
sizeof("request not supported") - 1}
,
{0, NULL, 0} {0, NULL, 0}
}; };
@ -91,7 +112,8 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_status_codes[] = {
#define LIBSSH2_PUBLICKEY_STATUS_TEXT_MID "\" Server Resports: \"" #define LIBSSH2_PUBLICKEY_STATUS_TEXT_MID "\" Server Resports: \""
#define LIBSSH2_PUBLICKEY_STATUS_TEXT_END "\"" #define LIBSSH2_PUBLICKEY_STATUS_TEXT_END "\""
static void static void
libssh2_publickey_status_error(const LIBSSH2_PUBLICKEY *pkey, LIBSSH2_SESSION *session, int status, libssh2_publickey_status_error(const LIBSSH2_PUBLICKEY * pkey,
LIBSSH2_SESSION * session, int status,
const unsigned char *message, int message_len) const unsigned char *message, int message_len)
{ {
const char *status_text; const char *status_text;
@ -112,32 +134,41 @@ libssh2_publickey_status_error(const LIBSSH2_PUBLICKEY *pkey, LIBSSH2_SESSION *s
status_text_len = libssh2_publickey_status_codes[status].name_len; status_text_len = libssh2_publickey_status_codes[status].name_len;
} }
m_len = (sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1) + status_text_len + m_len =
(sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1) + status_text_len +
(sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1) + message_len + (sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1) + message_len +
(sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1); (sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1);
m = LIBSSH2_ALLOC(session, m_len + 1); m = LIBSSH2_ALLOC(session, m_len + 1);
if (!m) { if (!m) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for status message", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for status message", 0);
return; return;
} }
s = m; s = m;
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_START, sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1); memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_START,
sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1);
s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1; s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1;
memcpy(s, status_text, status_text_len); s += status_text_len; memcpy(s, status_text, status_text_len);
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_MID, sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1); s += status_text_len;
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_MID,
sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1);
s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1; s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1;
memcpy(s, message, message_len); s += message_len; memcpy(s, message, message_len);
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_END, sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1); s += message_len;
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_END,
sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1);
s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END); s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, m, 1); libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, m, 1);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_packet_receive /* {{{ libssh2_publickey_packet_receive
* Read a packet from the subsystem * Read a packet from the subsystem
*/ */
static int static int
libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY *pkey, unsigned char **data, unsigned long *data_len) libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
unsigned char **data, unsigned long *data_len)
{ {
LIBSSH2_CHANNEL *channel = pkey->channel; LIBSSH2_CHANNEL *channel = pkey->channel;
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
@ -148,16 +179,18 @@ libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY *pkey, unsigned char **data,
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4); rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc != 4) {
else if (rc != 4) { libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid response from publickey subsystem", 0); "Invalid response from publickey subsystem", 0);
return -1; return -1;
} }
pkey->receive_packet_len = libssh2_ntohu32(buffer); pkey->receive_packet_len = libssh2_ntohu32(buffer);
pkey->receive_packet = LIBSSH2_ALLOC(session, pkey->receive_packet_len); pkey->receive_packet =
LIBSSH2_ALLOC(session, pkey->receive_packet_len);
if (!pkey->receive_packet) { if (!pkey->receive_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate publickey response buffer", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate publickey response buffer", 0);
return -1; return -1;
} }
@ -165,12 +198,14 @@ libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY *pkey, unsigned char **data,
} }
if (pkey->receive_state == libssh2_NB_state_sent) { if (pkey->receive_state == libssh2_NB_state_sent) {
rc = libssh2_channel_read_ex(channel, 0, (char *)pkey->receive_packet, pkey->receive_packet_len); rc = libssh2_channel_read_ex(channel, 0, (char *) pkey->receive_packet,
pkey->receive_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc != pkey->receive_packet_len) {
else if (rc != pkey->receive_packet_len) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for publickey subsystem response packet", 0); "Timeout waiting for publickey subsystem response packet",
0);
LIBSSH2_FREE(session, pkey->receive_packet); LIBSSH2_FREE(session, pkey->receive_packet);
pkey->receive_packet = NULL; pkey->receive_packet = NULL;
pkey->receive_state = libssh2_NB_state_idle; pkey->receive_state = libssh2_NB_state_idle;
@ -185,23 +220,28 @@ libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY *pkey, unsigned char **data,
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_response_id /* {{{ libssh2_publickey_response_id
* Translate a string response name to a numeric code * Translate a string response name to a numeric code
* Data will be incremented by 4 + response_len on success only * Data will be incremented by 4 + response_len on success only
*/ */
static int libssh2_publickey_response_id(unsigned char **pdata, int data_len) static int
libssh2_publickey_response_id(unsigned char **pdata, int data_len)
{ {
unsigned long response_len; unsigned long response_len;
unsigned char *data = *pdata; unsigned char *data = *pdata;
const LIBSSH2_PUBLICKEY_CODE_LIST *codes = libssh2_publickey_response_codes; const LIBSSH2_PUBLICKEY_CODE_LIST *codes =
libssh2_publickey_response_codes;
if (data_len < 4) { if (data_len < 4) {
/* Malformed response */ /* Malformed response */
return -1; return -1;
} }
response_len = libssh2_ntohu32(data); data += 4; data_len -= 4; response_len = libssh2_ntohu32(data);
data += 4;
data_len -= 4;
if (data_len < response_len) { if (data_len < response_len) {
/* Malformed response */ /* Malformed response */
return -1; return -1;
@ -218,12 +258,14 @@ static int libssh2_publickey_response_id(unsigned char **pdata, int data_len)
return -1; return -1;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_response_success /* {{{ libssh2_publickey_response_success
* Generic helper routine to wait for success response and nothing else * Generic helper routine to wait for success response and nothing else
*/ */
static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey) static int
libssh2_publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
{ {
LIBSSH2_SESSION *session = pkey->channel->session; LIBSSH2_SESSION *session = pkey->channel->session;
unsigned char *data, *s; unsigned char *data, *s;
@ -235,15 +277,17 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
rc = libssh2_publickey_packet_receive(pkey, &data, &data_len); rc = libssh2_publickey_packet_receive(pkey, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc) {
else if (rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from publickey subsystem", 0); "Timeout waiting for response from publickey subsystem",
0);
return -1; return -1;
} }
s = data; s = data;
if ((response = libssh2_publickey_response_id(&s, data_len)) < 0) { if ((response = libssh2_publickey_response_id(&s, data_len)) < 0) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid publickey subsystem response code", 0); libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code", 0);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return -1; return -1;
} }
@ -255,14 +299,20 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
unsigned long status, descr_len, lang_len; unsigned long status, descr_len, lang_len;
unsigned char *descr, *lang; unsigned char *descr, *lang;
status = libssh2_ntohu32(s); s += 4; status = libssh2_ntohu32(s);
descr_len = libssh2_ntohu32(s); s += 4; s += 4;
descr = s; s += descr_len; descr_len = libssh2_ntohu32(s);
lang_len = libssh2_ntohu32(s); s += 4; s += 4;
lang = s; s += lang_len; descr = s;
s += descr_len;
lang_len = libssh2_ntohu32(s);
s += 4;
lang = s;
s += lang_len;
if (s > data + data_len) { if (s > data + data_len) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Malformed publickey subsystem packet", 0); libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet", 0);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return -1; return -1;
} }
@ -272,13 +322,16 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
return 0; return 0;
} }
libssh2_publickey_status_error(pkey, session, status, descr, descr_len); libssh2_publickey_status_error(pkey, session, status, descr,
descr_len);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return -1; return -1;
} }
default: default:
/* Unknown/Unexpected */ /* Unknown/Unexpected */
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Unexpected publickey subsystem response, ignoring", 0); libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response, ignoring",
0);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
data = NULL; data = NULL;
} }
@ -286,6 +339,7 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
/* never reached, but include `return` to silence compiler warnings */ /* never reached, but include `return` to silence compiler warnings */
return -1; return -1;
} }
/* }}} */ /* }}} */
@ -296,7 +350,8 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
/* {{{ libssh2_publickey_init /* {{{ libssh2_publickey_init
* Startup the publickey subsystem * Startup the publickey subsystem
*/ */
LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session) LIBSSH2_API LIBSSH2_PUBLICKEY *
libssh2_publickey_init(LIBSSH2_SESSION * session)
{ {
/* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */ /* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */
unsigned char buffer[19]; unsigned char buffer[19];
@ -309,23 +364,32 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_pkey = NULL; session->pkeyInit_pkey = NULL;
session->pkeyInit_channel = NULL; session->pkeyInit_channel = NULL;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Initializing publickey subsystem"); _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
"Initializing publickey subsystem");
session->pkeyInit_state = libssh2_NB_state_allocated; session->pkeyInit_state = libssh2_NB_state_allocated;
} }
if (session->pkeyInit_state == libssh2_NB_state_allocated) { if (session->pkeyInit_state == libssh2_NB_state_allocated) {
do { do {
session->pkeyInit_channel = libssh2_channel_open_ex(session, "session", sizeof("session") - 1, session->pkeyInit_channel =
LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, libssh2_channel_open_ex(session, "session",
NULL, 0); sizeof("session") - 1,
if (!session->pkeyInit_channel && (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)) { LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
0);
if (!session->pkeyInit_channel
&& (libssh2_session_last_errno(session) ==
LIBSSH2_ERROR_EAGAIN)) {
/* The error state is already set, so leave it */ /* The error state is already set, so leave it */
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block to startup channel", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block to startup channel", 0);
return NULL; return NULL;
} } else if (!session->pkeyInit_channel
else if (!session->pkeyInit_channel && (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) { && (libssh2_session_last_errno(session) !=
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Unable to startup channel", 0); LIBSSH2_ERROR_EAGAIN)) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Unable to startup channel", 0);
goto err_exit; goto err_exit;
} }
} while (!session->pkeyInit_channel); } while (!session->pkeyInit_channel);
@ -334,14 +398,17 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
} }
if (session->pkeyInit_state == libssh2_NB_state_sent) { if (session->pkeyInit_state == libssh2_NB_state_sent) {
rc = libssh2_channel_process_startup(session->pkeyInit_channel, "subsystem", sizeof("subsystem") - 1, rc = libssh2_channel_process_startup(session->pkeyInit_channel,
"subsystem",
sizeof("subsystem") - 1,
"publickey", strlen("publickey")); "publickey", strlen("publickey"));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting publickkey subsystem", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickkey subsystem", 0);
return NULL; return NULL;
} } else if (rc) {
else if (rc) { libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Unable to request publickey subsystem", 0); "Unable to request publickey subsystem", 0);
goto err_exit; goto err_exit;
} }
@ -349,15 +416,19 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
} }
if (session->pkeyInit_state == libssh2_NB_state_sent1) { if (session->pkeyInit_state == libssh2_NB_state_sent1) {
rc = libssh2_channel_handle_extended_data2(session->pkeyInit_channel, LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); rc = libssh2_channel_handle_extended_data2(session->pkeyInit_channel,
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting publickkey subsystem", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickkey subsystem", 0);
return NULL; return NULL;
} }
session->pkeyInit_pkey = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PUBLICKEY)); session->pkeyInit_pkey =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PUBLICKEY));
if (!session->pkeyInit_pkey) { if (!session->pkeyInit_pkey) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a new publickey structure", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a new publickey structure", 0);
goto err_exit; goto err_exit;
} }
memset(session->pkeyInit_pkey, 0, sizeof(LIBSSH2_PUBLICKEY)); memset(session->pkeyInit_pkey, 0, sizeof(LIBSSH2_PUBLICKEY));
@ -365,25 +436,32 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_pkey->version = 0; session->pkeyInit_pkey->version = 0;
s = buffer; s = buffer;
libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4); s += 4; libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4);
libssh2_htonu32(s, sizeof("version") - 1); s += 4; s += 4;
memcpy(s, "version", sizeof("version") - 1); s += sizeof("version") - 1; libssh2_htonu32(s, sizeof("version") - 1);
libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION); s += 4; s += 4;
memcpy(s, "version", sizeof("version") - 1);
s += sizeof("version") - 1;
libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION);
s += 4;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Sending publickey version packet advertising version %d support", _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
"Sending publickey version packet advertising version %d support",
(int) LIBSSH2_PUBLICKEY_VERSION); (int) LIBSSH2_PUBLICKEY_VERSION);
session->pkeyInit_state = libssh2_NB_state_sent2; session->pkeyInit_state = libssh2_NB_state_sent2;
} }
if (session->pkeyInit_state == libssh2_NB_state_sent2) { if (session->pkeyInit_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_write_ex(session->pkeyInit_channel, 0, (char*)buffer, (s - buffer)); rc = libssh2_channel_write_ex(session->pkeyInit_channel, 0,
(char *) buffer, (s - buffer));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending publickkey version packet", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending publickkey version packet", 0);
return NULL; return NULL;
} } else if ((s - buffer) != rc) {
else if ((s - buffer) != rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey version packet", 0); "Unable to send publickey version packet", 0);
goto err_exit; goto err_exit;
} }
@ -392,19 +470,28 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
if (session->pkeyInit_state == libssh2_NB_state_sent3) { if (session->pkeyInit_state == libssh2_NB_state_sent3) {
while (1) { while (1) {
rc = libssh2_publickey_packet_receive(session->pkeyInit_pkey, &session->pkeyInit_data, &session->pkeyInit_data_len); rc = libssh2_publickey_packet_receive(session->pkeyInit_pkey,
&session->pkeyInit_data,
&session->pkeyInit_data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response from publickey subsystem", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from publickey subsystem",
0);
return NULL; return NULL;
} } else if (rc) {
else if (rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from publickey subsystem", 0); "Timeout waiting for response from publickey subsystem",
0);
goto err_exit; goto err_exit;
} }
s = session->pkeyInit_data; s = session->pkeyInit_data;
if ((response = libssh2_publickey_response_id(&s, session->pkeyInit_data_len)) < 0) { if ((response =
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid publickey subsystem response code", 0); libssh2_publickey_response_id(&s,
session->pkeyInit_data_len)) <
0) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code", 0);
goto err_exit; goto err_exit;
} }
@ -415,30 +502,44 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
unsigned long status, descr_len, lang_len; unsigned long status, descr_len, lang_len;
unsigned char *descr, *lang; unsigned char *descr, *lang;
status = libssh2_ntohu32(s); s += 4; status = libssh2_ntohu32(s);
descr_len = libssh2_ntohu32(s); s += 4; s += 4;
descr = s; s += descr_len; descr_len = libssh2_ntohu32(s);
lang_len = libssh2_ntohu32(s); s += 4; s += 4;
lang = s; s += lang_len; descr = s;
s += descr_len;
lang_len = libssh2_ntohu32(s);
s += 4;
lang = s;
s += lang_len;
if (s > session->pkeyInit_data + session->pkeyInit_data_len) { if (s >
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Malformed publickey subsystem packet", 0); session->pkeyInit_data + session->pkeyInit_data_len) {
libssh2_error(session,
LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet",
0);
goto err_exit; goto err_exit;
} }
libssh2_publickey_status_error(NULL, session, status, descr, descr_len); libssh2_publickey_status_error(NULL, session, status,
descr, descr_len);
goto err_exit; goto err_exit;
} }
case LIBSSH2_PUBLICKEY_RESPONSE_VERSION: case LIBSSH2_PUBLICKEY_RESPONSE_VERSION:
/* What we want */ /* What we want */
session->pkeyInit_pkey->version = libssh2_ntohu32(s); session->pkeyInit_pkey->version = libssh2_ntohu32(s);
if (session->pkeyInit_pkey->version > LIBSSH2_PUBLICKEY_VERSION) { if (session->pkeyInit_pkey->version >
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Truncating remote publickey version from %lu", LIBSSH2_PUBLICKEY_VERSION) {
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
"Truncating remote publickey version from %lu",
session->pkeyInit_pkey->version); session->pkeyInit_pkey->version);
session->pkeyInit_pkey->version = LIBSSH2_PUBLICKEY_VERSION; session->pkeyInit_pkey->version =
LIBSSH2_PUBLICKEY_VERSION;
} }
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Enabling publickey subsystem version %lu", _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
"Enabling publickey subsystem version %lu",
session->pkeyInit_pkey->version); session->pkeyInit_pkey->version);
LIBSSH2_FREE(session, session->pkeyInit_data); LIBSSH2_FREE(session, session->pkeyInit_data);
session->pkeyInit_data = NULL; session->pkeyInit_data = NULL;
@ -448,7 +549,8 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
default: default:
/* Unknown/Unexpected */ /* Unknown/Unexpected */
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response, ignoring", 0); "Unexpected publickey subsystem response, ignoring",
0);
LIBSSH2_FREE(session, session->pkeyInit_data); LIBSSH2_FREE(session, session->pkeyInit_data);
session->pkeyInit_data = NULL; session->pkeyInit_data = NULL;
} }
@ -461,7 +563,8 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
if (session->pkeyInit_channel) { if (session->pkeyInit_channel) {
rc = libssh2_channel_close(session->pkeyInit_channel); rc = libssh2_channel_close(session->pkeyInit_channel);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block closing channel", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block closing channel", 0);
return NULL; return NULL;
} }
} }
@ -476,14 +579,17 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_state = libssh2_NB_state_idle; session->pkeyInit_state = libssh2_NB_state_idle;
return NULL; return NULL;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_add_ex /* {{{ libssh2_publickey_add_ex
* Add a new public key entry * Add a new public key entry
*/ */
LIBSSH2_API int LIBSSH2_API int
libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, unsigned long name_len, libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
const unsigned char *blob, unsigned long blob_len, char overwrite, unsigned long num_attrs, unsigned long name_len, const unsigned char *blob,
unsigned long blob_len, char overwrite,
unsigned long num_attrs,
const libssh2_publickey_attribute attrs[]) const libssh2_publickey_attribute attrs[])
{ {
LIBSSH2_CHANNEL *channel = pkey->channel; LIBSSH2_CHANNEL *channel = pkey->channel;
@ -497,13 +603,15 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, uns
if (pkey->add_state == libssh2_NB_state_idle) { if (pkey->add_state == libssh2_NB_state_idle) {
pkey->add_packet = NULL; pkey->add_packet = NULL;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Adding %s publickey", name); _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Adding %s publickey",
name);
if (pkey->version == 1) { if (pkey->version == 1) {
for(i = 0; i < num_attrs; i++) { for(i = 0; i < num_attrs; i++) {
/* Search for a comment attribute */ /* Search for a comment attribute */
if (attrs[i].name_len == (sizeof("comment") - 1) && if (attrs[i].name_len == (sizeof("comment") - 1) &&
strncmp(attrs[i].name, "comment", sizeof("comment") - 1) == 0) { strncmp(attrs[i].name, "comment",
sizeof("comment") - 1) == 0) {
comment = (unsigned char *) attrs[i].value; comment = (unsigned char *) attrs[i].value;
comment_len = attrs[i].value_len; comment_len = attrs[i].value_len;
break; break;
@ -520,55 +628,77 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, uns
pkey->add_packet = LIBSSH2_ALLOC(session, packet_len); pkey->add_packet = LIBSSH2_ALLOC(session, packet_len);
if (!pkey->add_packet) { if (!pkey->add_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for publickey \"add\" packet", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for publickey \"add\" packet",
0);
return -1; return -1;
} }
pkey->add_s = pkey->add_packet; pkey->add_s = pkey->add_packet;
libssh2_htonu32(pkey->add_s, packet_len - 4); pkey->add_s += 4; libssh2_htonu32(pkey->add_s, packet_len - 4);
libssh2_htonu32(pkey->add_s, sizeof("add") - 1); pkey->add_s += 4; pkey->add_s += 4;
memcpy(pkey->add_s, "add", sizeof("add") - 1); pkey->add_s += sizeof("add") - 1; libssh2_htonu32(pkey->add_s, sizeof("add") - 1);
pkey->add_s += 4;
memcpy(pkey->add_s, "add", sizeof("add") - 1);
pkey->add_s += sizeof("add") - 1;
if (pkey->version == 1) { if (pkey->version == 1) {
libssh2_htonu32(pkey->add_s, comment_len); pkey->add_s += 4; libssh2_htonu32(pkey->add_s, comment_len);
pkey->add_s += 4;
if (comment) { if (comment) {
memcpy(pkey->add_s, comment, comment_len); pkey->add_s += comment_len; memcpy(pkey->add_s, comment, comment_len);
pkey->add_s += comment_len;
} }
libssh2_htonu32(pkey->add_s, name_len); pkey->add_s += 4; libssh2_htonu32(pkey->add_s, name_len);
memcpy(pkey->add_s, name, name_len); pkey->add_s += name_len; pkey->add_s += 4;
libssh2_htonu32(pkey->add_s, blob_len); pkey->add_s += 4; memcpy(pkey->add_s, name, name_len);
memcpy(pkey->add_s, blob, blob_len); pkey->add_s += blob_len; pkey->add_s += name_len;
libssh2_htonu32(pkey->add_s, blob_len);
pkey->add_s += 4;
memcpy(pkey->add_s, blob, blob_len);
pkey->add_s += blob_len;
} else { } else {
/* Version == 2 */ /* Version == 2 */
libssh2_htonu32(pkey->add_s, name_len); pkey->add_s += 4; libssh2_htonu32(pkey->add_s, name_len);
memcpy(pkey->add_s, name, name_len); pkey->add_s += name_len; pkey->add_s += 4;
libssh2_htonu32(pkey->add_s, blob_len); pkey->add_s += 4; memcpy(pkey->add_s, name, name_len);
memcpy(pkey->add_s, blob, blob_len); pkey->add_s += blob_len; pkey->add_s += name_len;
libssh2_htonu32(pkey->add_s, blob_len);
pkey->add_s += 4;
memcpy(pkey->add_s, blob, blob_len);
pkey->add_s += blob_len;
*(pkey->add_s++) = overwrite ? 0x01 : 0; *(pkey->add_s++) = overwrite ? 0x01 : 0;
libssh2_htonu32(pkey->add_s, num_attrs); pkey->add_s += 4; libssh2_htonu32(pkey->add_s, num_attrs);
pkey->add_s += 4;
for(i = 0; i < num_attrs; i++) { for(i = 0; i < num_attrs; i++) {
libssh2_htonu32(pkey->add_s, attrs[i].name_len); pkey->add_s += 4; libssh2_htonu32(pkey->add_s, attrs[i].name_len);
memcpy(pkey->add_s, attrs[i].name, attrs[i].name_len); pkey->add_s += attrs[i].name_len; pkey->add_s += 4;
libssh2_htonu32(pkey->add_s, attrs[i].value_len); pkey->add_s += 4; memcpy(pkey->add_s, attrs[i].name, attrs[i].name_len);
memcpy(pkey->add_s, attrs[i].value, attrs[i].value_len); pkey->add_s += attrs[i].value_len; pkey->add_s += attrs[i].name_len;
libssh2_htonu32(pkey->add_s, attrs[i].value_len);
pkey->add_s += 4;
memcpy(pkey->add_s, attrs[i].value, attrs[i].value_len);
pkey->add_s += attrs[i].value_len;
*(pkey->add_s++) = attrs[i].mandatory ? 0x01 : 0; *(pkey->add_s++) = attrs[i].mandatory ? 0x01 : 0;
} }
} }
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Sending publickey \"add\" packet: type=%s blob_len=%ld num_attrs=%ld", _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
"Sending publickey \"add\" packet: type=%s blob_len=%ld num_attrs=%ld",
name, blob_len, num_attrs); name, blob_len, num_attrs);
pkey->add_state = libssh2_NB_state_created; pkey->add_state = libssh2_NB_state_created;
} }
if (pkey->add_state == libssh2_NB_state_created) { if (pkey->add_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, (char *)pkey->add_packet, (pkey->add_s - pkey->add_packet)); rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->add_packet,
(pkey->add_s - pkey->add_packet));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if ((pkey->add_s - pkey->add_packet) != rc) {
else if ((pkey->add_s - pkey->add_packet) != rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey add packet", 0); "Unable to send publickey add packet", 0);
LIBSSH2_FREE(session, pkey->add_packet); LIBSSH2_FREE(session, pkey->add_packet);
pkey->add_packet = NULL; pkey->add_packet = NULL;
return -1; return -1;
@ -588,13 +718,15 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, uns
return rc; return rc;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_remove_ex /* {{{ libssh2_publickey_remove_ex
* Remove an existing publickey so that authentication can no longer be performed using it * Remove an existing publickey so that authentication can no longer be performed using it
*/ */
LIBSSH2_API int LIBSSH2_API int
libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, unsigned long name_len, libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
const unsigned char *name, unsigned long name_len,
const unsigned char *blob, unsigned long blob_len) const unsigned char *blob, unsigned long blob_len)
{ {
LIBSSH2_CHANNEL *channel = pkey->channel; LIBSSH2_CHANNEL *channel = pkey->channel;
@ -608,31 +740,43 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len); pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len);
if (!pkey->remove_packet) { if (!pkey->remove_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for publickey \"remove\" packet", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for publickey \"remove\" packet",
0);
return -1; return -1;
} }
pkey->remove_s = pkey->remove_packet; pkey->remove_s = pkey->remove_packet;
libssh2_htonu32(pkey->remove_s, packet_len - 4); pkey->remove_s += 4; libssh2_htonu32(pkey->remove_s, packet_len - 4);
libssh2_htonu32(pkey->remove_s, sizeof("remove") - 1); pkey->remove_s += 4; pkey->remove_s += 4;
memcpy(pkey->remove_s, "remove", sizeof("remove") - 1); pkey->remove_s += sizeof("remove") - 1; libssh2_htonu32(pkey->remove_s, sizeof("remove") - 1);
libssh2_htonu32(pkey->remove_s, name_len); pkey->remove_s += 4; pkey->remove_s += 4;
memcpy(pkey->remove_s, name, name_len); pkey->remove_s += name_len; memcpy(pkey->remove_s, "remove", sizeof("remove") - 1);
libssh2_htonu32(pkey->remove_s, blob_len); pkey->remove_s += 4; pkey->remove_s += sizeof("remove") - 1;
memcpy(pkey->remove_s, blob, blob_len); pkey->remove_s += blob_len; libssh2_htonu32(pkey->remove_s, name_len);
pkey->remove_s += 4;
memcpy(pkey->remove_s, name, name_len);
pkey->remove_s += name_len;
libssh2_htonu32(pkey->remove_s, blob_len);
pkey->remove_s += 4;
memcpy(pkey->remove_s, blob, blob_len);
pkey->remove_s += blob_len;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Sending publickey \"remove\" packet: type=%s blob_len=%ld", name, blob_len); _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
"Sending publickey \"remove\" packet: type=%s blob_len=%ld",
name, blob_len);
pkey->remove_state = libssh2_NB_state_created; pkey->remove_state = libssh2_NB_state_created;
} }
if (pkey->remove_state == libssh2_NB_state_created) { if (pkey->remove_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, (char *)pkey->remove_packet, (pkey->remove_s - pkey->remove_packet)); rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->remove_packet,
(pkey->remove_s - pkey->remove_packet));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if ((pkey->remove_s - pkey->remove_packet) != rc) {
else if ((pkey->remove_s - pkey->remove_packet) != rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey remove packet", 0); "Unable to send publickey remove packet", 0);
LIBSSH2_FREE(session, pkey->remove_packet); LIBSSH2_FREE(session, pkey->remove_packet);
pkey->remove_packet = NULL; pkey->remove_packet = NULL;
pkey->remove_state = libssh2_NB_state_idle; pkey->remove_state = libssh2_NB_state_idle;
@ -653,13 +797,15 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
return rc; return rc;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_list_fetch /* {{{ libssh2_publickey_list_fetch
* Fetch a list of supported public key from a server * Fetch a list of supported public key from a server
*/ */
LIBSSH2_API int LIBSSH2_API int
libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, libssh2_publickey_list **pkey_list) libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
libssh2_publickey_list ** pkey_list)
{ {
LIBSSH2_CHANNEL *channel = pkey->channel; LIBSSH2_CHANNEL *channel = pkey->channel;
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
@ -673,22 +819,29 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
pkey->listFetch_data = NULL; pkey->listFetch_data = NULL;
pkey->listFetch_s = pkey->listFetch_buffer; pkey->listFetch_s = pkey->listFetch_buffer;
libssh2_htonu32(pkey->listFetch_s, buffer_len - 4); pkey->listFetch_s += 4; libssh2_htonu32(pkey->listFetch_s, buffer_len - 4);
libssh2_htonu32(pkey->listFetch_s, sizeof("list") - 1); pkey->listFetch_s += 4; pkey->listFetch_s += 4;
memcpy(pkey->listFetch_s, "list", sizeof("list") - 1); pkey->listFetch_s += sizeof("list") - 1; libssh2_htonu32(pkey->listFetch_s, sizeof("list") - 1);
pkey->listFetch_s += 4;
memcpy(pkey->listFetch_s, "list", sizeof("list") - 1);
pkey->listFetch_s += sizeof("list") - 1;
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Sending publickey \"list\" packet"); _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
"Sending publickey \"list\" packet");
pkey->listFetch_state = libssh2_NB_state_created; pkey->listFetch_state = libssh2_NB_state_created;
} }
if (pkey->listFetch_state == libssh2_NB_state_created) { if (pkey->listFetch_state == libssh2_NB_state_created) {
rc = libssh2_channel_write_ex(channel, 0, (char *)pkey->listFetch_buffer, (pkey->listFetch_s - pkey->listFetch_buffer)); rc = libssh2_channel_write_ex(channel, 0,
(char *) pkey->listFetch_buffer,
(pkey->listFetch_s -
pkey->listFetch_buffer));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey list packet", 0); "Unable to send publickey list packet", 0);
pkey->listFetch_state = libssh2_NB_state_idle; pkey->listFetch_state = libssh2_NB_state_idle;
return -1; return -1;
} }
@ -697,18 +850,23 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
} }
while (1) { while (1) {
rc = libssh2_publickey_packet_receive(pkey, &pkey->listFetch_data, &pkey->listFetch_data_len); rc = libssh2_publickey_packet_receive(pkey, &pkey->listFetch_data,
&pkey->listFetch_data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc) {
else if (rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from publickey subsystem", 0); "Timeout waiting for response from publickey subsystem",
0);
goto err_exit; goto err_exit;
} }
pkey->listFetch_s = pkey->listFetch_data; pkey->listFetch_s = pkey->listFetch_data;
if ((response = libssh2_publickey_response_id(&pkey->listFetch_s, pkey->listFetch_data_len)) < 0) { if ((response =
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid publickey subsystem response code", 0); libssh2_publickey_response_id(&pkey->listFetch_s,
pkey->listFetch_data_len)) < 0) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code", 0);
goto err_exit; goto err_exit;
} }
@ -719,14 +877,21 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
unsigned long status, descr_len, lang_len; unsigned long status, descr_len, lang_len;
unsigned char *descr, *lang; unsigned char *descr, *lang;
status = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; status = libssh2_ntohu32(pkey->listFetch_s);
descr_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; pkey->listFetch_s += 4;
descr = pkey->listFetch_s; pkey->listFetch_s += descr_len; descr_len = libssh2_ntohu32(pkey->listFetch_s);
lang_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; pkey->listFetch_s += 4;
lang = pkey->listFetch_s; pkey->listFetch_s += lang_len; descr = pkey->listFetch_s;
pkey->listFetch_s += descr_len;
lang_len = libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
lang = pkey->listFetch_s;
pkey->listFetch_s += lang_len;
if (pkey->listFetch_s > pkey->listFetch_data + pkey->listFetch_data_len) { if (pkey->listFetch_s >
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Malformed publickey subsystem packet", 0); pkey->listFetch_data + pkey->listFetch_data_len) {
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet", 0);
goto err_exit; goto err_exit;
} }
@ -739,7 +904,8 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
return 0; return 0;
} }
libssh2_publickey_status_error(pkey, session, status, descr, descr_len); libssh2_publickey_status_error(pkey, session, status, descr,
descr_len);
goto err_exit; goto err_exit;
} }
case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY: case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY:
@ -748,9 +914,14 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
libssh2_publickey_list *newlist; libssh2_publickey_list *newlist;
/* Grow the key list if necessary */ /* Grow the key list if necessary */
max_keys += 8; max_keys += 8;
newlist = LIBSSH2_REALLOC(session, list, (max_keys + 1) * sizeof(libssh2_publickey_list)); newlist =
LIBSSH2_REALLOC(session, list,
(max_keys +
1) * sizeof(libssh2_publickey_list));
if (!newlist) { if (!newlist) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for publickey list", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for publickey list",
0);
goto err_exit; goto err_exit;
} }
list = newlist; list = newlist;
@ -758,12 +929,17 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
if (pkey->version == 1) { if (pkey->version == 1) {
unsigned long comment_len; unsigned long comment_len;
comment_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; comment_len = libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
if (comment_len) { if (comment_len) {
list[keys].num_attrs = 1; list[keys].num_attrs = 1;
list[keys].attrs = LIBSSH2_ALLOC(session, sizeof(libssh2_publickey_attribute)); list[keys].attrs =
LIBSSH2_ALLOC(session,
sizeof(libssh2_publickey_attribute));
if (!list[keys].attrs) { if (!list[keys].attrs) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for publickey attributes", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for publickey attributes",
0);
goto err_exit; goto err_exit;
} }
list[keys].attrs[0].name = "comment"; list[keys].attrs[0].name = "comment";
@ -777,29 +953,45 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
list[keys].num_attrs = 0; list[keys].num_attrs = 0;
list[keys].attrs = NULL; list[keys].attrs = NULL;
} }
list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s);
list[keys].name = pkey->listFetch_s; pkey->listFetch_s += list[keys].name_len; pkey->listFetch_s += 4;
list[keys].blob_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; list[keys].name = pkey->listFetch_s;
list[keys].blob = pkey->listFetch_s; pkey->listFetch_s += list[keys].blob_len; pkey->listFetch_s += list[keys].name_len;
list[keys].blob_len = libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
list[keys].blob = pkey->listFetch_s;
pkey->listFetch_s += list[keys].blob_len;
} else { } else {
/* Version == 2 */ /* Version == 2 */
list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s);
list[keys].name = pkey->listFetch_s; pkey->listFetch_s += list[keys].name_len; pkey->listFetch_s += 4;
list[keys].blob_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; list[keys].name = pkey->listFetch_s;
list[keys].blob = pkey->listFetch_s; pkey->listFetch_s += list[keys].blob_len; pkey->listFetch_s += list[keys].name_len;
list[keys].num_attrs = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4; list[keys].blob_len = libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
list[keys].blob = pkey->listFetch_s;
pkey->listFetch_s += list[keys].blob_len;
list[keys].num_attrs = libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4;
if (list[keys].num_attrs) { if (list[keys].num_attrs) {
list[keys].attrs = LIBSSH2_ALLOC(session, list[keys].num_attrs * sizeof(libssh2_publickey_attribute)); list[keys].attrs =
LIBSSH2_ALLOC(session,
list[keys].num_attrs *
sizeof(libssh2_publickey_attribute));
if (!list[keys].attrs) { if (!list[keys].attrs) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for publickey attributes", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for publickey attributes",
0);
goto err_exit; goto err_exit;
} }
for(i = 0; i < list[keys].num_attrs; i++) { for(i = 0; i < list[keys].num_attrs; i++) {
list[keys].attrs[i].name_len = libssh2_ntohu32(pkey->listFetch_s); list[keys].attrs[i].name_len =
libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4; pkey->listFetch_s += 4;
list[keys].attrs[i].name = (char *) pkey->listFetch_s; list[keys].attrs[i].name = (char *) pkey->listFetch_s;
pkey->listFetch_s += list[keys].attrs[i].name_len; pkey->listFetch_s += list[keys].attrs[i].name_len;
list[keys].attrs[i].value_len = libssh2_ntohu32(pkey->listFetch_s); list[keys].attrs[i].value_len =
libssh2_ntohu32(pkey->listFetch_s);
pkey->listFetch_s += 4; pkey->listFetch_s += 4;
list[keys].attrs[i].value = (char *) pkey->listFetch_s; list[keys].attrs[i].value = (char *) pkey->listFetch_s;
pkey->listFetch_s += list[keys].attrs[i].value_len; pkey->listFetch_s += list[keys].attrs[i].value_len;
@ -817,7 +1009,9 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
break; break;
default: default:
/* Unknown/Unexpected */ /* Unknown/Unexpected */
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Unexpected publickey subsystem response, ignoring", 0); libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Unexpected publickey subsystem response, ignoring",
0);
LIBSSH2_FREE(session, pkey->listFetch_data); LIBSSH2_FREE(session, pkey->listFetch_data);
pkey->listFetch_data = NULL; pkey->listFetch_data = NULL;
} }
@ -835,12 +1029,15 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
pkey->listFetch_state = libssh2_NB_state_idle; pkey->listFetch_state = libssh2_NB_state_idle;
return -1; return -1;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_list_free /* {{{ libssh2_publickey_list_free
* Free a previously fetched list of public keys * Free a previously fetched list of public keys
*/ */
LIBSSH2_API void libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey, libssh2_publickey_list *pkey_list) LIBSSH2_API void
libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey,
libssh2_publickey_list * pkey_list)
{ {
LIBSSH2_SESSION *session = pkey->channel->session; LIBSSH2_SESSION *session = pkey->channel->session;
libssh2_publickey_list *p = pkey_list; libssh2_publickey_list *p = pkey_list;
@ -855,12 +1052,14 @@ LIBSSH2_API void libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey, libssh2_pu
LIBSSH2_FREE(session, pkey_list); LIBSSH2_FREE(session, pkey_list);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_publickey_shutdown /* {{{ libssh2_publickey_shutdown
* Shutdown the publickey subsystem * Shutdown the publickey subsystem
*/ */
LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey) LIBSSH2_API int
libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
{ {
LIBSSH2_SESSION *session = pkey->channel->session; LIBSSH2_SESSION *session = pkey->channel->session;
@ -891,4 +1090,5 @@ LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey)
LIBSSH2_FREE(session, pkey); LIBSSH2_FREE(session, pkey);
return 0; return 0;
} }
/* }}} */ /* }}} */

435
src/scp.c
Просмотреть файл

@ -46,7 +46,8 @@
* otherwise the blocking error code would erase the true * otherwise the blocking error code would erase the true
* cause of the error. * cause of the error.
*/ */
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb) LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
{ {
int path_len = strlen(path); int path_len = strlen(path);
int rc; int rc;
@ -63,21 +64,28 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
session->scpRecv_command_len++; session->scpRecv_command_len++;
} }
session->scpRecv_command = LIBSSH2_ALLOC(session, session->scpRecv_command_len); session->scpRecv_command =
LIBSSH2_ALLOC(session, session->scpRecv_command_len);
if (!session->scpRecv_command) { if (!session->scpRecv_command) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a command buffer for SCP session", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a command buffer for SCP session",
0);
return NULL; return NULL;
} }
if (sb) { if (sb) {
memcpy(session->scpRecv_command, "scp -pf ", sizeof("scp -pf ") - 1); memcpy(session->scpRecv_command, "scp -pf ",
memcpy(session->scpRecv_command + sizeof("scp -pf ") - 1, path, path_len); sizeof("scp -pf ") - 1);
memcpy(session->scpRecv_command + sizeof("scp -pf ") - 1, path,
path_len);
} else { } else {
memcpy(session->scpRecv_command, "scp -f ", sizeof("scp -f ") - 1); memcpy(session->scpRecv_command, "scp -f ", sizeof("scp -f ") - 1);
memcpy(session->scpRecv_command + sizeof("scp -f ") - 1, path, path_len); memcpy(session->scpRecv_command + sizeof("scp -f ") - 1, path,
path_len);
} }
session->scpRecv_command[session->scpRecv_command_len - 1] = '\0'; session->scpRecv_command[session->scpRecv_command_len - 1] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Opening channel for SCP receive"); _libssh2_debug(session, LIBSSH2_DBG_SCP,
"Opening channel for SCP receive");
session->scpRecv_state = libssh2_NB_state_created; session->scpRecv_state = libssh2_NB_state_created;
} }
@ -85,18 +93,23 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
if (session->scpRecv_state == libssh2_NB_state_created) { if (session->scpRecv_state == libssh2_NB_state_created) {
/* Allocate a channel */ /* Allocate a channel */
do { do {
session->scpRecv_channel = libssh2_channel_open_ex(session, "session", sizeof("session") - 1, session->scpRecv_channel =
LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, libssh2_channel_open_ex(session, "session",
NULL, 0); sizeof("session") - 1,
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
0);
if (!session->scpRecv_channel) { if (!session->scpRecv_channel) {
if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { if (libssh2_session_last_errno(session) !=
LIBSSH2_ERROR_EAGAIN) {
LIBSSH2_FREE(session, session->scpRecv_command); LIBSSH2_FREE(session, session->scpRecv_command);
session->scpRecv_command = NULL; session->scpRecv_command = NULL;
session->scpRecv_state = libssh2_NB_state_idle; session->scpRecv_state = libssh2_NB_state_idle;
return NULL; return NULL;
} } else if (libssh2_session_last_errno(session) ==
else if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting up channel", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting up channel", 0);
return NULL; return NULL;
} }
} }
@ -107,12 +120,15 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
if (session->scpRecv_state == libssh2_NB_state_sent) { if (session->scpRecv_state == libssh2_NB_state_sent) {
/* Request SCP for the desired file */ /* Request SCP for the desired file */
rc = libssh2_channel_process_startup(session->scpRecv_channel, "exec", sizeof("exec") - 1, (char *)session->scpRecv_command, session->scpRecv_command_len); rc = libssh2_channel_process_startup(session->scpRecv_channel, "exec",
sizeof("exec") - 1,
(char *) session->scpRecv_command,
session->scpRecv_command_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting SCP startup", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting SCP startup", 0);
return NULL; return NULL;
} } else if (rc) {
else if (rc) {
LIBSSH2_FREE(session, session->scpRecv_command); LIBSSH2_FREE(session, session->scpRecv_command);
session->scpRecv_command = NULL; session->scpRecv_command = NULL;
goto scp_recv_error; goto scp_recv_error;
@ -128,12 +144,13 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
} }
if (session->scpRecv_state == libssh2_NB_state_sent1) { if (session->scpRecv_state == libssh2_NB_state_sent1) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0, (char *)session->scpRecv_response, 1); rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
(char *) session->scpRecv_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending initial wakeup", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending initial wakeup", 0);
return NULL; return NULL;
} } else if (rc != 1) {
else if (rc != 1) {
goto scp_recv_error; goto scp_recv_error;
} }
@ -143,20 +160,26 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
session->scpRecv_state = libssh2_NB_state_sent2; session->scpRecv_state = libssh2_NB_state_sent2;
} }
if ((session->scpRecv_state == libssh2_NB_state_sent2) || (session->scpRecv_state == libssh2_NB_state_sent3)) { if ((session->scpRecv_state == libssh2_NB_state_sent2)
while (sb && (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN)) { || (session->scpRecv_state == libssh2_NB_state_sent3)) {
while (sb
&& (session->scpRecv_response_len <
LIBSSH2_SCP_RESPONSE_BUFLEN)) {
unsigned char *s, *p; unsigned char *s, *p;
if (session->scpRecv_state == libssh2_NB_state_sent2) { if (session->scpRecv_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0, rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
(char *)session->scpRecv_response + session->scpRecv_response_len, 1); (char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for SCP response", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response", 0);
return NULL; return NULL;
} } else if (rc <= 0) {
else if (rc <= 0) {
/* Timeout, give up */ /* Timeout, give up */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Timed out waiting for SCP response", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Timed out waiting for SCP response", 0);
goto scp_recv_error; goto scp_recv_error;
} }
session->scpRecv_response_len++; session->scpRecv_response_len++;
@ -166,17 +189,25 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
* Set this as the default error for here, if * Set this as the default error for here, if
* we are successful it will be replaced * we are successful it will be replaced
*/ */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid data in SCP response, missing Time data", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid data in SCP response, missing Time data",
0);
session->scpRecv_err_len = libssh2_channel_packet_data_len(session->scpRecv_channel, 0); session->scpRecv_err_len =
session->scpRecv_err_msg = LIBSSH2_ALLOC(session, session->scpRecv_err_len+1); libssh2_channel_packet_data_len(session->
scpRecv_channel, 0);
session->scpRecv_err_msg =
LIBSSH2_ALLOC(session, session->scpRecv_err_len + 1);
if (!session->scpRecv_err_msg) { if (!session->scpRecv_err_msg) {
goto scp_recv_error; goto scp_recv_error;
} }
memset(session->scpRecv_err_msg, 0, session->scpRecv_err_len+1); memset(session->scpRecv_err_msg, 0,
session->scpRecv_err_len + 1);
/* Read the remote error message */ /* Read the remote error message */
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0, session->scpRecv_err_msg, session->scpRecv_err_len); rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
session->scpRecv_err_msg,
session->scpRecv_err_len);
if (rc <= 0) { if (rc <= 0) {
/* /*
* Since we have alread started reading this packet, it is * Since we have alread started reading this packet, it is
@ -184,29 +215,49 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
*/ */
LIBSSH2_FREE(session, session->scpRecv_err_msg); LIBSSH2_FREE(session, session->scpRecv_err_msg);
session->scpRecv_err_msg = NULL; session->scpRecv_err_msg = NULL;
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unknown error while getting error string", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unknown error while getting error string",
0);
goto scp_recv_error; goto scp_recv_error;
} }
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, session->scpRecv_err_msg, 1); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
session->scpRecv_err_msg, 1);
session->scpRecv_err_msg = NULL; session->scpRecv_err_msg = NULL;
goto scp_recv_error; goto scp_recv_error;
} }
if ((session->scpRecv_response_len > 1) && if ((session->scpRecv_response_len > 1) &&
((session->scpRecv_response[session->scpRecv_response_len-1] < '0') || ((session->
(session->scpRecv_response[session->scpRecv_response_len-1] > '9')) && scpRecv_response[session->scpRecv_response_len - 1] <
(session->scpRecv_response[session->scpRecv_response_len-1] != ' ') && '0')
(session->scpRecv_response[session->scpRecv_response_len-1] != '\r') && || (session->
(session->scpRecv_response[session->scpRecv_response_len-1] != '\n')) { scpRecv_response[session->scpRecv_response_len - 1] >
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid data in SCP response", 0); '9'))
&& (session->
scpRecv_response[session->scpRecv_response_len - 1] !=
' ')
&& (session->
scpRecv_response[session->scpRecv_response_len - 1] !=
'\r')
&& (session->
scpRecv_response[session->scpRecv_response_len - 1] !=
'\n')) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid data in SCP response", 0);
goto scp_recv_error; goto scp_recv_error;
} }
if ((session->scpRecv_response_len < 9) || (session->scpRecv_response[session->scpRecv_response_len-1] != '\n')) { if ((session->scpRecv_response_len < 9)
if (session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) { || (session->
scpRecv_response[session->scpRecv_response_len - 1] !=
'\n')) {
if (session->scpRecv_response_len ==
LIBSSH2_SCP_RESPONSE_BUFLEN) {
/* You had your chance */ /* You had your chance */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unterminated response from SCP server", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unterminated response from SCP server",
0);
goto scp_recv_error; goto scp_recv_error;
} }
/* Way too short to be an SCP response, or not done yet, short circuit */ /* Way too short to be an SCP response, or not done yet, short circuit */
@ -214,12 +265,21 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
} }
/* We're guaranteed not to go under response_len == 0 by the logic above */ /* We're guaranteed not to go under response_len == 0 by the logic above */
while ((session->scpRecv_response[session->scpRecv_response_len-1] == '\r') || (session->scpRecv_response[session->scpRecv_response_len-1] == '\n')) session->scpRecv_response_len--; while ((session->
session->scpRecv_response[session->scpRecv_response_len] = '\0'; scpRecv_response[session->scpRecv_response_len - 1] ==
'\r')
|| (session->
scpRecv_response[session->scpRecv_response_len -
1] == '\n'))
session->scpRecv_response_len--;
session->scpRecv_response[session->scpRecv_response_len] =
'\0';
if (session->scpRecv_response_len < 8) { if (session->scpRecv_response_len < 8) {
/* EOL came too soon */ /* EOL came too soon */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, too short", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, too short",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -228,7 +288,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
p = (unsigned char *) strchr((char *) s, ' '); p = (unsigned char *) strchr((char *) s, ' ');
if (!p || ((p - s) <= 0)) { if (!p || ((p - s) <= 0)) {
/* No spaces or space in the wrong spot */ /* No spaces or space in the wrong spot */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, malformed mtime", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, malformed mtime",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -237,13 +299,17 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
errno = 0; errno = 0;
session->scpRecv_mtime = strtol((char *) s, NULL, 10); session->scpRecv_mtime = strtol((char *) s, NULL, 10);
if (errno) { if (errno) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, invalid mtime", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid mtime",
0);
goto scp_recv_error; goto scp_recv_error;
} }
s = (unsigned char *) strchr((char *) p, ' '); s = (unsigned char *) strchr((char *) p, ' ');
if (!s || ((s - p) <= 0)) { if (!s || ((s - p) <= 0)) {
/* No spaces or space in the wrong spot */ /* No spaces or space in the wrong spot */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, malformed mtime.usec", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, malformed mtime.usec",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -252,7 +318,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
p = (unsigned char *) strchr((char *) s, ' '); p = (unsigned char *) strchr((char *) s, ' ');
if (!p || ((p - s) <= 0)) { if (!p || ((p - s) <= 0)) {
/* No spaces or space in the wrong spot */ /* No spaces or space in the wrong spot */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, too short or malformed", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, too short or malformed",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -261,7 +329,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
errno = 0; errno = 0;
session->scpRecv_atime = strtol((char *) s, NULL, 10); session->scpRecv_atime = strtol((char *) s, NULL, 10);
if (errno) { if (errno) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, invalid atime", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid atime",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -272,16 +342,20 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
} }
if (session->scpRecv_state == libssh2_NB_state_sent3) { if (session->scpRecv_state == libssh2_NB_state_sent3) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0, (char *)session->scpRecv_response, 1); rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting to send SCP ACK", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting to send SCP ACK", 0);
return NULL; return NULL;
} } else if (rc != 1) {
else if (rc != 1) {
goto scp_recv_error; goto scp_recv_error;
} }
_libssh2_debug(session, LIBSSH2_DBG_SCP, "mtime = %ld, atime = %ld", session->scpRecv_mtime, session->scpRecv_atime); _libssh2_debug(session, LIBSSH2_DBG_SCP,
"mtime = %ld, atime = %ld",
session->scpRecv_mtime, session->scpRecv_atime);
/* We *should* check that atime.usec is valid, but why let that stop use? */ /* We *should* check that atime.usec is valid, but why let that stop use? */
break; break;
@ -297,42 +371,62 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
session->scpRecv_state = libssh2_NB_state_sent5; session->scpRecv_state = libssh2_NB_state_sent5;
} }
if ((session->scpRecv_state == libssh2_NB_state_sent5) || (session->scpRecv_state == libssh2_NB_state_sent6)) { if ((session->scpRecv_state == libssh2_NB_state_sent5)
|| (session->scpRecv_state == libssh2_NB_state_sent6)) {
while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) { while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) {
char *s, *p, *e = NULL; char *s, *p, *e = NULL;
if (session->scpRecv_state == libssh2_NB_state_sent5) { if (session->scpRecv_state == libssh2_NB_state_sent5) {
rc = libssh2_channel_read_ex(session->scpRecv_channel, 0, rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
(char *)session->scpRecv_response + session->scpRecv_response_len, 1); (char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for SCP response", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response", 0);
return NULL; return NULL;
} } else if (rc <= 0) {
else if (rc <= 0) {
/* Timeout, give up */ /* Timeout, give up */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Timed out waiting for SCP response", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Timed out waiting for SCP response", 0);
goto scp_recv_error; goto scp_recv_error;
} }
session->scpRecv_response_len++; session->scpRecv_response_len++;
if (session->scpRecv_response[0] != 'C') { if (session->scpRecv_response[0] != 'C') {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server", 0);
goto scp_recv_error; goto scp_recv_error;
} }
if ((session->scpRecv_response_len > 1) && if ((session->scpRecv_response_len > 1) &&
(session->scpRecv_response[session->scpRecv_response_len-1] != '\r') && (session->
(session->scpRecv_response[session->scpRecv_response_len-1] != '\n') && scpRecv_response[session->scpRecv_response_len - 1] !=
((session->scpRecv_response[session->scpRecv_response_len-1] < 32) || '\r')
(session->scpRecv_response[session->scpRecv_response_len-1] > 126))) { && (session->
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid data in SCP response", 0); scpRecv_response[session->scpRecv_response_len - 1] !=
'\n')
&&
((session->
scpRecv_response[session->scpRecv_response_len - 1] < 32)
|| (session->
scpRecv_response[session->scpRecv_response_len - 1] >
126))) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid data in SCP response", 0);
goto scp_recv_error; goto scp_recv_error;
} }
if ((session->scpRecv_response_len < 7) || (session->scpRecv_response[session->scpRecv_response_len-1] != '\n')) { if ((session->scpRecv_response_len < 7)
if (session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) { || (session->
scpRecv_response[session->scpRecv_response_len - 1] !=
'\n')) {
if (session->scpRecv_response_len ==
LIBSSH2_SCP_RESPONSE_BUFLEN) {
/* You had your chance */ /* You had your chance */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unterminated response from SCP server", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unterminated response from SCP server",
0);
goto scp_recv_error; goto scp_recv_error;
} }
/* Way too short to be an SCP response, or not done yet, short circuit */ /* Way too short to be an SCP response, or not done yet, short circuit */
@ -340,15 +434,22 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
} }
/* We're guaranteed not to go under response_len == 0 by the logic above */ /* We're guaranteed not to go under response_len == 0 by the logic above */
while ((session->scpRecv_response[session->scpRecv_response_len-1] == '\r') || while ((session->
(session->scpRecv_response[session->scpRecv_response_len-1] == '\n')) { scpRecv_response[session->scpRecv_response_len - 1] ==
'\r')
|| (session->
scpRecv_response[session->scpRecv_response_len -
1] == '\n')) {
session->scpRecv_response_len--; session->scpRecv_response_len--;
} }
session->scpRecv_response[session->scpRecv_response_len] = '\0'; session->scpRecv_response[session->scpRecv_response_len] =
'\0';
if (session->scpRecv_response_len < 6) { if (session->scpRecv_response_len < 6) {
/* EOL came too soon */ /* EOL came too soon */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, too short", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, too short",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -357,7 +458,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
p = strchr(s, ' '); p = strchr(s, ' ');
if (!p || ((p - s) <= 0)) { if (!p || ((p - s) <= 0)) {
/* No spaces or space in the wrong spot */ /* No spaces or space in the wrong spot */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, malformed mode", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, malformed mode",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -366,14 +469,17 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
errno = 0; errno = 0;
session->scpRecv_mode = strtol(s, &e, 8); session->scpRecv_mode = strtol(s, &e, 8);
if ((e && *e) || errno) { if ((e && *e) || errno) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, invalid mode", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid mode",
0);
goto scp_recv_error; goto scp_recv_error;
} }
s = strchr(p, ' '); s = strchr(p, ' ');
if (!s || ((s - p) <= 0)) { if (!s || ((s - p) <= 0)) {
/* No spaces or space in the wrong spot */ /* No spaces or space in the wrong spot */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, too short or malformed", libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, too short or malformed",
0); 0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -383,7 +489,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
errno = 0; errno = 0;
session->scpRecv_size = strtol(p, &e, 10); session->scpRecv_size = strtol(p, &e, 10);
if ((e && *e) || errno) { if ((e && *e) || errno) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, invalid size", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid size",
0);
goto scp_recv_error; goto scp_recv_error;
} }
@ -394,15 +502,19 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
} }
if (session->scpRecv_state == libssh2_NB_state_sent6) { if (session->scpRecv_state == libssh2_NB_state_sent6) {
rc = libssh2_channel_write_ex(session->scpRecv_channel, 0, (char *)session->scpRecv_response, 1); rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending SCP ACK", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending SCP ACK", 0);
return NULL; return NULL;
} } else if (rc != 1) {
else if (rc != 1) {
goto scp_recv_error; goto scp_recv_error;
} }
_libssh2_debug(session, LIBSSH2_DBG_SCP, "mode = 0%lo size = %ld", session->scpRecv_mode, session->scpRecv_size); _libssh2_debug(session, LIBSSH2_DBG_SCP,
"mode = 0%lo size = %ld", session->scpRecv_mode,
session->scpRecv_size);
/* We *should* check that basename is valid, but why let that stop us? */ /* We *should* check that basename is valid, but why let that stop us? */
break; break;
@ -430,6 +542,7 @@ scp_recv_error:
session->scpRecv_state = libssh2_NB_state_idle; session->scpRecv_state = libssh2_NB_state_idle;
return NULL; return NULL;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_scp_send_ex /* {{{ libssh2_scp_send_ex
@ -440,7 +553,8 @@ scp_recv_error:
* cause of the error. * cause of the error.
*/ */
LIBSSH2_API LIBSSH2_CHANNEL * LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime) libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
size_t size, long mtime, long atime)
{ {
int path_len = strlen(path); int path_len = strlen(path);
unsigned const char *base; unsigned const char *base;
@ -453,30 +567,39 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
session->scpSend_command_len++; session->scpSend_command_len++;
} }
session->scpSend_command = LIBSSH2_ALLOC(session, session->scpSend_command_len); session->scpSend_command =
LIBSSH2_ALLOC(session, session->scpSend_command_len);
if (!session->scpSend_command) { if (!session->scpSend_command) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a command buffer for scp session", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a command buffer for scp session",
0);
return NULL; return NULL;
} }
if (mtime || atime) { if (mtime || atime) {
memcpy(session->scpSend_command, "scp -pt ", sizeof("scp -pt ") - 1); memcpy(session->scpSend_command, "scp -pt ",
memcpy(session->scpSend_command + sizeof("scp -pt ") - 1, path, path_len); sizeof("scp -pt ") - 1);
memcpy(session->scpSend_command + sizeof("scp -pt ") - 1, path,
path_len);
} else { } else {
memcpy(session->scpSend_command, "scp -t ", sizeof("scp -t ") - 1); memcpy(session->scpSend_command, "scp -t ", sizeof("scp -t ") - 1);
memcpy(session->scpSend_command + sizeof("scp -t ") - 1, path, path_len); memcpy(session->scpSend_command + sizeof("scp -t ") - 1, path,
path_len);
} }
session->scpSend_command[session->scpSend_command_len - 1] = '\0'; session->scpSend_command[session->scpSend_command_len - 1] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Opening channel for SCP send"); _libssh2_debug(session, LIBSSH2_DBG_SCP,
"Opening channel for SCP send");
/* Allocate a channel */ /* Allocate a channel */
session->scpSend_state = libssh2_NB_state_created; session->scpSend_state = libssh2_NB_state_created;
} }
if (session->scpSend_state == libssh2_NB_state_created) { if (session->scpSend_state == libssh2_NB_state_created) {
session->scpSend_channel = libssh2_channel_open_ex(session, "session", sizeof("session") - 1, session->scpSend_channel =
LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
if (!session->scpSend_channel) { if (!session->scpSend_channel) {
if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
/* previous call set libssh2_session_last_error(), pass it through */ /* previous call set libssh2_session_last_error(), pass it through */
@ -484,9 +607,10 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
session->scpSend_command = NULL; session->scpSend_command = NULL;
session->scpSend_state = libssh2_NB_state_idle; session->scpSend_state = libssh2_NB_state_idle;
return NULL; return NULL;
} } else if (libssh2_session_last_errno(session) ==
else if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting up channel", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting up channel", 0);
return NULL; return NULL;
} }
} }
@ -496,17 +620,20 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
if (session->scpSend_state == libssh2_NB_state_sent) { if (session->scpSend_state == libssh2_NB_state_sent) {
/* Request SCP for the desired file */ /* Request SCP for the desired file */
rc = libssh2_channel_process_startup(session->scpSend_channel, "exec", sizeof("exec") - 1, rc = libssh2_channel_process_startup(session->scpSend_channel, "exec",
(char *)session->scpSend_command, session->scpSend_command_len); sizeof("exec") - 1,
(char *) session->scpSend_command,
session->scpSend_command_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting SCP startup", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting SCP startup", 0);
return NULL; return NULL;
} } else if (rc) {
else if (rc) {
/* previous call set libssh2_session_last_error(), pass it through */ /* previous call set libssh2_session_last_error(), pass it through */
LIBSSH2_FREE(session, session->scpSend_command); LIBSSH2_FREE(session, session->scpSend_command);
session->scpSend_command = NULL; session->scpSend_command = NULL;
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Unknown error while getting error string", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unknown error while getting error string", 0);
goto scp_send_error; goto scp_send_error;
} }
LIBSSH2_FREE(session, session->scpSend_command); LIBSSH2_FREE(session, session->scpSend_command);
@ -517,21 +644,26 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
if (session->scpSend_state == libssh2_NB_state_sent1) { if (session->scpSend_state == libssh2_NB_state_sent1) {
/* Wait for ACK */ /* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, (char *)session->scpSend_response, 1); rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response from remote", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from remote", 0);
return NULL; return NULL;
} } else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
else if ((rc <= 0) || (session->scpSend_response[0] != 0)) { libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0); "Invalid ACK response from remote", 0);
goto scp_send_error; goto scp_send_error;
} }
if (mtime || atime) { if (mtime || atime) {
/* Send mtime and atime to be used for file */ /* Send mtime and atime to be used for file */
session->scpSend_response_len = snprintf((char *)session->scpSend_response, LIBSSH2_SCP_RESPONSE_BUFLEN, session->scpSend_response_len =
"T%ld 0 %ld 0\n", mtime, atime); snprintf((char *) session->scpSend_response,
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s", session->scpSend_response); LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime,
atime);
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
session->scpSend_response);
} }
session->scpSend_state = libssh2_NB_state_sent2; session->scpSend_state = libssh2_NB_state_sent2;
@ -540,14 +672,16 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
/* Send mtime and atime to be used for file */ /* Send mtime and atime to be used for file */
if (mtime || atime) { if (mtime || atime) {
if (session->scpSend_state == libssh2_NB_state_sent2) { if (session->scpSend_state == libssh2_NB_state_sent2) {
rc = libssh2_channel_write_ex(session->scpSend_channel, 0, (char *)session->scpSend_response, rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len); session->scpSend_response_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending time data for SCP file", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending time data for SCP file", 0);
return NULL; return NULL;
} } else if (rc != session->scpSend_response_len) {
else if (rc != session->scpSend_response_len) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send time data for SCP file", 0); "Unable to send time data for SCP file", 0);
goto scp_send_error; goto scp_send_error;
} }
@ -556,13 +690,16 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
if (session->scpSend_state == libssh2_NB_state_sent3) { if (session->scpSend_state == libssh2_NB_state_sent3) {
/* Wait for ACK */ /* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, (char *)session->scpSend_response, 1); rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response,
1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response", 0);
return NULL; return NULL;
} } else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
else if ((rc <= 0) || (session->scpSend_response[0] != 0)) { libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0); "Invalid ACK response from remote", 0);
goto scp_send_error; goto scp_send_error;
} }
@ -583,22 +720,27 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
base = (unsigned char *) path; base = (unsigned char *) path;
} }
session->scpSend_response_len = snprintf((char *)session->scpSend_response, LIBSSH2_SCP_RESPONSE_BUFLEN, session->scpSend_response_len =
"C0%o %lu %s\n", mode, (unsigned long)size, base); snprintf((char *) session->scpSend_response,
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s", session->scpSend_response); LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode,
(unsigned long) size, base);
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
session->scpSend_response);
session->scpSend_state = libssh2_NB_state_sent5; session->scpSend_state = libssh2_NB_state_sent5;
} }
if (session->scpSend_state == libssh2_NB_state_sent5) { if (session->scpSend_state == libssh2_NB_state_sent5) {
rc = libssh2_channel_write_ex(session->scpSend_channel, 0, (char *)session->scpSend_response, rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response,
session->scpSend_response_len); session->scpSend_response_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block send core file data for SCP file", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block send core file data for SCP file", 0);
return NULL; return NULL;
} } else if (rc != session->scpSend_response_len) {
else if (rc != session->scpSend_response_len) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send core file data for SCP file", 0); "Unable to send core file data for SCP file", 0);
goto scp_send_error; goto scp_send_error;
} }
@ -607,31 +749,37 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
if (session->scpSend_state == libssh2_NB_state_sent6) { if (session->scpSend_state == libssh2_NB_state_sent6) {
/* Wait for ACK */ /* Wait for ACK */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, (char *)session->scpSend_response, 1); rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response", 0);
return NULL; return NULL;
} } else if (rc <= 0) {
else if (rc <= 0) { libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0); "Invalid ACK response from remote", 0);
goto scp_send_error; goto scp_send_error;
} } else if (session->scpSend_response[0] != 0) {
else if (session->scpSend_response[0] != 0) {
/* /*
* Set this as the default error for here, if * Set this as the default error for here, if
* we are successful it will be replaced * we are successful it will be replaced
*/ */
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote", 0);
session->scpSend_err_len = libssh2_channel_packet_data_len(session->scpSend_channel, 0); session->scpSend_err_len =
session->scpSend_err_msg = LIBSSH2_ALLOC(session, session->scpSend_err_len+1); libssh2_channel_packet_data_len(session->scpSend_channel, 0);
session->scpSend_err_msg =
LIBSSH2_ALLOC(session, session->scpSend_err_len + 1);
if (!session->scpSend_err_msg) { if (!session->scpSend_err_msg) {
goto scp_send_error; goto scp_send_error;
} }
memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1); memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
/* Read the remote error message */ /* Read the remote error message */
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, session->scpSend_err_msg, session->scpSend_err_len); rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
session->scpSend_err_msg,
session->scpSend_err_len);
if (rc <= 0) { if (rc <= 0) {
/* /*
* Since we have alread started reading this packet, it is * Since we have alread started reading this packet, it is
@ -642,7 +790,8 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
goto scp_send_error; goto scp_send_error;
} }
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, session->scpSend_err_msg, 1); libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
session->scpSend_err_msg, 1);
session->scpSend_err_msg = NULL; session->scpSend_err_msg = NULL;
goto scp_send_error; goto scp_send_error;
} }
@ -658,5 +807,5 @@ scp_send_error:
session->scpSend_state = libssh2_NB_state_idle; session->scpSend_state = libssh2_NB_state_idle;
return NULL; return NULL;
} }
/* }}} */
/* }}} */

Просмотреть файл

@ -52,29 +52,35 @@
/* {{{ libssh2_default_alloc /* {{{ libssh2_default_alloc
*/ */
static LIBSSH2_ALLOC_FUNC(libssh2_default_alloc) static
LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
{ {
(void) abstract; (void) abstract;
return malloc(count); return malloc(count);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_default_free /* {{{ libssh2_default_free
*/ */
static LIBSSH2_FREE_FUNC(libssh2_default_free) static
LIBSSH2_FREE_FUNC(libssh2_default_free)
{ {
(void) abstract; (void) abstract;
free(ptr); free(ptr);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_default_realloc /* {{{ libssh2_default_realloc
*/ */
static LIBSSH2_REALLOC_FUNC(libssh2_default_realloc) static
LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
{ {
(void) abstract; (void) abstract;
return realloc(ptr, count); return realloc(ptr, count);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_banner_receive /* {{{ libssh2_banner_receive
@ -82,7 +88,8 @@ static LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
* Allocate a buffer and store the banner in session->remote.banner * Allocate a buffer and store the banner in session->remote.banner
* Returns: 0 on success, PACKET_EAGAIN if read would block, 1 on failure * Returns: 0 on success, PACKET_EAGAIN if read would block, 1 on failure
*/ */
static int libssh2_banner_receive(LIBSSH2_SESSION *session) static int
libssh2_banner_receive(LIBSSH2_SESSION * session)
{ {
int ret; int ret;
int banner_len; int banner_len;
@ -96,10 +103,13 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
} }
while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) && while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) &&
((banner_len == 0) || (session->banner_TxRx_banner[banner_len-1] != '\n'))) { ((banner_len == 0)
|| (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
char c = '\0'; char c = '\0';
ret = recv(session->socket_fd, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); ret =
recv(session->socket_fd, &c, 1,
LIBSSH2_SOCKET_RECV_FLAGS(session));
if (ret < 0) { if (ret < 0) {
#ifdef WIN32 #ifdef WIN32
@ -133,7 +143,8 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
} }
} }
if (ret <= 0) continue; if (ret <= 0)
continue;
if (c == '\0') { if (c == '\0') {
/* NULLs are not allowed in SSH banners */ /* NULLs are not allowed in SSH banners */
@ -155,18 +166,22 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_state = libssh2_NB_state_idle;
session->banner_TxRx_total_send = 0; session->banner_TxRx_total_send = 0;
if (!banner_len) return 1; if (!banner_len)
return 1;
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1); session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
if (!session->remote.banner) { if (!session->remote.banner) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocating space for remote banner", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Error allocating space for remote banner", 0);
return 1; return 1;
} }
memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len); memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
session->remote.banner[banner_len] = '\0'; session->remote.banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Received Banner: %s", session->remote.banner); _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Received Banner: %s",
session->remote.banner);
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_banner_send /* {{{ libssh2_banner_send
@ -177,7 +192,8 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
* sent, and this function should then be called with the same argument set * sent, and this function should then be called with the same argument set
* (same data pointer and same data_len) until zero or failure is returned. * (same data pointer and same data_len) until zero or failure is returned.
*/ */
static int libssh2_banner_send(LIBSSH2_SESSION *session) static int
libssh2_banner_send(LIBSSH2_SESSION * session)
{ {
char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF; char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF;
int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1; int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1;
@ -192,7 +208,6 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
banner_len = strlen((char *) session->local.banner); banner_len = strlen((char *) session->local.banner);
banner = (char *) session->local.banner; banner = (char *) session->local.banner;
} }
#ifdef LIBSSH2DEBUG #ifdef LIBSSH2DEBUG
/* Hack and slash to avoid sending CRLF in debug output */ /* Hack and slash to avoid sending CRLF in debug output */
if (banner_len < 256) { if (banner_len < 256) {
@ -203,13 +218,16 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
banner[255] = '\0'; banner[255] = '\0';
} }
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending Banner: %s", banner_dup); _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending Banner: %s",
banner_dup);
#endif #endif
session->banner_TxRx_state = libssh2_NB_state_created; session->banner_TxRx_state = libssh2_NB_state_created;
} }
ret = send(session->socket_fd, banner+session->banner_TxRx_total_send, banner_len-session->banner_TxRx_total_send, ret =
send(session->socket_fd, banner + session->banner_TxRx_total_send,
banner_len - session->banner_TxRx_total_send,
LIBSSH2_SOCKET_SEND_FLAGS(session)); LIBSSH2_SOCKET_SEND_FLAGS(session));
if (ret != (banner_len - session->banner_TxRx_total_send)) { if (ret != (banner_len - session->banner_TxRx_total_send)) {
@ -229,6 +247,7 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
return 0; return 0;
} }
/* }}} */ /* }}} */
/* /*
@ -236,7 +255,8 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
* non-blocking mode based on the 'nonblock' boolean argument. This function * non-blocking mode based on the 'nonblock' boolean argument. This function
* is copied from the libcurl sources with permission. * is copied from the libcurl sources with permission.
*/ */
static int _libssh2_nonblock(int sockfd, /* operate on this */ static int
_libssh2_nonblock(int sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */ ) int nonblock /* TRUE or FALSE */ )
{ {
#undef SETBLOCK #undef SETBLOCK
@ -304,8 +324,9 @@ static int _libssh2_nonblock(int sockfd, /* operate on this */
* _libssh2_get_socket_nonblocking() gets the given blocking or non-blocking * _libssh2_get_socket_nonblocking() gets the given blocking or non-blocking
* state of the socket. * state of the socket.
*/ */
static int _libssh2_get_socket_nonblocking(int sockfd) /* operate on this */ static int
{ _libssh2_get_socket_nonblocking(int sockfd)
{ /* operate on this */
#undef GETBLOCK #undef GETBLOCK
#define GETBLOCK 0 #define GETBLOCK 0
#ifdef HAVE_O_NONBLOCK #ifdef HAVE_O_NONBLOCK
@ -326,7 +347,8 @@ static int _libssh2_get_socket_nonblocking(int sockfd) /* operate on this */
unsigned int option_value; unsigned int option_value;
socklen_t option_len = sizeof(option_value); socklen_t option_len = sizeof(option_value);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&option_value, &option_len)) { if (getsockopt
(sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) {
/* Assume blocking on error */ /* Assume blocking on error */
return 1; return 1;
} }
@ -361,7 +383,8 @@ static int _libssh2_get_socket_nonblocking(int sockfd) /* operate on this */
/* {{{ libssh2_banner_set /* {{{ libssh2_banner_set
* Set the local banner * Set the local banner
*/ */
LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, const char *banner) LIBSSH2_API int
libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
{ {
int banner_len = banner ? strlen(banner) : 0; int banner_len = banner ? strlen(banner) : 0;
@ -376,19 +399,22 @@ LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, const char *banner)
session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3); session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
if (!session->local.banner) { if (!session->local.banner) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for local banner", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for local banner", 0);
return -1; return -1;
} }
memcpy(session->local.banner, banner, banner_len); memcpy(session->local.banner, banner, banner_len);
session->local.banner[banner_len] = '\0'; session->local.banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting local Banner: %s", session->local.banner); _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting local Banner: %s",
session->local.banner);
session->local.banner[banner_len++] = '\r'; session->local.banner[banner_len++] = '\r';
session->local.banner[banner_len++] = '\n'; session->local.banner[banner_len++] = '\n';
session->local.banner[banner_len++] = '\0'; session->local.banner[banner_len++] = '\0';
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ proto libssh2_session_init /* {{{ proto libssh2_session_init
@ -397,11 +423,10 @@ LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, const char *banner)
* It's allowable (but unadvisable) to define some but not all of the malloc callbacks * It's allowable (but unadvisable) to define some but not all of the malloc callbacks
* An additional pointer value may be optionally passed to be sent to the callbacks (so they know who's asking) * An additional pointer value may be optionally passed to be sent to the callbacks (so they know who's asking)
*/ */
LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex( LIBSSH2_API LIBSSH2_SESSION *
LIBSSH2_ALLOC_FUNC((*my_alloc)), libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
LIBSSH2_FREE_FUNC((*my_free)), LIBSSH2_FREE_FUNC((*my_free)),
LIBSSH2_REALLOC_FUNC((*my_realloc)), LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract)
void *abstract)
{ {
LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc; LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc;
LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free; LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free;
@ -425,11 +450,13 @@ LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(
session->free = local_free; session->free = local_free;
session->realloc = local_realloc; session->realloc = local_realloc;
session->abstract = abstract; session->abstract = abstract;
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "New session resource allocated"); _libssh2_debug(session, LIBSSH2_DBG_TRANS,
"New session resource allocated");
libssh2_crypto_init(); libssh2_crypto_init();
} }
return session; return session;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_callback_set /* {{{ libssh2_session_callback_set
@ -439,7 +466,8 @@ LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(
* FIXME: this function relies on that we can typecast function pointers * FIXME: this function relies on that we can typecast function pointers
* to void pointers, which isn't allowed in ISO C! * to void pointers, which isn't allowed in ISO C!
*/ */
LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session, LIBSSH2_API void *
libssh2_session_callback_set(LIBSSH2_SESSION * session,
int cbtype, void *callback) int cbtype, void *callback)
{ {
void *oldcb; void *oldcb;
@ -475,6 +503,7 @@ LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session,
return NULL; return NULL;
} }
/* }}} */ /* }}} */
/* {{{ proto libssh2_session_startup /* {{{ proto libssh2_session_startup
@ -484,7 +513,8 @@ LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session,
* callbacks in session * callbacks in session
* socket *must* be populated with an opened and connected socket. * socket *must* be populated with an opened and connected socket.
*/ */
LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket) LIBSSH2_API int
libssh2_session_startup(LIBSSH2_SESSION * session, int socket)
{ {
int rc; int rc;
@ -494,12 +524,14 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
/* FIXME: on some platforms (like win32) sockets are unsigned */ /* FIXME: on some platforms (like win32) sockets are unsigned */
if (socket < 0) { if (socket < 0) {
/* Did we forget something? */ /* Did we forget something? */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE, "Bad socket provided", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE,
"Bad socket provided", 0);
return LIBSSH2_ERROR_SOCKET_NONE; return LIBSSH2_ERROR_SOCKET_NONE;
} }
session->socket_fd = socket; session->socket_fd = socket;
session->socket_block = !_libssh2_get_socket_nonblocking(session->socket_fd); session->socket_block =
!_libssh2_get_socket_nonblocking(session->socket_fd);
if (session->socket_block) { if (session->socket_block) {
/* /*
* Since we can't be sure that we are in blocking or there * Since we can't be sure that we are in blocking or there
@ -517,12 +549,13 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
if (session->startup_state == libssh2_NB_state_created) { if (session->startup_state == libssh2_NB_state_created) {
rc = libssh2_banner_send(session); rc = libssh2_banner_send(session);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending banner to remote host", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending banner to remote host", 0);
return LIBSSH2_ERROR_EAGAIN; return LIBSSH2_ERROR_EAGAIN;
} } else if (rc) {
else if (rc) {
/* Unable to send banner? */ /* Unable to send banner? */
libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND, "Error sending banner to remote host", 0); libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND,
"Error sending banner to remote host", 0);
return LIBSSH2_ERROR_BANNER_SEND; return LIBSSH2_ERROR_BANNER_SEND;
} }
@ -532,12 +565,13 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
if (session->startup_state == libssh2_NB_state_sent) { if (session->startup_state == libssh2_NB_state_sent) {
rc = libssh2_banner_receive(session); rc = libssh2_banner_receive(session);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for banner", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for banner", 0);
return LIBSSH2_ERROR_EAGAIN; return LIBSSH2_ERROR_EAGAIN;
} } else if (rc) {
else if (rc) {
/* Unable to receive banner from remote */ /* Unable to receive banner from remote */
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE, "Timeout waiting for banner", 0); libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE,
"Timeout waiting for banner", 0);
return LIBSSH2_ERROR_BANNER_NONE; return LIBSSH2_ERROR_BANNER_NONE;
} }
@ -547,11 +581,12 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
if (session->startup_state == libssh2_NB_state_sent1) { if (session->startup_state == libssh2_NB_state_sent1) {
rc = libssh2_kex_exchange(session, 0, &session->startup_key_state); rc = libssh2_kex_exchange(session, 0, &session->startup_key_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block exchanging encryption keys", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block exchanging encryption keys", 0);
return LIBSSH2_ERROR_EAGAIN; return LIBSSH2_ERROR_EAGAIN;
} } else if (rc) {
else if (rc) { libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, "Unable to exchange encryption keys", 0); "Unable to exchange encryption keys", 0);
return LIBSSH2_ERROR_KEX_FAILURE; return LIBSSH2_ERROR_KEX_FAILURE;
} }
@ -559,24 +594,29 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
} }
if (session->startup_state == libssh2_NB_state_sent2) { if (session->startup_state == libssh2_NB_state_sent2) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Requesting userauth service"); _libssh2_debug(session, LIBSSH2_DBG_TRANS,
"Requesting userauth service");
/* Request the userauth service */ /* Request the userauth service */
session->startup_service[0] = SSH_MSG_SERVICE_REQUEST; session->startup_service[0] = SSH_MSG_SERVICE_REQUEST;
libssh2_htonu32(session->startup_service + 1, sizeof("ssh-userauth") - 1); libssh2_htonu32(session->startup_service + 1,
memcpy(session->startup_service + 5, "ssh-userauth", sizeof("ssh-userauth") - 1); sizeof("ssh-userauth") - 1);
memcpy(session->startup_service + 5, "ssh-userauth",
sizeof("ssh-userauth") - 1);
session->startup_state = libssh2_NB_state_sent3; session->startup_state = libssh2_NB_state_sent3;
} }
if (session->startup_state == libssh2_NB_state_sent3) { if (session->startup_state == libssh2_NB_state_sent3) {
rc = libssh2_packet_write(session, session->startup_service, sizeof("ssh-userauth") + 5 - 1); rc = libssh2_packet_write(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block asking for ssh-userauth service", 0); libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block asking for ssh-userauth service", 0);
return LIBSSH2_ERROR_EAGAIN; return LIBSSH2_ERROR_EAGAIN;
} } else if (rc) {
else if (rc) { libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to ask for ssh-userauth service", 0); "Unable to ask for ssh-userauth service", 0);
return LIBSSH2_ERROR_SOCKET_SEND; return LIBSSH2_ERROR_SOCKET_SEND;
} }
@ -584,21 +624,25 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
} }
if (session->startup_state == libssh2_NB_state_sent4) { if (session->startup_state == libssh2_NB_state_sent4) {
rc = libssh2_packet_require_ex(session, SSH_MSG_SERVICE_ACCEPT, &session->startup_data, &session->startup_data_len, rc = libssh2_packet_require_ex(session, SSH_MSG_SERVICE_ACCEPT,
0, NULL, 0, &session->startup_req_state); &session->startup_data,
&session->startup_data_len, 0, NULL, 0,
&session->startup_req_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return LIBSSH2_ERROR_EAGAIN; return LIBSSH2_ERROR_EAGAIN;
} } else if (rc) {
else if (rc) {
return LIBSSH2_ERROR_SOCKET_DISCONNECT; return LIBSSH2_ERROR_SOCKET_DISCONNECT;
} }
session->startup_service_length = libssh2_ntohu32(session->startup_data + 1); session->startup_service_length =
libssh2_ntohu32(session->startup_data + 1);
if ((session->startup_service_length != (sizeof("ssh-userauth") - 1)) || if ((session->startup_service_length != (sizeof("ssh-userauth") - 1))
strncmp("ssh-userauth", (char *)session->startup_data + 5, session->startup_service_length)) { || strncmp("ssh-userauth", (char *) session->startup_data + 5,
session->startup_service_length)) {
LIBSSH2_FREE(session, session->startup_data); LIBSSH2_FREE(session, session->startup_data);
session->startup_data = NULL; session->startup_data = NULL;
libssh2_error(session, LIBSSH2_ERROR_PROTO, "Invalid response received from server", 0); libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Invalid response received from server", 0);
return LIBSSH2_ERROR_PROTO; return LIBSSH2_ERROR_PROTO;
} }
LIBSSH2_FREE(session, session->startup_data); LIBSSH2_FREE(session, session->startup_data);
@ -612,18 +656,21 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
/* just for safety return some error */ /* just for safety return some error */
return LIBSSH2_ERROR_INVAL; return LIBSSH2_ERROR_INVAL;
} }
/* }}} */ /* }}} */
/* {{{ proto libssh2_session_free /* {{{ proto libssh2_session_free
* Frees the memory allocated to the session * Frees the memory allocated to the session
* Also closes and frees any channels attached to this session * Also closes and frees any channels attached to this session
*/ */
LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session) LIBSSH2_API int
libssh2_session_free(LIBSSH2_SESSION * session)
{ {
int rc; int rc;
if (session->free_state == libssh2_NB_state_idle) { if (session->free_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource", session->remote.banner); _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource",
session->remote.banner);
session->state = libssh2_NB_state_created; session->state = libssh2_NB_state_created;
} }
@ -673,11 +720,13 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session)
/* Client to Server */ /* Client to Server */
/* crypt */ /* crypt */
if (session->local.crypt && session->local.crypt->dtor) { if (session->local.crypt && session->local.crypt->dtor) {
session->local.crypt->dtor(session, &session->local.crypt_abstract); session->local.crypt->dtor(session,
&session->local.crypt_abstract);
} }
/* comp */ /* comp */
if (session->local.comp && session->local.comp->dtor) { if (session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1, &session->local.comp_abstract); session->local.comp->dtor(session, 1,
&session->local.comp_abstract);
} }
/* mac */ /* mac */
if (session->local.mac && session->local.mac->dtor) { if (session->local.mac && session->local.mac->dtor) {
@ -687,11 +736,13 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session)
/* Server to Client */ /* Server to Client */
/* crypt */ /* crypt */
if (session->remote.crypt && session->remote.crypt->dtor) { if (session->remote.crypt && session->remote.crypt->dtor) {
session->remote.crypt->dtor(session, &session->remote.crypt_abstract); session->remote.crypt->dtor(session,
&session->remote.crypt_abstract);
} }
/* comp */ /* comp */
if (session->remote.comp && session->remote.comp->dtor) { if (session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0, &session->remote.comp_abstract); session->remote.comp->dtor(session, 0,
&session->remote.comp_abstract);
} }
/* mac */ /* mac */
if (session->remote.mac && session->remote.mac->dtor) { if (session->remote.mac && session->remote.mac->dtor) {
@ -840,18 +891,23 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session)
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_disconnect_ex /* {{{ libssh2_session_disconnect_ex
*/ */
LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *description, const char *lang) LIBSSH2_API int
libssh2_session_disconnect_ex(LIBSSH2_SESSION * session, int reason,
const char *description, const char *lang)
{ {
unsigned char *s; unsigned char *s;
unsigned long descr_len = 0, lang_len = 0; unsigned long descr_len = 0, lang_len = 0;
int rc; int rc;
if (session->disconnect_state == libssh2_NB_state_idle) { if (session->disconnect_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Disconnecting: reason=%d, desc=%s, lang=%s", reason, description, lang); _libssh2_debug(session, LIBSSH2_DBG_TRANS,
"Disconnecting: reason=%d, desc=%s, lang=%s", reason,
description, lang);
if (description) { if (description) {
descr_len = strlen(description); descr_len = strlen(description);
} }
@ -861,23 +917,29 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
/* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */ /* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
session->disconnect_data_len = descr_len + lang_len + 13; session->disconnect_data_len = descr_len + lang_len + 13;
s = session->disconnect_data = LIBSSH2_ALLOC(session, session->disconnect_data_len); s = session->disconnect_data =
LIBSSH2_ALLOC(session, session->disconnect_data_len);
if (!session->disconnect_data) { if (!session->disconnect_data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for disconnect packet", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for disconnect packet",
0);
session->disconnect_state = libssh2_NB_state_idle; session->disconnect_state = libssh2_NB_state_idle;
return -1; return -1;
} }
*(s++) = SSH_MSG_DISCONNECT; *(s++) = SSH_MSG_DISCONNECT;
libssh2_htonu32(s, reason); s += 4; libssh2_htonu32(s, reason);
s += 4;
libssh2_htonu32(s, descr_len); s += 4; libssh2_htonu32(s, descr_len);
s += 4;
if (description) { if (description) {
memcpy(s, description, descr_len); memcpy(s, description, descr_len);
s += descr_len; s += descr_len;
} }
libssh2_htonu32(s, lang_len); s += 4; libssh2_htonu32(s, lang_len);
s += 4;
if (lang) { if (lang) {
memcpy(s, lang, lang_len); memcpy(s, lang, lang_len);
s += lang_len; s += lang_len;
@ -886,7 +948,8 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
session->disconnect_state = libssh2_NB_state_created; session->disconnect_state = libssh2_NB_state_created;
} }
rc = libssh2_packet_write(session, session->disconnect_data, session->disconnect_data_len); rc = libssh2_packet_write(session, session->disconnect_data,
session->disconnect_data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@ -897,6 +960,7 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_methods /* {{{ libssh2_session_methods
@ -904,7 +968,8 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
* NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation * NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation
* Strings should NOT be freed * Strings should NOT be freed
*/ */
LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type) LIBSSH2_API const char *
libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
{ {
/* All methods have char *name as their first element */ /* All methods have char *name as their first element */
const LIBSSH2_KEX_METHOD *method = NULL; const LIBSSH2_KEX_METHOD *method = NULL;
@ -951,27 +1016,32 @@ LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, int me
break; break;
default: default:
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0); libssh2_error(session, LIBSSH2_ERROR_INVAL,
"Invalid parameter specified for method_type", 0);
return NULL; return NULL;
break; break;
} }
if (!method) { if (!method) {
libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, "No method negotiated", 0); libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
"No method negotiated", 0);
return NULL; return NULL;
} }
return method->name; return method->name;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_abstract /* {{{ libssh2_session_abstract
* Retrieve a pointer to the abstract property * Retrieve a pointer to the abstract property
*/ */
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session) LIBSSH2_API void **
libssh2_session_abstract(LIBSSH2_SESSION * session)
{ {
return &session->abstract; return &session->abstract;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_last_error /* {{{ libssh2_session_last_error
@ -980,7 +1050,8 @@ LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session)
* Otherwise it is assumed to be owned by libssh2 * Otherwise it is assumed to be owned by libssh2
*/ */
LIBSSH2_API int LIBSSH2_API int
libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf) libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
int *errmsg_len, int want_buf)
{ {
/* No error to report */ /* No error to report */
if (!session->err_code) { if (!session->err_code) {
@ -1001,8 +1072,7 @@ libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_
} }
if (errmsg) { if (errmsg) {
char *serrmsg = session->err_msg ? session->err_msg : char *serrmsg = session->err_msg ? session->err_msg : (char *) "";
(char *)"";
int ownbuf = session->err_msg ? session->err_should_free : 0; int ownbuf = session->err_msg ? session->err_should_free : 0;
if (want_buf) { if (want_buf) {
@ -1029,6 +1099,7 @@ libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_
return session->err_code; return session->err_code;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_last_error /* {{{ libssh2_session_last_error
@ -1039,13 +1110,15 @@ libssh2_session_last_errno(LIBSSH2_SESSION *session)
{ {
return session->err_code; return session->err_code;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_flag /* {{{ libssh2_session_flag
* Set/Get session flags * Set/Get session flags
* Passing flag==0 will avoid changing session->flags while still returning its current value * Passing flag==0 will avoid changing session->flags while still returning its current value
*/ */
LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value) LIBSSH2_API int
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
{ {
if (value) { if (value) {
session->flags |= flag; session->flags |= flag;
@ -1055,16 +1128,19 @@ LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int val
return session->flags; return session->flags;
} }
/* }}} */ /* }}} */
/* {{{ _libssh2_session_set_blocking /* {{{ _libssh2_session_set_blocking
* Set a session's blocking mode on or off, return the previous status * Set a session's blocking mode on or off, return the previous status
* when this function is called. * when this function is called.
*/ */
int _libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking) int
_libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
{ {
int bl = session->socket_block; int bl = session->socket_block;
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Setting blocking mode on session %d", blocking); _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Setting blocking mode on session %d", blocking);
if (blocking == session->socket_block) { if (blocking == session->socket_block) {
/* avoid if already correct */ /* avoid if already correct */
return bl; return bl;
@ -1075,32 +1151,38 @@ int _libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
return bl; return bl;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_set_blocking /* {{{ libssh2_session_set_blocking
* Set a channel's blocking mode on or off, similar to a socket's * Set a channel's blocking mode on or off, similar to a socket's
* fcntl(fd, F_SETFL, O_NONBLOCK); type command * fcntl(fd, F_SETFL, O_NONBLOCK); type command
*/ */
LIBSSH2_API void libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking) LIBSSH2_API void
libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
{ {
(void) _libssh2_session_set_blocking(session, blocking); (void) _libssh2_session_set_blocking(session, blocking);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_get_blocking /* {{{ libssh2_session_get_blocking
* Returns a session's blocking mode on or off * Returns a session's blocking mode on or off
*/ */
LIBSSH2_API int libssh2_session_get_blocking(LIBSSH2_SESSION *session) LIBSSH2_API int
libssh2_session_get_blocking(LIBSSH2_SESSION * session)
{ {
return session->socket_block; return session->socket_block;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_poll_channel_read /* {{{ libssh2_poll_channel_read
* Returns 0 if no data is waiting on channel, * Returns 0 if no data is waiting on channel,
* non-0 if data is available * non-0 if data is available
*/ */
LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended) LIBSSH2_API int
libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = session->packets.head;
@ -1108,8 +1190,9 @@ LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended
while (packet) { while (packet) {
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) && (extended == 0) && if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) && (extended == 0) &&
(channel->local.id == libssh2_ntohu32(packet->data + 1))) || (channel->local.id == libssh2_ntohu32(packet->data + 1))) ||
((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (extended != 0) && ((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
(channel->local.id == libssh2_ntohu32(packet->data + 1)))) { && (extended != 0)
&& (channel->local.id == libssh2_ntohu32(packet->data + 1)))) {
/* Found data waiting to be read */ /* Found data waiting to be read */
return 1; return 1;
} }
@ -1118,32 +1201,38 @@ LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_poll_channel_write /* {{{ libssh2_poll_channel_write
* Returns 0 if writing to channel would block, * Returns 0 if writing to channel would block,
* non-0 if data can be written without blocking * non-0 if data can be written without blocking
*/ */
static inline int libssh2_poll_channel_write(LIBSSH2_CHANNEL *channel) static inline int
libssh2_poll_channel_write(LIBSSH2_CHANNEL * channel)
{ {
return channel->local.window_size ? 1 : 0; return channel->local.window_size ? 1 : 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_poll_listener_queued /* {{{ libssh2_poll_listener_queued
* Returns 0 if no connections are waiting to be accepted * Returns 0 if no connections are waiting to be accepted
* non-0 if one or more connections are available * non-0 if one or more connections are available
*/ */
static inline int libssh2_poll_listener_queued(LIBSSH2_LISTENER *listener) static inline int
libssh2_poll_listener_queued(LIBSSH2_LISTENER * listener)
{ {
return listener->queue ? 1 : 0; return listener->queue ? 1 : 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_poll /* {{{ libssh2_poll
* Poll sockets, channels, and listeners for activity * Poll sockets, channels, and listeners for activity
*/ */
LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout) LIBSSH2_API int
libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
{ {
long timeout_remaining; long timeout_remaining;
unsigned int i, active_fds; unsigned int i, active_fds;
@ -1173,19 +1262,23 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
sockets[i].fd = fds[i].fd.channel->session->socket_fd; sockets[i].fd = fds[i].fd.channel->session->socket_fd;
sockets[i].events = POLLIN; sockets[i].events = POLLIN;
sockets[i].revents = 0; sockets[i].revents = 0;
if (!session) session = fds[i].fd.channel->session; if (!session)
session = fds[i].fd.channel->session;
break; break;
case LIBSSH2_POLLFD_LISTENER: case LIBSSH2_POLLFD_LISTENER:
sockets[i].fd = fds[i].fd.listener->session->socket_fd; sockets[i].fd = fds[i].fd.listener->session->socket_fd;
sockets[i].events = POLLIN; sockets[i].events = POLLIN;
sockets[i].revents = 0; sockets[i].revents = 0;
if (!session) session = fds[i].fd.listener->session; if (!session)
session = fds[i].fd.listener->session;
break; break;
default: default:
if (session) libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, if (session)
"Invalid descriptor passed to libssh2_poll()", 0); libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
"Invalid descriptor passed to libssh2_poll()",
0);
return -1; return -1;
} }
} }
@ -1217,14 +1310,16 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
FD_SET(fds[i].fd.channel->session->socket_fd, &rfds); FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
if (fds[i].fd.channel->session->socket_fd > maxfd) if (fds[i].fd.channel->session->socket_fd > maxfd)
maxfd = fds[i].fd.channel->session->socket_fd; maxfd = fds[i].fd.channel->session->socket_fd;
if (!session) session = fds[i].fd.channel->session; if (!session)
session = fds[i].fd.channel->session;
break; break;
case LIBSSH2_POLLFD_LISTENER: case LIBSSH2_POLLFD_LISTENER:
FD_SET(fds[i].fd.listener->session->socket_fd, &rfds); FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
if (fds[i].fd.listener->session->socket_fd > maxfd) if (fds[i].fd.listener->session->socket_fd > maxfd)
maxfd = fds[i].fd.listener->session->socket_fd; maxfd = fds[i].fd.listener->session->socket_fd;
if (!session) session = fds[i].fd.listener->session; if (!session)
session = fds[i].fd.listener->session;
break; break;
default: default:
@ -1257,31 +1352,50 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
case LIBSSH2_POLLFD_CHANNEL: case LIBSSH2_POLLFD_CHANNEL:
if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want to be ready for read */ if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want to be ready for read */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* Not yet known to be ready for read */ ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* Not yet known to be ready for read */
fds[i].revents |= libssh2_poll_channel_read(fds[i].fd.channel, 0) ? LIBSSH2_POLLFD_POLLIN : 0; fds[i].revents |=
libssh2_poll_channel_read(fds[i].fd.channel,
0) ?
LIBSSH2_POLLFD_POLLIN : 0;
} }
if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && /* Want to be ready for extended read */ if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && /* Want to be ready for extended read */
((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) { /* Not yet known to be ready for extended read */ ((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) { /* Not yet known to be ready for extended read */
fds[i].revents |= libssh2_poll_channel_read(fds[i].fd.channel, 1) ? LIBSSH2_POLLFD_POLLEXT : 0; fds[i].revents |=
libssh2_poll_channel_read(fds[i].fd.channel,
1) ?
LIBSSH2_POLLFD_POLLEXT : 0;
} }
if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && /* Want to be ready for write */ if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && /* Want to be ready for write */
((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) { /* Not yet known to be ready for write */ ((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) { /* Not yet known to be ready for write */
fds[i].revents |= libssh2_poll_channel_write(fds[i].fd.channel) ? LIBSSH2_POLLFD_POLLOUT : 0; fds[i].revents |=
libssh2_poll_channel_write(fds[i].fd.
channel) ?
LIBSSH2_POLLFD_POLLOUT : 0;
} }
if (fds[i].fd.channel->remote.close || fds[i].fd.channel->local.close) { if (fds[i].fd.channel->remote.close
|| fds[i].fd.channel->local.close) {
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED; fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED;
} }
if (fds[i].fd.channel->session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { if (fds[i].fd.channel->session->socket_state ==
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED; LIBSSH2_SOCKET_DISCONNECTED) {
fds[i].revents |=
LIBSSH2_POLLFD_CHANNEL_CLOSED |
LIBSSH2_POLLFD_SESSION_CLOSED;
} }
break; break;
case LIBSSH2_POLLFD_LISTENER: case LIBSSH2_POLLFD_LISTENER:
if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want a connection */ if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want a connection */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* No connections known of yet */ ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* No connections known of yet */
fds[i].revents |= libssh2_poll_listener_queued(fds[i].fd.listener) ? LIBSSH2_POLLFD_POLLIN : 0; fds[i].revents |=
libssh2_poll_listener_queued(fds[i].fd.
listener) ?
LIBSSH2_POLLFD_POLLIN : 0;
} }
if (fds[i].fd.listener->session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { if (fds[i].fd.listener->session->socket_state ==
fds[i].revents |= LIBSSH2_POLLFD_LISTENER_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED; LIBSSH2_SOCKET_DISCONNECTED) {
fds[i].revents |=
LIBSSH2_POLLFD_LISTENER_CLOSED |
LIBSSH2_POLLFD_SESSION_CLOSED;
} }
break; break;
} }
@ -1295,7 +1409,6 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
/* Don't block on the sockets if we have channels/listeners which are ready */ /* Don't block on the sockets if we have channels/listeners which are ready */
timeout_remaining = 0; timeout_remaining = 0;
} }
#ifdef HAVE_POLL #ifdef HAVE_POLL
#ifdef HAVE_GETTIMEOFDAY #ifdef HAVE_GETTIMEOFDAY
@ -1329,20 +1442,26 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
case LIBSSH2_POLLFD_CHANNEL: case LIBSSH2_POLLFD_CHANNEL:
if (sockets[i].events & POLLIN) { if (sockets[i].events & POLLIN) {
/* Spin session until no data available */ /* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.channel->session) > 0); while (libssh2_packet_read(fds[i].fd.channel->session)
> 0);
} }
if (sockets[i].revents & POLLHUP) { if (sockets[i].revents & POLLHUP) {
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED; fds[i].revents |=
LIBSSH2_POLLFD_CHANNEL_CLOSED |
LIBSSH2_POLLFD_SESSION_CLOSED;
} }
sockets[i].revents = 0; sockets[i].revents = 0;
break; break;
case LIBSSH2_POLLFD_LISTENER: case LIBSSH2_POLLFD_LISTENER:
if (sockets[i].events & POLLIN) { if (sockets[i].events & POLLIN) {
/* Spin session until no data available */ /* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.listener->session) > 0); while (libssh2_packet_read(fds[i].fd.listener->session)
> 0);
} }
if (sockets[i].revents & POLLHUP) { if (sockets[i].revents & POLLHUP) {
fds[i].revents |= LIBSSH2_POLLFD_LISTENER_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED; fds[i].revents |=
LIBSSH2_POLLFD_LISTENER_CLOSED |
LIBSSH2_POLLFD_SESSION_CLOSED;
} }
sockets[i].revents = 0; sockets[i].revents = 0;
break; break;
@ -1389,14 +1508,17 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
case LIBSSH2_POLLFD_CHANNEL: case LIBSSH2_POLLFD_CHANNEL:
if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) { if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
/* Spin session until no data available */ /* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.channel->session) > 0); while (libssh2_packet_read(fds[i].fd.channel->session)
> 0);
} }
break; break;
case LIBSSH2_POLLFD_LISTENER: case LIBSSH2_POLLFD_LISTENER:
if (FD_ISSET(fds[i].fd.listener->session->socket_fd, &rfds)) { if (FD_ISSET
(fds[i].fd.listener->session->socket_fd, &rfds)) {
/* Spin session until no data available */ /* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.listener->session) > 0); while (libssh2_packet_read(fds[i].fd.listener->session)
> 0);
} }
break; break;
} }
@ -1407,5 +1529,5 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
return active_fds; return active_fds;
} }
/* }}} */
/* }}} */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -48,9 +48,9 @@
#ifdef LIBSSH2DEBUG #ifdef LIBSSH2DEBUG
#define UNPRINTABLE_CHAR '.' #define UNPRINTABLE_CHAR '.'
static void debugdump(LIBSSH2_SESSION *session, static void
const char *desc, unsigned char *ptr, debugdump(LIBSSH2_SESSION * session,
unsigned long size) const char *desc, unsigned char *ptr, unsigned long size)
{ {
size_t i; size_t i;
size_t c; size_t c;
@ -66,7 +66,7 @@ static void debugdump(LIBSSH2_SESSION *session,
for(i = 0; i < size; i += width) { for(i = 0; i < size; i += width) {
fprintf(stream, "%04lx: ", i); fprintf(stream, "%04lx: ", (long)i);
/* hex not disabled, show it */ /* hex not disabled, show it */
for(c = 0; c < width; c++) { for(c = 0; c < width; c++) {
@ -95,7 +95,8 @@ static void debugdump(LIBSSH2_SESSION *session,
* returns PACKET_NONE on success and PACKET_FAIL on failure * returns PACKET_NONE on success and PACKET_FAIL on failure
*/ */
static libssh2pack_t decrypt(LIBSSH2_SESSION *session, unsigned char *source, static libssh2pack_t
decrypt(LIBSSH2_SESSION * session, unsigned char *source,
unsigned char *dest, int len) unsigned char *dest, int len)
{ {
struct transportpacket *p = &session->packet; struct transportpacket *p = &session->packet;
@ -144,11 +145,11 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
if (encrypted) { if (encrypted) {
/* Calculate MAC hash */ /* Calculate MAC hash */
session->remote.mac->hash(session, session->remote.mac->hash(session, macbuf, /* store hash here */
macbuf, /* store hash here */
session->remote.seqno, session->remote.seqno,
p->init, 5, p->init, 5,
p->payload, session->fullpacket_payload_len, p->payload,
session->fullpacket_payload_len,
&session->remote.mac_abstract); &session->remote.mac_abstract);
/* Compare the calculated hash with the MAC we just read from /* Compare the calculated hash with the MAC we just read from
@ -168,8 +169,7 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
session->fullpacket_payload_len -= p->padding_length; session->fullpacket_payload_len -= p->padding_length;
/* Check for and deal with decompression */ /* Check for and deal with decompression */
if (session->remote.comp && if (session->remote.comp && strcmp(session->remote.comp->name, "none")) {
strcmp(session->remote.comp->name, "none")) {
unsigned char *data; unsigned char *data;
unsigned long data_len; unsigned long data_len;
int free_payload = 1; int free_payload = 1;
@ -178,7 +178,8 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
&data, &data_len, &data, &data_len,
LIBSSH2_PACKET_MAXDECOMP, LIBSSH2_PACKET_MAXDECOMP,
&free_payload, &free_payload,
p->payload, session->fullpacket_payload_len, p->payload,
session->fullpacket_payload_len,
&session->remote.comp_abstract)) { &session->remote.comp_abstract)) {
LIBSSH2_FREE(session, p->payload); LIBSSH2_FREE(session, p->payload);
return PACKET_FAIL; return PACKET_FAIL;
@ -188,16 +189,14 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
LIBSSH2_FREE(session, p->payload); LIBSSH2_FREE(session, p->payload);
p->payload = data; p->payload = data;
session->fullpacket_payload_len = data_len; session->fullpacket_payload_len = data_len;
} } else {
else {
if (data == p->payload) { if (data == p->payload) {
/* It's not to be freed, because the /* It's not to be freed, because the
* compression layer reused payload, So let's * compression layer reused payload, So let's
* do the same! * do the same!
*/ */
session->fullpacket_payload_len = data_len; session->fullpacket_payload_len = data_len;
} } else {
else {
/* No comp_method actually lets this happen, /* No comp_method actually lets this happen,
* but let's prepare for the future */ * but let's prepare for the future */
@ -207,9 +206,9 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
* brigade won't know what to do with it */ * brigade won't know what to do with it */
p->payload = LIBSSH2_ALLOC(session, data_len); p->payload = LIBSSH2_ALLOC(session, data_len);
if (!p->payload) { if (!p->payload) {
libssh2_error(session, libssh2_error(session, LIBSSH2_ERROR_ALLOC, (char *)
LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for copy of uncompressed data",
(char *)"Unable to allocate memory for copy of uncompressed data", 0); 0);
return PACKET_ENOMEM; return PACKET_ENOMEM;
} }
memcpy(p->payload, data, data_len); memcpy(p->payload, data, data_len);
@ -227,11 +226,12 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
} }
if (session->fullpacket_state == libssh2_NB_state_created) { if (session->fullpacket_state == libssh2_NB_state_created) {
rc = libssh2_packet_add(session, p->payload, session->fullpacket_payload_len, session->fullpacket_macstate); rc = libssh2_packet_add(session, p->payload,
session->fullpacket_payload_len,
session->fullpacket_macstate);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} } else if (rc < 0) {
else if (rc < 0) {
return PACKET_FAIL; return PACKET_FAIL;
} }
} }
@ -256,7 +256,8 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
* This function reads the binary stream as specified in chapter 6 of RFC4253 * This function reads the binary stream as specified in chapter 6 of RFC4253
* "The Secure Shell (SSH) Transport Layer Protocol" * "The Secure Shell (SSH) Transport Layer Protocol"
*/ */
libssh2pack_t libssh2_packet_read(LIBSSH2_SESSION *session) libssh2pack_t
libssh2_packet_read(LIBSSH2_SESSION * session)
{ {
libssh2pack_t rc; libssh2pack_t rc;
struct transportpacket *p = &session->packet; struct transportpacket *p = &session->packet;
@ -324,7 +325,9 @@ libssh2pack_t libssh2_packet_read(LIBSSH2_SESSION *session)
} }
/* now read a big chunk from the network into the temp buffer */ /* now read a big chunk from the network into the temp buffer */
nread = recv(session->socket_fd, &p->buf[remainbuf], PACKETBUFSIZE-remainbuf, nread =
recv(session->socket_fd, &p->buf[remainbuf],
PACKETBUFSIZE - remainbuf,
LIBSSH2_SOCKET_RECV_FLAGS(session)); LIBSSH2_SOCKET_RECV_FLAGS(session));
if (nread <= 0) { if (nread <= 0) {
/* check if this is due to EAGAIN and return /* check if this is due to EAGAIN and return
@ -382,7 +385,9 @@ libssh2pack_t libssh2_packet_read(LIBSSH2_SESSION *session)
/* total_num is the number of bytes following the initial /* total_num is the number of bytes following the initial
(5 bytes) packet length and padding length fields */ (5 bytes) packet length and padding length fields */
p->total_num = p->packet_length -1 + (encrypted ? session->remote.mac->mac_len : 0); p->total_num =
p->packet_length - 1 +
(encrypted ? session->remote.mac->mac_len : 0);
/* RFC4253 section 6.1 Maximum Packet Length says: /* RFC4253 section 6.1 Maximum Packet Length says:
* *
@ -515,11 +520,14 @@ libssh2_packet_read_point1:
return PACKET_FAIL; /* we never reach this point */ return PACKET_FAIL; /* we never reach this point */
} }
/* }}} */ /* }}} */
#ifndef OLDSEND #ifndef OLDSEND
static libssh2pack_t send_existing(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len, ssize_t *ret) static libssh2pack_t
send_existing(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len, ssize_t * ret)
{ {
ssize_t rc; ssize_t rc;
ssize_t length; ssize_t length;
@ -545,15 +553,15 @@ static libssh2pack_t send_existing(LIBSSH2_SESSION *session, unsigned char *data
/* number of bytes left to send */ /* number of bytes left to send */
length = p->ototal_num - p->osent; length = p->ototal_num - p->osent;
rc = send(session->socket_fd, &p->outbuf[p->osent], length, LIBSSH2_SOCKET_SEND_FLAGS(session)); rc = send(session->socket_fd, &p->outbuf[p->osent], length,
LIBSSH2_SOCKET_SEND_FLAGS(session));
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); LIBSSH2_FREE(session, p->outbuf);
p->outbuf = NULL; p->outbuf = NULL;
p->ototal_num = 0; p->ototal_num = 0;
} } else if (rc < 0) {
else if (rc < 0) {
/* nothing was sent */ /* nothing was sent */
if (errno != EAGAIN) { if (errno != EAGAIN) {
/* send failure! */ /* send failure! */
@ -562,7 +570,8 @@ static libssh2pack_t send_existing(LIBSSH2_SESSION *session, unsigned char *data
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
debugdump(session, "libssh2_packet_write send()", &p->outbuf[p->osent], length); debugdump(session, "libssh2_packet_write send()", &p->outbuf[p->osent],
length);
p->osent += length; /* we sent away this much data */ p->osent += length; /* we sent away this much data */
return PACKET_NONE; return PACKET_NONE;
@ -577,9 +586,13 @@ static libssh2pack_t send_existing(LIBSSH2_SESSION *session, unsigned char *data
* sent, and this function should then be called with the same argument set * sent, and this function should then be called with the same argument set
* (same data pointer and same data_len) until zero or failure is returned. * (same data pointer and same data_len) until zero or failure is returned.
*/ */
int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len) int
libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len)
{ {
int blocksize = (session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->blocksize : 8; int blocksize =
(session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->
blocksize : 8;
int padding_length; int padding_length;
int packet_length; int packet_length;
int total_length; int total_length;
@ -608,7 +621,8 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
/* check if we should compress */ /* check if we should compress */
if (encrypted && strcmp(session->local.comp->name, "none")) { if (encrypted && strcmp(session->local.comp->name, "none")) {
if (session->local.comp->comp(session, 1, &data, &data_len, LIBSSH2_PACKET_MAXCOMP, if (session->local.comp->
comp(session, 1, &data, &data_len, LIBSSH2_PACKET_MAXCOMP,
&free_data, data, data_len, &session->local.comp_abstract)) { &free_data, data, data_len, &session->local.comp_abstract)) {
return PACKET_COMPRESS; /* compression failure */ return PACKET_COMPRESS; /* compression failure */
} }
@ -650,7 +664,8 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
packet_length += padding_length; packet_length += padding_length;
/* append the MAC length to the total_length size */ /* append the MAC length to the total_length size */
total_length = packet_length + (encrypted?session->local.mac->mac_len:0); total_length =
packet_length + (encrypted ? session->local.mac->mac_len : 0);
/* allocate memory to store the outgoing packet in, in case we can't /* 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 send the whole one and thus need to keep it after this function
@ -678,14 +693,17 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
since that size includes the whole packet. The MAC is since that size includes the whole packet. The MAC is
calculated on the entire unencrypted packet, including all calculated on the entire unencrypted packet, including all
fields except the MAC field itself. */ fields except the MAC field itself. */
session->local.mac->hash(session, p->outbuf + packet_length, session->local.seqno, p->outbuf, packet_length, session->local.mac->hash(session, p->outbuf + packet_length,
NULL, 0, &session->local.mac_abstract); session->local.seqno, p->outbuf,
packet_length, NULL, 0,
&session->local.mac_abstract);
/* Encrypt the whole packet data, one block size at a time. /* Encrypt the whole packet data, one block size at a time.
The MAC field is not encrypted. */ The MAC field is not encrypted. */
for(i = 0; i < packet_length; i += session->local.crypt->blocksize) { for(i = 0; i < packet_length; i += session->local.crypt->blocksize) {
unsigned char *ptr = &p->outbuf[i]; unsigned char *ptr = &p->outbuf[i];
if (session->local.crypt->crypt(session, ptr, &session->local.crypt_abstract)) if (session->local.crypt->
crypt(session, ptr, &session->local.crypt_abstract))
return PACKET_FAIL; /* encryption failure */ return PACKET_FAIL; /* encryption failure */
} }
} }

Разница между файлами не показана из-за своего большого размера Загрузить разницу