* Renamed the functions in src/transport.c to be _libssh2_transport_ prefixed
and introduced a transport.h header. * Fixed the blocking mode to only change behavior not the actual underlying socket mode so we now always work with non-blocking sockets. This also introduces a new rule of thumb in libssh2 code: we don't call the external function calls internally. We use the internal (non-blocking) ones! * libssh2_channel_receive_window_adjust2 was added and libssh2_channel_receive_window_adjust is now deprecated * Introduced "local" header files with prototypes etc for different parts instead of cramming everything into libssh2_priv.h. channel.h is the first.
Этот коммит содержится в:
родитель
239bdffb59
Коммит
eabe072496
17
NEWS
17
NEWS
@ -1,3 +1,20 @@
|
|||||||
|
|
||||||
|
* Renamed the functions in src/transport.c to be _libssh2_transport_ prefixed
|
||||||
|
and introduced a transport.h header.
|
||||||
|
|
||||||
|
* Fixed the blocking mode to only change behavior not the actual underlying
|
||||||
|
socket mode so we now always work with non-blocking sockets. This also
|
||||||
|
introduces a new rule of thumb in libssh2 code: we don't call the
|
||||||
|
external function calls internally. We use the internal (non-blocking)
|
||||||
|
ones!
|
||||||
|
|
||||||
|
* libssh2_channel_receive_window_adjust2 was added and
|
||||||
|
libssh2_channel_receive_window_adjust is now deprecated
|
||||||
|
|
||||||
|
* Introduced "local" header files with prototypes etc for different parts
|
||||||
|
instead of cramming everything into libssh2_priv.h. channel.h is the
|
||||||
|
first.
|
||||||
|
|
||||||
- (Mar 19 2009) Daniel Stenberg: based on a patch by "E L" we now use errno
|
- (Mar 19 2009) Daniel Stenberg: based on a patch by "E L" we now use errno
|
||||||
properly after recv() and send() calls (that internally are now known as
|
properly after recv() and send() calls (that internally are now known as
|
||||||
_libssh2_recv() and _libssh2_send()) so that the API and more works fine on
|
_libssh2_recv() and _libssh2_send()) so that the API and more works fine on
|
||||||
|
4
TODO
4
TODO
@ -30,7 +30,9 @@ At next SONAME bump
|
|||||||
* stop using #defined macros as part of the official API. The macros should
|
* stop using #defined macros as part of the official API. The macros should
|
||||||
either be turned into real functions or discarded from the API.
|
either be turned into real functions or discarded from the API.
|
||||||
|
|
||||||
* remove the followign functions from the API/ABI
|
* remove the following functions from the API/ABI
|
||||||
|
|
||||||
libssh2_base64_decode()
|
libssh2_base64_decode()
|
||||||
libssh2_session_flag()
|
libssh2_session_flag()
|
||||||
|
libssh2_channel_handle_extended_data()
|
||||||
|
libssh2_channel_receive_window_adjust()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $Id: Makefile.am,v 1.36 2009/03/16 15:00:45 bagder Exp $
|
# $Id: Makefile.am,v 1.37 2009/03/26 15:41:15 bagder Exp $
|
||||||
|
|
||||||
EXTRA_DIST = template.3
|
EXTRA_DIST = template.3
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ dist_man_MANS = \
|
|||||||
libssh2_channel_process_startup.3 \
|
libssh2_channel_process_startup.3 \
|
||||||
libssh2_channel_read_ex.3 \
|
libssh2_channel_read_ex.3 \
|
||||||
libssh2_channel_receive_window_adjust.3 \
|
libssh2_channel_receive_window_adjust.3 \
|
||||||
|
libssh2_channel_receive_window_adjust2.3 \
|
||||||
libssh2_channel_request_pty_ex.3 \
|
libssh2_channel_request_pty_ex.3 \
|
||||||
libssh2_channel_send_eof.3 \
|
libssh2_channel_send_eof.3 \
|
||||||
libssh2_channel_set_blocking.3 \
|
libssh2_channel_set_blocking.3 \
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $Id: libssh2_channel_handle_extended_data.3,v 1.1 2007/06/13 20:09:15 jehousley Exp $
|
.\" $Id: libssh2_channel_handle_extended_data.3,v 1.2 2009/03/26 15:41:16 bagder Exp $
|
||||||
.\"
|
.\"
|
||||||
.TH libssh2_channel_handle_extended_data 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
|
.TH libssh2_channel_handle_extended_data 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
@ -10,6 +10,9 @@ void
|
|||||||
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
|
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
This function is deprecated. Use the
|
||||||
|
\fIlibssh2_channel_handle_extended_data2(3)\fP function instead!
|
||||||
|
|
||||||
\fIchannel\fP - Active channel stream to change extended data handling on.
|
\fIchannel\fP - Active channel stream to change extended data handling on.
|
||||||
|
|
||||||
\fIignore_mode\fP - One of the three LIBSSH2_CHANNEL_EXTENDED_DATA_* Constants.
|
\fIignore_mode\fP - One of the three LIBSSH2_CHANNEL_EXTENDED_DATA_* Constants.
|
||||||
@ -17,21 +20,18 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
|
|||||||
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL\fP: Queue extended data for eventual
|
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL\fP: Queue extended data for eventual
|
||||||
reading
|
reading
|
||||||
.br
|
.br
|
||||||
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_MERGE\fP: Treat extended data and ordinary
|
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_MERGE\fP: Treat extended data and ordinary
|
||||||
data the same. Merge all substreams such that calls to
|
data the same. Merge all substreams such that calls to
|
||||||
.BR libssh2_channel_read(3)
|
\fIlibssh2_channel_read(3)\fP will pull from all substreams on a
|
||||||
will pull from all substreams on a first-in/first-out basis.
|
first-in/first-out basis.
|
||||||
.br
|
.br
|
||||||
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE\fP: Discard all extended data as it
|
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE\fP: Discard all extended data as it
|
||||||
arrives.
|
arrives.
|
||||||
|
|
||||||
Change how a channel deals with extended data packets. By default all
|
Change how a channel deals with extended data packets. By default all extended
|
||||||
extended data is queued until read by
|
data is queued until read by \fIlibssh2_channel_read_ex(3)\fP
|
||||||
.BR libssh2_channel_read_ex(3)
|
|
||||||
|
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
None.
|
None.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR libssh2_channel_handle_extended_data2(3)
|
.BR libssh2_channel_handle_extended_data2(3)
|
||||||
.BR libssh2_channel_read_ex(3)
|
.BR libssh2_channel_read_ex(3)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $Id: libssh2_channel_receive_window_adjust.3,v 1.2 2009/03/16 23:25:14 bagder Exp $
|
.\" $Id: libssh2_channel_receive_window_adjust.3,v 1.3 2009/03/26 15:41:16 bagder Exp $
|
||||||
.\"
|
.\"
|
||||||
.TH libssh2_channel_receive_window_adjust 3 "15 Mar 2009" "libssh2 0.15" "libssh2 manual"
|
.TH libssh2_channel_receive_window_adjust 3 "15 Mar 2009" "libssh2 0.15" "libssh2 manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
@ -12,6 +12,9 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
|
|||||||
unsigned char force);
|
unsigned char force);
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
This function is deprecated in 1.1. Use
|
||||||
|
\fIlibssh2_channel_receive_window_adjust2(3)\fP!
|
||||||
|
|
||||||
Adjust the receive window for a channel by adjustment bytes. If the amount to
|
Adjust the receive window for a channel by adjustment bytes. If the amount to
|
||||||
be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
|
be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
|
||||||
adjustment amount will be queued for a later packet.
|
adjustment amount will be queued for a later packet.
|
||||||
|
29
docs/libssh2_channel_receive_window_adjust2.3
Обычный файл
29
docs/libssh2_channel_receive_window_adjust2.3
Обычный файл
@ -0,0 +1,29 @@
|
|||||||
|
.\" $Id: libssh2_channel_receive_window_adjust2.3,v 1.1 2009/03/26 15:41:16 bagder Exp $
|
||||||
|
.\"
|
||||||
|
.TH libssh2_channel_receive_window_adjust2 3 "26 Mar 2009" "libssh2 1.1" "libssh2 manual"
|
||||||
|
.SH NAME
|
||||||
|
libssh2_channel_receive_window_adjust2 - adjust the channel window
|
||||||
|
.SH SYNOPSIS
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL * channel,
|
||||||
|
unsigned long adjustment,
|
||||||
|
unsigned char force,
|
||||||
|
unsigned int *window);
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Adjust the receive window for a channel by adjustment bytes. If the amount to
|
||||||
|
be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
|
||||||
|
adjustment amount will be queued for a later packet.
|
||||||
|
|
||||||
|
This function stores the new size of the receive window (as understood by
|
||||||
|
remote end) in the variable 'window' points to.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
Return 0 on success and a negative value on error. If used in non-blocking
|
||||||
|
mode it will return LIBSSH2_ERROR_EAGAIN when it would otherwise block.
|
||||||
|
.SH ERRORS
|
||||||
|
.SH AVAILABILITY
|
||||||
|
Added in libssh2 1.1 since the previous API has deficiencies.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR libssh2_channel_window_read_ex(3)
|
@ -1,4 +1,4 @@
|
|||||||
.\" $Id: libssh2_channel_set_blocking.3,v 1.5 2007/06/14 17:23:13 jehousley Exp $
|
.\" $Id: libssh2_channel_set_blocking.3,v 1.6 2009/03/26 15:41:16 bagder Exp $
|
||||||
.\"
|
.\"
|
||||||
.TH libssh2_channel_set_blocking 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
|
.TH libssh2_channel_set_blocking 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
@ -8,7 +8,6 @@ libssh2_channel_set_blocking - set or clear blocking mode on channel
|
|||||||
|
|
||||||
void
|
void
|
||||||
libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking);
|
libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking);
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fIchannel\fP - channel stream to set or clean blocking status on.
|
\fIchannel\fP - channel stream to set or clean blocking status on.
|
||||||
|
|
||||||
@ -18,10 +17,8 @@ make it non-blocking.
|
|||||||
Currently this is just a short cut call to
|
Currently this is just a short cut call to
|
||||||
.BR libssh2_session_set_blocking(3)
|
.BR libssh2_session_set_blocking(3)
|
||||||
and therefore will affect the session and all channels.
|
and therefore will affect the session and all channels.
|
||||||
|
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
None
|
None
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR libssh2_session_set_blocking(3)
|
.BR libssh2_session_set_blocking(3)
|
||||||
.BR libssh2_channel_read_ex(3)
|
.BR libssh2_channel_read_ex(3)
|
||||||
|
@ -576,11 +576,18 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
|
|||||||
#define libssh2_channel_window_read(channel) \
|
#define libssh2_channel_window_read(channel) \
|
||||||
libssh2_channel_window_read_ex((channel), NULL, NULL)
|
libssh2_channel_window_read_ex((channel), NULL, NULL)
|
||||||
|
|
||||||
|
/* libssh2_channel_receive_window_adjust is DEPRECATED, do not use! */
|
||||||
LIBSSH2_API unsigned long
|
LIBSSH2_API unsigned long
|
||||||
libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
|
libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
|
||||||
unsigned long adjustment,
|
unsigned long adjustment,
|
||||||
unsigned char force);
|
unsigned char force);
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
|
||||||
|
unsigned long adjustment,
|
||||||
|
unsigned char force,
|
||||||
|
unsigned int *storewindow);
|
||||||
|
|
||||||
LIBSSH2_API ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel,
|
LIBSSH2_API ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel,
|
||||||
int stream_id, const char *buf,
|
int stream_id, const char *buf,
|
||||||
size_t buflen);
|
size_t buflen);
|
||||||
@ -603,6 +610,7 @@ LIBSSH2_API int libssh2_session_get_blocking(LIBSSH2_SESSION* session);
|
|||||||
LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel,
|
LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel,
|
||||||
int blocking);
|
int blocking);
|
||||||
|
|
||||||
|
/* libssh2_channel_handle_extended_data is DEPRECATED, do not use! */
|
||||||
LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
|
LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
|
||||||
int ignore_mode);
|
int ignore_mode);
|
||||||
LIBSSH2_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
|
LIBSSH2_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
# $Id: Makefile.am,v 1.16 2009/03/17 10:19:54 jas4711 Exp $
|
# $Id: Makefile.am,v 1.17 2009/03/26 15:41:17 bagder Exp $
|
||||||
AUTOMAKE_OPTIONS = foreign nostdinc
|
AUTOMAKE_OPTIONS = foreign nostdinc
|
||||||
|
|
||||||
libssh2_la_SOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c \
|
libssh2_la_SOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c \
|
||||||
misc.c packet.c publickey.c scp.c session.c sftp.c userauth.c \
|
misc.c packet.c publickey.c scp.c session.c sftp.c userauth.c \
|
||||||
libssh2_priv.h openssl.h libgcrypt.h transport.c version.c
|
libssh2_priv.h openssl.h libgcrypt.h transport.c version.c transport.h \
|
||||||
|
channel.h
|
||||||
|
|
||||||
if LIBGCRYPT
|
if LIBGCRYPT
|
||||||
libssh2_la_SOURCES += libgcrypt.c pem.c
|
libssh2_la_SOURCES += libgcrypt.c pem.c
|
||||||
|
645
src/channel.c
645
src/channel.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
64
src/channel.h
Обычный файл
64
src/channel.h
Обычный файл
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef __LIBSSH2_CHANNEL_H
|
||||||
|
#define __LIBSSH2_CHANNEL_H
|
||||||
|
/* Copyright (c) 2008-2009 by Daniel Stenberg
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms,
|
||||||
|
* with or without modification, are permitted provided
|
||||||
|
* that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the
|
||||||
|
* following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the copyright holder nor the names
|
||||||
|
* of any other contributors may be used to endorse or
|
||||||
|
* promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _libssh2_channel_receive_window_adjust
|
||||||
|
*
|
||||||
|
* Adjust the receive window for a channel by adjustment bytes. If the amount
|
||||||
|
* to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
|
||||||
|
* adjustment amount will be queued for a later packet.
|
||||||
|
*
|
||||||
|
* Always non-blocking.
|
||||||
|
*/
|
||||||
|
int _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
|
||||||
|
unsigned long adjustment,
|
||||||
|
unsigned char force,
|
||||||
|
unsigned int *store);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _libssh2_channel_flush
|
||||||
|
*
|
||||||
|
* Flush data from one (or all) stream
|
||||||
|
* Returns number of bytes flushed, or negative on failure
|
||||||
|
*/
|
||||||
|
int _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid);
|
||||||
|
|
||||||
|
#endif /* __LIBSSH2_CHANNEL_H */
|
||||||
|
|
12
src/kex.c
12
src/kex.c
@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
#include "libssh2_priv.h"
|
#include "libssh2_priv.h"
|
||||||
|
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
/* TODO: Switch this to an inline and handle alloc() failures */
|
/* TODO: Switch this to an inline and handle alloc() failures */
|
||||||
/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */
|
/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */
|
||||||
#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
|
#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
|
||||||
@ -139,8 +141,8 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exchange_state->state == libssh2_NB_state_created) {
|
if (exchange_state->state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, exchange_state->e_packet,
|
rc = _libssh2_transport_write(session, exchange_state->e_packet,
|
||||||
exchange_state->e_packet_len);
|
exchange_state->e_packet_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
@ -415,7 +417,7 @@ kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exchange_state->state == libssh2_NB_state_sent2) {
|
if (exchange_state->state == libssh2_NB_state_sent2) {
|
||||||
rc = _libssh2_packet_write(session, &exchange_state->c, 1);
|
rc = _libssh2_transport_write(session, &exchange_state->c, 1);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
@ -837,7 +839,7 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key_state->state == libssh2_NB_state_created) {
|
if (key_state->state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, key_state->request,
|
rc = _libssh2_transport_write(session, key_state->request,
|
||||||
key_state->request_len);
|
key_state->request_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
@ -1136,7 +1138,7 @@ static int kexinit(LIBSSH2_SESSION * session)
|
|||||||
data_len = session->kexinit_data_len;
|
data_len = session->kexinit_data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _libssh2_packet_write(session, data, data_len);
|
rc = _libssh2_transport_write(session, data, data_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
session->kexinit_data = data;
|
session->kexinit_data = data;
|
||||||
session->kexinit_data_len = data_len;
|
session->kexinit_data_len = data_len;
|
||||||
|
@ -684,6 +684,9 @@ struct _LIBSSH2_SESSION
|
|||||||
unsigned char *session_id;
|
unsigned char *session_id;
|
||||||
unsigned long session_id_len;
|
unsigned long session_id_len;
|
||||||
|
|
||||||
|
/* this is set to TRUE if a blocking API behavior is requested */
|
||||||
|
int api_block_mode;
|
||||||
|
|
||||||
/* Server's public key */
|
/* Server's public key */
|
||||||
const LIBSSH2_HOSTKEY_METHOD *hostkey;
|
const LIBSSH2_HOSTKEY_METHOD *hostkey;
|
||||||
void *server_hostkey_abstract;
|
void *server_hostkey_abstract;
|
||||||
@ -716,9 +719,10 @@ struct _LIBSSH2_SESSION
|
|||||||
|
|
||||||
/* Actual I/O socket */
|
/* Actual I/O socket */
|
||||||
int socket_fd;
|
int socket_fd;
|
||||||
int socket_block;
|
|
||||||
int socket_state;
|
int socket_state;
|
||||||
int socket_block_directions;
|
int socket_block_directions;
|
||||||
|
int socket_prev_blockstate; /* stores the state of the socket blockiness
|
||||||
|
when libssh2_session_startup() is called */
|
||||||
|
|
||||||
/* Error tracking */
|
/* Error tracking */
|
||||||
char *err_msg;
|
char *err_msg;
|
||||||
@ -1145,7 +1149,8 @@ ssize_t _libssh2_send(int socket, const void *buffer, size_t length, int flags);
|
|||||||
|
|
||||||
#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
|
#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
|
||||||
waiting for more data to arrive */
|
waiting for more data to arrive */
|
||||||
int _libssh2_waitsocket(LIBSSH2_SESSION * session, long seconds);
|
|
||||||
|
int _libssh2_wait_socket(LIBSSH2_SESSION *session);
|
||||||
|
|
||||||
|
|
||||||
/* CAUTION: some of these error codes are returned in the public API and is
|
/* CAUTION: some of these error codes are returned in the public API and is
|
||||||
@ -1223,4 +1228,40 @@ int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen);
|
|||||||
int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
|
int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
|
||||||
unsigned char **i, unsigned int *ilen);
|
unsigned char **i, unsigned int *ilen);
|
||||||
|
|
||||||
|
|
||||||
|
/* Conveniance-macros to allow code like this;
|
||||||
|
|
||||||
|
int rc = BLOCK_ADJUST(rc, session, session_startup(session, sock) );
|
||||||
|
|
||||||
|
int rc = BLOCK_ADJUST_ERRNO(ptr, session, session_startup(session, sock) );
|
||||||
|
|
||||||
|
The point of course being to make sure that while in non-blocking mode
|
||||||
|
these always return no matter what the return code is, but in blocking mode
|
||||||
|
it blocks if EAGAIN is the reason for the return from the underlying
|
||||||
|
function.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define BLOCK_ADJUST(rc,sess,x) \
|
||||||
|
do { \
|
||||||
|
rc = x; \
|
||||||
|
if(!sess->api_block_mode || (rc != LIBSSH2_ERROR_EAGAIN)) \
|
||||||
|
break; \
|
||||||
|
rc = _libssh2_wait_socket(sess); \
|
||||||
|
if(rc) \
|
||||||
|
break; \
|
||||||
|
} while(1)
|
||||||
|
|
||||||
|
#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \
|
||||||
|
do { \
|
||||||
|
int rc; \
|
||||||
|
ptr = x; \
|
||||||
|
if(!sess->api_block_mode || \
|
||||||
|
(libssh2_session_last_errno(sess) != LIBSSH2_ERROR_EAGAIN)) \
|
||||||
|
break; \
|
||||||
|
rc = _libssh2_wait_socket(sess); \
|
||||||
|
if(rc) \
|
||||||
|
break; \
|
||||||
|
} while(1)
|
||||||
|
|
||||||
|
|
||||||
#endif /* LIBSSH2_H */
|
#endif /* LIBSSH2_H */
|
||||||
|
74
src/packet.c
74
src/packet.c
@ -59,6 +59,8 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_packet_queue_listener
|
* libssh2_packet_queue_listener
|
||||||
*
|
*
|
||||||
@ -202,8 +204,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (listen_state->state == libssh2_NB_state_created) {
|
if (listen_state->state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, listen_state->packet,
|
rc = _libssh2_transport_write(session, listen_state->packet,
|
||||||
17);
|
17);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
@ -256,7 +258,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
p += sizeof(FwdNotReq) - 1;
|
p += sizeof(FwdNotReq) - 1;
|
||||||
_libssh2_htonu32(p, 0);
|
_libssh2_htonu32(p, 0);
|
||||||
|
|
||||||
rc = _libssh2_packet_write(session, listen_state->packet, packet_len);
|
rc = _libssh2_transport_write(session, listen_state->packet,
|
||||||
|
packet_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
@ -374,7 +377,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (x11open_state->state == libssh2_NB_state_created) {
|
if (x11open_state->state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, x11open_state->packet, 17);
|
rc = _libssh2_transport_write(session, x11open_state->packet, 17);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
@ -422,7 +425,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
p += sizeof(X11FwdUnAvil) - 1;
|
p += sizeof(X11FwdUnAvil) - 1;
|
||||||
_libssh2_htonu32(p, 0);
|
_libssh2_htonu32(p, 0);
|
||||||
|
|
||||||
rc = _libssh2_packet_write(session, x11open_state->packet, packet_len);
|
rc = _libssh2_transport_write(session, x11open_state->packet, packet_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
@ -922,11 +925,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The KEXINIT message has been added to the queue.
|
* The KEXINIT message has been added to the queue. The packAdd and
|
||||||
* The packAdd and readPack states need to be reset
|
* readPack states need to be reset because libssh2_kex_exchange
|
||||||
* because libssh2_kex_exchange (eventually) calls upon
|
* (eventually) calls upon _libssh2_transport_read to read the rest of
|
||||||
* libssh2_packet_read to read the rest of the key exchange
|
* the key exchange conversation.
|
||||||
* conversation.
|
|
||||||
*/
|
*/
|
||||||
session->readPack_state = libssh2_NB_state_idle;
|
session->readPack_state = libssh2_NB_state_idle;
|
||||||
session->packet.total_num = 0;
|
session->packet.total_num = 0;
|
||||||
@ -1029,39 +1031,10 @@ _libssh2_packet_askv(LIBSSH2_SESSION * session,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* _libssh2_waitsocket
|
|
||||||
*
|
|
||||||
* Returns
|
|
||||||
* negative on error
|
|
||||||
* >0 on incoming data
|
|
||||||
* 0 on timeout
|
|
||||||
*
|
|
||||||
* FIXME: convert to use poll on systems that have it.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
_libssh2_waitsocket(LIBSSH2_SESSION * session, long seconds)
|
|
||||||
{
|
|
||||||
struct timeval timeout;
|
|
||||||
int rc;
|
|
||||||
fd_set fd;
|
|
||||||
|
|
||||||
timeout.tv_sec = seconds;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
FD_ZERO(&fd);
|
|
||||||
|
|
||||||
FD_SET(session->socket_fd, &fd);
|
|
||||||
|
|
||||||
rc = select(session->socket_fd + 1, &fd, NULL, NULL, &timeout);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _libssh2_packet_require
|
* _libssh2_packet_require
|
||||||
*
|
*
|
||||||
* Loops _libssh2_packet_read() until the packet requested is available
|
* Loops _libssh2_transport_read() until the packet requested is available
|
||||||
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
|
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
|
||||||
*
|
*
|
||||||
* Returns negative on error
|
* Returns negative on error
|
||||||
@ -1091,11 +1064,11 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
||||||
libssh2pack_t ret = _libssh2_packet_read(session);
|
libssh2pack_t ret = _libssh2_transport_read(session);
|
||||||
if (ret == PACKET_EAGAIN) {
|
if (ret == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if ((ret == 0) && (!session->socket_block)) {
|
} else if (ret == 0) {
|
||||||
/* If we are in non-blocking and there is no data, return that */
|
/* There is no data, return that. TODO: is this really correct? */
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
state->start = 0;
|
state->start = 0;
|
||||||
@ -1111,7 +1084,7 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
|
|||||||
/* nothing available, wait until data arrives or we time out */
|
/* nothing available, wait until data arrives or we time out */
|
||||||
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
|
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
|
||||||
|
|
||||||
if ((left <= 0) || (_libssh2_waitsocket(session, left) <= 0)) {
|
if (left <= 0) {
|
||||||
state->start = 0;
|
state->start = 0;
|
||||||
return PACKET_TIMEOUT;
|
return PACKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
@ -1125,7 +1098,7 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
|
|||||||
/*
|
/*
|
||||||
* _libssh2_packet_burn
|
* _libssh2_packet_burn
|
||||||
*
|
*
|
||||||
* Loops _libssh2_packet_read() until any packet is available and promptly
|
* Loops _libssh2_transport_read() until any packet is available and promptly
|
||||||
* discards it.
|
* discards it.
|
||||||
* Used during KEX exchange to discard badly guessed KEX_INIT packets
|
* Used during KEX exchange to discard badly guessed KEX_INIT packets
|
||||||
*/
|
*/
|
||||||
@ -1158,7 +1131,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
||||||
if ((ret = _libssh2_packet_read(session)) == PACKET_EAGAIN) {
|
if ((ret = _libssh2_transport_read(session)) == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
*state = libssh2_NB_state_idle;
|
*state = libssh2_NB_state_idle;
|
||||||
@ -1185,7 +1158,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
|
|||||||
/*
|
/*
|
||||||
* _libssh2_packet_requirev
|
* _libssh2_packet_requirev
|
||||||
*
|
*
|
||||||
* Loops _libssh2_packet_read() until one of a list of packet types requested is
|
* Loops _libssh2_transport_read() until one of a list of packet types requested is
|
||||||
* available
|
* available
|
||||||
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
|
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
|
||||||
* packet_types is a null terminated list of packet_type numbers
|
* packet_types is a null terminated list of packet_type numbers
|
||||||
@ -1212,7 +1185,7 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
|
while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
|
||||||
int ret = _libssh2_packet_read(session);
|
int ret = _libssh2_transport_read(session);
|
||||||
if ((ret < 0) && (ret != PACKET_EAGAIN)) {
|
if ((ret < 0) && (ret != PACKET_EAGAIN)) {
|
||||||
state->start = 0;
|
state->start = 0;
|
||||||
return ret;
|
return ret;
|
||||||
@ -1220,10 +1193,11 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
|
|||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
|
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
|
||||||
|
|
||||||
if ((left <= 0) || (_libssh2_waitsocket(session, left) <= 0)) {
|
if (left <= 0) {
|
||||||
state->start = 0;
|
state->start = 0;
|
||||||
return PACKET_TIMEOUT;
|
return PACKET_TIMEOUT;
|
||||||
} else if (ret == PACKET_EAGAIN) {
|
}
|
||||||
|
else if (ret == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
187
src/session.c
187
src/session.c
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||||
|
* Copyright (c) 2009 by Daniel Stenberg
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@ -396,12 +397,13 @@ libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* proto libssh2_session_init
|
* libssh2_session_init_ex
|
||||||
*
|
*
|
||||||
* Allocate and initialize a libssh2 session structure
|
* Allocate and initialize a libssh2 session structure. Allows for malloc
|
||||||
* Allows for malloc callbacks in case the calling program has its own memory manager
|
* callbacks in case the calling program has its own memory manager It's
|
||||||
* It's allowable (but unadvisable) to define some but not all of the malloc callbacks
|
* allowable (but unadvisable) to define some but not all of the malloc
|
||||||
* An additional pointer value may be optionally passed to be sent to the callbacks (so they know who's asking)
|
* 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_API LIBSSH2_SESSION *
|
||||||
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
||||||
@ -430,6 +432,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
|||||||
session->free = local_free;
|
session->free = local_free;
|
||||||
session->realloc = local_realloc;
|
session->realloc = local_realloc;
|
||||||
session->abstract = abstract;
|
session->abstract = abstract;
|
||||||
|
session->api_block_mode = 1; /* blocking API by default */
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
|
||||||
"New session resource allocated");
|
"New session resource allocated");
|
||||||
libssh2_crypto_init();
|
libssh2_crypto_init();
|
||||||
@ -485,16 +488,46 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* proto libssh2_session_startup
|
* _libssh2_wait_socket()
|
||||||
*
|
*
|
||||||
* session: LIBSSH2_SESSION struct allocated and owned by the calling program
|
* Utility function that waits for action on the socket. Returns 0 when ready
|
||||||
* Returns: 0 on success, or non-zero on failure
|
* to run again or error on timeout.
|
||||||
* Any memory allocated by libssh2 will use alloc/realloc/free
|
|
||||||
* callbacks in session
|
|
||||||
* socket *must* be populated with an opened and connected socket.
|
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
int _libssh2_wait_socket(LIBSSH2_SESSION *session)
|
||||||
libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
|
{
|
||||||
|
fd_set fd;
|
||||||
|
fd_set *writefd = NULL;
|
||||||
|
fd_set *readfd = NULL;
|
||||||
|
int dir;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
FD_ZERO(&fd);
|
||||||
|
FD_SET(session->socket_fd, &fd);
|
||||||
|
|
||||||
|
/* now make sure we wait in the correct direction */
|
||||||
|
dir = libssh2_session_block_directions(session);
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
|
||||||
|
readfd = &fd;
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
|
||||||
|
writefd = &fd;
|
||||||
|
|
||||||
|
/* Note that this COULD be made to use a timeout that perhaps could be
|
||||||
|
customizable by the app or something... */
|
||||||
|
rc = select(session->socket_fd + 1, readfd, writefd, NULL, NULL);
|
||||||
|
|
||||||
|
if(rc <= 0) {
|
||||||
|
/* timeout (or error), bail out with a timeout error */
|
||||||
|
session->err_code = LIBSSH2_ERROR_TIMEOUT;
|
||||||
|
return LIBSSH2_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* ready to try again */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
session_startup(LIBSSH2_SESSION *session, int sock)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -510,15 +543,12 @@ libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
|
|||||||
}
|
}
|
||||||
session->socket_fd = sock;
|
session->socket_fd = sock;
|
||||||
|
|
||||||
session->socket_block =
|
session->socket_prev_blockstate =
|
||||||
!get_socket_nonblocking(session->socket_fd);
|
!get_socket_nonblocking(session->socket_fd);
|
||||||
if (session->socket_block) {
|
|
||||||
/*
|
if (session->socket_prev_blockstate) {
|
||||||
* Since we can't be sure that we are in blocking or there
|
/* If in blocking state chang to non-blocking */
|
||||||
* was an error detecting the state, so set to blocking to
|
session_nonblock(session->socket_fd, 1);
|
||||||
* be sure
|
|
||||||
*/
|
|
||||||
session_nonblock(session->socket_fd, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
session->startup_state = libssh2_NB_state_created;
|
session->startup_state = libssh2_NB_state_created;
|
||||||
@ -588,8 +618,8 @@ libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->startup_state == libssh2_NB_state_sent3) {
|
if (session->startup_state == libssh2_NB_state_sent3) {
|
||||||
rc = _libssh2_packet_write(session, session->startup_service,
|
rc = _libssh2_transport_write(session, session->startup_service,
|
||||||
sizeof("ssh-userauth") + 5 - 1);
|
sizeof("ssh-userauth") + 5 - 1);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||||
"Would block asking for ssh-userauth service", 0);
|
"Would block asking for ssh-userauth service", 0);
|
||||||
@ -638,14 +668,33 @@ libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
|
|||||||
return LIBSSH2_ERROR_INVAL;
|
return LIBSSH2_ERROR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* proto libssh2_session_startup
|
||||||
|
*
|
||||||
|
* session: LIBSSH2_SESSION struct allocated and owned by the calling program
|
||||||
|
* Returns: 0 on success, or non-zero on failure
|
||||||
|
* Any memory allocated by libssh2 will use alloc/realloc/free
|
||||||
|
* callbacks in session.
|
||||||
|
* The 'sock' socket *must* be populated with an opened and connected socket.
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
BLOCK_ADJUST(rc, session, session_startup(session, sock) );
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_session_free
|
* libssh2_session_free
|
||||||
*
|
*
|
||||||
* Frees the memory allocated to the session
|
* Frees the memory allocated to the session
|
||||||
* Also closes and frees any channels attached to this session
|
* Also closes and frees any channels attached to this session
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
static int
|
||||||
libssh2_session_free(LIBSSH2_SESSION * session)
|
session_free(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -869,16 +918,37 @@ libssh2_session_free(LIBSSH2_SESSION * session)
|
|||||||
LIBSSH2_FREE(session, tmp);
|
LIBSSH2_FREE(session, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(session->socket_prev_blockstate)
|
||||||
|
/* if the socket was previously blocking, put it back so */
|
||||||
|
session_nonblock(session->socket_fd, 0);
|
||||||
|
|
||||||
LIBSSH2_FREE(session, session);
|
LIBSSH2_FREE(session, session);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_session_disconnect_ex
|
/*
|
||||||
|
* libssh2_session_free
|
||||||
|
*
|
||||||
|
* Frees the memory allocated to the session
|
||||||
|
* Also closes and frees any channels attached to this session
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_session_disconnect_ex(LIBSSH2_SESSION * session, int reason,
|
libssh2_session_free(LIBSSH2_SESSION * session)
|
||||||
const char *description, const char *lang)
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
BLOCK_ADJUST(rc, session, session_free(session) );
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_session_disconnect_ex
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
session_disconnect(LIBSSH2_SESSION *session, int reason,
|
||||||
|
const char *description, const char *lang)
|
||||||
{
|
{
|
||||||
unsigned char *s;
|
unsigned char *s;
|
||||||
unsigned long descr_len = 0, lang_len = 0;
|
unsigned long descr_len = 0, lang_len = 0;
|
||||||
@ -928,8 +998,8 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION * session, int reason,
|
|||||||
session->disconnect_state = libssh2_NB_state_created;
|
session->disconnect_state = libssh2_NB_state_created;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _libssh2_packet_write(session, session->disconnect_data,
|
rc = _libssh2_transport_write(session, session->disconnect_data,
|
||||||
session->disconnect_data_len);
|
session->disconnect_data_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
@ -941,10 +1011,27 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION * session, int reason,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_session_disconnect_ex
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
|
||||||
|
const char *desc, const char *lang)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
BLOCK_ADJUST(rc, session,
|
||||||
|
session_disconnect(session, reason, desc, lang));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* libssh2_session_methods
|
/* libssh2_session_methods
|
||||||
|
*
|
||||||
* Return the currently active methods for method_type
|
* Return the currently active methods for method_type
|
||||||
* NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation
|
*
|
||||||
* Strings should NOT be freed
|
* 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_API const char *
|
||||||
libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
|
libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
|
||||||
@ -1019,9 +1106,10 @@ libssh2_session_abstract(LIBSSH2_SESSION * session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_session_last_error
|
/* libssh2_session_last_error
|
||||||
* Returns error code and populates an error string into errmsg
|
*
|
||||||
* If want_buf is non-zero then the string placed into errmsg must be freed by the calling program
|
* Returns error code and populates an error string into errmsg If want_buf is
|
||||||
* Otherwise it is assumed to be owned by libssh2
|
* non-zero then the string placed into errmsg must be freed by the calling
|
||||||
|
* program. Otherwise it is assumed to be owned by libssh2
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
|
libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
|
||||||
@ -1101,22 +1189,17 @@ libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
|
|||||||
|
|
||||||
/* _libssh2_session_set_blocking
|
/* _libssh2_session_set_blocking
|
||||||
*
|
*
|
||||||
* Set a session's blocking mode on or off, return the previous status
|
* Set a session's blocking mode on or off, return the previous status when
|
||||||
* when this function is called.
|
* this function is called. Note this function does not alter the state of the
|
||||||
|
* actual socket involved.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
_libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
|
_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
|
||||||
{
|
{
|
||||||
int bl = session->socket_block;
|
int bl = session->api_block_mode;
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
_libssh2_debug(session, LIBSSH2_DBG_CONN,
|
||||||
"Setting blocking mode on session %d", blocking);
|
"Setting blocking mode %s", blocking?"ON":"OFF");
|
||||||
if (blocking == session->socket_block) {
|
session->api_block_mode = blocking;
|
||||||
/* avoid if already correct */
|
|
||||||
return bl;
|
|
||||||
}
|
|
||||||
session->socket_block = blocking;
|
|
||||||
|
|
||||||
session_nonblock(session->socket_fd, !blocking);
|
|
||||||
|
|
||||||
return bl;
|
return bl;
|
||||||
}
|
}
|
||||||
@ -1139,7 +1222,7 @@ libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
|
|||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_session_get_blocking(LIBSSH2_SESSION * session)
|
libssh2_session_get_blocking(LIBSSH2_SESSION * session)
|
||||||
{
|
{
|
||||||
return session->socket_block;
|
return session->api_block_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1418,7 +1501,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
|
|||||||
case LIBSSH2_POLLFD_CHANNEL:
|
case LIBSSH2_POLLFD_CHANNEL:
|
||||||
if (sockets[i].events & POLLIN) {
|
if (sockets[i].events & POLLIN) {
|
||||||
/* Spin session until no data available */
|
/* Spin session until no data available */
|
||||||
while (_libssh2_packet_read(fds[i].fd.channel->session)
|
while (_libssh2_transport_read(fds[i].fd.channel->session)
|
||||||
> 0);
|
> 0);
|
||||||
}
|
}
|
||||||
if (sockets[i].revents & POLLHUP) {
|
if (sockets[i].revents & POLLHUP) {
|
||||||
@ -1431,7 +1514,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
|
|||||||
case LIBSSH2_POLLFD_LISTENER:
|
case LIBSSH2_POLLFD_LISTENER:
|
||||||
if (sockets[i].events & POLLIN) {
|
if (sockets[i].events & POLLIN) {
|
||||||
/* Spin session until no data available */
|
/* Spin session until no data available */
|
||||||
while (_libssh2_packet_read(fds[i].fd.listener->session)
|
while (_libssh2_transport_read(fds[i].fd.listener->session)
|
||||||
> 0);
|
> 0);
|
||||||
}
|
}
|
||||||
if (sockets[i].revents & POLLHUP) {
|
if (sockets[i].revents & POLLHUP) {
|
||||||
@ -1484,7 +1567,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
|
|||||||
case LIBSSH2_POLLFD_CHANNEL:
|
case LIBSSH2_POLLFD_CHANNEL:
|
||||||
if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
|
if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
|
||||||
/* Spin session until no data available */
|
/* Spin session until no data available */
|
||||||
while (_libssh2_packet_read(fds[i].fd.channel->session)
|
while (_libssh2_transport_read(fds[i].fd.channel->session)
|
||||||
> 0);
|
> 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1493,7 +1576,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
|
|||||||
if (FD_ISSET
|
if (FD_ISSET
|
||||||
(fds[i].fd.listener->session->socket_fd, &rfds)) {
|
(fds[i].fd.listener->session->socket_fd, &rfds)) {
|
||||||
/* Spin session until no data available */
|
/* Spin session until no data available */
|
||||||
while (_libssh2_packet_read(fds[i].fd.listener->session)
|
while (_libssh2_transport_read(fds[i].fd.listener->session)
|
||||||
> 0);
|
> 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
294
src/sftp.c
294
src/sftp.c
@ -89,7 +89,7 @@
|
|||||||
* Add a packet to the SFTP packet brigade
|
* Add a packet to the SFTP packet brigade
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
|
sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
|
||||||
unsigned long data_len)
|
unsigned long data_len)
|
||||||
{
|
{
|
||||||
LIBSSH2_SESSION *session = sftp->channel->session;
|
LIBSSH2_SESSION *session = sftp->channel->session;
|
||||||
@ -127,7 +127,7 @@ sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
|
|||||||
* Frame an SFTP packet off the channel
|
* Frame an SFTP packet off the channel
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
sftp_packet_read(LIBSSH2_SFTP * sftp)
|
sftp_packet_read(LIBSSH2_SFTP *sftp)
|
||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
@ -225,7 +225,7 @@ sftp_packet_read(LIBSSH2_SFTP * sftp)
|
|||||||
* Checks if there's a matching SFTP packet available.
|
* Checks if there's a matching SFTP packet available.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
|
sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
|
||||||
unsigned long request_id, unsigned char **data,
|
unsigned long request_id, unsigned char **data,
|
||||||
unsigned long *data_len)
|
unsigned long *data_len)
|
||||||
{
|
{
|
||||||
@ -280,7 +280,7 @@ sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
|
|||||||
* A la libssh2_packet_require
|
* A la libssh2_packet_require
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
|
sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
|
||||||
unsigned long request_id, unsigned char **data,
|
unsigned long request_id, unsigned char **data,
|
||||||
unsigned long *data_len)
|
unsigned long *data_len)
|
||||||
{
|
{
|
||||||
@ -322,7 +322,7 @@ sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
|
|||||||
* Require one of N possible reponses
|
* Require one of N possible reponses
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
|
sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
|
||||||
const unsigned char *valid_responses,
|
const unsigned char *valid_responses,
|
||||||
unsigned long request_id, unsigned char **data,
|
unsigned long request_id, unsigned char **data,
|
||||||
unsigned long *data_len)
|
unsigned long *data_len)
|
||||||
@ -360,12 +360,8 @@ sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
|
|||||||
if (left <= 0) {
|
if (left <= 0) {
|
||||||
sftp->requirev_start = 0;
|
sftp->requirev_start = 0;
|
||||||
return PACKET_TIMEOUT;
|
return PACKET_TIMEOUT;
|
||||||
} else if (sftp->channel->session->socket_block
|
}
|
||||||
&& (_libssh2_waitsocket(sftp->channel->session, left) <=
|
else if (ret == PACKET_EAGAIN) {
|
||||||
0)) {
|
|
||||||
sftp->requirev_start = 0;
|
|
||||||
return PACKET_TIMEOUT;
|
|
||||||
} else if (ret == PACKET_EAGAIN) {
|
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -521,12 +517,11 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_sftp_init
|
* sftp_init
|
||||||
*
|
*
|
||||||
* Startup an SFTP session
|
* Startup an SFTP session
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API LIBSSH2_SFTP *
|
static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
||||||
libssh2_sftp_init(LIBSSH2_SESSION * session)
|
|
||||||
{
|
{
|
||||||
unsigned char *data, *s;
|
unsigned char *data, *s;
|
||||||
unsigned long data_len;
|
unsigned long data_len;
|
||||||
@ -693,11 +688,23 @@ libssh2_sftp_init(LIBSSH2_SESSION * session)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_sftp_init
|
||||||
|
*
|
||||||
|
* Startup an SFTP session
|
||||||
|
*/
|
||||||
|
LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
LIBSSH2_SFTP *ptr;
|
||||||
|
BLOCK_ADJUST_ERRNO(ptr, session, sftp_init(session));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_shutdown
|
/* libssh2_sftp_shutdown
|
||||||
* Shutsdown the SFTP subsystem
|
* Shutsdown the SFTP subsystem
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)
|
libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Make sure all memory used in the state variables are free
|
* Make sure all memory used in the state variables are free
|
||||||
@ -754,12 +761,12 @@ libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)
|
|||||||
* SFTP File and Directory Ops *
|
* SFTP File and Directory Ops *
|
||||||
******************************* */
|
******************************* */
|
||||||
|
|
||||||
/* libssh2_sftp_open_ex
|
/* sftp_open
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API LIBSSH2_SFTP_HANDLE *
|
static LIBSSH2_SFTP_HANDLE *
|
||||||
libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
|
sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
|
||||||
unsigned int filename_len, unsigned long flags, long mode,
|
unsigned int filename_len, unsigned long flags, long mode,
|
||||||
int open_type)
|
int open_type)
|
||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
@ -932,12 +939,25 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
|
|||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_read
|
/* libssh2_sftp_open_ex
|
||||||
|
*/
|
||||||
|
LIBSSH2_API LIBSSH2_SFTP_HANDLE *
|
||||||
|
libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename,
|
||||||
|
unsigned int filename_len, unsigned long flags, long mode,
|
||||||
|
int open_type)
|
||||||
|
{
|
||||||
|
LIBSSH2_SFTP_HANDLE *hnd;
|
||||||
|
BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session,
|
||||||
|
sftp_open(sftp, filename, filename_len, flags, mode,
|
||||||
|
open_type));
|
||||||
|
return hnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sftp_read
|
||||||
* Read from an SFTP file handle
|
* Read from an SFTP file handle
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API ssize_t
|
static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||||
libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
size_t buffer_maxlen)
|
||||||
size_t buffer_maxlen)
|
|
||||||
{
|
{
|
||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -1108,14 +1128,26 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
|||||||
return total_read;
|
return total_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_readdir
|
/* libssh2_sftp_read
|
||||||
|
* Read from an SFTP file handle
|
||||||
|
*/
|
||||||
|
LIBSSH2_API ssize_t
|
||||||
|
libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
|
||||||
|
size_t buffer_maxlen)
|
||||||
|
{
|
||||||
|
ssize_t rc;
|
||||||
|
BLOCK_ADJUST(rc, hnd->sftp->channel->session,
|
||||||
|
sftp_read(hnd, buffer, buffer_maxlen));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sftp_readdir
|
||||||
* Read from an SFTP directory handle
|
* Read from an SFTP directory handle
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
||||||
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
|
||||||
size_t buffer_maxlen, char *longentry,
|
size_t buffer_maxlen, char *longentry,
|
||||||
size_t longentry_maxlen,
|
size_t longentry_maxlen,
|
||||||
LIBSSH2_SFTP_ATTRIBUTES * attrs)
|
LIBSSH2_SFTP_ATTRIBUTES *attrs)
|
||||||
{
|
{
|
||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -1311,12 +1343,27 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
|||||||
longentry_maxlen, attrs);
|
longentry_maxlen, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_write
|
/* libssh2_sftp_readdir_ex
|
||||||
|
* Read from an SFTP directory handle
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
|
||||||
|
size_t buffer_maxlen, char *longentry,
|
||||||
|
size_t longentry_maxlen,
|
||||||
|
LIBSSH2_SFTP_ATTRIBUTES *attrs)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, hnd->sftp->channel->session,
|
||||||
|
sftp_readdir(hnd, buffer, buffer_maxlen, longentry,
|
||||||
|
longentry_maxlen, attrs));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sftp_write
|
||||||
* Write data to a file handle
|
* Write data to a file handle
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API ssize_t
|
static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
|
||||||
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
|
size_t count)
|
||||||
size_t count)
|
|
||||||
{
|
{
|
||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -1405,12 +1452,27 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_fstat_ex
|
/* libssh2_sftp_write
|
||||||
|
* Write data to a file handle
|
||||||
|
*/
|
||||||
|
LIBSSH2_API ssize_t
|
||||||
|
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
ssize_t rc;
|
||||||
|
BLOCK_ADJUST(rc, hnd->sftp->channel->session,
|
||||||
|
sftp_write(hnd, buffer, count));
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sftp_fstat
|
||||||
|
*
|
||||||
* Get or Set stat on a file
|
* Get or Set stat on a file
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
|
||||||
libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
|
LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
|
||||||
LIBSSH2_SFTP_ATTRIBUTES * attrs, int setstat)
|
|
||||||
{
|
{
|
||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -1506,6 +1568,19 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* libssh2_sftp_fstat_ex
|
||||||
|
* Get or Set stat on a file
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * hnd,
|
||||||
|
LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, hnd->sftp->channel->session,
|
||||||
|
sftp_fstat(hnd, attrs, setstat));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_seek
|
/* libssh2_sftp_seek
|
||||||
* Set the read/write pointer to an arbitrary position within the file
|
* Set the read/write pointer to an arbitrary position within the file
|
||||||
*/
|
*/
|
||||||
@ -1542,12 +1617,13 @@ libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE * handle)
|
|||||||
return handle->u.file.offset;
|
return handle->u.file.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_close_handle
|
/* sftp_close_handle
|
||||||
|
*
|
||||||
* Close a file or directory handle
|
* Close a file or directory handle
|
||||||
* Also frees handle resource and unlinks it from the SFTP structure
|
* Also frees handle resource and unlinks it from the SFTP structure
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
static int
|
||||||
libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
|
sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
|
||||||
{
|
{
|
||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -1647,16 +1723,23 @@ libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **********************
|
/* libssh2_sftp_close_handle
|
||||||
* SFTP Miscellaneous *
|
*
|
||||||
********************** */
|
* Close a file or directory handle
|
||||||
|
* Also frees handle resource and unlinks it from the SFTP structure
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *hnd)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_close_handle(hnd));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_unlink_ex
|
/* sftp_unlink
|
||||||
* Delete a file from the remote server
|
* Delete a file from the remote server
|
||||||
*/
|
*/
|
||||||
/* libssh2_sftp_unlink_ex - NB-UNSAFE?? */
|
static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
|
||||||
LIBSSH2_API int
|
|
||||||
libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
|
|
||||||
unsigned int filename_len)
|
unsigned int filename_len)
|
||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -1738,11 +1821,25 @@ libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_rename_ex
|
/* libssh2_sftp_unlink_ex
|
||||||
* Rename a file on the remote server
|
* Delete a file from the remote server
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
|
libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename,
|
||||||
|
unsigned int filename_len)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, sftp->channel->session,
|
||||||
|
sftp_unlink(sftp, filename, filename_len));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sftp_rename
|
||||||
|
*
|
||||||
|
* Rename a file on the remote server
|
||||||
|
*/
|
||||||
|
static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
|
||||||
unsigned int source_filename_len,
|
unsigned int source_filename_len,
|
||||||
const char *dest_filename,
|
const char *dest_filename,
|
||||||
unsigned int dest_filename_len, long flags)
|
unsigned int dest_filename_len, long flags)
|
||||||
@ -1865,11 +1962,28 @@ libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
|
|||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_mkdir_ex
|
/* libssh2_sftp_rename_ex
|
||||||
* Create an SFTP directory
|
* Rename a file on the remote server
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp, const char *path,
|
libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename,
|
||||||
|
unsigned int source_filename_len,
|
||||||
|
const char *dest_filename,
|
||||||
|
unsigned int dest_filename_len, long flags)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, sftp->channel->session,
|
||||||
|
sftp_rename(sftp, source_filename, source_filename_len,
|
||||||
|
dest_filename, dest_filename_len, flags));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sftp_mkdir
|
||||||
|
*
|
||||||
|
* Create an SFTP directory
|
||||||
|
*/
|
||||||
|
static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
unsigned int path_len, long mode)
|
unsigned int path_len, long mode)
|
||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -1957,12 +2071,25 @@ libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp, const char *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_rmdir_ex
|
/*
|
||||||
|
* libssh2_sftp_mkdir_ex
|
||||||
|
*
|
||||||
|
* Create an SFTP directory
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
|
unsigned int path_len, long mode)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, sftp->channel->session,
|
||||||
|
sftp_mkdir(sftp, path, path_len, mode));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sftp_rmdir
|
||||||
* Remove a directory
|
* Remove a directory
|
||||||
*/
|
*/
|
||||||
/* libssh2_sftp_rmdir_ex - NB-UNSAFE?? */
|
static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
LIBSSH2_API int
|
|
||||||
libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
|
|
||||||
unsigned int path_len)
|
unsigned int path_len)
|
||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
@ -2042,12 +2169,23 @@ libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_stat_ex
|
/* libssh2_sftp_rmdir_ex
|
||||||
|
* Remove a directory
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
|
unsigned int path_len)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, sftp->channel->session,
|
||||||
|
sftp_rmdir(sftp, path, path_len));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sftp_stat
|
||||||
* Stat a file or symbolic link
|
* Stat a file or symbolic link
|
||||||
*/
|
*/
|
||||||
/* libssh2_sftp_stat_ex - NB-UNSAFE?? */
|
static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
LIBSSH2_API int
|
|
||||||
libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
|
|
||||||
unsigned int path_len, int stat_type,
|
unsigned int path_len, int stat_type,
|
||||||
LIBSSH2_SFTP_ATTRIBUTES * attrs)
|
LIBSSH2_SFTP_ATTRIBUTES * attrs)
|
||||||
{
|
{
|
||||||
@ -2159,11 +2297,24 @@ libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_symlink_ex
|
/* libssh2_sftp_stat_ex
|
||||||
* Read or set a symlink
|
* Stat a file or symbolic link
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
|
libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
|
unsigned int path_len, int stat_type,
|
||||||
|
LIBSSH2_SFTP_ATTRIBUTES *attrs)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, sftp->channel->session,
|
||||||
|
sftp_stat(sftp, path, path_len, stat_type, attrs));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sftp_symlink
|
||||||
|
* Read or set a symlink
|
||||||
|
*/
|
||||||
|
static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
unsigned int path_len, char *target,
|
unsigned int path_len, char *target,
|
||||||
unsigned int target_len, int link_type)
|
unsigned int target_len, int link_type)
|
||||||
{
|
{
|
||||||
@ -2301,11 +2452,26 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
|
|||||||
return link_len;
|
return link_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* libssh2_sftp_symlink_ex
|
||||||
|
* Read or set a symlink
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path,
|
||||||
|
unsigned int path_len, char *target,
|
||||||
|
unsigned int target_len, int link_type)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, sftp->channel->session,
|
||||||
|
sftp_symlink(sftp, path, path_len, target, target_len,
|
||||||
|
link_type));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* libssh2_sftp_last_error
|
/* libssh2_sftp_last_error
|
||||||
* Returns the last error code reported by SFTP
|
* Returns the last error code reported by SFTP
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API unsigned long
|
LIBSSH2_API unsigned long
|
||||||
libssh2_sftp_last_error(LIBSSH2_SFTP * sftp)
|
libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
|
||||||
{
|
{
|
||||||
return sftp->last_errno;
|
return sftp->last_errno;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */
|
#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */
|
||||||
#define MAX_MACSIZE 20 /* MUST fit biggest MAC length we support */
|
#define MAX_MACSIZE 20 /* MUST fit biggest MAC length we support */
|
||||||
|
|
||||||
@ -220,7 +222,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
|||||||
|
|
||||||
session->fullpacket_packet_type = p->payload[0];
|
session->fullpacket_packet_type = p->payload[0];
|
||||||
|
|
||||||
debugdump(session, "libssh2_packet_read() plain",
|
debugdump(session, "libssh2_transport_read() plain",
|
||||||
p->payload, session->fullpacket_payload_len);
|
p->payload, session->fullpacket_payload_len);
|
||||||
|
|
||||||
session->fullpacket_state = libssh2_NB_state_created;
|
session->fullpacket_state = libssh2_NB_state_created;
|
||||||
@ -244,7 +246,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _libssh2_packet_read
|
* _libssh2_transport_read
|
||||||
*
|
*
|
||||||
* Collect a packet into the input brigade block only controls whether or not
|
* Collect a packet into the input brigade block only controls whether or not
|
||||||
* to wait for a packet to start.
|
* to wait for a packet to start.
|
||||||
@ -259,7 +261,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
|||||||
* "The Secure Shell (SSH) Transport Layer Protocol"
|
* "The Secure Shell (SSH) Transport Layer Protocol"
|
||||||
*/
|
*/
|
||||||
libssh2pack_t
|
libssh2pack_t
|
||||||
_libssh2_packet_read(LIBSSH2_SESSION * session)
|
_libssh2_transport_read(LIBSSH2_SESSION * session)
|
||||||
{
|
{
|
||||||
libssh2pack_t rc;
|
libssh2pack_t rc;
|
||||||
struct transportpacket *p = &session->packet;
|
struct transportpacket *p = &session->packet;
|
||||||
@ -313,7 +315,7 @@ _libssh2_packet_read(LIBSSH2_SESSION * session)
|
|||||||
if (session->readPack_state == libssh2_NB_state_jump1) {
|
if (session->readPack_state == libssh2_NB_state_jump1) {
|
||||||
session->readPack_state = libssh2_NB_state_idle;
|
session->readPack_state = libssh2_NB_state_idle;
|
||||||
encrypted = session->readPack_encrypted;
|
encrypted = session->readPack_encrypted;
|
||||||
goto libssh2_packet_read_point1;
|
goto libssh2_transport_read_point1;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -373,7 +375,7 @@ _libssh2_packet_read(LIBSSH2_SESSION * session)
|
|||||||
}
|
}
|
||||||
return PACKET_FAIL;
|
return PACKET_FAIL;
|
||||||
}
|
}
|
||||||
debugdump(session, "libssh2_packet_read() raw",
|
debugdump(session, "libssh2_transport_read() raw",
|
||||||
&p->buf[remainbuf], nread);
|
&p->buf[remainbuf], nread);
|
||||||
/* advance write pointer */
|
/* advance write pointer */
|
||||||
p->writeidx += nread;
|
p->writeidx += nread;
|
||||||
@ -542,7 +544,7 @@ _libssh2_packet_read(LIBSSH2_SESSION * session)
|
|||||||
|
|
||||||
if (!remainpack) {
|
if (!remainpack) {
|
||||||
/* we have a full packet */
|
/* we have a full packet */
|
||||||
libssh2_packet_read_point1:
|
libssh2_transport_read_point1:
|
||||||
rc = fullpacket(session, encrypted);
|
rc = fullpacket(session, encrypted);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
|
|
||||||
@ -618,7 +620,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugdump(session, "libssh2_packet_write send()", &p->outbuf[p->osent],
|
debugdump(session, "libssh2_transport_write send()", &p->outbuf[p->osent],
|
||||||
length);
|
length);
|
||||||
p->osent += length; /* we sent away this much data */
|
p->osent += length; /* we sent away this much data */
|
||||||
|
|
||||||
@ -626,7 +628,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_packet_write
|
* libssh2_transport_write
|
||||||
*
|
*
|
||||||
* Send a packet, encrypting it and adding a MAC code if necessary
|
* Send a packet, encrypting it and adding a MAC code if necessary
|
||||||
* Returns 0 on success, non-zero on failure.
|
* Returns 0 on success, non-zero on failure.
|
||||||
@ -641,8 +643,8 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
* (RFC4253 section 6.1)
|
* (RFC4253 section 6.1)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
_libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
|
_libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
unsigned long data_len)
|
unsigned long data_len)
|
||||||
{
|
{
|
||||||
int blocksize =
|
int blocksize =
|
||||||
(session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->
|
(session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->
|
||||||
@ -663,7 +665,7 @@ _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
unsigned char *orgdata = data;
|
unsigned char *orgdata = data;
|
||||||
unsigned long orgdata_len = data_len;
|
unsigned long orgdata_len = data_len;
|
||||||
|
|
||||||
debugdump(session, "libssh2_packet_write plain", data, data_len);
|
debugdump(session, "libssh2_transport_write plain", data, data_len);
|
||||||
|
|
||||||
/* FIRST, check if we have a pending write to complete */
|
/* FIRST, check if we have a pending write to complete */
|
||||||
rc = send_existing(session, data, data_len, &ret);
|
rc = send_existing(session, data, data_len, &ret);
|
||||||
@ -769,7 +771,7 @@ _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||||
|
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
debugdump(session, "libssh2_packet_write send()", p->outbuf, ret);
|
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
|
||||||
}
|
}
|
||||||
if (ret != total_length) {
|
if (ret != total_length) {
|
||||||
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
|
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
|
||||||
|
80
src/transport.h
Обычный файл
80
src/transport.h
Обычный файл
@ -0,0 +1,80 @@
|
|||||||
|
#ifndef __LIBSSH2_TRANSPORT_H
|
||||||
|
#define __LIBSSH2_TRANSPORT_H
|
||||||
|
|
||||||
|
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2009 by Daniel Stenberg
|
||||||
|
* Author: Daniel Stenberg <daniel@haxx.se>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms,
|
||||||
|
* with or without modification, are permitted provided
|
||||||
|
* that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the
|
||||||
|
* following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the copyright holder nor the names
|
||||||
|
* of any other contributors may be used to endorse or
|
||||||
|
* promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file handles reading and writing to the SECSH transport layer. RFC4253.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libssh2_priv.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_transport_write
|
||||||
|
*
|
||||||
|
* Send a packet, encrypting it and adding a MAC code if necessary
|
||||||
|
* Returns 0 on success, non-zero on failure.
|
||||||
|
*
|
||||||
|
* Returns PACKET_EAGAIN if it would block - and if it does so, you should
|
||||||
|
* call this function again as soon as it is likely that more data can be
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* NOTE: this function does not verify that 'data_len' is less than ~35000
|
||||||
|
* which is what all implementations should support at least as packet size.
|
||||||
|
* (RFC4253 section 6.1)
|
||||||
|
*/
|
||||||
|
int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
unsigned long data_len);
|
||||||
|
/*
|
||||||
|
* _libssh2_transport_read
|
||||||
|
*
|
||||||
|
* Collect a packet into the input brigade block only controls whether or not
|
||||||
|
* to wait for a packet to start.
|
||||||
|
*
|
||||||
|
* Returns packet type added to input brigade (PACKET_NONE if nothing added),
|
||||||
|
* or PACKET_FAIL on failure and PACKET_EAGAIN if it couldn't process a full
|
||||||
|
* packet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function reads the binary stream as specified in chapter 6 of RFC4253
|
||||||
|
* "The Secure Shell (SSH) Transport Layer Protocol"
|
||||||
|
*/
|
||||||
|
libssh2pack_t _libssh2_transport_read(LIBSSH2_SESSION * session);
|
||||||
|
|
||||||
|
#endif /* __LIBSSH2_TRANSPORT_H */
|
284
src/userauth.c
284
src/userauth.c
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||||
|
* Copyright (c) 2009 by Daniel Stenberg
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@ -45,16 +46,17 @@
|
|||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
/* {{{ proto libssh2_userauth_list
|
/* libssh2_userauth_list
|
||||||
|
*
|
||||||
* List authentication methods
|
* List authentication methods
|
||||||
* Will yield successful login if "none" happens to be allowable for this user
|
* Will yield successful login if "none" happens to be allowable for this user
|
||||||
* Not a common configuration for any SSH server though
|
* Not a common configuration for any SSH server though
|
||||||
* username should be NULL, or a null terminated string
|
* username should be NULL, or a null terminated string
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API char *
|
static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
||||||
libssh2_userauth_list(LIBSSH2_SESSION * session, const char *username,
|
unsigned int username_len)
|
||||||
unsigned int username_len)
|
|
||||||
{
|
{
|
||||||
static const unsigned char reply_codes[3] =
|
static const unsigned char reply_codes[3] =
|
||||||
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
|
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
|
||||||
@ -101,7 +103,7 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_list_state == libssh2_NB_state_created) {
|
if (session->userauth_list_state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, session->userauth_list_data,
|
rc = _libssh2_transport_write(session, session->userauth_list_data,
|
||||||
session->userauth_list_data_len);
|
session->userauth_list_data_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||||
@ -161,6 +163,23 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *username,
|
|||||||
return (char *) session->userauth_list_data;
|
return (char *) session->userauth_list_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* libssh2_userauth_list
|
||||||
|
*
|
||||||
|
* List authentication methods
|
||||||
|
* Will yield successful login if "none" happens to be allowable for this user
|
||||||
|
* Not a common configuration for any SSH server though
|
||||||
|
* username should be NULL, or a null terminated string
|
||||||
|
*/
|
||||||
|
LIBSSH2_API char *
|
||||||
|
libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user,
|
||||||
|
unsigned int user_len)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
BLOCK_ADJUST_ERRNO(ptr, session,
|
||||||
|
userauth_list(session, user, user_len));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_userauth_authenticated
|
* libssh2_userauth_authenticated
|
||||||
*
|
*
|
||||||
@ -173,16 +192,16 @@ libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
|
|||||||
return session->state & LIBSSH2_STATE_AUTHENTICATED;
|
return session->state & LIBSSH2_STATE_AUTHENTICATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ libssh2_userauth_password
|
|
||||||
|
/* userauth_password
|
||||||
* Plain ol' login
|
* Plain ol' login
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
static int
|
||||||
libssh2_userauth_password_ex(LIBSSH2_SESSION * session, const char *username,
|
userauth_password(LIBSSH2_SESSION *session, const char *username,
|
||||||
unsigned int username_len, const char *password,
|
unsigned int username_len, const char *password,
|
||||||
unsigned int password_len,
|
unsigned int password_len,
|
||||||
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
|
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
|
||||||
{
|
{
|
||||||
unsigned char *s;
|
unsigned char *s;
|
||||||
static const unsigned char reply_codes[4] =
|
static const unsigned char reply_codes[4] =
|
||||||
@ -208,8 +227,8 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION * session, const char *username,
|
|||||||
LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
|
LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
|
||||||
if (!session->userauth_pswd_data) {
|
if (!session->userauth_pswd_data) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for userauth-password request",
|
"Unable to allocate memory for userauth-password"
|
||||||
0);
|
" request", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +263,7 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION * session, const char *username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_pswd_state == libssh2_NB_state_created) {
|
if (session->userauth_pswd_state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, session->userauth_pswd_data,
|
rc = _libssh2_transport_write(session, session->userauth_pswd_data,
|
||||||
session->userauth_pswd_data_len);
|
session->userauth_pswd_data_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
@ -378,7 +397,7 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION * session, const char *username,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
|
if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
|
||||||
rc = _libssh2_packet_write(session,
|
rc = _libssh2_transport_write(session,
|
||||||
session->userauth_pswd_data,
|
session->userauth_pswd_data,
|
||||||
session->
|
session->
|
||||||
userauth_pswd_data_len);
|
userauth_pswd_data_len);
|
||||||
@ -425,7 +444,25 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION * session, const char *username,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/*
|
||||||
|
* libssh2_userauth_password_ex
|
||||||
|
*
|
||||||
|
* Plain ol' login
|
||||||
|
*/
|
||||||
|
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
|
||||||
|
unsigned int username_len, const char *password,
|
||||||
|
unsigned int password_len,
|
||||||
|
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, session,
|
||||||
|
userauth_password(session, username, username_len,
|
||||||
|
password, password_len,
|
||||||
|
passwd_change_cb));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* file_read_publickey
|
* file_read_publickey
|
||||||
@ -529,9 +566,9 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ libssh2_file_read_privatekey
|
|
||||||
|
/* libssh2_file_read_privatekey
|
||||||
* Read a PEM encoded private key from an id_??? style file
|
* Read a PEM encoded private key from an id_??? style file
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -574,22 +611,19 @@ libssh2_file_read_privatekey(LIBSSH2_SESSION * session,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ libssh2_userauth_hostbased_fromfile_ex
|
|
||||||
|
/* userauth_hostbased_fromfile
|
||||||
* Authenticate using a keypair found in the named files
|
* Authenticate using a keypair found in the named files
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
static int
|
||||||
libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
|
userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||||
const char *username,
|
const char *username, unsigned int username_len,
|
||||||
unsigned int username_len,
|
const char *publickey, const char *privatekey,
|
||||||
const char *publickey,
|
const char *passphrase, const char *hostname,
|
||||||
const char *privatekey,
|
unsigned int hostname_len,
|
||||||
const char *passphrase,
|
const char *local_username,
|
||||||
const char *hostname,
|
unsigned int local_username_len)
|
||||||
unsigned int hostname_len,
|
|
||||||
const char *local_username,
|
|
||||||
unsigned int local_username_len)
|
|
||||||
{
|
{
|
||||||
static const unsigned char reply_codes[3] =
|
static const unsigned char reply_codes[3] =
|
||||||
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
|
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
|
||||||
@ -632,10 +666,9 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
*/
|
*/
|
||||||
session->userauth_host_s = session->userauth_host_packet =
|
session->userauth_host_s = session->userauth_host_packet =
|
||||||
LIBSSH2_ALLOC(session,
|
LIBSSH2_ALLOC(session,
|
||||||
session->userauth_host_packet_len + 4 + (4 +
|
session->userauth_host_packet_len + 4 +
|
||||||
session->
|
(4 + session->userauth_host_method_len) +
|
||||||
userauth_host_method_len)
|
(4 + pubkeydata_len));
|
||||||
+ (4 + pubkeydata_len));
|
|
||||||
if (!session->userauth_host_packet) {
|
if (!session->userauth_host_packet) {
|
||||||
LIBSSH2_FREE(session, session->userauth_host_method);
|
LIBSSH2_FREE(session, session->userauth_host_method);
|
||||||
session->userauth_host_method = NULL;
|
session->userauth_host_method = NULL;
|
||||||
@ -716,10 +749,14 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
if (sig_len > pubkeydata_len) {
|
if (sig_len > pubkeydata_len) {
|
||||||
unsigned char *newpacket;
|
unsigned char *newpacket;
|
||||||
/* Should *NEVER* happen, but...well.. better safe than sorry */
|
/* Should *NEVER* happen, but...well.. better safe than sorry */
|
||||||
newpacket = LIBSSH2_REALLOC(session, session->userauth_host_packet, session->userauth_host_packet_len + 4 + (4 + session->userauth_host_method_len) + (4 + sig_len)); /* PK sigblob */
|
newpacket = LIBSSH2_REALLOC(session, session->userauth_host_packet,
|
||||||
|
session->userauth_host_packet_len + 4 +
|
||||||
|
(4 + session->userauth_host_method_len)
|
||||||
|
+ (4 + sig_len)); /* PK sigblob */
|
||||||
if (!newpacket) {
|
if (!newpacket) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Failed allocating additional space for userauth-hostbased packet",
|
"Failed allocating additional space for "
|
||||||
|
"userauth-hostbased packet",
|
||||||
0);
|
0);
|
||||||
LIBSSH2_FREE(session, sig);
|
LIBSSH2_FREE(session, sig);
|
||||||
LIBSSH2_FREE(session, session->userauth_host_packet);
|
LIBSSH2_FREE(session, session->userauth_host_packet);
|
||||||
@ -760,7 +797,7 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_host_state == libssh2_NB_state_created) {
|
if (session->userauth_host_state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, session->userauth_host_packet,
|
rc = _libssh2_transport_write(session, session->userauth_host_packet,
|
||||||
session->userauth_host_s -
|
session->userauth_host_s -
|
||||||
session->userauth_host_packet);
|
session->userauth_host_packet);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
@ -809,24 +846,50 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
LIBSSH2_FREE(session, session->userauth_host_data);
|
LIBSSH2_FREE(session, session->userauth_host_data);
|
||||||
session->userauth_host_data = NULL;
|
session->userauth_host_data = NULL;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||||
"Invalid signature for supplied public key, or bad username/public key combination",
|
"Invalid signature for supplied public key, or bad "
|
||||||
|
"username/public key combination",
|
||||||
0);
|
0);
|
||||||
session->userauth_host_state = libssh2_NB_state_idle;
|
session->userauth_host_state = libssh2_NB_state_idle;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* libssh2_userauth_hostbased_fromfile_ex
|
||||||
|
|
||||||
/* {{{ libssh2_userauth_publickey_fromfile_ex
|
|
||||||
* Authenticate using a keypair found in the named files
|
* Authenticate using a keypair found in the named files
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
|
libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
|
||||||
const char *username,
|
const char *user,
|
||||||
unsigned int username_len,
|
unsigned int user_len,
|
||||||
const char *publickey,
|
const char *publickey,
|
||||||
const char *privatekey,
|
const char *privatekey,
|
||||||
const char *passphrase)
|
const char *passphrase,
|
||||||
|
const char *host,
|
||||||
|
unsigned int host_len,
|
||||||
|
const char *localuser,
|
||||||
|
unsigned int localuser_len)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, session,
|
||||||
|
userauth_hostbased_fromfile(session, user, user_len,
|
||||||
|
publickey, privatekey,
|
||||||
|
passphrase, host, host_len,
|
||||||
|
localuser, localuser_len));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* userauth_publickey_fromfile
|
||||||
|
* Authenticate using a keypair found in the named files
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
||||||
|
const char *username,
|
||||||
|
unsigned int username_len,
|
||||||
|
const char *publickey,
|
||||||
|
const char *privatekey,
|
||||||
|
const char *passphrase)
|
||||||
{
|
{
|
||||||
unsigned long pubkeydata_len = 0;
|
unsigned long pubkeydata_len = 0;
|
||||||
unsigned char reply_codes[4] =
|
unsigned char reply_codes[4] =
|
||||||
@ -865,9 +928,8 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
*/
|
*/
|
||||||
session->userauth_pblc_s = session->userauth_pblc_packet =
|
session->userauth_pblc_s = session->userauth_pblc_packet =
|
||||||
LIBSSH2_ALLOC(session,
|
LIBSSH2_ALLOC(session,
|
||||||
session->userauth_pblc_packet_len + 4 + (4 +
|
session->userauth_pblc_packet_len + 4 +
|
||||||
session->
|
(4 + session->userauth_pblc_method_len)
|
||||||
userauth_pblc_method_len)
|
|
||||||
+ (4 + pubkeydata_len));
|
+ (4 + pubkeydata_len));
|
||||||
if (!session->userauth_pblc_packet) {
|
if (!session->userauth_pblc_packet) {
|
||||||
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
||||||
@ -916,7 +978,7 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_pblc_state == libssh2_NB_state_created) {
|
if (session->userauth_pblc_state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, session->userauth_pblc_packet,
|
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
|
||||||
session->userauth_pblc_packet_len);
|
session->userauth_pblc_packet_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
@ -1039,10 +1101,15 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
if (sig_len > pubkeydata_len) {
|
if (sig_len > pubkeydata_len) {
|
||||||
unsigned char *newpacket;
|
unsigned char *newpacket;
|
||||||
/* Should *NEVER* happen, but...well.. better safe than sorry */
|
/* Should *NEVER* happen, but...well.. better safe than sorry */
|
||||||
newpacket = LIBSSH2_REALLOC(session, session->userauth_pblc_packet, session->userauth_pblc_packet_len + 4 + (4 + session->userauth_pblc_method_len) + (4 + sig_len)); /* PK sigblob */
|
newpacket = LIBSSH2_REALLOC(session,
|
||||||
|
session->userauth_pblc_packet,
|
||||||
|
session->userauth_pblc_packet_len + 4 +
|
||||||
|
(4 + session->userauth_pblc_method_len)
|
||||||
|
+ (4 + sig_len)); /* PK sigblob */
|
||||||
if (!newpacket) {
|
if (!newpacket) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Failed allocating additional space for userauth-publickey packet",
|
"Failed allocating additional space for "
|
||||||
|
"userauth-publickey packet",
|
||||||
0);
|
0);
|
||||||
LIBSSH2_FREE(session, sig);
|
LIBSSH2_FREE(session, sig);
|
||||||
LIBSSH2_FREE(session, session->userauth_pblc_packet);
|
LIBSSH2_FREE(session, session->userauth_pblc_packet);
|
||||||
@ -1085,7 +1152,7 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
|
if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
|
||||||
rc = _libssh2_packet_write(session, session->userauth_pblc_packet,
|
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
|
||||||
session->userauth_pblc_s -
|
session->userauth_pblc_s -
|
||||||
session->userauth_pblc_packet);
|
session->userauth_pblc_packet);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
@ -1133,22 +1200,44 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
|
|||||||
LIBSSH2_FREE(session, session->userauth_pblc_data);
|
LIBSSH2_FREE(session, session->userauth_pblc_data);
|
||||||
session->userauth_pblc_data = NULL;
|
session->userauth_pblc_data = NULL;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||||
"Invalid signature for supplied public key, or bad username/public key combination",
|
"Invalid signature for supplied public key, or bad "
|
||||||
|
"username/public key combination",
|
||||||
0);
|
0);
|
||||||
session->userauth_pblc_state = libssh2_NB_state_idle;
|
session->userauth_pblc_state = libssh2_NB_state_idle;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* libssh2_userauth_publickey_fromfile_ex
|
||||||
|
* Authenticate using a keypair found in the named files
|
||||||
/* {{{ libssh2_userauth_keyboard_interactive
|
|
||||||
* Authenticate using a challenge-response authentication
|
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
|
||||||
const char *username,
|
const char *user,
|
||||||
unsigned int username_len,
|
unsigned int user_len,
|
||||||
LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
|
const char *publickey,
|
||||||
|
const char *privatekey,
|
||||||
|
const char *passphrase)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, session,
|
||||||
|
userauth_publickey_fromfile(session, user, user_len,
|
||||||
|
publickey, privatekey,
|
||||||
|
passphrase));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* userauth_keyboard_interactive
|
||||||
|
*
|
||||||
|
* Authenticate using a challenge-response authentication
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
||||||
|
const char *username,
|
||||||
|
unsigned int username_len,
|
||||||
|
LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
|
||||||
{
|
{
|
||||||
unsigned char *s;
|
unsigned char *s;
|
||||||
int rc;
|
int rc;
|
||||||
@ -1171,19 +1260,23 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
memset(&session->userauth_kybd_packet_requirev_state, 0,
|
memset(&session->userauth_kybd_packet_requirev_state, 0,
|
||||||
sizeof(session->userauth_kybd_packet_requirev_state));
|
sizeof(session->userauth_kybd_packet_requirev_state));
|
||||||
|
|
||||||
session->userauth_kybd_packet_len = 1 /* byte SSH_MSG_USERAUTH_REQUEST */
|
session->userauth_kybd_packet_len =
|
||||||
+ 4 + username_len /* string user name (ISO-10646 UTF-8, as defined in [RFC-3629]) */
|
1 /* byte SSH_MSG_USERAUTH_REQUEST */
|
||||||
+ 4 + 14 /* string service name (US-ASCII) */
|
+ 4 + username_len /* string user name (ISO-10646 UTF-8, as
|
||||||
+ 4 + 20 /* string "keyboard-interactive" (US-ASCII) */
|
defined in [RFC-3629]) */
|
||||||
+ 4 + 0 /* string language tag (as defined in [RFC-3066]) */
|
+ 4 + 14 /* string service name (US-ASCII) */
|
||||||
+ 4 + 0 /* string submethods (ISO-10646 UTF-8) */
|
+ 4 + 20 /* string "keyboard-interactive" (US-ASCII) */
|
||||||
|
+ 4 + 0 /* string language tag (as defined in
|
||||||
|
[RFC-3066]) */
|
||||||
|
+ 4 + 0 /* string submethods (ISO-10646 UTF-8) */
|
||||||
;
|
;
|
||||||
|
|
||||||
session->userauth_kybd_data = s =
|
session->userauth_kybd_data = s =
|
||||||
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
|
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for keyboard-interactive authentication",
|
"Unable to allocate memory for "
|
||||||
|
"keyboard-interactive authentication",
|
||||||
0);
|
0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1223,7 +1316,7 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_kybd_state == libssh2_NB_state_created) {
|
if (session->userauth_kybd_state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_packet_write(session, session->userauth_kybd_data,
|
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
|
||||||
session->userauth_kybd_packet_len);
|
session->userauth_kybd_packet_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
@ -1284,7 +1377,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
LIBSSH2_ALLOC(session, session->userauth_kybd_auth_name_len);
|
LIBSSH2_ALLOC(session, session->userauth_kybd_auth_name_len);
|
||||||
if (!session->userauth_kybd_auth_name) {
|
if (!session->userauth_kybd_auth_name) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for keyboard-interactive 'name' request field",
|
"Unable to allocate memory for "
|
||||||
|
"keyboard-interactive 'name' request field",
|
||||||
0);
|
0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1300,7 +1394,9 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
session->userauth_kybd_auth_instruction_len);
|
session->userauth_kybd_auth_instruction_len);
|
||||||
if (!session->userauth_kybd_auth_instruction) {
|
if (!session->userauth_kybd_auth_instruction) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for keyboard-interactive 'instruction' request field",
|
"Unable to allocate memory for "
|
||||||
|
"keyboard-interactive 'instruction' "
|
||||||
|
"request field",
|
||||||
0);
|
0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1324,7 +1420,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
session->userauth_kybd_num_prompts);
|
session->userauth_kybd_num_prompts);
|
||||||
if (!session->userauth_kybd_prompts) {
|
if (!session->userauth_kybd_prompts) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for keyboard-interactive prompts array",
|
"Unable to allocate memory for "
|
||||||
|
"keyboard-interactive prompts array",
|
||||||
0);
|
0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1338,7 +1435,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
session->userauth_kybd_num_prompts);
|
session->userauth_kybd_num_prompts);
|
||||||
if (!session->userauth_kybd_responses) {
|
if (!session->userauth_kybd_responses) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for keyboard-interactive responses array",
|
"Unable to allocate memory for "
|
||||||
|
"keyboard-interactive responses array",
|
||||||
0);
|
0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1355,7 +1453,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
session->userauth_kybd_prompts[i].length);
|
session->userauth_kybd_prompts[i].length);
|
||||||
if (!session->userauth_kybd_prompts[i].text) {
|
if (!session->userauth_kybd_prompts[i].text) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for keyboard-interactive prompt message",
|
"Unable to allocate memory for "
|
||||||
|
"keyboard-interactive prompt message",
|
||||||
0);
|
0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1377,9 +1476,11 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
&session->abstract);
|
&session->abstract);
|
||||||
|
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
_libssh2_debug(session, LIBSSH2_DBG_AUTH,
|
||||||
"Keyboard-interactive response callback function invoked");
|
"Keyboard-interactive response callback function"
|
||||||
|
" invoked");
|
||||||
|
|
||||||
session->userauth_kybd_packet_len = 1 /* byte SSH_MSG_USERAUTH_INFO_RESPONSE */
|
session->userauth_kybd_packet_len =
|
||||||
|
1 /* byte SSH_MSG_USERAUTH_INFO_RESPONSE */
|
||||||
+ 4 /* int num-responses */
|
+ 4 /* int num-responses */
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1393,7 +1494,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
|
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for keyboard-interactive response packet",
|
"Unable to allocate memory for keyboard-"
|
||||||
|
"interactive response packet",
|
||||||
0);
|
0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1415,14 +1517,15 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
|
if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
|
||||||
rc = _libssh2_packet_write(session, session->userauth_kybd_data,
|
rc = _libssh2_transport_write(session, session->userauth_kybd_data,
|
||||||
session->userauth_kybd_packet_len);
|
session->userauth_kybd_packet_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
if (rc) {
|
if (rc) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send userauth-keyboard-interactive request",
|
"Unable to send userauth-keyboard-interactive"
|
||||||
|
" request",
|
||||||
0);
|
0);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1468,4 +1571,21 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/*
|
||||||
|
* libssh2_userauth_keyboard_interactive_ex
|
||||||
|
*
|
||||||
|
* Authenticate using a challenge-response authentication
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session,
|
||||||
|
const char *user,
|
||||||
|
unsigned int user_len,
|
||||||
|
LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
BLOCK_ADJUST(rc, session,
|
||||||
|
userauth_keyboard_interactive(session, user, user_len,
|
||||||
|
response_callback));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user