Compare commits

...

7 Commits

Author SHA1 Message Date
Sara Golemon
7c64e21df6 Bump for release 2005-03-23 00:30:05 +00:00
Sara Golemon
c67bb667aa Add libssh2_poll() 2005-03-23 00:21:26 +00:00
Sara Golemon
141ac5b856 Add sys/uio.h for FBSD builds and remove old stdio references 2005-03-21 21:26:08 +00:00
Sara Golemon
9f64f34dfe Swap compression mode preferences, prefer none over zlib by default 2005-03-17 19:20:32 +00:00
Sara Golemon
a1b87a952c Late news 2005-03-17 19:09:45 +00:00
Sara Golemon
7db9aeecf8 Possible fix for compatability with OpenSSL < 0.9.7 2005-03-02 01:55:51 +00:00
Sara Golemon
99e5547442 strm->next_out doesn't *stay* == out, only free out 2005-02-28 17:02:39 +00:00
10 changed files with 381 additions and 11 deletions

15
README
View File

@@ -1,6 +1,21 @@
libssh2 - SSH2 library
======================
Version 0.8
-----------
Fix potential segfault in compression/decompression.
Fix compatability with older versions of OpenSSL
Swapped order of none,zlib compression modes to prefer no compression by default.
Added sys/uio.h for platforms (FBSD) which need it in order to define struct iovec.
Added libssh2_poll() to check status of sockets/channels/listeners.
Removed unnecessary inclusion of stdio.h (holdover from debugging)
Version 0.7
-----------

View File

@@ -1,5 +1,5 @@
# AC_PREREQ(2.57)
AC_INIT(libssh2,0.7,sarag@libssh2.org)
AC_INIT(libssh2,0.8,sarag@libssh2.org)
AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADER([include/libssh2_config.h])
@@ -162,7 +162,8 @@ fi
# Checks for header files.
# AC_HEADER_STDC
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h])
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h sys/select.h])
AC_CHECK_FUNCS(poll gettimeofday select)
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST

View File

@@ -67,8 +67,8 @@ typedef unsigned long long libssh2_uint64_t;
typedef long long libssh2_int64_t;
#endif
#define LIBSSH2_VERSION "0.7"
#define LIBSSH2_APINO 200502132140
#define LIBSSH2_VERSION "0.8"
#define LIBSSH2_APINO 200503221619
/* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
@@ -143,6 +143,37 @@ typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
typedef struct _LIBSSH2_POLLFD {
unsigned char type; /* LIBSSH2_POLLFD_* below */
union {
int socket; /* File descriptors -- examined with system select() call */
LIBSSH2_CHANNEL *channel; /* Examined by checking internal state */
LIBSSH2_LISTENER *listener; /* Read polls only -- are inbound connections waiting to be accepted? */
} fd;
unsigned long events; /* Requested Events */
unsigned long revents; /* Returned Events */
} LIBSSH2_POLLFD;
/* Poll FD Descriptor Types */
#define LIBSSH2_POLLFD_SOCKET 1
#define LIBSSH2_POLLFD_CHANNEL 2
#define LIBSSH2_POLLFD_LISTENER 3
/* Note: Win32 Doesn't actually have a poll() implementation, so some of these values are faked with select() data */
/* Poll FD events/revents -- Match sys/poll.h where possible */
#define LIBSSH2_POLLFD_POLLIN 0x0001 /* Data available to be read or connection available -- All */
#define LIBSSH2_POLLFD_POLLPRI 0x0002 /* Priority data available to be read -- Socket only */
#define LIBSSH2_POLLFD_POLLEXT 0x0002 /* Extended data available to be read -- Channel only */
#define LIBSSH2_POLLFD_POLLOUT 0x0004 /* Can may be written -- Socket/Channel */
/* revents only */
#define LIBSSH2_POLLFD_POLLERR 0x0008 /* Error Condition -- Socket */
#define LIBSSH2_POLLFD_POLLHUP 0x0010 /* HangUp/EOF -- Socket/Channel */
#define LIBSSH2_POLLFD_POLLNVAL 0x0020 /* Invalid request -- Socket Only */
#define LIBSSH2_POLLFD_POLLEX 0x0040 /* Exception Condition -- Socket/Win32 */
/* Hash Types */
#define LIBSSH2_HOSTKEY_HASH_MD5 1
#define LIBSSH2_HOSTKEY_HASH_SHA1 2
@@ -198,6 +229,7 @@ typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
#define LIBSSH2_ERROR_REQUEST_DENIED -32
#define LIBSSH2_ERROR_METHOD_NOT_SUPPORTED -33
#define LIBSSH2_ERROR_INVAL -34
#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35
/* Session API */
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);
@@ -239,6 +271,8 @@ LIBSSH2_API int libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
#define libssh2_userauth_hostbased_fromfile(session, username, publickey, privatekey, passphrase, hostname) \
libssh2_userauth_hostbased_fromfile_ex((session), (username), strlen(username), (publickey), (privatekey), (passphrase), (hostname), strlen(hostname), (username), strlen(username))
LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
/* Channel API */
#define LIBSSH2_CHANNEL_WINDOW_DEFAULT 65536
#define LIBSSH2_CHANNEL_PACKET_DEFAULT 16384

