1
1

* 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.
Этот коммит содержится в:
Daniel Stenberg 2009-03-26 15:41:14 +00:00
родитель 239bdffb59
Коммит eabe072496
19 изменённых файлов: 1370 добавлений и 437 удалений

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
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

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

@ -30,7 +30,9 @@ At next SONAME bump
* stop using #defined macros as part of the official API. The macros should
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_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
@ -19,6 +19,7 @@ dist_man_MANS = \
libssh2_channel_process_startup.3 \
libssh2_channel_read_ex.3 \
libssh2_channel_receive_window_adjust.3 \
libssh2_channel_receive_window_adjust2.3 \
libssh2_channel_request_pty_ex.3 \
libssh2_channel_send_eof.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"
.SH NAME
@ -10,6 +10,9 @@ void
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
.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.
\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
reading
.br
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_MERGE\fP: Treat extended data and ordinary
data the same. Merge all substreams such that calls to
.BR libssh2_channel_read(3)
will pull from all substreams on a first-in/first-out basis.
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_MERGE\fP: Treat extended data and ordinary
data the same. Merge all substreams such that calls to
\fIlibssh2_channel_read(3)\fP will pull from all substreams on a
first-in/first-out basis.
.br
\fBLIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE\fP: Discard all extended data as it
arrives.
Change how a channel deals with extended data packets. By default all
extended data is queued until read by
.BR libssh2_channel_read_ex(3)
Change how a channel deals with extended data packets. By default all extended
data is queued until read by \fIlibssh2_channel_read_ex(3)\fP
.SH RETURN VALUE
None.
.SH SEE ALSO
.BR libssh2_channel_handle_extended_data2(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"
.SH NAME
@ -12,6 +12,9 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
unsigned char force);
.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
be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
adjustment amount will be queued for a later packet.

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

@ -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"
.SH NAME
@ -8,7 +8,6 @@ libssh2_channel_set_blocking - set or clear blocking mode on channel
void
libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking);
.SH DESCRIPTION
\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
.BR libssh2_session_set_blocking(3)
and therefore will affect the session and all channels.
.SH RETURN VALUE
None
.SH SEE ALSO
.BR libssh2_session_set_blocking(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) \
libssh2_channel_window_read_ex((channel), NULL, NULL)
/* libssh2_channel_receive_window_adjust is DEPRECATED, do not use! */
LIBSSH2_API unsigned long
libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
unsigned long adjustment,
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,
int stream_id, const char *buf,
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,
int blocking);
/* libssh2_channel_handle_extended_data is DEPRECATED, do not use! */
LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
int ignore_mode);
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
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 \
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
libssh2_la_SOURCES += libgcrypt.c pem.c

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

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 */

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

