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]
Этот коммит содержится в:
родитель
4c3dd3ea9f
Коммит
210459db4b
899
src/channel.c
899
src/channel.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
74
src/comp.c
74
src/comp.c
@ -47,15 +47,15 @@
|
||||
/* {{{ libssh2_comp_method_none_comp
|
||||
* 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,
|
||||
unsigned char **dest,
|
||||
unsigned long *dest_len,
|
||||
unsigned long payload_limit,
|
||||
int *free_dest,
|
||||
const unsigned char *src,
|
||||
unsigned long src_len,
|
||||
void **abstract)
|
||||
unsigned long src_len, void **abstract)
|
||||
{
|
||||
(void) session;
|
||||
(void) compress;
|
||||
@ -68,6 +68,7 @@ static int libssh2_comp_method_none_comp(LIBSSH2_SESSION *session,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
static const LIBSSH2_COMP_METHOD libssh2_comp_method_none = {
|
||||
@ -87,32 +88,39 @@ static const LIBSSH2_COMP_METHOD libssh2_comp_method_none = {
|
||||
* 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;
|
||||
|
||||
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_FREE(session, address);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_comp_method_zlib_init
|
||||
* 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;
|
||||
int status;
|
||||
|
||||
strm = LIBSSH2_ALLOC(session, sizeof(z_stream));
|
||||
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;
|
||||
}
|
||||
memset(strm, 0, sizeof(z_stream));
|
||||
@ -136,20 +144,21 @@ static int libssh2_comp_method_zlib_init(LIBSSH2_SESSION *session, int compress,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_comp_method_zlib_comp
|
||||
* 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,
|
||||
unsigned char **dest,
|
||||
unsigned long *dest_len,
|
||||
unsigned long payload_limit,
|
||||
int *free_dest,
|
||||
const unsigned char *src,
|
||||
unsigned long src_len,
|
||||
void **abstract)
|
||||
unsigned long src_len, void **abstract)
|
||||
{
|
||||
z_stream *strm = *abstract;
|
||||
/* 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;
|
||||
strm->avail_out = out_maxlen;
|
||||
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;
|
||||
}
|
||||
while (strm->avail_in) {
|
||||
@ -185,7 +196,8 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
|
||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||
}
|
||||
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);
|
||||
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;
|
||||
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) &&
|
||||
!compress && limiter++) {
|
||||
if ((out_maxlen > (int) payload_limit) && !compress && limiter++) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ZLIB,
|
||||
"Excessive growth in decompression phase", 0);
|
||||
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);
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
out = newout;
|
||||
strm->next_out = (unsigned char *) out + out_ofs;
|
||||
strm->avail_out += compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||
} else while (!strm->avail_out) {
|
||||
strm->avail_out +=
|
||||
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||
} else
|
||||
while (!strm->avail_out) {
|
||||
/* Done with input, might be a byte or two in internal buffer during compress
|
||||
* Or potentially many bytes if it's a decompress
|
||||
*/
|
||||
@ -220,7 +236,9 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
|
||||
char *newout;
|
||||
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
@ -234,7 +252,9 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
|
||||
|
||||
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
@ -248,7 +268,8 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
|
||||
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||
}
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
@ -261,12 +282,15 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_comp_method_zlib_dtor
|
||||
* 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;
|
||||
|
||||
@ -286,6 +310,7 @@ static int libssh2_comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compress,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
static const LIBSSH2_COMP_METHOD libssh2_comp_method_zlib = {
|
||||
@ -308,7 +333,8 @@ static const LIBSSH2_COMP_METHOD *_libssh2_comp_methods[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const LIBSSH2_COMP_METHOD **libssh2_comp_methods(void) {
|
||||
const LIBSSH2_COMP_METHOD **
|
||||
libssh2_comp_methods(void)
|
||||
{
|
||||
return _libssh2_comp_methods;
|
||||
}
|
||||
|
||||
|
31
src/crypt.c
31
src/crypt.c
@ -41,11 +41,14 @@
|
||||
/* {{{ libssh2_crypt_none_crypt
|
||||
* 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! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
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 */
|
||||
|
||||
struct crypt_ctx {
|
||||
struct crypt_ctx
|
||||
{
|
||||
int encrypt;
|
||||
_libssh2_cipher_type(algo);
|
||||
_libssh2_cipher_ctx h;
|
||||
};
|
||||
|
||||
static int _libssh2_init (LIBSSH2_SESSION *session,
|
||||
static int
|
||||
_libssh2_init(LIBSSH2_SESSION * session,
|
||||
const LIBSSH2_CRYPT_METHOD * method,
|
||||
unsigned char *iv, int *free_iv,
|
||||
unsigned char *secret, int *free_secret,
|
||||
@ -79,8 +84,7 @@ static int _libssh2_init (LIBSSH2_SESSION *session,
|
||||
}
|
||||
ctx->encrypt = encrypt;
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
@ -90,15 +94,17 @@ static int _libssh2_init (LIBSSH2_SESSION *session,
|
||||
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;
|
||||
(void) session;
|
||||
return _libssh2_cipher_crypt(&cctx->h, cctx->algo,
|
||||
cctx->encrypt, block);
|
||||
return _libssh2_cipher_crypt(&cctx->h, cctx->algo, 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;
|
||||
if (cctx && *cctx) {
|
||||
@ -147,7 +153,8 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_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",
|
||||
16, /* blocksize */
|
||||
16, /* initial value length */
|
||||
@ -242,6 +249,8 @@ static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
|
||||
};
|
||||
|
||||
/* Expose to kex.c */
|
||||
const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void) {
|
||||
const LIBSSH2_CRYPT_METHOD **
|
||||
libssh2_crypt_methods(void)
|
||||
{
|
||||
return _libssh2_crypt_methods;
|
||||
}
|
||||
|
130
src/hostkey.c
130
src/hostkey.c
@ -47,7 +47,8 @@
|
||||
* 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
|
||||
* 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);
|
||||
s += 4;
|
||||
|
||||
e = s; s += e_len;
|
||||
n_len = libssh2_ntohu32(s); s += 4;
|
||||
n = s; s += n_len;
|
||||
e = s;
|
||||
s += e_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,
|
||||
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;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_rsa_initPEM
|
||||
* Load a Private Key from a PEM file
|
||||
*/
|
||||
static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session,
|
||||
const char *privkeyfile, unsigned const char *passphrase, void **abstract)
|
||||
static int
|
||||
libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
|
||||
const char *privkeyfile,
|
||||
unsigned const char *passphrase,
|
||||
void **abstract)
|
||||
{
|
||||
libssh2_rsa_ctx *rsactx;
|
||||
FILE *fp;
|
||||
@ -125,32 +133,40 @@ static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_rsa_sign
|
||||
* 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,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m,
|
||||
unsigned long m_len,
|
||||
void **abstract)
|
||||
unsigned long m_len, void **abstract)
|
||||
{
|
||||
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
|
||||
(void) session;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_rsa_signv
|
||||
* 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,
|
||||
unsigned long veccount, const struct iovec datavec[], void **abstract)
|
||||
static int
|
||||
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);
|
||||
int ret;
|
||||
@ -172,13 +188,14 @@ static int libssh2_hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION *session, unsign
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_rsa_dtor
|
||||
* Shutdown the hostkey
|
||||
*/
|
||||
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_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
|
||||
(void) session;
|
||||
@ -189,6 +206,7 @@ static int libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION *session,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
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 *
|
||||
*********** */
|
||||
|
||||
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
|
||||
* 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;
|
||||
len = libssh2_ntohu32(s); s += 4;
|
||||
len = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) {
|
||||
return -1;
|
||||
} s += 7;
|
||||
}
|
||||
s += 7;
|
||||
|
||||
p_len = libssh2_ntohu32(s); s += 4;
|
||||
p = s; s += p_len;
|
||||
q_len = libssh2_ntohu32(s); s += 4;
|
||||
q = s; 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;
|
||||
p_len = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
p = s;
|
||||
s += p_len;
|
||||
q_len = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
q = s;
|
||||
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,
|
||||
y, y_len, NULL, 0);
|
||||
_libssh2_dsa_new(&dsactx, p, p_len, q, q_len, g, g_len, y, y_len, NULL, 0);
|
||||
|
||||
*abstract = dsactx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_dss_initPEM
|
||||
* 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,
|
||||
unsigned const char *passphrase,
|
||||
void **abstract)
|
||||
@ -285,31 +315,44 @@ static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_dss_sign
|
||||
* 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,
|
||||
const unsigned char *m, unsigned long m_len, void **abstract)
|
||||
static int
|
||||
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);
|
||||
|
||||
/* 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) {
|
||||
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 _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_dss_signv
|
||||
* 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,
|
||||
unsigned long veccount, const struct iovec datavec[], void **abstract)
|
||||
static int
|
||||
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);
|
||||
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);
|
||||
|
||||
if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH,
|
||||
*signature))
|
||||
{
|
||||
if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) {
|
||||
LIBSSH2_FREE(session, *signature);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_hostkey_method_ssh_dss_dtor
|
||||
* Shutdown the hostkey method
|
||||
*/
|
||||
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_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
|
||||
(void) session;
|
||||
@ -356,6 +398,7 @@ static int libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION *session,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_dss = {
|
||||
@ -380,7 +423,8 @@ static const LIBSSH2_HOSTKEY_METHOD *_libssh2_hostkey_methods[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void)
|
||||
const LIBSSH2_HOSTKEY_METHOD **
|
||||
libssh2_hostkey_methods(void)
|
||||
{
|
||||
return _libssh2_hostkey_methods;
|
||||
}
|
||||
@ -391,7 +435,8 @@ const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void)
|
||||
* Length of buffer is determined by hash type
|
||||
* 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) {
|
||||
#if LIBSSH2_MD5
|
||||
@ -406,6 +451,5 @@ LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
|
738
src/kex.c
738
src/kex.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -38,7 +38,8 @@
|
||||
#include "libssh2_priv.h"
|
||||
#include <string.h>
|
||||
|
||||
int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
int
|
||||
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
|
||||
const unsigned char *edata,
|
||||
unsigned long elen,
|
||||
const unsigned char *ndata,
|
||||
@ -53,8 +54,7 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
unsigned long e1len,
|
||||
const unsigned char *e2data,
|
||||
unsigned long e2len,
|
||||
const unsigned char *coeffdata,
|
||||
unsigned long coefflen)
|
||||
const unsigned char *coeffdata, unsigned long coefflen)
|
||||
{
|
||||
int rc;
|
||||
(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)))",
|
||||
nlen, ndata, elen, edata);
|
||||
}
|
||||
if (rc)
|
||||
{
|
||||
if (rc) {
|
||||
*rsa = NULL;
|
||||
return -1;
|
||||
}
|
||||
@ -81,11 +80,11 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
|
||||
int
|
||||
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m,
|
||||
unsigned long m_len)
|
||||
const unsigned char *m, unsigned long m_len)
|
||||
{
|
||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||
gcry_sexp_t s_sig, s_hash;
|
||||
@ -100,8 +99,7 @@ int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s %b)))",
|
||||
sig_len, sig);
|
||||
rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig);
|
||||
if (rc != 0) {
|
||||
gcry_sexp_release(s_hash);
|
||||
return -1;
|
||||
@ -114,7 +112,8 @@ int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
|
||||
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,
|
||||
unsigned long p_len,
|
||||
const unsigned char *q,
|
||||
@ -123,8 +122,7 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
|
||||
unsigned long g_len,
|
||||
const unsigned char *y,
|
||||
unsigned long y_len,
|
||||
const unsigned char *x,
|
||||
unsigned long x_len)
|
||||
const unsigned char *x, unsigned long x_len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@ -147,10 +145,10 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_rsa_new_private (libssh2_rsa_ctx **rsa,
|
||||
int
|
||||
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase)
|
||||
FILE * fp, unsigned const char *passphrase)
|
||||
{
|
||||
char *data, *save_data;
|
||||
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,
|
||||
q, qlen, e1, e1len, e2, e2len,
|
||||
coeff, coefflen)) {
|
||||
q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
@ -243,10 +240,10 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa,
|
||||
int
|
||||
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase)
|
||||
FILE * fp, unsigned const char *passphrase)
|
||||
{
|
||||
char *data, *save_data;
|
||||
unsigned int datalen;
|
||||
@ -313,8 +310,7 @@ int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (_libssh2_dsa_new (dsa, p, plen, q, qlen,
|
||||
g, glen, y, ylen, x, xlen)) {
|
||||
if (_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
@ -326,12 +322,12 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session,
|
||||
int
|
||||
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_dsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len,
|
||||
unsigned char **signature,
|
||||
unsigned long *signature_len)
|
||||
unsigned char **signature, unsigned long *signature_len)
|
||||
{
|
||||
gcry_sexp_t sig_sexp;
|
||||
gcry_sexp_t data;
|
||||
@ -379,10 +375,10 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx,
|
||||
int
|
||||
_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len,
|
||||
unsigned char *sig)
|
||||
unsigned long hash_len, unsigned char *sig)
|
||||
{
|
||||
unsigned char zhash[SHA_DIGEST_LENGTH + 1];
|
||||
gcry_sexp_t sig_sexp;
|
||||
@ -398,8 +394,7 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx,
|
||||
memcpy(zhash + 1, hash, hash_len);
|
||||
zhash[0] = 0;
|
||||
|
||||
if (gcry_sexp_build (&data, NULL, "(data (value %b))",
|
||||
hash_len + 1, zhash)) {
|
||||
if (gcry_sexp_build(&data, NULL, "(data (value %b))", hash_len + 1, zhash)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -476,10 +471,10 @@ out:
|
||||
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 *m,
|
||||
unsigned long m_len)
|
||||
const unsigned char *m, unsigned long m_len)
|
||||
{
|
||||
unsigned char hash[SHA_DIGEST_LENGTH + 1];
|
||||
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;
|
||||
}
|
||||
|
||||
int _libssh2_cipher_init (_libssh2_cipher_ctx *h,
|
||||
int
|
||||
_libssh2_cipher_init(_libssh2_cipher_ctx * h,
|
||||
_libssh2_cipher_type(algo),
|
||||
unsigned char *iv,
|
||||
unsigned char *secret,
|
||||
int encrypt)
|
||||
unsigned char *iv, unsigned char *secret, int encrypt)
|
||||
{
|
||||
int mode = 0, ret;
|
||||
int keylen = gcry_cipher_get_algo_keylen(algo);
|
||||
@ -544,10 +538,10 @@ int _libssh2_cipher_init (_libssh2_cipher_ctx *h,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx,
|
||||
int
|
||||
_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
_libssh2_cipher_type(algo),
|
||||
int encrypt,
|
||||
unsigned char *block)
|
||||
int encrypt, unsigned char *block)
|
||||
{
|
||||
size_t blklen = gcry_cipher_get_algo_blklen(algo);
|
||||
int ret;
|
||||
@ -557,11 +551,9 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx,
|
||||
}
|
||||
|
||||
if (encrypt) {
|
||||
ret = gcry_cipher_encrypt (*ctx, block, blklen,
|
||||
block, blklen);
|
||||
ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen);
|
||||
} else {
|
||||
ret = gcry_cipher_decrypt (*ctx, block, blklen,
|
||||
block, blklen);
|
||||
ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -108,17 +108,14 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
unsigned long e1len,
|
||||
const unsigned char *e2data,
|
||||
unsigned long e2len,
|
||||
const unsigned char *coeffdata,
|
||||
unsigned long coefflen);
|
||||
const unsigned char *coeffdata, unsigned long coefflen);
|
||||
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase);
|
||||
FILE * fp, unsigned const char *passphrase);
|
||||
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m,
|
||||
unsigned long m_len);
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
@ -139,20 +136,16 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsa,
|
||||
unsigned long glen,
|
||||
const unsigned char *ydata,
|
||||
unsigned long ylen,
|
||||
const unsigned char *x,
|
||||
unsigned long x_len);
|
||||
const unsigned char *x, unsigned long x_len);
|
||||
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase);
|
||||
FILE * fp, unsigned const char *passphrase);
|
||||
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsa,
|
||||
const unsigned char *sig,
|
||||
const unsigned char *m,
|
||||
unsigned long m_len);
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len,
|
||||
unsigned char *sig);
|
||||
unsigned long hash_len, unsigned char *sig);
|
||||
|
||||
#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,
|
||||
_libssh2_cipher_type(algo),
|
||||
unsigned char *iv,
|
||||
unsigned char *secret,
|
||||
int encrypt);
|
||||
unsigned char *secret, int encrypt);
|
||||
|
||||
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
_libssh2_cipher_type(algo),
|
||||
int encrypt,
|
||||
unsigned char *block);
|
||||
int encrypt, unsigned char *block);
|
||||
|
||||
#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 enum {
|
||||
typedef enum
|
||||
{
|
||||
libssh2_NB_state_idle = 0,
|
||||
libssh2_NB_state_allocated,
|
||||
libssh2_NB_state_created,
|
||||
@ -144,16 +145,19 @@ typedef enum {
|
||||
libssh2_NB_state_jump3
|
||||
} libssh2_nonblocking_states;
|
||||
|
||||
typedef struct packet_require_state_t {
|
||||
typedef struct packet_require_state_t
|
||||
{
|
||||
libssh2_nonblocking_states state;
|
||||
time_t start;
|
||||
} packet_require_state_t;
|
||||
|
||||
typedef struct packet_requirev_state_t {
|
||||
typedef struct packet_requirev_state_t
|
||||
{
|
||||
time_t start;
|
||||
} packet_requirev_state_t;
|
||||
|
||||
typedef struct kmdhgGPsha1kex_state_t {
|
||||
typedef struct kmdhgGPsha1kex_state_t
|
||||
{
|
||||
libssh2_nonblocking_states state;
|
||||
unsigned char *e_packet;
|
||||
unsigned char *s_packet;
|
||||
@ -180,7 +184,8 @@ typedef struct kmdhgGPsha1kex_state_t {
|
||||
libssh2_nonblocking_states burn_state;
|
||||
} kmdhgGPsha1kex_state_t;
|
||||
|
||||
typedef struct key_exchange_state_low_t {
|
||||
typedef struct key_exchange_state_low_t
|
||||
{
|
||||
libssh2_nonblocking_states state;
|
||||
packet_require_state_t req_state;
|
||||
kmdhgGPsha1kex_state_t exchange_state;
|
||||
@ -192,7 +197,8 @@ typedef struct key_exchange_state_low_t {
|
||||
unsigned long data_len;
|
||||
} key_exchange_state_low_t;
|
||||
|
||||
typedef struct key_exchange_state_t {
|
||||
typedef struct key_exchange_state_t
|
||||
{
|
||||
libssh2_nonblocking_states state;
|
||||
packet_require_state_t req_state;
|
||||
key_exchange_state_low_t key_state_low;
|
||||
@ -204,7 +210,8 @@ typedef struct key_exchange_state_t {
|
||||
|
||||
#define FwdNotReq "Forward not requested"
|
||||
|
||||
typedef struct packet_queue_listener_state_t {
|
||||
typedef struct packet_queue_listener_state_t
|
||||
{
|
||||
libssh2_nonblocking_states state;
|
||||
unsigned char packet[17 + (sizeof(FwdNotReq) - 1)];
|
||||
unsigned char *host;
|
||||
@ -220,7 +227,8 @@ typedef struct packet_queue_listener_state_t {
|
||||
|
||||
#define X11FwdUnAvil "X11 Forward Unavailable"
|
||||
|
||||
typedef struct packet_x11_open_state_t {
|
||||
typedef struct packet_x11_open_state_t
|
||||
{
|
||||
libssh2_nonblocking_states state;
|
||||
unsigned char packet[17 + (sizeof(X11FwdUnAvil) - 1)];
|
||||
unsigned char *shost;
|
||||
@ -231,7 +239,8 @@ typedef struct packet_x11_open_state_t {
|
||||
uint32_t shost_len;
|
||||
} packet_x11_open_state_t;
|
||||
|
||||
struct _LIBSSH2_PACKET {
|
||||
struct _LIBSSH2_PACKET
|
||||
{
|
||||
unsigned char type;
|
||||
|
||||
/* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */
|
||||
@ -250,11 +259,13 @@ struct _LIBSSH2_PACKET {
|
||||
LIBSSH2_PACKET *next, *prev;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_PACKET_BRIGADE {
|
||||
struct _LIBSSH2_PACKET_BRIGADE
|
||||
{
|
||||
LIBSSH2_PACKET *head, *tail;
|
||||
};
|
||||
|
||||
typedef struct _libssh2_channel_data {
|
||||
typedef struct _libssh2_channel_data
|
||||
{
|
||||
/* Identifier */
|
||||
unsigned long id;
|
||||
|
||||
@ -265,7 +276,8 @@ typedef struct _libssh2_channel_data {
|
||||
char close, eof, extended_data_ignore_mode;
|
||||
} libssh2_channel_data;
|
||||
|
||||
struct _LIBSSH2_CHANNEL {
|
||||
struct _LIBSSH2_CHANNEL
|
||||
{
|
||||
unsigned char *channel_type;
|
||||
unsigned channel_type_len;
|
||||
|
||||
@ -355,11 +367,13 @@ struct _LIBSSH2_CHANNEL {
|
||||
libssh2_nonblocking_states extData2_state;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_CHANNEL_BRIGADE {
|
||||
struct _LIBSSH2_CHANNEL_BRIGADE
|
||||
{
|
||||
LIBSSH2_CHANNEL *head, *tail;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_LISTENER {
|
||||
struct _LIBSSH2_LISTENER
|
||||
{
|
||||
LIBSSH2_SESSION *session;
|
||||
|
||||
char *host;
|
||||
@ -377,7 +391,8 @@ struct _LIBSSH2_LISTENER {
|
||||
size_t chanFwdCncl_data_len;
|
||||
};
|
||||
|
||||
typedef struct _libssh2_endpoint_data {
|
||||
typedef struct _libssh2_endpoint_data
|
||||
{
|
||||
unsigned char *banner;
|
||||
|
||||
unsigned char *kexinit;
|
||||
@ -402,7 +417,8 @@ typedef struct _libssh2_endpoint_data {
|
||||
|
||||
#define PACKETBUFSIZE 4096
|
||||
|
||||
struct transportpacket {
|
||||
struct transportpacket
|
||||
{
|
||||
/* ------------- for incoming data --------------- */
|
||||
unsigned char buf[PACKETBUFSIZE];
|
||||
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 */
|
||||
};
|
||||
|
||||
struct _LIBSSH2_PUBLICKEY {
|
||||
struct _LIBSSH2_PUBLICKEY
|
||||
{
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
unsigned long version;
|
||||
|
||||
@ -464,7 +481,8 @@ struct _LIBSSH2_PUBLICKEY {
|
||||
unsigned long listFetch_data_len;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_SFTP_HANDLE {
|
||||
struct _LIBSSH2_SFTP_HANDLE
|
||||
{
|
||||
LIBSSH2_SFTP *sftp;
|
||||
LIBSSH2_SFTP_HANDLE *prev, *next;
|
||||
|
||||
@ -473,11 +491,14 @@ struct _LIBSSH2_SFTP_HANDLE {
|
||||
|
||||
char handle_type;
|
||||
|
||||
union _libssh2_sftp_handle_data {
|
||||
struct _libssh2_sftp_handle_file_data {
|
||||
union _libssh2_sftp_handle_data
|
||||
{
|
||||
struct _libssh2_sftp_handle_file_data
|
||||
{
|
||||
libssh2_uint64_t offset;
|
||||
} file;
|
||||
struct _libssh2_sftp_handle_dir_data {
|
||||
struct _libssh2_sftp_handle_dir_data
|
||||
{
|
||||
unsigned long names_left;
|
||||
void *names_packet;
|
||||
char *next_name;
|
||||
@ -490,7 +511,8 @@ struct _LIBSSH2_SFTP_HANDLE {
|
||||
unsigned char *close_packet;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_SFTP {
|
||||
struct _LIBSSH2_SFTP
|
||||
{
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
|
||||
unsigned long request_id, version;
|
||||
@ -570,7 +592,8 @@ struct _LIBSSH2_SFTP {
|
||||
|
||||
#define LIBSSH2_SCP_RESPONSE_BUFLEN 256
|
||||
|
||||
struct _LIBSSH2_SESSION {
|
||||
struct _LIBSSH2_SESSION
|
||||
{
|
||||
/* Memory management callbacks */
|
||||
void *abstract;
|
||||
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 */
|
||||
|
||||
struct _LIBSSH2_KEX_METHOD {
|
||||
struct _LIBSSH2_KEX_METHOD
|
||||
{
|
||||
const char *name;
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
struct _LIBSSH2_HOSTKEY_METHOD {
|
||||
struct _LIBSSH2_HOSTKEY_METHOD
|
||||
{
|
||||
const char *name;
|
||||
unsigned long hash_len;
|
||||
|
||||
int (*init)(LIBSSH2_SESSION *session, const unsigned char *hostkey_data, unsigned long hostkey_data_len, void **abstract);
|
||||
int (*initPEM)(LIBSSH2_SESSION *session, const char *privkeyfile, unsigned const char *passphrase, 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 (*init) (LIBSSH2_SESSION * session, const unsigned char *hostkey_data,
|
||||
unsigned long hostkey_data_len, void **abstract);
|
||||
int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile,
|
||||
unsigned const char *passphrase, 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);
|
||||
};
|
||||
|
||||
struct _LIBSSH2_CRYPT_METHOD {
|
||||
struct _LIBSSH2_CRYPT_METHOD
|
||||
{
|
||||
const char *name;
|
||||
|
||||
int blocksize;
|
||||
@ -855,23 +890,31 @@ struct _LIBSSH2_CRYPT_METHOD {
|
||||
|
||||
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 (*crypt)(LIBSSH2_SESSION *session, unsigned char *block, void **abstract);
|
||||
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 (*crypt) (LIBSSH2_SESSION * session, unsigned char *block,
|
||||
void **abstract);
|
||||
int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
|
||||
|
||||
_libssh2_cipher_type(algo);
|
||||
};
|
||||
|
||||
struct _LIBSSH2_COMP_METHOD {
|
||||
struct _LIBSSH2_COMP_METHOD
|
||||
{
|
||||
const char *name;
|
||||
|
||||
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,
|
||||
const unsigned char *src, unsigned long src_len, void **abstract);
|
||||
int (*comp) (LIBSSH2_SESSION * session, int compress, unsigned char **dest,
|
||||
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);
|
||||
};
|
||||
|
||||
struct _LIBSSH2_MAC_METHOD {
|
||||
struct _LIBSSH2_MAC_METHOD
|
||||
{
|
||||
const char *name;
|
||||
|
||||
/* The length of a given MAC packet */
|
||||
@ -881,8 +924,12 @@ struct _LIBSSH2_MAC_METHOD {
|
||||
int key_len;
|
||||
|
||||
/* Message Authentication Code Hashing algo */
|
||||
int (*init)(LIBSSH2_SESSION *session, unsigned char *key, int *free_key, 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 (*init) (LIBSSH2_SESSION * session, unsigned char *key, int *free_key,
|
||||
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);
|
||||
};
|
||||
|
||||
@ -895,7 +942,8 @@ struct _LIBSSH2_MAC_METHOD {
|
||||
#define LIBSSH2_DBG_ERROR 7
|
||||
#define LIBSSH2_DBG_PUBLICKEY 8
|
||||
#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
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
/* 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)
|
||||
#else
|
||||
/* no gcc and not C99, do static and hopefully inline */
|
||||
static inline void _libssh2_debug(LIBSSH2_SESSION *session, int context,
|
||||
const char *format, ...) {}
|
||||
static inline void
|
||||
_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1037,16 +1087,38 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type,
|
||||
const unsigned char *match_buf,
|
||||
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_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);
|
||||
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_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);
|
||||
LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id);
|
||||
unsigned long libssh2_channel_packet_data_len(LIBSSH2_CHANNEL *channel, int stream_id);
|
||||
LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION * session,
|
||||
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 */
|
||||
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,
|
||||
const char *headerbegin,
|
||||
const char *headerend,
|
||||
FILE *fp,
|
||||
char **data, unsigned int *datalen);
|
||||
FILE * fp, 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,
|
||||
unsigned char **i, unsigned int *ilen);
|
||||
|
85
src/mac.c
85
src/mac.c
@ -41,12 +41,15 @@
|
||||
/* {{{ libssh2_mac_none_MAC
|
||||
* Minimalist MAC: No MAC
|
||||
*/
|
||||
static int libssh2_mac_none_MAC(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)
|
||||
static int
|
||||
libssh2_mac_none_MAC(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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
@ -63,7 +66,9 @@ static LIBSSH2_MAC_METHOD libssh2_mac_method_none = {
|
||||
/* {{{ libssh2_mac_method_common_init
|
||||
* 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;
|
||||
*free_key = 0;
|
||||
@ -71,12 +76,14 @@ static int libssh2_mac_method_common_init(LIBSSH2_SESSION *session, unsigned cha
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_mac_method_common_dtor
|
||||
* 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) {
|
||||
LIBSSH2_FREE(session, *abstract);
|
||||
@ -85,14 +92,19 @@ static int libssh2_mac_method_common_dtor(LIBSSH2_SESSION *session, void **abstr
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_mac_method_hmac_sha1_hash
|
||||
* Calculate hash using full sha1 value
|
||||
*/
|
||||
static int libssh2_mac_method_hmac_sha1_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)
|
||||
static int
|
||||
libssh2_mac_method_hmac_sha1_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)
|
||||
{
|
||||
libssh2_hmac_ctx ctx;
|
||||
unsigned char seqno_buf[4];
|
||||
@ -111,6 +123,7 @@ static int libssh2_mac_method_hmac_sha1_hash(LIBSSH2_SESSION *session, unsigned
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
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
|
||||
* 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,
|
||||
const unsigned char *packet, unsigned long packet_len,
|
||||
const unsigned char *addtl, unsigned long addtl_len, void **abstract)
|
||||
static int
|
||||
libssh2_mac_method_hmac_sha1_96_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)
|
||||
{
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
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
|
||||
* Calculate hash using full md5 value
|
||||
*/
|
||||
static int libssh2_mac_method_hmac_md5_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)
|
||||
static int
|
||||
libssh2_mac_method_hmac_md5_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)
|
||||
{
|
||||
libssh2_hmac_ctx ctx;
|
||||
unsigned char seqno_buf[4];
|
||||
@ -171,6 +194,7 @@ static int libssh2_mac_method_hmac_md5_hash(LIBSSH2_SESSION *session, unsigned c
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
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
|
||||
* 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,
|
||||
const unsigned char *packet, unsigned long packet_len,
|
||||
const unsigned char *addtl, unsigned long addtl_len, void **abstract)
|
||||
static int
|
||||
libssh2_mac_method_hmac_md5_96_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)
|
||||
{
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
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
|
||||
* Calculate hash using ripemd160 value
|
||||
*/
|
||||
static int libssh2_mac_method_hmac_ripemd160_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)
|
||||
static int
|
||||
libssh2_mac_method_hmac_ripemd160_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)
|
||||
{
|
||||
libssh2_hmac_ctx ctx;
|
||||
unsigned char seqno_buf[4];
|
||||
@ -232,6 +267,7 @@ static int libssh2_mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION *session, unsi
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160 = {
|
||||
@ -268,7 +304,8 @@ static const LIBSSH2_MAC_METHOD *_libssh2_mac_methods[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const LIBSSH2_MAC_METHOD **libssh2_mac_methods(void) {
|
||||
const LIBSSH2_MAC_METHOD **
|
||||
libssh2_mac_methods(void)
|
||||
{
|
||||
return _libssh2_mac_methods;
|
||||
}
|
||||
|
||||
|
37
src/misc.c
37
src/misc.c
@ -42,17 +42,20 @@
|
||||
|
||||
/* {{{ 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];
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_ntohu64
|
||||
* 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
|
||||
*/
|
||||
libssh2_uint64_t libssh2_ntohu64(const unsigned char *buf)
|
||||
libssh2_uint64_t
|
||||
libssh2_ntohu64(const unsigned char *buf)
|
||||
{
|
||||
unsigned long msl, lsl;
|
||||
|
||||
@ -61,22 +64,26 @@ libssh2_uint64_t libssh2_ntohu64(const unsigned char *buf)
|
||||
|
||||
return ((msl * 65536) * 65536) + lsl;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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[1] = (value >> 16) & 0xFF;
|
||||
buf[2] = (value >> 8) & 0xFF;
|
||||
buf[3] = value & 0xFF;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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;
|
||||
|
||||
@ -90,6 +97,7 @@ void libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
|
||||
buf[6] = (value >> 8) & 0xFF;
|
||||
buf[7] = value & 0xFF;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* 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
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ libssh2_base64_decode
|
||||
* 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,
|
||||
const char *src, unsigned int src_len)
|
||||
LIBSSH2_API int
|
||||
libssh2_base64_decode(LIBSSH2_SESSION * session, char **data,
|
||||
unsigned int *datalen, const char *src,
|
||||
unsigned int src_len)
|
||||
{
|
||||
unsigned char *s, *d;
|
||||
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++) {
|
||||
if ((v = libssh2_base64_reverse_table[*s]) < 0) continue;
|
||||
if ((v = libssh2_base64_reverse_table[*s]) < 0)
|
||||
continue;
|
||||
switch (i % 4) {
|
||||
case 0:
|
||||
d[len] = v << 2;
|
||||
@ -171,17 +183,19 @@ LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, uns
|
||||
*datalen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
#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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _libssh2_debug(LIBSSH2_SESSION *session, int context,
|
||||
const char *format, ...)
|
||||
void
|
||||
_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
|
||||
{
|
||||
char buffer[1536];
|
||||
int len;
|
||||
@ -217,7 +231,8 @@ void _libssh2_debug(LIBSSH2_SESSION *session, int context,
|
||||
}
|
||||
|
||||
#else
|
||||
LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask)
|
||||
LIBSSH2_API int
|
||||
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
|
||||
{
|
||||
(void) session;
|
||||
(void) bitmask;
|
||||
|
@ -43,7 +43,8 @@
|
||||
#define EVP_MAX_BLOCK_LENGTH 32
|
||||
#endif
|
||||
|
||||
int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
int
|
||||
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
|
||||
const unsigned char *edata,
|
||||
unsigned long elen,
|
||||
const unsigned char *ndata,
|
||||
@ -58,8 +59,7 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
unsigned long e1len,
|
||||
const unsigned char *e2data,
|
||||
unsigned long e2len,
|
||||
const unsigned char *coeffdata,
|
||||
unsigned long coefflen)
|
||||
const unsigned char *coeffdata, unsigned long coefflen)
|
||||
{
|
||||
*rsa = RSA_new();
|
||||
|
||||
@ -91,11 +91,11 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsactx,
|
||||
int
|
||||
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m,
|
||||
unsigned long m_len)
|
||||
const unsigned char *m, unsigned long m_len)
|
||||
{
|
||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||
int ret;
|
||||
@ -106,7 +106,8 @@ int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsactx,
|
||||
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,
|
||||
unsigned long p_len,
|
||||
const unsigned char *q,
|
||||
@ -115,8 +116,7 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
|
||||
unsigned long g_len,
|
||||
const unsigned char *y,
|
||||
unsigned long y_len,
|
||||
const unsigned char *x,
|
||||
unsigned long x_len)
|
||||
const unsigned char *x, unsigned long x_len)
|
||||
{
|
||||
*dsactx = DSA_new();
|
||||
|
||||
@ -140,10 +140,10 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsactx,
|
||||
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 *m,
|
||||
unsigned long m_len)
|
||||
const unsigned char *m, unsigned long m_len)
|
||||
{
|
||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||
DSA_SIG dsasig;
|
||||
@ -162,21 +162,20 @@ int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx *dsactx,
|
||||
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),
|
||||
unsigned char *iv,
|
||||
unsigned char *secret,
|
||||
int encrypt)
|
||||
unsigned char *iv, unsigned char *secret, int encrypt)
|
||||
{
|
||||
EVP_CIPHER_CTX_init(h);
|
||||
EVP_CipherInit(h, algo(), secret, iv, encrypt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx,
|
||||
int
|
||||
_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
_libssh2_cipher_type(algo),
|
||||
int encrypt,
|
||||
unsigned char *block)
|
||||
int encrypt, unsigned char *block)
|
||||
{
|
||||
int blocksize = ctx->cipher->block_size;
|
||||
unsigned char buf[EVP_MAX_BLOCK_LENGTH];
|
||||
@ -199,8 +198,7 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx,
|
||||
* calling program
|
||||
*/
|
||||
static int
|
||||
passphrase_cb(char *buf, int size,
|
||||
int rwflag, char *passphrase)
|
||||
passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
|
||||
{
|
||||
int passphrase_len = strlen(passphrase);
|
||||
(void) rwflag;
|
||||
@ -214,10 +212,10 @@ passphrase_cb(char *buf, int size,
|
||||
return passphrase_len;
|
||||
}
|
||||
|
||||
int _libssh2_rsa_new_private (libssh2_rsa_ctx **rsa,
|
||||
int
|
||||
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase)
|
||||
FILE * fp, unsigned const char *passphrase)
|
||||
{
|
||||
(void) session;
|
||||
if (!EVP_get_cipherbyname("des")) {
|
||||
@ -235,10 +233,10 @@ int _libssh2_rsa_new_private (libssh2_rsa_ctx **rsa,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa,
|
||||
int
|
||||
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase)
|
||||
FILE * fp, unsigned const char *passphrase)
|
||||
{
|
||||
(void) session;
|
||||
if (!EVP_get_cipherbyname("des")) {
|
||||
@ -256,12 +254,12 @@ int _libssh2_dsa_new_private (libssh2_dsa_ctx **dsa,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session,
|
||||
int
|
||||
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len,
|
||||
unsigned char **signature,
|
||||
unsigned long *signature_len)
|
||||
unsigned char **signature, unsigned long *signature_len)
|
||||
{
|
||||
int ret;
|
||||
unsigned char *sig;
|
||||
@ -287,10 +285,10 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION *session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *dsactx,
|
||||
int
|
||||
_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len,
|
||||
unsigned char *signature)
|
||||
unsigned long hash_len, unsigned char *signature)
|
||||
{
|
||||
DSA_SIG *sig;
|
||||
int r_len, s_len, rs_pad;
|
||||
|
@ -146,17 +146,14 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
unsigned long e1len,
|
||||
const unsigned char *e2data,
|
||||
unsigned long e2len,
|
||||
const unsigned char *coeffdata,
|
||||
unsigned long coefflen);
|
||||
const unsigned char *coeffdata, unsigned long coefflen);
|
||||
int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase);
|
||||
FILE * fp, unsigned const char *passphrase);
|
||||
int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m,
|
||||
unsigned long m_len);
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
@ -177,20 +174,16 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsa,
|
||||
unsigned long glen,
|
||||
const unsigned char *ydata,
|
||||
unsigned long ylen,
|
||||
const unsigned char *x,
|
||||
unsigned long x_len);
|
||||
const unsigned char *x, unsigned long x_len);
|
||||
int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
FILE *fp,
|
||||
unsigned const char *passphrase);
|
||||
FILE * fp, unsigned const char *passphrase);
|
||||
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *sig,
|
||||
const unsigned char *m,
|
||||
unsigned long m_len);
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
const unsigned char *hash,
|
||||
unsigned long hash_len,
|
||||
unsigned char *sig);
|
||||
unsigned long hash_len, unsigned char *sig);
|
||||
|
||||
#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,
|
||||
_libssh2_cipher_type(algo),
|
||||
unsigned char *iv,
|
||||
unsigned char *secret,
|
||||
int encrypt);
|
||||
unsigned char *secret, int encrypt);
|
||||
|
||||
int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
||||
_libssh2_cipher_type(algo),
|
||||
int encrypt,
|
||||
unsigned char *block);
|
||||
int encrypt, unsigned char *block);
|
||||
|
||||
#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx)
|
||||
|
||||
|
301
src/packet.c
301
src/packet.c
@ -80,18 +80,27 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
(void) datalen;
|
||||
|
||||
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->packet_size = libssh2_ntohu32(s); s += 4;
|
||||
listen_state->initial_window_size = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
listen_state->packet_size = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
|
||||
listen_state->host_len = libssh2_ntohu32(s); s += 4;
|
||||
listen_state->host = s; s += listen_state->host_len;
|
||||
listen_state->port = libssh2_ntohu32(s); s += 4;
|
||||
listen_state->host_len = 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 = s; s += listen_state->shost_len;
|
||||
listen_state->sport = libssh2_ntohu32(s); s += 4;
|
||||
listen_state->shost_len = 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,
|
||||
"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) {
|
||||
if ((listen->port == (int) listen_state->port) &&
|
||||
(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 */
|
||||
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->channel_type_len = sizeof("forwarded-tcpip") - 1;
|
||||
channel->channel_type = LIBSSH2_ALLOC(session,
|
||||
channel->channel_type_len + 1);
|
||||
channel->
|
||||
channel_type_len +
|
||||
1);
|
||||
if (!channel->channel_type) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"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->remote.id = listen_state->sender_channel;
|
||||
channel->remote.window_size_initial = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
|
||||
channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
|
||||
channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
|
||||
channel->remote.window_size_initial =
|
||||
LIBSSH2_CHANNEL_WINDOW_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.window_size_initial = listen_state->initial_window_size;
|
||||
channel->local.window_size = listen_state->initial_window_size;
|
||||
channel->local.window_size_initial =
|
||||
listen_state->initial_window_size;
|
||||
channel->local.window_size =
|
||||
listen_state->initial_window_size;
|
||||
channel->local.packet_size = listen_state->packet_size;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||
@ -185,8 +203,7 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
17);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send channel open confirmation",
|
||||
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);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send open failure", 0);
|
||||
listen_state->state = libssh2_NB_state_idle;
|
||||
@ -250,6 +266,7 @@ libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_packet_x11_open
|
||||
@ -271,12 +288,18 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
(void) datalen;
|
||||
|
||||
if (x11open_state->state == libssh2_NB_state_idle) {
|
||||
x11open_state->sender_channel = libssh2_ntohu32(s); s += 4;
|
||||
x11open_state->initial_window_size = libssh2_ntohu32(s); s += 4;
|
||||
x11open_state->packet_size = libssh2_ntohu32(s); 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;
|
||||
x11open_state->sender_channel = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
x11open_state->initial_window_size = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
x11open_state->packet_size = libssh2_ntohu32(s);
|
||||
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,
|
||||
"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->channel_type_len = sizeof("x11") - 1;
|
||||
channel->channel_type = LIBSSH2_ALLOC(session,
|
||||
channel->channel_type_len + 1);
|
||||
channel->channel_type_len +
|
||||
1);
|
||||
if (!channel->channel_type) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||
"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 */
|
||||
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.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.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
|
||||
|
||||
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.packet_size = x11open_state->packet_size;
|
||||
|
||||
@ -331,10 +358,14 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
channel->remote.packet_size);
|
||||
p = x11open_state->packet;
|
||||
*(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
|
||||
libssh2_htonu32(p, channel->remote.id); p += 4;
|
||||
libssh2_htonu32(p, channel->local.id); p += 4;
|
||||
libssh2_htonu32(p, channel->remote.window_size_initial); p += 4;
|
||||
libssh2_htonu32(p, channel->remote.packet_size); p += 4;
|
||||
libssh2_htonu32(p, channel->remote.id);
|
||||
p += 4;
|
||||
libssh2_htonu32(p, channel->local.id);
|
||||
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;
|
||||
}
|
||||
@ -343,8 +374,7 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
rc = libssh2_packet_write(session, x11open_state->packet, 17);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send channel open confirmation", 0);
|
||||
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
|
||||
* 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;
|
||||
return 0;
|
||||
@ -378,9 +409,12 @@ libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
x11_exit:
|
||||
p = x11open_state->packet;
|
||||
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
|
||||
libssh2_htonu32(p, x11open_state->sender_channel); p += 4;
|
||||
libssh2_htonu32(p, failure_code); p += 4;
|
||||
libssh2_htonu32(p, sizeof(X11FwdUnAvil) - 1); p += 4;
|
||||
libssh2_htonu32(p, x11open_state->sender_channel);
|
||||
p += 4;
|
||||
libssh2_htonu32(p, failure_code);
|
||||
p += 4;
|
||||
libssh2_htonu32(p, sizeof(X11FwdUnAvil) - 1);
|
||||
p += 4;
|
||||
memcpy(s, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1);
|
||||
p += sizeof(X11FwdUnAvil) - 1;
|
||||
libssh2_htonu32(p, 0);
|
||||
@ -388,8 +422,7 @@ x11_exit:
|
||||
rc = libssh2_packet_write(session, x11open_state->packet, packet_len);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send open failure", 0);
|
||||
x11open_state->state = libssh2_NB_state_idle;
|
||||
@ -398,12 +431,14 @@ x11_exit:
|
||||
x11open_state->state = libssh2_NB_state_idle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_packet_new
|
||||
* 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)
|
||||
{
|
||||
int rc;
|
||||
@ -469,11 +504,9 @@ int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data,
|
||||
*/
|
||||
if (session->packAdd_state == libssh2_NB_state_jump1) {
|
||||
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;
|
||||
}
|
||||
else if (session->packAdd_state == libssh2_NB_state_jump3) {
|
||||
} else if (session->packAdd_state == libssh2_NB_state_jump3) {
|
||||
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_channel = libssh2_channel_locate(session,
|
||||
libssh2_ntohu32(data + 1));
|
||||
libssh2_ntohu32
|
||||
(data + 1));
|
||||
|
||||
if (!session->packAdd_channel) {
|
||||
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,
|
||||
"%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->remote.id,
|
||||
stream_id);
|
||||
}
|
||||
#endif
|
||||
if ((session->packAdd_channel->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) &&
|
||||
(data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
|
||||
if ((session->packAdd_channel->remote.
|
||||
extended_data_ignore_mode ==
|
||||
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE)
|
||||
&& (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
|
||||
/* Pretend we didn't receive this */
|
||||
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 */
|
||||
libssh2_packet_add_jump_point1:
|
||||
session->packAdd_state = libssh2_NB_state_jump1;
|
||||
rc = libssh2_channel_receive_window_adjust(session->packAdd_channel,
|
||||
datalen - 13, 0);
|
||||
rc = libssh2_channel_receive_window_adjust(session->
|
||||
packAdd_channel,
|
||||
datalen - 13,
|
||||
0);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
@ -636,7 +675,8 @@ libssh2_packet_add_jump_point1:
|
||||
* REMEMBER! remote means remote as source of data,
|
||||
* 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
|
||||
* packet_size
|
||||
@ -645,7 +685,9 @@ libssh2_packet_add_jump_point1:
|
||||
LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
|
||||
"Packet contains more data than we offered to receive, truncating",
|
||||
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) {
|
||||
/*
|
||||
@ -663,15 +705,19 @@ libssh2_packet_add_jump_point1:
|
||||
/* Reset EOF status */
|
||||
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_CHANNEL_WINDOW_EXCEEDED,
|
||||
"Remote sent more data than current window allows, truncating",
|
||||
0);
|
||||
datalen = session->packAdd_channel->remote.window_size + session->packAdd_data_head;
|
||||
datalen =
|
||||
session->packAdd_channel->remote.window_size +
|
||||
session->packAdd_data_head;
|
||||
} else {
|
||||
/* 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;
|
||||
@ -679,7 +725,8 @@ libssh2_packet_add_jump_point1:
|
||||
case SSH_MSG_CHANNEL_EOF:
|
||||
{
|
||||
session->packAdd_channel = libssh2_channel_locate(session,
|
||||
libssh2_ntohu32(data + 1));
|
||||
libssh2_ntohu32
|
||||
(data + 1));
|
||||
|
||||
if (!session->packAdd_channel) {
|
||||
/* We may have freed already, just quietly ignore this... */
|
||||
@ -704,13 +751,17 @@ libssh2_packet_add_jump_point1:
|
||||
case SSH_MSG_CHANNEL_REQUEST:
|
||||
{
|
||||
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 */
|
||||
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) {
|
||||
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,
|
||||
"Exit status %lu received for channel %lu/%lu",
|
||||
session->packAdd_channel->exit_status,
|
||||
@ -728,7 +779,8 @@ libssh2_packet_add_jump_point1:
|
||||
case SSH_MSG_CHANNEL_CLOSE:
|
||||
{
|
||||
session->packAdd_channel = libssh2_channel_locate(session,
|
||||
libssh2_ntohu32(data + 1));
|
||||
libssh2_ntohu32
|
||||
(data + 1));
|
||||
|
||||
if (!session->packAdd_channel) {
|
||||
/* We may have freed already, just quietly ignore this... */
|
||||
@ -753,13 +805,17 @@ libssh2_packet_add_jump_point1:
|
||||
|
||||
case SSH_MSG_CHANNEL_OPEN:
|
||||
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
|
||||
((sizeof("forwarded-tcpip")-1) == libssh2_ntohu32(data + 1)) &&
|
||||
(memcmp(data + 5, "forwarded-tcpip", sizeof("forwarded-tcpip") - 1) == 0)) {
|
||||
((sizeof("forwarded-tcpip") - 1) == libssh2_ntohu32(data + 1))
|
||||
&&
|
||||
(memcmp
|
||||
(data + 5, "forwarded-tcpip",
|
||||
sizeof("forwarded-tcpip") - 1) == 0)) {
|
||||
|
||||
libssh2_packet_add_jump_point2:
|
||||
session->packAdd_state = libssh2_NB_state_jump2;
|
||||
rc = libssh2_packet_queue_listener(session, data, datalen,
|
||||
&session->packAdd_Qlstn_state);
|
||||
&session->
|
||||
packAdd_Qlstn_state);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
@ -790,7 +846,8 @@ libssh2_packet_add_jump_point3:
|
||||
{
|
||||
unsigned long bytestoadd = libssh2_ntohu32(data + 5);
|
||||
session->packAdd_channel = libssh2_channel_locate(session,
|
||||
libssh2_ntohu32(data + 1));
|
||||
libssh2_ntohu32
|
||||
(data + 1));
|
||||
|
||||
if (session->packAdd_channel && 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) {
|
||||
session->packAdd_packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
|
||||
session->packAdd_packet =
|
||||
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
|
||||
if (!session->packAdd_packet) {
|
||||
_libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate memory for LIBSSH2_PACKET");
|
||||
@ -869,14 +927,18 @@ libssh2_packet_add_jump_point3:
|
||||
session->packAdd_state = libssh2_NB_state_idle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_packet_ask
|
||||
* Scan the brigade for a matching packet type, optionally poll the socket for
|
||||
* a packet first
|
||||
*/
|
||||
int 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)
|
||||
int
|
||||
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;
|
||||
|
||||
@ -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);
|
||||
|
||||
while (packet) {
|
||||
if (packet->data[0] == packet_type && (packet->data_len >= (match_ofs + match_len)) &&
|
||||
(!match_buf || (memcmp(packet->data + match_ofs, match_buf, match_len) == 0))) {
|
||||
if (packet->data[0] == packet_type
|
||||
&& (packet->data_len >= (match_ofs + match_len)) && (!match_buf
|
||||
||
|
||||
(memcmp
|
||||
(packet->
|
||||
data +
|
||||
match_ofs,
|
||||
match_buf,
|
||||
match_len)
|
||||
== 0))) {
|
||||
*data = packet->data;
|
||||
*data_len = packet->data_len;
|
||||
|
||||
@ -921,13 +991,15 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, u
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_packet_askv
|
||||
* Scan for any of a list of packet types in the brigade, optionally poll the
|
||||
* 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,
|
||||
unsigned char **data, unsigned long *data_len,
|
||||
unsigned long match_ofs,
|
||||
@ -952,6 +1024,7 @@ int libssh2_packet_askv_ex(LIBSSH2_SESSION *session,
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ waitsocket
|
||||
@ -962,7 +1035,8 @@ int libssh2_packet_askv_ex(LIBSSH2_SESSION *session,
|
||||
*
|
||||
* 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;
|
||||
int rc;
|
||||
@ -987,42 +1061,48 @@ int libssh2_waitsocket(LIBSSH2_SESSION *session, long seconds)
|
||||
* Returns negative on error
|
||||
* 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,
|
||||
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_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)
|
||||
{
|
||||
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 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
libssh2pack_t ret = libssh2_packet_read(session);
|
||||
if (ret == 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 */
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
} else if (ret < 0) {
|
||||
state->start = 0;
|
||||
/* an error which is not just because of blocking */
|
||||
return ret;
|
||||
}
|
||||
else if (ret == packet_type) {
|
||||
} else if (ret == packet_type) {
|
||||
/* 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;
|
||||
return ret;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
} else if (ret == 0) {
|
||||
/* nothing available, wait until data arrives or we time out */
|
||||
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 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_packet_burn
|
||||
@ -1043,7 +1124,9 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
|
||||
* discards it
|
||||
* 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 long data_len;
|
||||
@ -1056,32 +1139,34 @@ int libssh2_packet_burn(LIBSSH2_SESSION *session, libssh2_nonblocking_states *st
|
||||
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];
|
||||
/* A packet was available in the packet brigade, burn it */
|
||||
LIBSSH2_FREE(session, data);
|
||||
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;
|
||||
}
|
||||
|
||||
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
||||
if ((ret = libssh2_packet_read(session)) == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
} else if (ret < 0) {
|
||||
*state = libssh2_NB_state_idle;
|
||||
return ret;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
} else if (ret == 0) {
|
||||
/* FIXME: this might busyloop */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
LIBSSH2_FREE(session, data);
|
||||
*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 */
|
||||
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
|
||||
*/
|
||||
|
||||
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_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)
|
||||
{
|
||||
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
|
||||
brigade */
|
||||
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)) {
|
||||
state->start = 0;
|
||||
return PACKET_TIMEOUT;
|
||||
}
|
||||
else if (ret == PACKET_EAGAIN) {
|
||||
} else if (ret == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
if (strchr((char *) packet_types, ret)) {
|
||||
/* 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;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
92
src/pem.c
92
src/pem.c
@ -37,18 +37,16 @@
|
||||
|
||||
#include "libssh2_priv.h"
|
||||
|
||||
static int readline (char *line, int line_size, FILE *fp)
|
||||
{
|
||||
if (!fgets(line, line_size, fp))
|
||||
static int
|
||||
readline(char *line, int line_size, FILE * fp)
|
||||
{
|
||||
if (!fgets(line, line_size, fp)) {
|
||||
return -1;
|
||||
}
|
||||
if (*line && line[strlen(line) - 1] == '\n')
|
||||
{
|
||||
if (*line && line[strlen(line) - 1] == '\n') {
|
||||
line[strlen(line) - 1] = '\0';
|
||||
}
|
||||
if (*line && line[strlen(line) - 1] == '\r')
|
||||
{
|
||||
if (*line && line[strlen(line) - 1] == '\r') {
|
||||
line[strlen(line) - 1] = '\0';
|
||||
}
|
||||
return 0;
|
||||
@ -56,21 +54,19 @@ static int readline (char *line, int line_size, FILE *fp)
|
||||
|
||||
#define LINE_SIZE 128
|
||||
|
||||
int _libssh2_pem_parse (LIBSSH2_SESSION *session,
|
||||
int
|
||||
_libssh2_pem_parse(LIBSSH2_SESSION * session,
|
||||
const char *headerbegin,
|
||||
const char *headerend,
|
||||
FILE *fp,
|
||||
char **data, unsigned int *datalen)
|
||||
FILE * fp, char **data, unsigned int *datalen)
|
||||
{
|
||||
char line[LINE_SIZE];
|
||||
char *b64data = NULL;
|
||||
unsigned int b64datalen = 0;
|
||||
int ret;
|
||||
|
||||
do
|
||||
{
|
||||
if (readline(line, LINE_SIZE, fp))
|
||||
{
|
||||
do {
|
||||
if (readline(line, LINE_SIZE, fp)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -78,18 +74,14 @@ int _libssh2_pem_parse (LIBSSH2_SESSION *session,
|
||||
|
||||
*line = '\0';
|
||||
|
||||
do
|
||||
{
|
||||
if (*line)
|
||||
{
|
||||
do {
|
||||
if (*line) {
|
||||
char *tmp;
|
||||
size_t linelen;
|
||||
|
||||
linelen = strlen(line);
|
||||
tmp = LIBSSH2_REALLOC (session, b64data,
|
||||
b64datalen + linelen);
|
||||
if (!tmp)
|
||||
{
|
||||
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
||||
if (!tmp) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
@ -98,16 +90,13 @@ int _libssh2_pem_parse (LIBSSH2_SESSION *session,
|
||||
b64datalen += linelen;
|
||||
}
|
||||
|
||||
if (readline(line, LINE_SIZE, fp))
|
||||
{
|
||||
if (readline(line, LINE_SIZE, fp)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
} while (strcmp(line, headerend) != 0);
|
||||
|
||||
if (libssh2_base64_decode(session, data, datalen,
|
||||
b64data, b64datalen))
|
||||
{
|
||||
if (libssh2_base64_decode(session, data, datalen, b64data, b64datalen)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
@ -120,59 +109,51 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_asn1_length (const unsigned char *data,
|
||||
unsigned int datalen,
|
||||
unsigned int *len)
|
||||
static int
|
||||
read_asn1_length(const unsigned char *data,
|
||||
unsigned int datalen, unsigned int *len)
|
||||
{
|
||||
unsigned int lenlen;
|
||||
int nextpos;
|
||||
|
||||
if (datalen < 1)
|
||||
{
|
||||
if (datalen < 1) {
|
||||
return -1;
|
||||
}
|
||||
*len = data[0];
|
||||
|
||||
if (*len >= 0x80)
|
||||
{
|
||||
if (*len >= 0x80) {
|
||||
lenlen = *len & 0x7F;
|
||||
*len = data[1];
|
||||
if (1 + lenlen > datalen)
|
||||
{
|
||||
if (1 + lenlen > datalen) {
|
||||
return -1;
|
||||
}
|
||||
if (lenlen > 1)
|
||||
{
|
||||
if (lenlen > 1) {
|
||||
*len <<= 8;
|
||||
*len |= data[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
lenlen = 0;
|
||||
}
|
||||
|
||||
nextpos = 1 + lenlen;
|
||||
if (lenlen > 2 || 1 + lenlen + *len > datalen)
|
||||
{
|
||||
if (lenlen > 2 || 1 + lenlen + *len > datalen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
int lenlen;
|
||||
|
||||
if (*datalen < 1)
|
||||
{
|
||||
if (*datalen < 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*data)[0] != '\x30')
|
||||
{
|
||||
if ((*data)[0] != '\x30') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -180,8 +161,7 @@ int _libssh2_pem_decode_sequence (unsigned char **data, unsigned int *datalen)
|
||||
(*datalen)--;
|
||||
|
||||
lenlen = read_asn1_length(*data, *datalen, &len);
|
||||
if (lenlen < 0 || lenlen + len != *datalen)
|
||||
{
|
||||
if (lenlen < 0 || lenlen + len != *datalen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -191,19 +171,18 @@ int _libssh2_pem_decode_sequence (unsigned char **data, unsigned int *datalen)
|
||||
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 int len;
|
||||
int lenlen;
|
||||
|
||||
if (*datalen < 1)
|
||||
{
|
||||
if (*datalen < 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*data)[0] != '\x02')
|
||||
{
|
||||
if ((*data)[0] != '\x02') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -211,8 +190,7 @@ int _libssh2_pem_decode_integer (unsigned char **data, unsigned int *datalen,
|
||||
(*datalen)--;
|
||||
|
||||
lenlen = read_asn1_length(*data, *datalen, &len);
|
||||
if (lenlen < 0 || lenlen + len > *datalen)
|
||||
{
|
||||
if (lenlen < 0 || lenlen + len > *datalen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
566
src/publickey.c
566
src/publickey.c
@ -45,16 +45,20 @@
|
||||
#define LIBSSH2_PUBLICKEY_RESPONSE_VERSION 1
|
||||
#define LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY 2
|
||||
|
||||
typedef struct _LIBSSH2_PUBLICKEY_CODE_LIST {
|
||||
typedef struct _LIBSSH2_PUBLICKEY_CODE_LIST
|
||||
{
|
||||
int code;
|
||||
const char *name;
|
||||
int name_len;
|
||||
} LIBSSH2_PUBLICKEY_CODE_LIST;
|
||||
|
||||
static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_response_codes[] = {
|
||||
{ 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_STATUS, "status", sizeof("status") - 1}
|
||||
,
|
||||
{LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1}
|
||||
,
|
||||
{LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey", sizeof("publickey") - 1}
|
||||
,
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
@ -72,15 +76,32 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_response_codes[] = {
|
||||
#define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX 8
|
||||
|
||||
static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_status_codes[] = {
|
||||
{ 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_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 },
|
||||
{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_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}
|
||||
};
|
||||
|
||||
@ -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_END "\""
|
||||
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 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;
|
||||
}
|
||||
|
||||
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_END) - 1);
|
||||
m = LIBSSH2_ALLOC(session, m_len + 1);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
memcpy(s, status_text, status_text_len); s += status_text_len;
|
||||
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_MID, sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1);
|
||||
memcpy(s, status_text, status_text_len);
|
||||
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;
|
||||
memcpy(s, message, message_len); s += message_len;
|
||||
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_END, sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1);
|
||||
memcpy(s, message, message_len);
|
||||
s += message_len;
|
||||
memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_END,
|
||||
sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1);
|
||||
s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END);
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, m, 1);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_publickey_packet_receive
|
||||
* Read a packet from the subsystem
|
||||
*/
|
||||
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_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);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc != 4) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid response from publickey subsystem", 0);
|
||||
} else if (rc != 4) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
|
||||
"Invalid response from publickey subsystem", 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -165,12 +198,14 @@ libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY *pkey, unsigned char **data,
|
||||
}
|
||||
|
||||
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) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc != pkey->receive_packet_len) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for publickey subsystem response packet", 0);
|
||||
} else if (rc != pkey->receive_packet_len) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
|
||||
"Timeout waiting for publickey subsystem response packet",
|
||||
0);
|
||||
LIBSSH2_FREE(session, pkey->receive_packet);
|
||||
pkey->receive_packet = NULL;
|
||||
pkey->receive_state = libssh2_NB_state_idle;
|
||||
@ -185,23 +220,28 @@ libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY *pkey, unsigned char **data,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_publickey_response_id
|
||||
* Translate a string response name to a numeric code
|
||||
* 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 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) {
|
||||
/* Malformed response */
|
||||
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) {
|
||||
/* Malformed response */
|
||||
return -1;
|
||||
@ -218,12 +258,14 @@ static int libssh2_publickey_response_id(unsigned char **pdata, int data_len)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_publickey_response_success
|
||||
* 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;
|
||||
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);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from publickey subsystem", 0);
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
|
||||
"Timeout waiting for response from publickey subsystem",
|
||||
0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = data;
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
@ -255,14 +299,20 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
|
||||
unsigned long status, descr_len, lang_len;
|
||||
unsigned char *descr, *lang;
|
||||
|
||||
status = libssh2_ntohu32(s); s += 4;
|
||||
descr_len = libssh2_ntohu32(s); s += 4;
|
||||
descr = s; s += descr_len;
|
||||
lang_len = libssh2_ntohu32(s); s += 4;
|
||||
lang = s; s += lang_len;
|
||||
status = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
descr_len = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
descr = s;
|
||||
s += descr_len;
|
||||
lang_len = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
lang = s;
|
||||
s += lang_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);
|
||||
return -1;
|
||||
}
|
||||
@ -272,13 +322,16 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
/* 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);
|
||||
data = NULL;
|
||||
}
|
||||
@ -286,6 +339,7 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
|
||||
/* never reached, but include `return` to silence compiler warnings */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
@ -296,7 +350,8 @@ static int libssh2_publickey_response_success(LIBSSH2_PUBLICKEY *pkey)
|
||||
/* {{{ libssh2_publickey_init
|
||||
* 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) */
|
||||
unsigned char buffer[19];
|
||||
@ -309,23 +364,32 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
|
||||
session->pkeyInit_pkey = 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;
|
||||
}
|
||||
|
||||
if (session->pkeyInit_state == libssh2_NB_state_allocated) {
|
||||
do {
|
||||
session->pkeyInit_channel = libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
|
||||
LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT,
|
||||
NULL, 0);
|
||||
if (!session->pkeyInit_channel && (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)) {
|
||||
session->pkeyInit_channel =
|
||||
libssh2_channel_open_ex(session, "session",
|
||||
sizeof("session") - 1,
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
else if (!session->pkeyInit_channel && (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Unable to startup channel", 0);
|
||||
} else if (!session->pkeyInit_channel
|
||||
&& (libssh2_session_last_errno(session) !=
|
||||
LIBSSH2_ERROR_EAGAIN)) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
|
||||
"Unable to startup channel", 0);
|
||||
goto err_exit;
|
||||
}
|
||||
} 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) {
|
||||
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"));
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Unable to request publickey subsystem", 0);
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
|
||||
"Unable to request publickey subsystem", 0);
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
session->pkeyInit_pkey = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PUBLICKEY));
|
||||
session->pkeyInit_pkey =
|
||||
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PUBLICKEY));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
s = buffer;
|
||||
libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4); s += 4;
|
||||
libssh2_htonu32(s, sizeof("version") - 1); s += 4;
|
||||
memcpy(s, "version", sizeof("version") - 1); s += sizeof("version") - 1;
|
||||
libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION); s += 4;
|
||||
libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4);
|
||||
s += 4;
|
||||
libssh2_htonu32(s, sizeof("version") - 1);
|
||||
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);
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if ((s - buffer) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey version packet", 0);
|
||||
} else if ((s - buffer) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send publickey version packet", 0);
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from publickey subsystem", 0);
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
|
||||
"Timeout waiting for response from publickey subsystem",
|
||||
0);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
s = session->pkeyInit_data;
|
||||
if ((response = libssh2_publickey_response_id(&s, session->pkeyInit_data_len)) < 0) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid publickey subsystem response code", 0);
|
||||
if ((response =
|
||||
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;
|
||||
}
|
||||
|
||||
@ -415,30 +502,44 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
|
||||
unsigned long status, descr_len, lang_len;
|
||||
unsigned char *descr, *lang;
|
||||
|
||||
status = libssh2_ntohu32(s); s += 4;
|
||||
descr_len = libssh2_ntohu32(s); s += 4;
|
||||
descr = s; s += descr_len;
|
||||
lang_len = libssh2_ntohu32(s); s += 4;
|
||||
lang = s; s += lang_len;
|
||||
status = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
descr_len = libssh2_ntohu32(s);
|
||||
s += 4;
|
||||
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) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Malformed publickey subsystem packet", 0);
|
||||
if (s >
|
||||
session->pkeyInit_data + session->pkeyInit_data_len) {
|
||||
libssh2_error(session,
|
||||
LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
|
||||
"Malformed publickey subsystem packet",
|
||||
0);
|
||||
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;
|
||||
}
|
||||
|
||||
case LIBSSH2_PUBLICKEY_RESPONSE_VERSION:
|
||||
/* What we want */
|
||||
session->pkeyInit_pkey->version = libssh2_ntohu32(s);
|
||||
if (session->pkeyInit_pkey->version > LIBSSH2_PUBLICKEY_VERSION) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Truncating remote publickey version from %lu",
|
||||
if (session->pkeyInit_pkey->version >
|
||||
LIBSSH2_PUBLICKEY_VERSION) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
|
||||
"Truncating remote publickey version from %lu",
|
||||
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);
|
||||
LIBSSH2_FREE(session, session->pkeyInit_data);
|
||||
session->pkeyInit_data = NULL;
|
||||
@ -448,7 +549,8 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
|
||||
default:
|
||||
/* Unknown/Unexpected */
|
||||
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);
|
||||
session->pkeyInit_data = NULL;
|
||||
}
|
||||
@ -461,7 +563,8 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
|
||||
if (session->pkeyInit_channel) {
|
||||
rc = libssh2_channel_close(session->pkeyInit_channel);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -476,14 +579,17 @@ LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session)
|
||||
session->pkeyInit_state = libssh2_NB_state_idle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_publickey_add_ex
|
||||
* Add a new public key entry
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, unsigned long name_len,
|
||||
const unsigned char *blob, unsigned long blob_len, char overwrite, unsigned long num_attrs,
|
||||
libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
|
||||
unsigned long name_len, const unsigned char *blob,
|
||||
unsigned long blob_len, char overwrite,
|
||||
unsigned long num_attrs,
|
||||
const libssh2_publickey_attribute attrs[])
|
||||
{
|
||||
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) {
|
||||
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) {
|
||||
for(i = 0; i < num_attrs; i++) {
|
||||
/* Search for a comment attribute */
|
||||
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_len = attrs[i].value_len;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
pkey->add_s = pkey->add_packet;
|
||||
libssh2_htonu32(pkey->add_s, packet_len - 4); pkey->add_s += 4;
|
||||
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;
|
||||
libssh2_htonu32(pkey->add_s, packet_len - 4);
|
||||
pkey->add_s += 4;
|
||||
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) {
|
||||
libssh2_htonu32(pkey->add_s, comment_len); pkey->add_s += 4;
|
||||
libssh2_htonu32(pkey->add_s, comment_len);
|
||||
pkey->add_s += 4;
|
||||
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;
|
||||
memcpy(pkey->add_s, name, name_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;
|
||||
libssh2_htonu32(pkey->add_s, name_len);
|
||||
pkey->add_s += 4;
|
||||
memcpy(pkey->add_s, name, name_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 {
|
||||
/* Version == 2 */
|
||||
|
||||
libssh2_htonu32(pkey->add_s, name_len); pkey->add_s += 4;
|
||||
memcpy(pkey->add_s, name, name_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;
|
||||
libssh2_htonu32(pkey->add_s, name_len);
|
||||
pkey->add_s += 4;
|
||||
memcpy(pkey->add_s, name, name_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;
|
||||
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++) {
|
||||
libssh2_htonu32(pkey->add_s, attrs[i].name_len); pkey->add_s += 4;
|
||||
memcpy(pkey->add_s, attrs[i].name, attrs[i].name_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;
|
||||
libssh2_htonu32(pkey->add_s, attrs[i].name_len);
|
||||
pkey->add_s += 4;
|
||||
memcpy(pkey->add_s, attrs[i].name, attrs[i].name_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;
|
||||
}
|
||||
}
|
||||
|
||||
_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);
|
||||
|
||||
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) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if ((pkey->add_s - pkey->add_packet) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey add packet", 0);
|
||||
} else if ((pkey->add_s - pkey->add_packet) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send publickey add packet", 0);
|
||||
LIBSSH2_FREE(session, pkey->add_packet);
|
||||
pkey->add_packet = NULL;
|
||||
return -1;
|
||||
@ -588,13 +718,15 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, uns
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_publickey_remove_ex
|
||||
* Remove an existing publickey so that authentication can no longer be performed using it
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
pkey->remove_s = pkey->remove_packet;
|
||||
libssh2_htonu32(pkey->remove_s, packet_len - 4); pkey->remove_s += 4;
|
||||
libssh2_htonu32(pkey->remove_s, sizeof("remove") - 1); pkey->remove_s += 4;
|
||||
memcpy(pkey->remove_s, "remove", sizeof("remove") - 1); pkey->remove_s += sizeof("remove") - 1;
|
||||
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_htonu32(pkey->remove_s, packet_len - 4);
|
||||
pkey->remove_s += 4;
|
||||
libssh2_htonu32(pkey->remove_s, sizeof("remove") - 1);
|
||||
pkey->remove_s += 4;
|
||||
memcpy(pkey->remove_s, "remove", sizeof("remove") - 1);
|
||||
pkey->remove_s += sizeof("remove") - 1;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if ((pkey->remove_s - pkey->remove_packet) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey remove packet", 0);
|
||||
} else if ((pkey->remove_s - pkey->remove_packet) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send publickey remove packet", 0);
|
||||
LIBSSH2_FREE(session, pkey->remove_packet);
|
||||
pkey->remove_packet = NULL;
|
||||
pkey->remove_state = libssh2_NB_state_idle;
|
||||
@ -653,13 +797,15 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_publickey_list_fetch
|
||||
* Fetch a list of supported public key from a server
|
||||
*/
|
||||
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_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_s = pkey->listFetch_buffer;
|
||||
libssh2_htonu32(pkey->listFetch_s, buffer_len - 4); pkey->listFetch_s += 4;
|
||||
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_htonu32(pkey->listFetch_s, buffer_len - 4);
|
||||
pkey->listFetch_s += 4;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey list packet", 0);
|
||||
} else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send publickey list packet", 0);
|
||||
pkey->listFetch_state = libssh2_NB_state_idle;
|
||||
return -1;
|
||||
}
|
||||
@ -697,18 +850,23 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
|
||||
}
|
||||
|
||||
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) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from publickey subsystem", 0);
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
|
||||
"Timeout waiting for response from publickey subsystem",
|
||||
0);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
pkey->listFetch_s = pkey->listFetch_data;
|
||||
if ((response = 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);
|
||||
if ((response =
|
||||
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;
|
||||
}
|
||||
|
||||
@ -719,14 +877,21 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
|
||||
unsigned long status, descr_len, lang_len;
|
||||
unsigned char *descr, *lang;
|
||||
|
||||
status = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4;
|
||||
descr_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4;
|
||||
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;
|
||||
status = libssh2_ntohu32(pkey->listFetch_s);
|
||||
pkey->listFetch_s += 4;
|
||||
descr_len = libssh2_ntohu32(pkey->listFetch_s);
|
||||
pkey->listFetch_s += 4;
|
||||
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) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Malformed publickey subsystem packet", 0);
|
||||
if (pkey->listFetch_s >
|
||||
pkey->listFetch_data + pkey->listFetch_data_len) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
|
||||
"Malformed publickey subsystem packet", 0);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
@ -739,7 +904,8 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
|
||||
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;
|
||||
}
|
||||
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;
|
||||
/* Grow the key list if necessary */
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
list = newlist;
|
||||
@ -758,12 +929,17 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, l
|
||||
if (pkey->version == 1) {
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
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].attrs = NULL;
|
||||
}
|
||||
list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4;
|
||||
list[keys].name = pkey->listFetch_s; 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;
|
||||
list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s);
|
||||
pkey->listFetch_s += 4;
|
||||
list[keys].name = pkey->listFetch_s;
|
||||
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 {
|
||||
/* Version == 2 */
|
||||
list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4;
|
||||
list[keys].name = pkey->listFetch_s; 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;
|
||||
list[keys].num_attrs = libssh2_ntohu32(pkey->listFetch_s); pkey->listFetch_s += 4;
|
||||
list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s);
|
||||
pkey->listFetch_s += 4;
|
||||
list[keys].name = pkey->listFetch_s;
|
||||
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;
|
||||
list[keys].num_attrs = libssh2_ntohu32(pkey->listFetch_s);
|
||||
pkey->listFetch_s += 4;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
list[keys].attrs[i].name = (char *) pkey->listFetch_s;
|
||||
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;
|
||||
list[keys].attrs[i].value = (char *) pkey->listFetch_s;
|
||||
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;
|
||||
default:
|
||||
/* 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);
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_publickey_list_free
|
||||
* 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_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_publickey_shutdown
|
||||
* 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;
|
||||
|
||||
@ -891,4 +1090,5 @@ LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey)
|
||||
LIBSSH2_FREE(session, pkey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
435
src/scp.c
435
src/scp.c
@ -46,7 +46,8 @@
|
||||
* otherwise the blocking error code would erase the true
|
||||
* 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 rc;
|
||||
@ -63,21 +64,28 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
if (sb) {
|
||||
memcpy(session->scpRecv_command, "scp -pf ", sizeof("scp -pf ") - 1);
|
||||
memcpy(session->scpRecv_command + sizeof("scp -pf ") - 1, path, path_len);
|
||||
memcpy(session->scpRecv_command, "scp -pf ",
|
||||
sizeof("scp -pf ") - 1);
|
||||
memcpy(session->scpRecv_command + sizeof("scp -pf ") - 1, path,
|
||||
path_len);
|
||||
} else {
|
||||
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';
|
||||
|
||||
_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;
|
||||
}
|
||||
@ -85,18 +93,23 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
if (session->scpRecv_state == libssh2_NB_state_created) {
|
||||
/* Allocate a channel */
|
||||
do {
|
||||
session->scpRecv_channel = libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
|
||||
LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT,
|
||||
NULL, 0);
|
||||
session->scpRecv_channel =
|
||||
libssh2_channel_open_ex(session, "session",
|
||||
sizeof("session") - 1,
|
||||
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
|
||||
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
|
||||
0);
|
||||
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);
|
||||
session->scpRecv_command = NULL;
|
||||
session->scpRecv_state = libssh2_NB_state_idle;
|
||||
return NULL;
|
||||
}
|
||||
else if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting up channel", 0);
|
||||
} else if (libssh2_session_last_errno(session) ==
|
||||
LIBSSH2_ERROR_EAGAIN) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block starting up channel", 0);
|
||||
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) {
|
||||
/* 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) {
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
LIBSSH2_FREE(session, session->scpRecv_command);
|
||||
session->scpRecv_command = NULL;
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if (rc != 1) {
|
||||
} else if (rc != 1) {
|
||||
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;
|
||||
}
|
||||
|
||||
if ((session->scpRecv_state == libssh2_NB_state_sent2) || (session->scpRecv_state == libssh2_NB_state_sent3)) {
|
||||
while (sb && (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN)) {
|
||||
if ((session->scpRecv_state == libssh2_NB_state_sent2)
|
||||
|| (session->scpRecv_state == libssh2_NB_state_sent3)) {
|
||||
while (sb
|
||||
&& (session->scpRecv_response_len <
|
||||
LIBSSH2_SCP_RESPONSE_BUFLEN)) {
|
||||
unsigned char *s, *p;
|
||||
|
||||
if (session->scpRecv_state == libssh2_NB_state_sent2) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if (rc <= 0) {
|
||||
} else if (rc <= 0) {
|
||||
/* 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;
|
||||
}
|
||||
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
|
||||
* 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_msg = LIBSSH2_ALLOC(session, session->scpRecv_err_len+1);
|
||||
session->scpRecv_err_len =
|
||||
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) {
|
||||
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 */
|
||||
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) {
|
||||
/*
|
||||
* 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);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
goto scp_recv_error;
|
||||
}
|
||||
|
||||
if ((session->scpRecv_response_len > 1) &&
|
||||
((session->scpRecv_response[session->scpRecv_response_len-1] < '0') ||
|
||||
(session->scpRecv_response[session->scpRecv_response_len-1] > '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);
|
||||
((session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1] <
|
||||
'0')
|
||||
|| (session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1] >
|
||||
'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;
|
||||
}
|
||||
|
||||
if ((session->scpRecv_response_len < 9) || (session->scpRecv_response[session->scpRecv_response_len-1] != '\n')) {
|
||||
if (session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) {
|
||||
if ((session->scpRecv_response_len < 9)
|
||||
|| (session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1] !=
|
||||
'\n')) {
|
||||
if (session->scpRecv_response_len ==
|
||||
LIBSSH2_SCP_RESPONSE_BUFLEN) {
|
||||
/* 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;
|
||||
}
|
||||
/* 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 */
|
||||
while ((session->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';
|
||||
while ((session->
|
||||
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) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -228,7 +288,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
p = (unsigned char *) strchr((char *) s, ' ');
|
||||
if (!p || ((p - s) <= 0)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -237,13 +299,17 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
errno = 0;
|
||||
session->scpRecv_mtime = strtol((char *) s, NULL, 10);
|
||||
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;
|
||||
}
|
||||
s = (unsigned char *) strchr((char *) p, ' ');
|
||||
if (!s || ((s - p) <= 0)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -252,7 +318,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
p = (unsigned char *) strchr((char *) s, ' ');
|
||||
if (!p || ((p - s) <= 0)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -261,7 +329,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
errno = 0;
|
||||
session->scpRecv_atime = strtol((char *) s, NULL, 10);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -272,16 +342,20 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if (rc != 1) {
|
||||
} else if (rc != 1) {
|
||||
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? */
|
||||
break;
|
||||
@ -297,42 +371,62 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
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) {
|
||||
char *s, *p, *e = NULL;
|
||||
|
||||
if (session->scpRecv_state == libssh2_NB_state_sent5) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if (rc <= 0) {
|
||||
} else if (rc <= 0) {
|
||||
/* 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;
|
||||
}
|
||||
session->scpRecv_response_len++;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ((session->scpRecv_response_len > 1) &&
|
||||
(session->scpRecv_response[session->scpRecv_response_len-1] != '\r') &&
|
||||
(session->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);
|
||||
(session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1] !=
|
||||
'\r')
|
||||
&& (session->
|
||||
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;
|
||||
}
|
||||
|
||||
if ((session->scpRecv_response_len < 7) || (session->scpRecv_response[session->scpRecv_response_len-1] != '\n')) {
|
||||
if (session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) {
|
||||
if ((session->scpRecv_response_len < 7)
|
||||
|| (session->
|
||||
scpRecv_response[session->scpRecv_response_len - 1] !=
|
||||
'\n')) {
|
||||
if (session->scpRecv_response_len ==
|
||||
LIBSSH2_SCP_RESPONSE_BUFLEN) {
|
||||
/* 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;
|
||||
}
|
||||
/* 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 */
|
||||
while ((session->scpRecv_response[session->scpRecv_response_len-1] == '\r') ||
|
||||
(session->scpRecv_response[session->scpRecv_response_len-1] == '\n')) {
|
||||
while ((session->
|
||||
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';
|
||||
session->scpRecv_response[session->scpRecv_response_len] =
|
||||
'\0';
|
||||
|
||||
if (session->scpRecv_response_len < 6) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -357,7 +458,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
p = strchr(s, ' ');
|
||||
if (!p || ((p - s) <= 0)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -366,14 +469,17 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
errno = 0;
|
||||
session->scpRecv_mode = strtol(s, &e, 8);
|
||||
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;
|
||||
}
|
||||
|
||||
s = strchr(p, ' ');
|
||||
if (!s || ((s - p) <= 0)) {
|
||||
/* 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);
|
||||
goto scp_recv_error;
|
||||
}
|
||||
@ -383,7 +489,9 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
errno = 0;
|
||||
session->scpRecv_size = strtol(p, &e, 10);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -394,15 +502,19 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if (rc != 1) {
|
||||
} else if (rc != 1) {
|
||||
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? */
|
||||
break;
|
||||
@ -430,6 +542,7 @@ scp_recv_error:
|
||||
session->scpRecv_state = libssh2_NB_state_idle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_scp_send_ex
|
||||
@ -440,7 +553,8 @@ scp_recv_error:
|
||||
* cause of the error.
|
||||
*/
|
||||
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);
|
||||
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 = LIBSSH2_ALLOC(session, session->scpSend_command_len);
|
||||
session->scpSend_command =
|
||||
LIBSSH2_ALLOC(session, session->scpSend_command_len);
|
||||
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;
|
||||
}
|
||||
|
||||
if (mtime || atime) {
|
||||
memcpy(session->scpSend_command, "scp -pt ", sizeof("scp -pt ") - 1);
|
||||
memcpy(session->scpSend_command + sizeof("scp -pt ") - 1, path, path_len);
|
||||
memcpy(session->scpSend_command, "scp -pt ",
|
||||
sizeof("scp -pt ") - 1);
|
||||
memcpy(session->scpSend_command + sizeof("scp -pt ") - 1, path,
|
||||
path_len);
|
||||
} else {
|
||||
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';
|
||||
|
||||
_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 */
|
||||
|
||||
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,
|
||||
LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
|
||||
session->scpSend_channel =
|
||||
libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
|
||||
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
|
||||
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
|
||||
if (!session->scpSend_channel) {
|
||||
if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
|
||||
/* 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_state = libssh2_NB_state_idle;
|
||||
return NULL;
|
||||
}
|
||||
else if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting up channel", 0);
|
||||
} else if (libssh2_session_last_errno(session) ==
|
||||
LIBSSH2_ERROR_EAGAIN) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||
"Would block starting up channel", 0);
|
||||
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) {
|
||||
/* Request SCP for the desired file */
|
||||
rc = libssh2_channel_process_startup(session->scpSend_channel, "exec", sizeof("exec") - 1,
|
||||
(char *)session->scpSend_command, session->scpSend_command_len);
|
||||
rc = libssh2_channel_process_startup(session->scpSend_channel, "exec",
|
||||
sizeof("exec") - 1,
|
||||
(char *) session->scpSend_command,
|
||||
session->scpSend_command_len);
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
/* previous call set libssh2_session_last_error(), pass it through */
|
||||
LIBSSH2_FREE(session, session->scpSend_command);
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
/* 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) {
|
||||
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;
|
||||
}
|
||||
else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0);
|
||||
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid ACK response from remote", 0);
|
||||
goto scp_send_error;
|
||||
}
|
||||
|
||||
if (mtime || atime) {
|
||||
/* Send mtime and atime to be used for file */
|
||||
session->scpSend_response_len = snprintf((char *)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_response_len =
|
||||
snprintf((char *) 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;
|
||||
@ -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 */
|
||||
if (mtime || atime) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
else if (rc != session->scpSend_response_len) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send time data for SCP file", 0);
|
||||
} else if (rc != session->scpSend_response_len) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send time data for SCP file", 0);
|
||||
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) {
|
||||
/* 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) {
|
||||
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;
|
||||
}
|
||||
else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0);
|
||||
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid ACK response from remote", 0);
|
||||
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;
|
||||
}
|
||||
|
||||
session->scpSend_response_len = snprintf((char *)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_response_len =
|
||||
snprintf((char *) 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;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
else if (rc != session->scpSend_response_len) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send core file data for SCP file", 0);
|
||||
} else if (rc != session->scpSend_response_len) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to send core file data for SCP file", 0);
|
||||
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) {
|
||||
/* 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) {
|
||||
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;
|
||||
}
|
||||
else if (rc <= 0) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0);
|
||||
} else if (rc <= 0) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||
"Invalid ACK response from remote", 0);
|
||||
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
|
||||
* 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_msg = LIBSSH2_ALLOC(session, session->scpSend_err_len+1);
|
||||
session->scpSend_err_len =
|
||||
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) {
|
||||
goto scp_send_error;
|
||||
}
|
||||
memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
|
||||
|
||||
/* 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) {
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
goto scp_send_error;
|
||||
}
|
||||
@ -658,5 +807,5 @@ scp_send_error:
|
||||
session->scpSend_state = libssh2_NB_state_idle;
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* }}} */
|
||||
|
350
src/session.c
350
src/session.c
@ -52,29 +52,35 @@
|
||||
|
||||
/* {{{ libssh2_default_alloc
|
||||
*/
|
||||
static LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
|
||||
static
|
||||
LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
|
||||
{
|
||||
(void) abstract;
|
||||
return malloc(count);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_default_free
|
||||
*/
|
||||
static LIBSSH2_FREE_FUNC(libssh2_default_free)
|
||||
static
|
||||
LIBSSH2_FREE_FUNC(libssh2_default_free)
|
||||
{
|
||||
(void) abstract;
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_default_realloc
|
||||
*/
|
||||
static LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
|
||||
static
|
||||
LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
|
||||
{
|
||||
(void) abstract;
|
||||
return realloc(ptr, count);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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
|
||||
* 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 banner_len;
|
||||
@ -96,10 +103,13 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
|
||||
}
|
||||
|
||||
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';
|
||||
|
||||
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) {
|
||||
#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') {
|
||||
/* 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_total_send = 0;
|
||||
|
||||
if (!banner_len) return 1;
|
||||
if (!banner_len)
|
||||
return 1;
|
||||
|
||||
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
|
||||
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;
|
||||
}
|
||||
memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
|
||||
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;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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
|
||||
* (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;
|
||||
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 = (char *) session->local.banner;
|
||||
}
|
||||
|
||||
#ifdef LIBSSH2DEBUG
|
||||
/* Hack and slash to avoid sending CRLF in debug output */
|
||||
if (banner_len < 256) {
|
||||
@ -203,13 +218,16 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
|
||||
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
|
||||
|
||||
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));
|
||||
|
||||
if (ret != (banner_len - session->banner_TxRx_total_send)) {
|
||||
@ -229,6 +247,7 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
|
||||
|
||||
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
|
||||
* 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 */ )
|
||||
{
|
||||
#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
|
||||
* 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
|
||||
#define GETBLOCK 0
|
||||
#ifdef HAVE_O_NONBLOCK
|
||||
@ -326,7 +347,8 @@ static int _libssh2_get_socket_nonblocking(int sockfd) /* operate on this */
|
||||
unsigned int 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 */
|
||||
return 1;
|
||||
}
|
||||
@ -361,7 +383,8 @@ static int _libssh2_get_socket_nonblocking(int sockfd) /* operate on this */
|
||||
/* {{{ libssh2_banner_set
|
||||
* 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;
|
||||
|
||||
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
memcpy(session->local.banner, banner, banner_len);
|
||||
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++] = '\n';
|
||||
session->local.banner[banner_len++] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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
|
||||
* 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_ALLOC_FUNC((*my_alloc)),
|
||||
LIBSSH2_API LIBSSH2_SESSION *
|
||||
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
||||
LIBSSH2_FREE_FUNC((*my_free)),
|
||||
LIBSSH2_REALLOC_FUNC((*my_realloc)),
|
||||
void *abstract)
|
||||
LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract)
|
||||
{
|
||||
LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc;
|
||||
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->realloc = local_realloc;
|
||||
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();
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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
|
||||
* 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)
|
||||
{
|
||||
void *oldcb;
|
||||
@ -475,6 +503,7 @@ LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto libssh2_session_startup
|
||||
@ -484,7 +513,8 @@ LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session,
|
||||
* callbacks in session
|
||||
* 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;
|
||||
|
||||
@ -494,12 +524,14 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
|
||||
/* FIXME: on some platforms (like win32) sockets are unsigned */
|
||||
if (socket < 0) {
|
||||
/* 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;
|
||||
}
|
||||
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) {
|
||||
/*
|
||||
* 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) {
|
||||
rc = libssh2_banner_send(session);
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -532,12 +565,13 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
|
||||
if (session->startup_state == libssh2_NB_state_sent) {
|
||||
rc = libssh2_banner_receive(session);
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -547,11 +581,12 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
|
||||
if (session->startup_state == libssh2_NB_state_sent1) {
|
||||
rc = libssh2_kex_exchange(session, 0, &session->startup_key_state);
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, "Unable to exchange encryption keys", 0);
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
|
||||
"Unable to exchange encryption keys", 0);
|
||||
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) {
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Requesting userauth service");
|
||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||
"Requesting userauth service");
|
||||
|
||||
/* Request the userauth service */
|
||||
session->startup_service[0] = SSH_MSG_SERVICE_REQUEST;
|
||||
libssh2_htonu32(session->startup_service + 1, sizeof("ssh-userauth") - 1);
|
||||
memcpy(session->startup_service + 5, "ssh-userauth", sizeof("ssh-userauth") - 1);
|
||||
libssh2_htonu32(session->startup_service + 1,
|
||||
sizeof("ssh-userauth") - 1);
|
||||
memcpy(session->startup_service + 5, "ssh-userauth",
|
||||
sizeof("ssh-userauth") - 1);
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to ask for ssh-userauth service", 0);
|
||||
} else if (rc) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||
"Unable to ask for ssh-userauth service", 0);
|
||||
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) {
|
||||
rc = libssh2_packet_require_ex(session, SSH_MSG_SERVICE_ACCEPT, &session->startup_data, &session->startup_data_len,
|
||||
0, NULL, 0, &session->startup_req_state);
|
||||
rc = libssh2_packet_require_ex(session, SSH_MSG_SERVICE_ACCEPT,
|
||||
&session->startup_data,
|
||||
&session->startup_data_len, 0, NULL, 0,
|
||||
&session->startup_req_state);
|
||||
if (rc == PACKET_EAGAIN) {
|
||||
return LIBSSH2_ERROR_EAGAIN;
|
||||
}
|
||||
else if (rc) {
|
||||
} else if (rc) {
|
||||
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)) ||
|
||||
strncmp("ssh-userauth", (char *)session->startup_data + 5, session->startup_service_length)) {
|
||||
if ((session->startup_service_length != (sizeof("ssh-userauth") - 1))
|
||||
|| strncmp("ssh-userauth", (char *) session->startup_data + 5,
|
||||
session->startup_service_length)) {
|
||||
LIBSSH2_FREE(session, session->startup_data);
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto libssh2_session_free
|
||||
* Frees the memory allocated to the 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;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -673,11 +720,13 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session)
|
||||
/* Client to Server */
|
||||
/* crypt */
|
||||
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 */
|
||||
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 */
|
||||
if (session->local.mac && session->local.mac->dtor) {
|
||||
@ -687,11 +736,13 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session)
|
||||
/* Server to Client */
|
||||
/* crypt */
|
||||
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 */
|
||||
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 */
|
||||
if (session->remote.mac && session->remote.mac->dtor) {
|
||||
@ -840,18 +891,23 @@ LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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 long descr_len = 0, lang_len = 0;
|
||||
int rc;
|
||||
|
||||
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) {
|
||||
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) */
|
||||
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) {
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(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) {
|
||||
memcpy(s, description, descr_len);
|
||||
s += descr_len;
|
||||
}
|
||||
|
||||
libssh2_htonu32(s, lang_len); s += 4;
|
||||
libssh2_htonu32(s, lang_len);
|
||||
s += 4;
|
||||
if (lang) {
|
||||
memcpy(s, lang, 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
@ -897,6 +960,7 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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
|
||||
* 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 */
|
||||
const LIBSSH2_KEX_METHOD *method = NULL;
|
||||
@ -951,27 +1016,32 @@ LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, int me
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
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 method->name;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_session_abstract
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ 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
|
||||
*/
|
||||
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 */
|
||||
if (!session->err_code) {
|
||||
@ -1001,8 +1072,7 @@ libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_
|
||||
}
|
||||
|
||||
if (errmsg) {
|
||||
char *serrmsg = session->err_msg ? session->err_msg :
|
||||
(char *)"";
|
||||
char *serrmsg = session->err_msg ? session->err_msg : (char *) "";
|
||||
int ownbuf = session->err_msg ? session->err_should_free : 0;
|
||||
|
||||
if (want_buf) {
|
||||
@ -1029,6 +1099,7 @@ libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_
|
||||
|
||||
return session->err_code;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_session_last_error
|
||||
@ -1039,13 +1110,15 @@ libssh2_session_last_errno(LIBSSH2_SESSION *session)
|
||||
{
|
||||
return session->err_code;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_session_flag
|
||||
* Set/Get session flags
|
||||
* 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) {
|
||||
session->flags |= flag;
|
||||
@ -1055,16 +1128,19 @@ LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int val
|
||||
|
||||
return session->flags;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _libssh2_session_set_blocking
|
||||
* Set a session's blocking mode on or off, return the previous status
|
||||
* 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;
|
||||
_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) {
|
||||
/* avoid if already correct */
|
||||
return bl;
|
||||
@ -1075,32 +1151,38 @@ int _libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
|
||||
|
||||
return bl;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_session_set_blocking
|
||||
* Set a channel's blocking mode on or off, similar to a socket's
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_session_get_blocking
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_poll_channel_read
|
||||
* Returns 0 if no data is waiting on channel,
|
||||
* 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_PACKET *packet = session->packets.head;
|
||||
@ -1108,8 +1190,9 @@ LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended
|
||||
while (packet) {
|
||||
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) && (extended == 0) &&
|
||||
(channel->local.id == libssh2_ntohu32(packet->data + 1))) ||
|
||||
((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (extended != 0) &&
|
||||
(channel->local.id == libssh2_ntohu32(packet->data + 1)))) {
|
||||
((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
|
||||
&& (extended != 0)
|
||||
&& (channel->local.id == libssh2_ntohu32(packet->data + 1)))) {
|
||||
/* Found data waiting to be read */
|
||||
return 1;
|
||||
}
|
||||
@ -1118,32 +1201,38 @@ LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_poll_channel_write
|
||||
* Returns 0 if writing to channel would block,
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_poll_listener_queued
|
||||
* Returns 0 if no connections are waiting to be accepted
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_poll
|
||||
* 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;
|
||||
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].events = POLLIN;
|
||||
sockets[i].revents = 0;
|
||||
if (!session) session = fds[i].fd.channel->session;
|
||||
if (!session)
|
||||
session = fds[i].fd.channel->session;
|
||||
break;
|
||||
|
||||
case LIBSSH2_POLLFD_LISTENER:
|
||||
sockets[i].fd = fds[i].fd.listener->session->socket_fd;
|
||||
sockets[i].events = POLLIN;
|
||||
sockets[i].revents = 0;
|
||||
if (!session) session = fds[i].fd.listener->session;
|
||||
if (!session)
|
||||
session = fds[i].fd.listener->session;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (session) libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
|
||||
"Invalid descriptor passed to libssh2_poll()", 0);
|
||||
if (session)
|
||||
libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
|
||||
"Invalid descriptor passed to libssh2_poll()",
|
||||
0);
|
||||
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);
|
||||
if (fds[i].fd.channel->session->socket_fd > maxfd)
|
||||
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;
|
||||
|
||||
case LIBSSH2_POLLFD_LISTENER:
|
||||
FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
|
||||
if (fds[i].fd.listener->session->socket_fd > maxfd)
|
||||
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;
|
||||
|
||||
default:
|
||||
@ -1257,31 +1352,50 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
|
||||
case LIBSSH2_POLLFD_CHANNEL:
|
||||
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_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 */
|
||||
((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 */
|
||||
((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;
|
||||
}
|
||||
if (fds[i].fd.channel->session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
|
||||
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED;
|
||||
if (fds[i].fd.channel->session->socket_state ==
|
||||
LIBSSH2_SOCKET_DISCONNECTED) {
|
||||
fds[i].revents |=
|
||||
LIBSSH2_POLLFD_CHANNEL_CLOSED |
|
||||
LIBSSH2_POLLFD_SESSION_CLOSED;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIBSSH2_POLLFD_LISTENER:
|
||||
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_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) {
|
||||
fds[i].revents |= LIBSSH2_POLLFD_LISTENER_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED;
|
||||
if (fds[i].fd.listener->session->socket_state ==
|
||||
LIBSSH2_SOCKET_DISCONNECTED) {
|
||||
fds[i].revents |=
|
||||
LIBSSH2_POLLFD_LISTENER_CLOSED |
|
||||
LIBSSH2_POLLFD_SESSION_CLOSED;
|
||||
}
|
||||
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 */
|
||||
timeout_remaining = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
@ -1329,20 +1442,26 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
|
||||
case LIBSSH2_POLLFD_CHANNEL:
|
||||
if (sockets[i].events & POLLIN) {
|
||||
/* 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) {
|
||||
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;
|
||||
break;
|
||||
case LIBSSH2_POLLFD_LISTENER:
|
||||
if (sockets[i].events & POLLIN) {
|
||||
/* 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) {
|
||||
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;
|
||||
break;
|
||||
@ -1389,14 +1508,17 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
|
||||
case LIBSSH2_POLLFD_CHANNEL:
|
||||
if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
|
||||
/* 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;
|
||||
|
||||
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 */
|
||||
while (libssh2_packet_read(fds[i].fd.listener->session) > 0);
|
||||
while (libssh2_packet_read(fds[i].fd.listener->session)
|
||||
> 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1407,5 +1529,5 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
|
||||
|
||||
return active_fds;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* }}} */
|
||||
|
949
src/sftp.c
949
src/sftp.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -48,9 +48,9 @@
|
||||
|
||||
#ifdef LIBSSH2DEBUG
|
||||
#define UNPRINTABLE_CHAR '.'
|
||||
static void debugdump(LIBSSH2_SESSION *session,
|
||||
const char *desc, unsigned char *ptr,
|
||||
unsigned long size)
|
||||
static void
|
||||
debugdump(LIBSSH2_SESSION * session,
|
||||
const char *desc, unsigned char *ptr, unsigned long size)
|
||||
{
|
||||
size_t i;
|
||||
size_t c;
|
||||
@ -66,7 +66,7 @@ static void debugdump(LIBSSH2_SESSION *session,
|
||||
|
||||
for(i = 0; i < size; i += width) {
|
||||
|
||||
fprintf(stream, "%04lx: ", i);
|
||||
fprintf(stream, "%04lx: ", (long)i);
|
||||
|
||||
/* hex not disabled, show it */
|
||||
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
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
struct transportpacket *p = &session->packet;
|
||||
@ -144,11 +145,11 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
|
||||
if (encrypted) {
|
||||
|
||||
/* Calculate MAC hash */
|
||||
session->remote.mac->hash(session,
|
||||
macbuf, /* store hash here */
|
||||
session->remote.mac->hash(session, macbuf, /* store hash here */
|
||||
session->remote.seqno,
|
||||
p->init, 5,
|
||||
p->payload, session->fullpacket_payload_len,
|
||||
p->payload,
|
||||
session->fullpacket_payload_len,
|
||||
&session->remote.mac_abstract);
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Check for and deal with decompression */
|
||||
if (session->remote.comp &&
|
||||
strcmp(session->remote.comp->name, "none")) {
|
||||
if (session->remote.comp && strcmp(session->remote.comp->name, "none")) {
|
||||
unsigned char *data;
|
||||
unsigned long data_len;
|
||||
int free_payload = 1;
|
||||
@ -178,7 +178,8 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
|
||||
&data, &data_len,
|
||||
LIBSSH2_PACKET_MAXDECOMP,
|
||||
&free_payload,
|
||||
p->payload, session->fullpacket_payload_len,
|
||||
p->payload,
|
||||
session->fullpacket_payload_len,
|
||||
&session->remote.comp_abstract)) {
|
||||
LIBSSH2_FREE(session, p->payload);
|
||||
return PACKET_FAIL;
|
||||
@ -188,16 +189,14 @@ fullpacket(LIBSSH2_SESSION *session, int encrypted /* 1 or 0 */)
|
||||
LIBSSH2_FREE(session, p->payload);
|
||||
p->payload = data;
|
||||
session->fullpacket_payload_len = data_len;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (data == p->payload) {
|
||||
/* It's not to be freed, because the
|
||||
* compression layer reused payload, So let's
|
||||
* do the same!
|
||||
*/
|
||||
session->fullpacket_payload_len = data_len;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* No comp_method actually lets this happen,
|
||||
* 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 */
|
||||
p->payload = LIBSSH2_ALLOC(session, data_len);
|
||||
if (!p->payload) {
|
||||
libssh2_error(session,
|
||||
LIBSSH2_ERROR_ALLOC,
|
||||
(char *)"Unable to allocate memory for copy of uncompressed data", 0);
|
||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC, (char *)
|
||||
"Unable to allocate memory for copy of uncompressed data",
|
||||
0);
|
||||
return PACKET_ENOMEM;
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
return PACKET_EAGAIN;
|
||||
}
|
||||
else if (rc < 0) {
|
||||
} else if (rc < 0) {
|
||||
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
|
||||
* "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;
|
||||
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 */
|
||||
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));
|
||||
if (nread <= 0) {
|
||||
/* 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
|
||||
(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:
|
||||
*
|
||||
@ -515,11 +520,14 @@ libssh2_packet_read_point1:
|
||||
|
||||
return PACKET_FAIL; /* we never reach this point */
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
#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 length;
|
||||
@ -545,15 +553,15 @@ static libssh2pack_t send_existing(LIBSSH2_SESSION *session, unsigned char *data
|
||||
/* number of bytes left to send */
|
||||
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) {
|
||||
/* the remainder of the package was sent */
|
||||
LIBSSH2_FREE(session, p->outbuf);
|
||||
p->outbuf = NULL;
|
||||
p->ototal_num = 0;
|
||||
}
|
||||
else if (rc < 0) {
|
||||
} else if (rc < 0) {
|
||||
/* nothing was sent */
|
||||
if (errno != EAGAIN) {
|
||||
/* send failure! */
|
||||
@ -562,7 +570,8 @@ static libssh2pack_t send_existing(LIBSSH2_SESSION *session, unsigned char *data
|
||||
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 */
|
||||
|
||||
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
|
||||
* (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 packet_length;
|
||||
int total_length;
|
||||
@ -608,7 +621,8 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
|
||||
|
||||
/* check if we should compress */
|
||||
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)) {
|
||||
return PACKET_COMPRESS; /* compression failure */
|
||||
}
|
||||
@ -650,7 +664,8 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
|
||||
packet_length += padding_length;
|
||||
|
||||
/* 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
|
||||
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
|
||||
calculated on the entire unencrypted packet, including all
|
||||
fields except the MAC field itself. */
|
||||
session->local.mac->hash(session, p->outbuf + packet_length, session->local.seqno, p->outbuf, packet_length,
|
||||
NULL, 0, &session->local.mac_abstract);
|
||||
session->local.mac->hash(session, p->outbuf + packet_length,
|
||||
session->local.seqno, p->outbuf,
|
||||
packet_length, NULL, 0,
|
||||
&session->local.mac_abstract);
|
||||
|
||||
/* Encrypt the whole packet data, one block size at a time.
|
||||
The MAC field is not encrypted. */
|
||||
for(i = 0; i < packet_length; i += session->local.crypt->blocksize) {
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
781
src/userauth.c
781
src/userauth.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
x
Ссылка в новой задаче
Block a user