View File

@@ -6,12 +6,21 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
@@ -27,12 +36,18 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

View File

@@ -166,7 +166,7 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
}
if (status != Z_OK) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0);
LIBSSH2_FREE(session, strm->next_out);
LIBSSH2_FREE(session, out);
return -1;
}
if (strm->avail_in) {
@@ -220,7 +220,7 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
}
if (status != Z_OK) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0);
LIBSSH2_FREE(session, strm->next_out);
LIBSSH2_FREE(session, out);
return -1;
}
}
@@ -272,10 +272,10 @@ static LIBSSH2_COMP_METHOD libssh2_comp_method_zlib = {
*********************** */
static LIBSSH2_COMP_METHOD *_libssh2_comp_methods[] = {
&libssh2_comp_method_none,
#ifdef LIBSSH2_HAVE_ZLIB
&libssh2_comp_method_zlib,
#endif /* LIBSSH2_HAVE_ZLIB */
&libssh2_comp_method_none,
NULL
};

View File

@@ -40,6 +40,11 @@
#include <openssl/pem.h>
#include <openssl/evp.h>
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifndef OPENSSL_NO_RSA
/* ***********
* ssh-rsa *
@@ -124,7 +129,7 @@ static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session, unsi
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
* Someone buy me an OpenSSL manual and I'll read up on it.
*/
OPENSSL_add_all_algorithms_noconf();
OpenSSL_add_all_ciphers();
}
rsactx = PEM_read_RSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
if (!rsactx) {
@@ -338,7 +343,7 @@ static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session, unsi
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
* Someone buy me an OpenSSL manual and I'll read up on it.
*/
OPENSSL_add_all_algorithms_noconf();
OpenSSL_add_all_ciphers();
}
dsactx = PEM_read_DSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
if (!dsactx) {

View File

@@ -44,6 +44,10 @@
#include <openssl/evp.h>
#include <openssl/rand.h>
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
/* {{{ libssh2_packet_queue_listener
* Queue a connection request for a listener

View File

@@ -37,7 +37,6 @@
#include "libssh2_priv.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#define LIBSSH2_SCP_RESPONSE_BUFLEN 256

View File

@@ -42,6 +42,26 @@
#endif
#include <stdlib.h>
#ifdef HAVE_GETTIMEOFDAY
#include <sys/time.h>
#include <math.h>
#endif
#ifdef HAVE_POLL
# include <sys/poll.h>
#else
# ifdef HAVE_SELECT
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# else
# include <sys/time.h>
# include <sys/types.h>
# endif
# endif
#endif
/* {{{ libssh2_default_alloc
*/
static LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
@@ -616,3 +636,275 @@ LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int val
return session->flags;
}
/* }}} */
/* {{{ libssh2_poll_channel_read
* Returns 0 if no data is waiting on channel,
* non-0 if data is available
*/
static int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended)
{
LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head;
while (packet) {
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) && (extended == 0) && (channel->local.id == libssh2_ntohu32(packet->data + 1))) ||
((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (extended != 0) && (channel->local.id == libssh2_ntohu32(packet->data + 1)))) {
/* Found data waiting to be read */
return 1;
}
packet = packet->next;
}
return 0;
}
/* }}} */
/* {{{ libssh2_poll_channel_write
* Returns 0 if writing to channel would block,
* non-0 if data can be written without blocking
*/
inline int libssh2_poll_channel_write(LIBSSH2_CHANNEL *channel)
{
return channel->local.window_size ? 1 : 0;
}
/* }}} */
/* {{{ libssh2_poll_listener_queued
* Returns 0 if no connections are waiting to be accepted
* non-0 if one or more connections are available
*/
inline int libssh2_poll_listener_queued(LIBSSH2_LISTENER *listener)
{
return listener->queue ? 1 : 0;
}
/* }}} */
/* {{{ libssh2_poll
* Poll sockets, channels, and listeners for activity
*/
LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
{
long timeout_remaining;
int i, active_fds;
#ifdef HAVE_POLL
LIBSSH2_SESSION *session = NULL;
struct pollfd sockets[nfds];
/* Setup sockets for polling */
for(i = 0; i < nfds; i++) {
fds[i].revents = 0;
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
sockets[i].fd = fds[i].fd.socket;
sockets[i].events = fds[i].events;
sockets[i].revents = 0;
break;
case LIBSSH2_POLLFD_CHANNEL:
sockets[i].fd = fds[i].fd.channel->session->socket_fd;
sockets[i].events = POLLIN;
sockets[i].revents = 0;
if (!session) session = fds[i].fd.channel->session;
break;
case LIBSSH2_POLLFD_LISTENER:
sockets[i].fd = fds[i].fd.listener->session->socket_fd;
sockets[i].events = POLLIN;
sockets[i].revents = 0;
if (!session) session = fds[i].fd.listener->session;
break;
default:
if (session) libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, "Invalid descriptor passed to libssh2_poll()", 0);
return -1;
}
}
#elif defined(HAVE_SELECT)
LIBSSH2_SESSION *session = NULL;
int maxfd = 0;
fd_set rfds,wfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
for(i = 0; i < nfds; i++) {
fds[i].revents = 0;
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
if (fds[i].events & LIBSSH2_POLLFD_POLLIN) {
FD_SET(fds[i].fd.socket, &rfds);
if (fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket;
}
if (fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
FD_SET(fds[i].fd.socket, &wfds);
if (fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
if (fds[i].fd.channel->session->socket_fd > maxfd) maxfd = fds[i].fd.channel->session->socket_fd;
if (!session) session = fds[i].fd.channel->session;
break;
case LIBSSH2_POLLFD_LISTENER:
FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
if (fds[i].fd.listener->session->socket_fd > maxfd) maxfd = fds[i].fd.listener->session->socket_fd;
if (!session) session = fds[i].fd.listener->session;
break;
default:
if (session) libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, "Invalid descriptor passed to libssh2_poll()", 0);
return -1;
}
}
#else
/* No select() or poll()
* no sockets sturcture to setup
*/
timeout = 0;
#endif /* HAVE_POLL or HAVE_SELECT */
timeout_remaining = timeout;
do {
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
int sysret;
#endif
active_fds = 0;
for (i = 0; i < nfds; i++) {
if (fds[i].events != fds[i].revents) {
switch (fds[i].type) {
case LIBSSH2_POLLFD_CHANNEL:
if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want to be ready for read */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* Not yet known to be ready for read */
fds[i].revents |= libssh2_poll_channel_read(fds[i].fd.channel, 0) ? LIBSSH2_POLLFD_POLLIN : 0;
}
if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && /* Want to be ready for extended read */
((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) { /* Not yet known to be ready for extended read */
fds[i].revents |= libssh2_poll_channel_read(fds[i].fd.channel, 1) ? LIBSSH2_POLLFD_POLLEXT : 0;
}
if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && /* Want to be ready for write */
((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) { /* Not yet known to be ready for write */
fds[i].revents |= libssh2_poll_channel_write(fds[i].fd.channel) ? LIBSSH2_POLLFD_POLLOUT : 0;
}
break;
case LIBSSH2_POLLFD_LISTENER:
if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want a connection */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* No connections known of yet */
fds[i].revents |= libssh2_poll_listener_queued(fds[i].fd.listener) ? LIBSSH2_POLLFD_POLLIN : 0;
}
break;
}
}
if (fds[i].revents) {
active_fds++;
}
}
if (active_fds) {
/* Don't block on the sockets if we have channels/listeners which are ready */
timeout_remaining = 0;
}
#ifdef HAVE_POLL
#ifdef HAVE_GETTIMEOFDAY
{
struct timeval tv_begin, tv_end;
gettimeofday((struct timeval *)&tv_begin, NULL);
sysret = poll(sockets, nfds, timeout_remaining);
gettimeofday((struct timeval *)&tv_end, NULL);
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
timeout_remaining -= ceil((tv_end.tv_usec - tv_begin.tv_usec) / 1000);
}
#else
/* If the platform doesn't support gettimeofday,
* then just make the call non-blocking and walk away
*/
sysret = poll(sockets, nfds, timeout_remaining);
timeout_remaining = 0;
#endif /* HAVE_GETTIMEOFDAY */
if (sysret > 0) {
for (i = 0; i < nfds; i++) {
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
fds[i].revents = sockets[i].revents;
sockets[i].revents = 0; /* In case we loop again, be nice */
if (fds[i].revents) {
active_fds++;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
if (sockets[i].events & POLLIN) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.channel->session, 0) > 0);
}
sockets[i].revents = 0;
break;
case LIBSSH2_POLLFD_LISTENER:
if (sockets[i].events & POLLIN) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.listener->session, 0) > 0);
}
sockets[i].revents = 0;
break;
}
}
}
#elif defined(HAVE_SELECT)
tv.tv_sec = timeout_remaining / 1000;
tv.tv_usec = (timeout_remaining % 1000) * 1000;
#ifdef HAVE_GETTIMEOFDAY
{
struct timeval tv_begin, tv_end;
gettimeofday((struct timeval *)&tv_begin, NULL);
sysret = select(maxfd, &rfds, &wfds, NULL, &tv);
gettimeofday((struct timeval *)&tv_end, NULL);
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
timeout_remaining -= ceil((tv_end.tv_usec - tv_begin.tv_usec) / 1000);
}
#else
/* If the platform doesn't support gettimeofday,
* then just make the call non-blocking and walk away
*/
sysret = select(maxfd, &rfds, &wfds, NULL, &tv);
timeout_remaining = 0;
#endif
if (sysret > 0) {
for (i = 0; i < nfds; i++) {
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
if (FD_ISSET(fds[i].fd.socket, &rfds)) {
fds[i].revents |= LIBSSH2_POLLFD_POLLIN;
}
if (FD_ISSET(fds[i].fd.socket, &wfds)) {
fds[i].revents |= LIBSSH2_POLLFD_POLLOUT;
}
if (fds[i].revents) {
active_fds++;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.channel->session, 0) > 0);
}
break;
case LIBSSH2_POLLFD_LISTENER:
if (FD_ISSET(fds[i].fd.listener->session->socket_fd, &rfds)) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.listener->session, 0) > 0);
}
break;
}
}
}
#endif /* else no select() or poll() -- timeout (and by extension timeout_remaining) will be equal to 0 */
} while ((timeout_remaining > 0) && !active_fds);
return active_fds;
}
/* }}} */

View File

@@ -36,7 +36,12 @@
*/
#include "libssh2_priv.h"
#include <stdio.h>
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
/* {{{ proto libssh2_userauth_list
* List authentication methods