@ -37,6 +37,8 @@
#include "libssh2_priv.h"
#include "transport.h"
/* TODO: Switch this to an inline and handle alloc() failures */
/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */
#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) {
rc = _libssh2_packet_write(session, exchange_state->e_packet,
exchange_state->e_packet_len);
rc = _libssh2_transport_write(session, exchange_state->e_packet,
exchange_state->e_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} 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) {
rc = _libssh2_packet_write(session, &exchange_state->c, 1);
rc = _libssh2_transport_write(session, &exchange_state->c, 1);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@ -837,7 +839,7 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
}
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);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
@ -1136,7 +1138,7 @@ static int kexinit(LIBSSH2_SESSION * session)
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) {
session->kexinit_data = data;
session->kexinit_data_len = data_len;

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

@ -684,6 +684,9 @@ struct _LIBSSH2_SESSION
unsigned char *session_id;
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 */
const LIBSSH2_HOSTKEY_METHOD *hostkey;
void *server_hostkey_abstract;
@ -716,9 +719,10 @@ struct _LIBSSH2_SESSION
/* Actual I/O socket */
int socket_fd;
int socket_block;
int socket_state;
int socket_block_directions;
int socket_prev_blockstate; /* stores the state of the socket blockiness
when libssh2_session_startup() is called */
/* Error tracking */
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
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
@ -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,
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 */

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

@ -59,6 +59,8 @@
#include <sys/types.h>
#include "transport.h"
/*
* 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) {
rc = _libssh2_packet_write(session, listen_state->packet,
17);
rc = _libssh2_transport_write(session, listen_state->packet,
17);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@ -256,7 +258,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
p += sizeof(FwdNotReq) - 1;
_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) {
return PACKET_EAGAIN;
} else if (rc) {
@ -374,7 +377,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
}
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) {
return PACKET_EAGAIN;
} else if (rc) {
@ -422,7 +425,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
p += sizeof(X11FwdUnAvil) - 1;
_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) {
return PACKET_EAGAIN;
} 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 packAdd and readPack states need to be reset
* because libssh2_kex_exchange (eventually) calls upon
* libssh2_packet_read to read the rest of the key exchange
* conversation.
* The KEXINIT message has been added to the queue. The packAdd and
* readPack states need to be reset because libssh2_kex_exchange
* (eventually) calls upon _libssh2_transport_read to read the rest of
* the key exchange conversation.
*/
session->readPack_state = libssh2_NB_state_idle;
session->packet.total_num = 0;
@ -1029,39 +1031,10 @@ _libssh2_packet_askv(LIBSSH2_SESSION * session,
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
*
* 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
*
* 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) {
libssh2pack_t ret = _libssh2_packet_read(session);
libssh2pack_t ret = _libssh2_transport_read(session);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if ((ret == 0) && (!session->socket_block)) {
/* If we are in non-blocking and there is no data, return that */
} else if (ret == 0) {
/* There is no data, return that. TODO: is this really correct? */
return PACKET_EAGAIN;
} else if (ret < 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 */
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
if ((left <= 0) || (_libssh2_waitsocket(session, left) <= 0)) {
if (left <= 0) {
state->start = 0;
return PACKET_TIMEOUT;
}
@ -1125,7 +1098,7 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
/*
* _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.
* 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) {
if ((ret = _libssh2_packet_read(session)) == PACKET_EAGAIN) {
if ((ret = _libssh2_transport_read(session)) == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (ret < 0) {
*state = libssh2_NB_state_idle;
@ -1185,7 +1158,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
/*
* _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
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
* 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) {
int ret = _libssh2_packet_read(session);
int ret = _libssh2_transport_read(session);
if ((ret < 0) && (ret != PACKET_EAGAIN)) {
state->start = 0;
return ret;
@ -1220,10 +1193,11 @@ _libssh2_packet_requirev(LIBSSH2_SESSION * session,
if (ret <= 0) {
long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
if ((left <= 0) || (_libssh2_waitsocket(session, left) <= 0)) {
if (left <= 0) {
state->start = 0;
return PACKET_TIMEOUT;
} else if (ret == PACKET_EAGAIN) {
}
else if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
}

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

@ -1,4 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* All rights reserved.
*
* 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
* Allows for malloc callbacks in case the calling program has its own memory manager
* It's allowable (but unadvisable) to define some but not all of the malloc callbacks
* An additional pointer value may be optionally passed to be sent to the callbacks (so they know who's asking)
* Allocate and initialize a libssh2 session structure. Allows for malloc
* callbacks in case the calling program has its own memory manager It's
* allowable (but unadvisable) to define some but not all of the malloc
* callbacks An additional pointer value may be optionally passed to be sent
* to the callbacks (so they know who's asking)
*/
LIBSSH2_API LIBSSH2_SESSION *
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
@ -430,6 +432,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
session->free = local_free;
session->realloc = local_realloc;
session->abstract = abstract;
session->api_block_mode = 1; /* blocking API by default */
_libssh2_debug(session, LIBSSH2_DBG_TRANS,
"New session resource allocated");
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
* Returns: 0 on success, or non-zero on failure
* Any memory allocated by libssh2 will use alloc/realloc/free
* callbacks in session
* socket *must* be populated with an opened and connected socket.
* Utility function that waits for action on the socket. Returns 0 when ready
* to run again or error on timeout.
*/
LIBSSH2_API int
libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
int _libssh2_wait_socket(LIBSSH2_SESSION *session)
{
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;
@ -510,15 +543,12 @@ libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
}
session->socket_fd = sock;
session->socket_block =
session->socket_prev_blockstate =
!get_socket_nonblocking(session->socket_fd);
if (session->socket_block) {
/*
* Since we can't be sure that we are in blocking or there
* was an error detecting the state, so set to blocking to
* be sure
*/
session_nonblock(session->socket_fd, 0);
if (session->socket_prev_blockstate) {
/* If in blocking state chang to non-blocking */
session_nonblock(session->socket_fd, 1);
}
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) {
rc = _libssh2_packet_write(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1);
rc = _libssh2_transport_write(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block asking for ssh-userauth service", 0);
@ -638,14 +668,33 @@ libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
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
*
* Frees the memory allocated to the session
* Also closes and frees any channels attached to this session
*/
LIBSSH2_API int
libssh2_session_free(LIBSSH2_SESSION * session)
static int
session_free(LIBSSH2_SESSION *session)
{
int rc;
@ -869,16 +918,37 @@ libssh2_session_free(LIBSSH2_SESSION * session)
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);
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_session_disconnect_ex(LIBSSH2_SESSION * session, int reason,
const char *description, const char *lang)
libssh2_session_free(LIBSSH2_SESSION * session)
{
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 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;
}
rc = _libssh2_packet_write(session, session->disconnect_data,
session->disconnect_data_len);
rc = _libssh2_transport_write(session, session->disconnect_data,
session->disconnect_data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
@ -941,10 +1011,27 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION * session, int reason,
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
*
* 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_session_methods(LIBSSH2_SESSION * session, int method_type)
@ -1019,9 +1106,10 @@ libssh2_session_abstract(LIBSSH2_SESSION * session)
}
/* 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
* Otherwise it is assumed to be owned by libssh2
*
* 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. Otherwise it is assumed to be owned by libssh2
*/
LIBSSH2_API int
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
*
* Set a session's blocking mode on or off, return the previous status
* when this function is called.
* Set a session's blocking mode on or off, return the previous status when
* this function is called. Note this function does not alter the state of the
* actual socket involved.
*/
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,
"Setting blocking mode on session %d", blocking);
if (blocking == session->socket_block) {
/* avoid if already correct */
return bl;
}
session->socket_block = blocking;
session_nonblock(session->socket_fd, !blocking);
"Setting blocking mode %s", blocking?"ON":"OFF");
session->api_block_mode = blocking;
return bl;
}
@ -1139,7 +1222,7 @@ libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
LIBSSH2_API int
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:
if (sockets[i].events & POLLIN) {
/* 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);
}
if (sockets[i].revents & POLLHUP) {
@ -1431,7 +1514,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
case LIBSSH2_POLLFD_LISTENER:
if (sockets[i].events & POLLIN) {
/* 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);
}
if (sockets[i].revents & POLLHUP) {
@ -1484,7 +1567,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
case LIBSSH2_POLLFD_CHANNEL:
if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
/* Spin session until no data available */
while (_libssh2_packet_read(fds[i].fd.channel->session)
while (_libssh2_transport_read(fds[i].fd.channel->session)
> 0);
}
break;
@ -1493,7 +1576,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
if (FD_ISSET
(fds[i].fd.listener->session->socket_fd, &rfds)) {
/* Spin session until no data available */
while (_libssh2_packet_read(fds[i].fd.listener->session)
while (_libssh2_transport_read(fds[i].fd.listener->session)
> 0);
}
break;

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

@ -89,7 +89,7 @@
* Add a packet to the SFTP packet brigade
*/
static int
sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
unsigned long data_len)
{
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
*/
static int
sftp_packet_read(LIBSSH2_SFTP * sftp)
sftp_packet_read(LIBSSH2_SFTP *sftp)
{
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
@ -225,7 +225,7 @@ sftp_packet_read(LIBSSH2_SFTP * sftp)
* Checks if there's a matching SFTP packet available.
*/
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 *data_len)
{
@ -280,7 +280,7 @@ sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
* A la libssh2_packet_require
*/
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 *data_len)
{
@ -322,7 +322,7 @@ sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
* Require one of N possible reponses
*/
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,
unsigned long request_id, unsigned char **data,
unsigned long *data_len)
@ -360,12 +360,8 @@ sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
if (left <= 0) {
sftp->requirev_start = 0;
return PACKET_TIMEOUT;
} else if (sftp->channel->session->socket_block
&& (_libssh2_waitsocket(sftp->channel->session, left) <=
0)) {
sftp->requirev_start = 0;
return PACKET_TIMEOUT;
} else if (ret == PACKET_EAGAIN) {
}
else if (ret == 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
*/
LIBSSH2_API LIBSSH2_SFTP *
libssh2_sftp_init(LIBSSH2_SESSION * session)
static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
{
unsigned char *data, *s;
unsigned long data_len;
@ -693,11 +688,23 @@ libssh2_sftp_init(LIBSSH2_SESSION * session)
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
* Shutsdown the SFTP subsystem
*/
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
@ -754,12 +761,12 @@ libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)
* SFTP File and Directory Ops *
******************************* */
/* libssh2_sftp_open_ex
/* sftp_open
*/
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)
static LIBSSH2_SFTP_HANDLE *
sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
unsigned int filename_len, unsigned long flags, long mode,
int open_type)
{
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
@ -932,12 +939,25 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
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
*/
LIBSSH2_API ssize_t
libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
size_t buffer_maxlen)
static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
size_t buffer_maxlen)
{
LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel;
@ -1108,14 +1128,26 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
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
*/
LIBSSH2_API int
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
size_t buffer_maxlen, char *longentry,
size_t longentry_maxlen,
LIBSSH2_SFTP_ATTRIBUTES * attrs)
LIBSSH2_SFTP_ATTRIBUTES *attrs)
{
LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel;
@ -1311,12 +1343,27 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
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
*/
LIBSSH2_API ssize_t
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
size_t count)
static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
size_t count)
{
LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel;
@ -1405,12 +1452,27 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
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
*/
LIBSSH2_API int
libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
LIBSSH2_SFTP_ATTRIBUTES * attrs, int setstat)
static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
{
LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel;
@ -1506,6 +1568,19 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
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
* 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;
}
/* libssh2_sftp_close_handle
/* sftp_close_handle
*
* 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 * handle)
static int
sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
{
LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel;
@ -1647,16 +1723,23 @@ libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
return 0;
}
/* **********************
* SFTP Miscellaneous *
********************** */
/* libssh2_sftp_close_handle
*
* 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
*/
/* libssh2_sftp_unlink_ex - NB-UNSAFE?? */
LIBSSH2_API int
libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
unsigned int filename_len)
{
LIBSSH2_CHANNEL *channel = sftp->channel;
@ -1738,11 +1821,25 @@ libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
}
}
/* libssh2_sftp_rename_ex
* Rename a file on the remote server
/* libssh2_sftp_unlink_ex
* Delete a file from the remote server
*/
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,
const char *dest_filename,
unsigned int dest_filename_len, long flags)
@ -1865,11 +1962,28 @@ libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
return retcode;
}
/* libssh2_sftp_mkdir_ex
* Create an SFTP directory
/* libssh2_sftp_rename_ex
* Rename a file on the remote server
*/
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)
{
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
*/
/* libssh2_sftp_rmdir_ex - NB-UNSAFE?? */
LIBSSH2_API int
libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
unsigned int path_len)
{
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
*/
/* libssh2_sftp_stat_ex - NB-UNSAFE?? */
LIBSSH2_API int
libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
unsigned int path_len, int stat_type,
LIBSSH2_SFTP_ATTRIBUTES * attrs)
{
@ -2159,11 +2297,24 @@ libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
return 0;
}
/* libssh2_sftp_symlink_ex
* Read or set a symlink
/* libssh2_sftp_stat_ex
* Stat a file or symbolic link
*/
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 target_len, int link_type)
{
@ -2301,11 +2452,26 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
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
* Returns the last error code reported by SFTP
*/
LIBSSH2_API unsigned long
libssh2_sftp_last_error(LIBSSH2_SFTP * sftp)
libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
{
return sftp->last_errno;
}

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

@ -44,6 +44,8 @@
#include <assert.h>
#include "transport.h"
#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */
#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];
debugdump(session, "libssh2_packet_read() plain",
debugdump(session, "libssh2_transport_read() plain",
p->payload, session->fullpacket_payload_len);
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
* 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"
*/
libssh2pack_t
_libssh2_packet_read(LIBSSH2_SESSION * session)
_libssh2_transport_read(LIBSSH2_SESSION * session)
{
libssh2pack_t rc;
struct transportpacket *p = &session->packet;
@ -313,7 +315,7 @@ _libssh2_packet_read(LIBSSH2_SESSION * session)
if (session->readPack_state == libssh2_NB_state_jump1) {
session->readPack_state = libssh2_NB_state_idle;
encrypted = session->readPack_encrypted;
goto libssh2_packet_read_point1;
goto libssh2_transport_read_point1;
}
do {
@ -373,7 +375,7 @@ _libssh2_packet_read(LIBSSH2_SESSION * session)
}
return PACKET_FAIL;
}
debugdump(session, "libssh2_packet_read() raw",
debugdump(session, "libssh2_transport_read() raw",
&p->buf[remainbuf], nread);
/* advance write pointer */
p->writeidx += nread;
@ -542,7 +544,7 @@ _libssh2_packet_read(LIBSSH2_SESSION * session)
if (!remainpack) {
/* we have a full packet */
libssh2_packet_read_point1:
libssh2_transport_read_point1:
rc = fullpacket(session, encrypted);
if (rc == PACKET_EAGAIN) {
@ -618,7 +620,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
return PACKET_EAGAIN;
}
debugdump(session, "libssh2_packet_write send()", &p->outbuf[p->osent],
debugdump(session, "libssh2_transport_write send()", &p->outbuf[p->osent],
length);
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
* Returns 0 on success, non-zero on failure.
@ -641,8 +643,8 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
* (RFC4253 section 6.1)
*/
int
_libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len)
_libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len)
{
int blocksize =
(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 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 */
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));
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 > 0) || ((ret == -1) && (errno == EAGAIN))) {

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 */

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

@ -1,4 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@ -45,16 +46,17 @@
#include <sys/uio.h>
#endif
#include "transport.h"
/* {{{ proto libssh2_userauth_list
/* 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 *username,
unsigned int username_len)
static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
unsigned int username_len)
{
static const unsigned char reply_codes[3] =
{ 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) {
rc = _libssh2_packet_write(session, session->userauth_list_data,
rc = _libssh2_transport_write(session, session->userauth_list_data,
session->userauth_list_data_len);
if (rc == PACKET_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;
}
/* 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
*
@ -173,16 +192,16 @@ libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
return session->state & LIBSSH2_STATE_AUTHENTICATED;
}
/* }}} */
/* {{{ libssh2_userauth_password
/* userauth_password
* 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)))
static int
userauth_password(LIBSSH2_SESSION *session, const char *username,
unsigned int username_len, const char *password,
unsigned int password_len,
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
{
unsigned char *s;
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);
if (!session->userauth_pswd_data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for userauth-password request",
0);
"Unable to allocate memory for userauth-password"
" request", 0);
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) {
rc = _libssh2_packet_write(session, session->userauth_pswd_data,
rc = _libssh2_transport_write(session, session->userauth_pswd_data,
session->userauth_pswd_data_len);
if (rc == 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) {
rc = _libssh2_packet_write(session,
rc = _libssh2_transport_write(session,
session->userauth_pswd_data,
session->
userauth_pswd_data_len);
@ -425,7 +444,25 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION * session, const char *username,
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
@ -529,9 +566,9 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
return 0;
}
/* }}} */
/* {{{ libssh2_file_read_privatekey
/* libssh2_file_read_privatekey
* Read a PEM encoded private key from an id_??? style file
*/
static int
@ -574,22 +611,19 @@ libssh2_file_read_privatekey(LIBSSH2_SESSION * session,
return 0;
}
/* }}} */
/* {{{ libssh2_userauth_hostbased_fromfile_ex
/* userauth_hostbased_fromfile
* Authenticate using a keypair found in the named files
*/
LIBSSH2_API int
libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
const char *username,
unsigned int username_len,
const char *publickey,
const char *privatekey,
const char *passphrase,
const char *hostname,
unsigned int hostname_len,
const char *local_username,
unsigned int local_username_len)
static int
userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
const char *username, unsigned int username_len,
const char *publickey, const char *privatekey,
const char *passphrase, const char *hostname,
unsigned int hostname_len,
const char *local_username,
unsigned int local_username_len)
{
static const unsigned char reply_codes[3] =
{ 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 =
LIBSSH2_ALLOC(session,
session->userauth_host_packet_len + 4 + (4 +
session->
userauth_host_method_len)
+ (4 + pubkeydata_len));
session->userauth_host_packet_len + 4 +
(4 + session->userauth_host_method_len) +
(4 + pubkeydata_len));
if (!session->userauth_host_packet) {
LIBSSH2_FREE(session, session->userauth_host_method);
session->userauth_host_method = NULL;
@ -716,10 +749,14 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
if (sig_len > pubkeydata_len) {
unsigned char *newpacket;
/* 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) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Failed allocating additional space for userauth-hostbased packet",
"Failed allocating additional space for "
"userauth-hostbased packet",
0);
LIBSSH2_FREE(session, sig);
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) {
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_packet);
if (rc == PACKET_EAGAIN) {
@ -809,24 +846,50 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
LIBSSH2_FREE(session, session->userauth_host_data);
session->userauth_host_data = NULL;
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);
session->userauth_host_state = libssh2_NB_state_idle;
return -1;
}
/* }}} */
/* {{{ libssh2_userauth_publickey_fromfile_ex
/* libssh2_userauth_hostbased_fromfile_ex
* Authenticate using a keypair found in the named files
*/
LIBSSH2_API int
libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
const char *username,
unsigned int username_len,
libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
const char *user,
unsigned int user_len,
const char *publickey,
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 char reply_codes[4] =
@ -865,9 +928,8 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
*/
session->userauth_pblc_s = session->userauth_pblc_packet =
LIBSSH2_ALLOC(session,
session->userauth_pblc_packet_len + 4 + (4 +
session->
userauth_pblc_method_len)
session->userauth_pblc_packet_len + 4 +
(4 + session->userauth_pblc_method_len)
+ (4 + pubkeydata_len));
if (!session->userauth_pblc_packet) {
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) {
rc = _libssh2_packet_write(session, session->userauth_pblc_packet,
rc = _libssh2_transport_write(session, session->userauth_pblc_packet,
session->userauth_pblc_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
@ -1039,10 +1101,15 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
if (sig_len > pubkeydata_len) {
unsigned char *newpacket;
/* 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) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Failed allocating additional space for userauth-publickey packet",
"Failed allocating additional space for "
"userauth-publickey packet",
0);
LIBSSH2_FREE(session, sig);
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) {
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_packet);
if (rc == PACKET_EAGAIN) {
@ -1133,22 +1200,44 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
LIBSSH2_FREE(session, session->userauth_pblc_data);
session->userauth_pblc_data = NULL;
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);
session->userauth_pblc_state = libssh2_NB_state_idle;
return -1;
}
/* }}} */
/* {{{ libssh2_userauth_keyboard_interactive
* Authenticate using a challenge-response authentication
/* libssh2_userauth_publickey_fromfile_ex
* Authenticate using a keypair found in the named files
*/
LIBSSH2_API int
libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
const char *username,
unsigned int username_len,
LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
const char *user,
unsigned int user_len,
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;
int rc;
@ -1171,19 +1260,23 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
memset(&session->userauth_kybd_packet_requirev_state, 0,
sizeof(session->userauth_kybd_packet_requirev_state));
session->userauth_kybd_packet_len = 1 /* byte SSH_MSG_USERAUTH_REQUEST */
+ 4 + username_len /* string user name (ISO-10646 UTF-8, as defined in [RFC-3629]) */
+ 4 + 14 /* string service name (US-ASCII) */
+ 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_packet_len =
1 /* byte SSH_MSG_USERAUTH_REQUEST */
+ 4 + username_len /* string user name (ISO-10646 UTF-8, as
defined in [RFC-3629]) */
+ 4 + 14 /* string service name (US-ASCII) */
+ 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 =
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
if (!s) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for keyboard-interactive authentication",
"Unable to allocate memory for "
"keyboard-interactive authentication",
0);
return -1;
}
@ -1223,7 +1316,7 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
}
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);
if (rc == 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);
if (!session->userauth_kybd_auth_name) {
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);
goto cleanup;
}
@ -1300,7 +1394,9 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
session->userauth_kybd_auth_instruction_len);
if (!session->userauth_kybd_auth_instruction) {
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);
goto cleanup;
}
@ -1324,7 +1420,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
session->userauth_kybd_num_prompts);
if (!session->userauth_kybd_prompts) {
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);
goto cleanup;
}
@ -1338,7 +1435,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
session->userauth_kybd_num_prompts);
if (!session->userauth_kybd_responses) {
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);
goto cleanup;
}
@ -1355,7 +1453,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
session->userauth_kybd_prompts[i].length);
if (!session->userauth_kybd_prompts[i].text) {
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);
goto cleanup;
}
@ -1377,9 +1476,11 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
&session->abstract);
_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 */
;
@ -1393,7 +1494,8 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
if (!s) {
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);
goto cleanup;
}
@ -1415,14 +1517,15 @@ libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
}
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);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
}
if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-keyboard-interactive request",
"Unable to send userauth-keyboard-interactive"
" request",
0);
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;
}