2009-03-27 20:20:48 +00:00
|
|
|
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
|
2015-03-11 12:16:18 +01:00
|
|
|
* Copyright (c) 2009-2015 by Daniel Stenberg
|
2010-02-25 15:58:52 +01:00
|
|
|
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
|
2004-12-07 21:17:20 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "libssh2_priv.h"
|
|
|
|
#include <errno.h>
|
2007-04-12 22:18:27 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2004-12-07 21:17:20 +00:00
|
|
|
#include <unistd.h>
|
2005-01-03 22:46:15 +00:00
|
|
|
#endif
|
2004-12-07 21:17:20 +00:00
|
|
|
#include <stdlib.h>
|
2007-06-06 12:34:06 +00:00
|
|
|
#include <fcntl.h>
|
2004-12-07 21:17:20 +00:00
|
|
|
|
2005-03-23 00:21:26 +00:00
|
|
|
#ifdef HAVE_GETTIMEOFDAY
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
#ifdef HAVE_ALLOCA_H
|
|
|
|
#include <alloca.h>
|
|
|
|
#endif
|
2005-03-23 00:21:26 +00:00
|
|
|
|
2009-03-27 07:03:00 +00:00
|
|
|
#include "transport.h"
|
2010-04-24 20:21:22 +02:00
|
|
|
#include "session.h"
|
2010-04-24 21:14:16 +02:00
|
|
|
#include "channel.h"
|
2010-12-15 09:52:18 +01:00
|
|
|
#include "mac.h"
|
2011-08-05 23:46:12 +02:00
|
|
|
#include "misc.h"
|
2009-03-27 07:03:00 +00:00
|
|
|
|
2009-03-17 13:48:35 +00:00
|
|
|
/* libssh2_default_alloc
|
2004-12-07 21:17:20 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
static
|
|
|
|
LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
|
2004-12-07 21:17:20 +00:00
|
|
|
{
|
2007-08-06 20:48:04 +00:00
|
|
|
(void) abstract;
|
2007-05-28 17:56:08 +00:00
|
|
|
return malloc(count);
|
2004-12-07 21:17:20 +00:00
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
|
2009-03-17 13:48:35 +00:00
|
|
|
/* libssh2_default_free
|
2004-12-07 21:17:20 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
static
|
|
|
|
LIBSSH2_FREE_FUNC(libssh2_default_free)
|
2004-12-07 21:17:20 +00:00
|
|
|
{
|
2007-08-06 20:48:04 +00:00
|
|
|
(void) abstract;
|
2007-05-28 17:56:08 +00:00
|
|
|
free(ptr);
|
2004-12-07 21:17:20 +00:00
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
|
2009-03-17 13:48:35 +00:00
|
|
|
/* libssh2_default_realloc
|
2004-12-07 21:17:20 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
static
|
|
|
|
LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
|
2004-12-07 21:17:20 +00:00
|
|
|
{
|
2007-08-06 20:48:04 +00:00
|
|
|
(void) abstract;
|
2007-05-28 17:56:08 +00:00
|
|
|
return realloc(ptr, count);
|
2004-12-07 21:17:20 +00:00
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
|
2009-03-17 13:48:35 +00:00
|
|
|
/*
|
|
|
|
* banner_receive
|
|
|
|
*
|
2004-12-07 21:17:20 +00:00
|
|
|
* Wait for a hello from the remote host
|
|
|
|
* Allocate a buffer and store the banner in session->remote.banner
|
2011-01-31 15:50:27 +01:00
|
|
|
* Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative
|
|
|
|
* on failure
|
2004-12-07 21:17:20 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
static int
|
2009-03-17 13:48:35 +00:00
|
|
|
banner_receive(LIBSSH2_SESSION * session)
|
2004-12-07 21:17:20 +00:00
|
|
|
{
|
2007-06-06 12:34:06 +00:00
|
|
|
int ret;
|
|
|
|
int banner_len;
|
2004-12-07 21:17:20 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
if (session->banner_TxRx_state == libssh2_NB_state_idle) {
|
|
|
|
banner_len = 0;
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
session->banner_TxRx_state = libssh2_NB_state_created;
|
|
|
|
} else {
|
|
|
|
banner_len = session->banner_TxRx_total_send;
|
|
|
|
}
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-08-06 20:48:04 +00:00
|
|
|
while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) &&
|
|
|
|
((banner_len == 0)
|
|
|
|
|| (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
|
2007-05-28 17:56:08 +00:00
|
|
|
char c = '\0';
|
2004-12-07 21:17:20 +00:00
|
|
|
|
2009-08-24 23:22:39 +02:00
|
|
|
/* no incoming block yet! */
|
|
|
|
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
|
|
|
|
|
2011-08-11 22:26:56 +02:00
|
|
|
ret = LIBSSH2_RECV(session, &c, 1,
|
2009-03-19 12:45:59 +00:00
|
|
|
LIBSSH2_SOCKET_RECV_FLAGS(session));
|
2010-10-07 11:21:56 +02:00
|
|
|
if (ret < 0) {
|
2010-11-12 21:53:35 +01:00
|
|
|
if(session->api_block_mode || (ret != -EAGAIN))
|
2010-10-07 11:21:56 +02:00
|
|
|
/* ignore EAGAIN when non-blocking */
|
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
2010-11-12 21:53:35 +01:00
|
|
|
"Error recving %d bytes: %d", 1, -ret);
|
2010-10-07 11:21:56 +02:00
|
|
|
}
|
2009-12-08 08:40:30 +01:00
|
|
|
else
|
2009-12-08 08:52:03 +01:00
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
2010-10-07 11:21:56 +02:00
|
|
|
"Recved %d bytes banner", ret);
|
2004-12-07 21:17:20 +00:00
|
|
|
|
2007-05-28 17:56:08 +00:00
|
|
|
if (ret < 0) {
|
2010-11-12 21:53:35 +01:00
|
|
|
if (ret == -EAGAIN) {
|
2008-11-24 13:31:00 +00:00
|
|
|
session->socket_block_directions =
|
|
|
|
LIBSSH2_SESSION_BLOCK_INBOUND;
|
2007-06-06 12:34:06 +00:00
|
|
|
session->banner_TxRx_total_send = banner_len;
|
2010-04-17 13:18:15 +02:00
|
|
|
return LIBSSH2_ERROR_EAGAIN;
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
2007-08-08 21:43:12 +00:00
|
|
|
|
|
|
|
/* Some kinda error */
|
|
|
|
session->banner_TxRx_state = libssh2_NB_state_idle;
|
|
|
|
session->banner_TxRx_total_send = 0;
|
2010-10-07 11:21:56 +02:00
|
|
|
return LIBSSH2_ERROR_SOCKET_RECV;
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
|
|
|
|
2007-08-08 21:43:12 +00:00
|
|
|
if (ret == 0) {
|
|
|
|
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
|
2012-04-17 05:03:43 +02:00
|
|
|
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
|
2007-08-08 21:43:12 +00:00
|
|
|
}
|
2007-05-28 17:56:08 +00:00
|
|
|
|
|
|
|
if (c == '\0') {
|
|
|
|
/* NULLs are not allowed in SSH banners */
|
2007-06-06 12:34:06 +00:00
|
|
|
session->banner_TxRx_state = libssh2_NB_state_idle;
|
|
|
|
session->banner_TxRx_total_send = 0;
|
2010-10-07 11:21:56 +02:00
|
|
|
return LIBSSH2_ERROR_BANNER_RECV;
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
session->banner_TxRx_banner[banner_len++] = c;
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (banner_len &&
|
2007-08-06 20:48:04 +00:00
|
|
|
((session->banner_TxRx_banner[banner_len - 1] == '\n') ||
|
|
|
|
(session->banner_TxRx_banner[banner_len - 1] == '\r'))) {
|
2007-05-28 17:56:08 +00:00
|
|
|
banner_len--;
|
|
|
|
}
|
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
/* From this point on, we are done here */
|
|
|
|
session->banner_TxRx_state = libssh2_NB_state_idle;
|
|
|
|
session->banner_TxRx_total_send = 0;
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-08-06 20:48:04 +00:00
|
|
|
if (!banner_len)
|
2010-10-07 11:21:56 +02:00
|
|
|
return LIBSSH2_ERROR_BANNER_RECV;
|
2007-05-28 17:56:08 +00:00
|
|
|
|
|
|
|
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
|
|
|
|
if (!session->remote.banner) {
|
2010-04-16 00:18:51 +02:00
|
|
|
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
|
|
|
"Error allocating space for remote banner");
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
2007-06-06 12:34:06 +00:00
|
|
|
memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
|
2007-05-28 17:56:08 +00:00
|
|
|
session->remote.banner[banner_len] = '\0';
|
2009-12-08 08:52:03 +01:00
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
|
2007-08-06 20:48:04 +00:00
|
|
|
session->remote.banner);
|
2010-10-07 11:21:56 +02:00
|
|
|
return LIBSSH2_ERROR_NONE;
|
2004-12-07 21:17:20 +00:00
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
|
2009-03-17 13:48:35 +00:00
|
|
|
/*
|
|
|
|
* banner_send
|
|
|
|
*
|
2004-12-07 21:17:20 +00:00
|
|
|
* Send the default banner, or the one set via libssh2_setopt_string
|
2007-06-06 12:34:06 +00:00
|
|
|
*
|
2010-10-07 11:21:56 +02:00
|
|
|
* Returns LIBSSH2_ERROR_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
|
2007-06-06 12:34:06 +00:00
|
|
|
* (same data pointer and same data_len) until zero or failure is returned.
|
2004-12-07 21:17:20 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
static int
|
2009-03-17 13:48:35 +00:00
|
|
|
banner_send(LIBSSH2_SESSION * session)
|
2004-12-07 21:17:20 +00:00
|
|
|
{
|
2007-08-06 20:48:04 +00:00
|
|
|
char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF;
|
2007-05-28 17:56:08 +00:00
|
|
|
int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1;
|
2007-06-06 12:34:06 +00:00
|
|
|
ssize_t ret;
|
2007-02-02 23:23:36 +00:00
|
|
|
#ifdef LIBSSH2DEBUG
|
2007-05-28 17:56:08 +00:00
|
|
|
char banner_dup[256];
|
2007-06-06 12:34:06 +00:00
|
|
|
#endif
|
2007-05-28 17:56:08 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
if (session->banner_TxRx_state == libssh2_NB_state_idle) {
|
|
|
|
if (session->local.banner) {
|
|
|
|
/* setopt_string will have given us our \r\n characters */
|
2007-08-06 20:48:04 +00:00
|
|
|
banner_len = strlen((char *) session->local.banner);
|
|
|
|
banner = (char *) session->local.banner;
|
2007-06-06 12:34:06 +00:00
|
|
|
}
|
|
|
|
#ifdef LIBSSH2DEBUG
|
|
|
|
/* Hack and slash to avoid sending CRLF in debug output */
|
|
|
|
if (banner_len < 256) {
|
|
|
|
memcpy(banner_dup, banner, banner_len - 2);
|
|
|
|
banner_dup[banner_len - 2] = '\0';
|
|
|
|
} else {
|
|
|
|
memcpy(banner_dup, banner, 255);
|
|
|
|
banner[255] = '\0';
|
|
|
|
}
|
|
|
|
|
2009-12-08 08:52:03 +01:00
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s",
|
2007-08-06 20:48:04 +00:00
|
|
|
banner_dup);
|
2007-06-06 12:34:06 +00:00
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
session->banner_TxRx_state = libssh2_NB_state_created;
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
|
|
|
|
2009-08-24 23:22:39 +02:00
|
|
|
/* no outgoing block yet! */
|
|
|
|
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
|
|
|
|
2011-08-11 22:26:56 +02:00
|
|
|
ret = LIBSSH2_SEND(session,
|
2009-03-19 12:45:59 +00:00
|
|
|
banner + session->banner_TxRx_total_send,
|
|
|
|
banner_len - session->banner_TxRx_total_send,
|
|
|
|
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
2009-12-08 08:40:30 +01:00
|
|
|
if (ret < 0)
|
2009-12-08 08:52:03 +01:00
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
2009-12-08 08:40:30 +01:00
|
|
|
"Error sending %d bytes: %d",
|
2010-11-12 21:53:35 +01:00
|
|
|
banner_len - session->banner_TxRx_total_send, -ret);
|
2009-12-08 08:40:30 +01:00
|
|
|
else
|
2009-12-08 08:52:03 +01:00
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
2009-12-08 08:40:30 +01:00
|
|
|
"Sent %d/%d bytes at %p+%d", ret,
|
|
|
|
banner_len - session->banner_TxRx_total_send,
|
|
|
|
banner, session->banner_TxRx_total_send);
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-08-06 20:48:04 +00:00
|
|
|
if (ret != (banner_len - session->banner_TxRx_total_send)) {
|
2010-11-13 01:52:25 +01:00
|
|
|
if (ret >= 0 || ret == -EAGAIN) {
|
2007-06-06 12:34:06 +00:00
|
|
|
/* the whole packet could not be sent, save the what was */
|
2008-11-24 13:31:00 +00:00
|
|
|
session->socket_block_directions =
|
|
|
|
LIBSSH2_SESSION_BLOCK_OUTBOUND;
|
2010-11-13 01:52:25 +01:00
|
|
|
if (ret > 0)
|
|
|
|
session->banner_TxRx_total_send += ret;
|
2010-04-17 13:18:15 +02:00
|
|
|
return LIBSSH2_ERROR_EAGAIN;
|
2007-06-06 12:34:06 +00:00
|
|
|
}
|
|
|
|
session->banner_TxRx_state = libssh2_NB_state_idle;
|
|
|
|
session->banner_TxRx_total_send = 0;
|
2010-10-07 11:21:56 +02:00
|
|
|
return LIBSSH2_ERROR_SOCKET_RECV;
|
2007-06-06 12:34:06 +00:00
|
|
|
}
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
/* Set the state back to idle */
|
|
|
|
session->banner_TxRx_state = libssh2_NB_state_idle;
|
|
|
|
session->banner_TxRx_total_send = 0;
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
return 0;
|
2005-05-11 05:11:31 +00:00
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
/*
|
2009-03-17 13:48:35 +00:00
|
|
|
* session_nonblock() sets the given socket to either blocking or
|
2007-06-06 12:34:06 +00:00
|
|
|
* non-blocking mode based on the 'nonblock' boolean argument. This function
|
|
|
|
* is copied from the libcurl sources with permission.
|
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
static int
|
2009-08-24 14:13:00 +02:00
|
|
|
session_nonblock(libssh2_socket_t sockfd, /* operate on this */
|
2009-03-17 13:48:35 +00:00
|
|
|
int nonblock /* TRUE or FALSE */ )
|
2007-06-06 12:34:06 +00:00
|
|
|
{
|
|
|
|
#undef SETBLOCK
|
|
|
|
#define SETBLOCK 0
|
|
|
|
#ifdef HAVE_O_NONBLOCK
|
|
|
|
/* most recent unix versions */
|
|
|
|
int flags;
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
flags = fcntl(sockfd, F_GETFL, 0);
|
|
|
|
if (nonblock)
|
|
|
|
return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
|
|
|
else
|
|
|
|
return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
|
|
|
|
#undef SETBLOCK
|
|
|
|
#define SETBLOCK 1
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#if defined(HAVE_FIONBIO) && (SETBLOCK == 0)
|
2010-04-25 19:57:45 +02:00
|
|
|
/* older unix versions and VMS*/
|
2007-06-06 12:34:06 +00:00
|
|
|
int flags;
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
flags = nonblock;
|
|
|
|
return ioctl(sockfd, FIONBIO, &flags);
|
|
|
|
#undef SETBLOCK
|
|
|
|
#define SETBLOCK 2
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0)
|
|
|
|
/* Windows? */
|
|
|
|
unsigned long flags;
|
|
|
|
flags = nonblock;
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
return ioctlsocket(sockfd, FIONBIO, &flags);
|
|
|
|
#undef SETBLOCK
|
|
|
|
#define SETBLOCK 3
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0)
|
|
|
|
/* presumably for Amiga */
|
2007-08-06 20:48:04 +00:00
|
|
|
return IoctlSocket(sockfd, FIONBIO, (long) nonblock);
|
2007-06-06 12:34:06 +00:00
|
|
|
#undef SETBLOCK
|
|
|
|
#define SETBLOCK 4
|
2005-05-11 05:11:31 +00:00
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0)
|
|
|
|
/* BeOS */
|
|
|
|
long b = nonblock ? 1 : 0;
|
|
|
|
return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
|
|
|
|
#undef SETBLOCK
|
|
|
|
#define SETBLOCK 5
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#ifdef HAVE_DISABLED_NONBLOCKING
|
2007-08-06 20:48:04 +00:00
|
|
|
return 0; /* returns success */
|
2007-06-06 12:34:06 +00:00
|
|
|
#undef SETBLOCK
|
|
|
|
#define SETBLOCK 6
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#if (SETBLOCK == 0)
|
|
|
|
#error "no non-blocking method was found/used/set"
|
|
|
|
#endif
|
|
|
|
}
|
2004-12-07 21:17:20 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
/*
|
2009-03-17 13:48:35 +00:00
|
|
|
* get_socket_nonblocking()
|
|
|
|
*
|
|
|
|
* gets the given blocking or non-blocking state of the socket.
|
2007-06-06 12:34:06 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
static int
|
2009-03-17 13:48:35 +00:00
|
|
|
get_socket_nonblocking(int sockfd)
|
2007-08-06 20:48:04 +00:00
|
|
|
{ /* operate on this */
|
2007-06-06 12:34:06 +00:00
|
|
|
#undef GETBLOCK
|
|
|
|
#define GETBLOCK 0
|
|
|
|
#ifdef HAVE_O_NONBLOCK
|
|
|
|
/* most recent unix versions */
|
|
|
|
int flags;
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) {
|
|
|
|
/* Assume blocking on error */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return (flags & O_NONBLOCK);
|
|
|
|
#undef GETBLOCK
|
|
|
|
#define GETBLOCK 1
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-22 16:46:36 +00:00
|
|
|
#if defined(WSAEWOULDBLOCK) && (GETBLOCK == 0)
|
|
|
|
/* Windows? */
|
|
|
|
unsigned int option_value;
|
|
|
|
socklen_t option_len = sizeof(option_value);
|
|
|
|
|
2007-08-06 20:48:04 +00:00
|
|
|
if (getsockopt
|
|
|
|
(sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) {
|
2007-06-22 16:46:36 +00:00
|
|
|
/* Assume blocking on error */
|
|
|
|
return 1;
|
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
return (int) option_value;
|
2007-06-22 16:46:36 +00:00
|
|
|
#undef GETBLOCK
|
|
|
|
#define GETBLOCK 2
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0)
|
|
|
|
/* BeOS */
|
|
|
|
long b;
|
|
|
|
if (getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) {
|
|
|
|
/* Assume blocking on error */
|
|
|
|
return 1;
|
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
return (int) b;
|
2007-06-06 12:34:06 +00:00
|
|
|
#undef GETBLOCK
|
|
|
|
#define GETBLOCK 5
|
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2010-04-25 19:57:45 +02:00
|
|
|
#if defined(SO_STATE) && defined( __VMS ) && (GETBLOCK == 0)
|
|
|
|
|
|
|
|
/* VMS TCP/IP Services */
|
|
|
|
|
|
|
|
size_t sockstat = 0;
|
|
|
|
int callstat = 0;
|
|
|
|
size_t size = sizeof( int );
|
|
|
|
|
|
|
|
callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE,
|
|
|
|
(char *)&sockstat, &size);
|
|
|
|
if ( callstat == -1 ) return(0);
|
|
|
|
if ( (sockstat&SS_NBIO) )return(1);
|
|
|
|
return(0);
|
|
|
|
|
|
|
|
#undef GETBLOCK
|
|
|
|
#define GETBLOCK 6
|
|
|
|
#endif
|
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#ifdef HAVE_DISABLED_NONBLOCKING
|
2007-08-06 20:48:04 +00:00
|
|
|
return 1; /* returns blocking */
|
2007-06-06 12:34:06 +00:00
|
|
|
#undef GETBLOCK
|
2010-04-25 19:57:45 +02:00
|
|
|
#define GETBLOCK 7
|
2007-06-06 12:34:06 +00:00
|
|
|
#endif
|
2007-07-23 21:18:43 +00:00
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
#if (GETBLOCK == 0)
|
|
|
|
#error "no non-blocking method was found/used/get"
|
|
|
|
#endif
|
2004-12-07 21:17:20 +00:00
|
|
|
}
|
|
|
|
|
2011-09-09 23:11:42 +02:00
|
|
|
/* libssh2_session_banner_set
|
|
|
|
* Set the local banner to use in the server handshake.
|
2004-12-24 23:10:15 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
LIBSSH2_API int
|
2011-09-09 23:11:42 +02:00
|
|
|
libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner)
|
2004-12-24 23:10:15 +00:00
|
|
|
{
|
2010-12-29 23:36:45 +01:00
|
|
|
size_t banner_len = banner ? strlen(banner) : 0;
|
2007-05-28 17:56:08 +00:00
|
|
|
|
|
|
|
if (session->local.banner) {
|
|
|
|
LIBSSH2_FREE(session, session->local.banner);
|
|
|
|
session->local.banner = NULL;
|
|
|
|
}
|
|
|
|
|
2010-12-29 23:36:45 +01:00
|
|
|
if (!banner_len)
|
2007-05-28 17:56:08 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
|
|
|
|
if (!session->local.banner) {
|
2010-04-16 00:18:51 +02:00
|
|
|
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
|
|
|
"Unable to allocate memory for local banner");
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(session->local.banner, banner, banner_len);
|
2010-04-18 15:30:03 +02:00
|
|
|
|
|
|
|
/* first zero terminate like this so that the debug output is nice */
|
2007-05-28 17:56:08 +00:00
|
|
|
session->local.banner[banner_len] = '\0';
|
2009-12-08 08:52:03 +01:00
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s",
|
2007-08-06 20:48:04 +00:00
|
|
|
session->local.banner);
|
2007-05-28 17:56:08 +00:00
|
|
|
session->local.banner[banner_len++] = '\r';
|
|
|
|
session->local.banner[banner_len++] = '\n';
|
2010-04-18 15:30:03 +02:00
|
|
|
session->local.banner[banner_len] = '\0';
|
2007-05-28 17:56:08 +00:00
|
|
|
|
|
|
|
return 0;
|
2004-12-24 23:10:15 +00:00
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
|
2011-09-09 23:11:42 +02:00
|
|
|
/* libssh2_banner_set
|
|
|
|
* Set the local banner. DEPRECATED VERSION
|
|
|
|
*/
|
|
|
|
LIBSSH2_API int
|
|
|
|
libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
|
|
|
|
{
|
|
|
|
return libssh2_session_banner_set(session, banner);
|
|
|
|
}
|
|
|
|
|
2009-03-17 13:48:35 +00:00
|
|
|
/*
|
2009-03-26 15:41:14 +00:00
|
|
|
* libssh2_session_init_ex
|
2009-03-17 13:48:35 +00:00
|
|
|
*
|
2009-03-26 15:41:14 +00:00
|
|
|
* 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)
|
2004-12-07 21:17:20 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
LIBSSH2_API LIBSSH2_SESSION *
|
|
|
|
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
|
|
|
LIBSSH2_FREE_FUNC((*my_free)),
|
|
|
|
LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract)
|
2004-12-07 21:17:20 +00:00
|
|
|
{
|
2007-08-06 20:48:04 +00:00
|
|
|
LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc;
|
|
|
|
LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free;
|
|
|
|
LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc;
|
2007-05-28 17:56:08 +00:00
|
|
|
LIBSSH2_SESSION *session;
|
|
|
|
|
2007-06-06 12:34:06 +00:00
|
|
|
if (my_alloc) {
|
2007-08-06 20:48:04 +00:00
|
|
|
local_alloc = my_alloc;
|
2007-06-06 12:34:06 +00:00
|
|
|
}
|
|
|
|
if (my_free) {
|
2007-08-06 20:48:04 +00:00
|
|
|
local_free = my_free;
|
2007-06-06 12:34:06 +00:00
|
|
|
}
|
|
|
|
if (my_realloc) {
|
2007-08-06 20:48:04 +00:00
|
|
|
local_realloc = my_realloc;
|
2007-06-06 12:34:06 +00:00
|
|
|
}
|
2007-05-28 17:56:08 +00:00
|
|
|
|
2009-07-07 13:09:11 +02:00
|
|
|
session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract);
|
2007-05-28 17:56:08 +00:00
|
|
|
if (session) {
|
|
|
|
memset(session, 0, sizeof(LIBSSH2_SESSION));
|
2007-08-06 20:48:04 +00:00
|
|
|
session->alloc = local_alloc;
|
|
|
|
session->free = local_free;
|
|
|
|
session->realloc = local_realloc;
|
2011-08-11 22:26:56 +02:00
|
|
|
session->send = _libssh2_send;
|
|
|
|
session->recv = _libssh2_recv;
|
2007-08-06 20:48:04 +00:00
|
|
|
session->abstract = abstract;
|
2011-05-03 11:20:24 +12:00
|
|
|
session->api_timeout = 0; /* timeout-free API by default */
|
2009-03-26 15:41:14 +00:00
|
|
|
session->api_block_mode = 1; /* blocking API by default */
|
2009-12-08 08:52:03 +01:00
|
|
|
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
2007-08-06 20:48:04 +00:00
|
|
|
"New session resource allocated");
|
2010-03-19 09:14:21 +01:00
|
|
|
_libssh2_init_if_needed ();
|
2007-05-28 17:56:08 +00:00
|
|
|
}
|
|
|
|
return session;
|
2004-12-07 21:17:20 +00:00
|
|
|
}
|
2007-08-06 20:48:04 +00:00
|
|
|
|
2009-03-17 13:48:35 +00:00
|
|
|
/*
|
|
|
|
* libssh2_session_callback_set
|
|
|
|
*
|
2004-12-09 18:24:14 +00:00
|
|
|
* Set (or reset) a callback function
|
|
|
|
* Returns the prior address
|
2007-07-23 21:18:43 +00:00
|
|
|
*
|
|
|
|
* FIXME: this function relies on that we can typecast function pointers
|
|
|
|
* to void pointers, which isn't allowed in ISO C!
|
2004-12-09 18:24:14 +00:00
|
|
|
*/
|
2007-08-06 20:48:04 +00:00
|
|
|
LIBSSH2_API void *
|
|
|
|
libssh2_session_callback_set(LIBSSH2_SESSION * session,
|
|
|
|
int cbtype, void *callback)
|
2004-12-09 18:24:14 +00:00
|
|
|
{
|
2007-05-28 17:56:08 +00:00
|
|
|
void *oldcb;
|
|
|
|
|
|
|
|
switch (cbtype) {
|
2007-08-06 20:48:04 +00:00
|
|
|
case LIBSSH2_CALLBACK_IGNORE:
|
|
|
|
oldcb = session->ssh_msg_ignore;
|
|
|
|
session->ssh_msg_ignore = callback;
|
|
|
|
return oldcb;
|
2007-05-28 17:56:08 +00:00
|
|
|
|
2007-08-06 20:48:04 +00:00
|
|
|
case LIBSSH2_CALLBACK_DEBUG:
|
|
|
|
oldcb = session->ssh_msg_debug;
|
|
|
|
session->ssh_msg_debug = callback;
|
|
|
|
return oldcb;
|
2007-05-28 17:56:08 +00:00
|
|
|
|
2007-08-06 20:48:04 +00:00
|
|
|
case LIBSSH2_CALLBACK_DISCONNECT:
|
|
|
|
oldcb = session->ssh_msg_disconnect;
|
|
|
|
session->ssh_msg_disconnect = callback;
|
|
|
|
return oldcb;
|
2007-05-28 17:56:08 +00:00
|
|
|
|
2007-08-06 20:48:04 +00:00
|
|
|
case LIBSSH2_CALLBACK_MACERROR:
|
|
|
|
oldcb = session->macerror;
|
|
|
|
session->macerror = callback;
|
|
|
|
return oldcb;
|
2007-05-28 17:56:08 +00:00
|
|
|
|
|