Compare commits

..

40 Commits

Author SHA1 Message Date
Andreas Schneider
c4d1d8b684 build: Increase version numbers. 2010-07-13 10:15:22 +02:00
Andreas Schneider
10e27f26be build: Updated ChangeLog. 2010-07-12 09:48:22 +02:00
Andreas Schneider
9791bc3eeb poll: Added poll constants for Windows.
WSAPoll uses different constanst values as the POSIX implementation,
what else ...
2010-07-09 09:46:57 +02:00
Andreas Schneider
4ad7828797 options: Added option to bind a client to an ip address.
Thanks to Donatello Boccaforno <donatello.boccaforno@gmail.com>.
2010-07-07 12:40:49 +02:00
Aris Adamantiadis
af8315b9ce Fixed ssh_socket_poll behaviour 2010-07-07 10:00:09 +02:00
Andreas Schneider
94fdcf7a2a socket: Fixed ssh_socket_poll().
If we don't have date to read or write, leave ssh_socket_poll().
2010-07-06 23:18:16 +02:00
Andreas Schneider
59a95fc3a7 poll: FD_SETSIZE is only for the count value of FD_SET on Windows. 2010-07-06 00:40:19 +02:00
Andreas Schneider
c1729c36d9 socket: Fixed a prototype. 2010-06-25 16:20:38 +02:00
Andreas Schneider
23efab0f8f socket: Fixed conflicting types. 2010-06-24 20:05:10 +02:00
Andreas Schneider
e50752a925 poll: Another attempt to get bsd_poll() working correctly. 2010-06-24 09:17:39 +02:00
Andreas Schneider
fd45c1b36b poll: Fixed building with poll-emulation on UNIX. 2010-06-24 09:16:58 +02:00
Andreas Schneider
5080671581 agent: Use the our poll typedef. 2010-06-24 09:14:07 +02:00
Andreas Schneider
e67fafd60f poll: Added a comment to the bsd_poll() implementation. 2010-06-22 14:45:08 +02:00
Andreas Schneider
a2a98fb5bc poll: Handle FD_SETSIZE in bsd_poll(). 2010-06-22 14:44:54 +02:00
Andreas Schneider
e2480fbaba poll: Fixed a comparsion. 2010-06-22 14:43:09 +02:00
Andreas Schneider
23e6b36209 poll: Fixed a typo. 2010-06-21 15:41:58 +02:00
Andreas Schneider
541b38b772 poll: Check if maxfd has been set. 2010-06-20 21:16:29 +02:00
Andreas Schneider
a85a4cc192 connect: Fixed some socket build warnings on windows. 2010-06-18 12:43:12 +02:00
Andreas Schneider
54ef77123a server: Fixed types and checks of fd's. 2010-06-17 13:36:14 +02:00
Andreas Schneider
4c679fd8a6 poll: Fixed type of the fd variables and use SSH_INVALID_SOCKET. 2010-06-17 13:35:40 +02:00
Andreas Schneider
21d918c68a client: Fixed fd type and checks. 2010-06-17 13:33:52 +02:00
Andreas Schneider
544fc28e6b channel: Fixed the type of the max fd variable in ssh_channel_select(). 2010-06-17 13:32:14 +02:00
Andreas Schneider
601081ebb6 agent: Use ssh_poll in agent code. 2010-06-17 13:31:35 +02:00
Andreas Schneider
22d975a24b socket: Fixed checks for max fd. 2010-06-17 13:18:23 +02:00
Andreas Schneider
aeb9f3e389 poll: Fixed brackets. 2010-06-17 12:02:06 +02:00
Andreas Schneider
d3a4e01137 poll: Fixed another wrong invalid fd check in bsd_poll. 2010-06-17 11:49:28 +02:00
Andreas Schneider
a1b9ae5048 poll: Some code cleanup for easier debugging. 2010-06-17 11:23:58 +02:00
Andreas Schneider
a375ebe29b poll: Fixed a malfunction with wrong max fd value check. 2010-06-17 11:23:50 +02:00
Andreas Schneider
b2f49a6a93 config: Use ssh log and error functions for problems. 2010-06-03 16:46:17 +02:00
Andreas Schneider
99fb5987ce socket: Fixed signed values which could be seen as an unary operator. 2010-06-02 10:14:53 +02:00
Andreas Schneider
be389dd644 socket: According to execle(2) environ shouldn't be const. 2010-06-01 21:47:15 +02:00
Andreas Schneider
a6a7922dbd Update Changelog. 2010-05-31 19:36:32 +02:00
Aris Adamantiadis
608e81bc00 Fix warning for snprintf 2010-05-31 11:52:36 +03:00
Aris Adamantiadis
7e17838c0b Fix unclean null termination in ~ expending 2010-05-31 11:50:52 +03:00
Andreas Schneider
84f6945a9c Increased version numbers. 2010-05-30 11:26:11 +02:00
Andreas Schneider
3ae187dbe7 misc: Make sure the expanded string is null-terminated. 2010-05-30 11:00:38 +02:00
Andreas Schneider
26989ab001 session: Fixed setting up default identity files. 2010-05-28 10:47:37 +02:00
Andreas Schneider
5b2e39cd79 options: Make sure that we have always have default options set. 2010-05-21 10:21:03 +02:00
Andreas Schneider
13af149ef9 options: Set the local username if still not set. 2010-05-21 10:19:06 +02:00
Andreas Schneider
3453cafd95 keyfiles: Fixed possible problem with known_hosts path. 2010-05-21 10:03:13 +02:00
21 changed files with 197 additions and 92 deletions

View File

@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0") set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "4") set(APPLICATION_VERSION_MINOR "4")
set(APPLICATION_VERSION_PATCH "3") set(APPLICATION_VERSION_PATCH "5")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}") set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
# Increment AGE. Set REVISION to 0 # Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes: # If the source code was changed, but there were no interface changes:
# Increment REVISION. # Increment REVISION.
set(LIBRARY_VERSION "4.1.0") set(LIBRARY_VERSION "4.1.2")
set(LIBRARY_SOVERSION "4") set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked

View File

@@ -13,7 +13,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
### versions ### versions
set(CPACK_PACKAGE_VERSION_MAJOR "0") set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "4") set(CPACK_PACKAGE_VERSION_MINOR "4")
set(CPACK_PACKAGE_VERSION_PATCH "3") set(CPACK_PACKAGE_VERSION_PATCH "5")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")

View File

@@ -1,6 +1,17 @@
ChangeLog ChangeLog
========== ==========
version 0.4.5 (released 2010-07-13)
* Added option to bind a client to an ip address.
* Fixed the ssh socket polling function.
* Fixed Windows related bugs in bsd_poll().
* Fixed serveral build warnings.
version 0.4.4 (released 2010-06-01)
* Fixed a bug in the expand function for escape sequences.
* Fixed a bug in the tilde expand function.
* Fixed a bug in setting the options.
version 0.4.3 (released 2010-05-18) version 0.4.3 (released 2010-05-18)
* Added global/keepalive responses. * Added global/keepalive responses.
* Added runtime detection of WSAPoll(). * Added runtime detection of WSAPoll().

View File

@@ -79,7 +79,7 @@
/* libssh version */ /* libssh version */
#define LIBSSH_VERSION_MAJOR 0 #define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 4 #define LIBSSH_VERSION_MINOR 4
#define LIBSSH_VERSION_MICRO 3 #define LIBSSH_VERSION_MICRO 5
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \ #define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \ LIBSSH_VERSION_MINOR, \
@@ -119,10 +119,16 @@ typedef struct ssh_string_struct* ssh_string;
/* Socket type */ /* Socket type */
#ifdef _WIN32 #ifdef _WIN32
#define socket_t SOCKET #ifndef socket_t
#else typedef SOCKET socket_t;
#endif /* socket_t */
#else /* _WIN32 */
#ifndef socket_t
typedef int socket_t; typedef int socket_t;
#endif #endif
#endif /* _WIN32 */
#define SSH_INVALID_SOCKET ((socket_t) -1)
/* the offsets of methods */ /* the offsets of methods */
enum ssh_kex_types_e { enum ssh_kex_types_e {
@@ -265,7 +271,8 @@ enum ssh_options_e {
SSH_OPTIONS_CIPHERS_S_C, SSH_OPTIONS_CIPHERS_S_C,
SSH_OPTIONS_COMPRESSION_C_S, SSH_OPTIONS_COMPRESSION_C_S,
SSH_OPTIONS_COMPRESSION_S_C, SSH_OPTIONS_COMPRESSION_S_C,
SSH_OPTIONS_PROXYCOMMAND SSH_OPTIONS_PROXYCOMMAND,
SSH_OPTIONS_BINDADDR
}; };
enum { enum {

View File

@@ -38,6 +38,45 @@ typedef struct ssh_pollfd_struct {
short revents; /* returned events */ short revents; /* returned events */
} ssh_pollfd_t; } ssh_pollfd_t;
typedef unsigned long int nfds_t;
#ifdef _WIN32
#ifndef POLLRDNORM
#define POLLRDNORM 0x0100
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0x0200
#endif
#ifndef POLLIN
#define POLLIN (POLLRDNORM | POLLRDBAND)
#endif
#ifndef POLLPRI
#define POLLPRI 0x0400
#endif
#ifndef POLLWRNORM
#define POLLWRNORM 0x0010
#endif
#ifndef POLLOUT
#define POLLOUT (POLLWRNORM)
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0x0020
#endif
#ifndef POLLERR
#define POLLERR 0x0001
#endif
#ifndef POLLHUP
#define POLLHUP 0x0002
#endif
#ifndef POLLNVAL
#define POLLNVAL 0x0004
#endif
#else /* _WIN32 */
/* poll.c */ /* poll.c */
#ifndef POLLIN #ifndef POLLIN
#define POLLIN 0x001 /* There is data to read. */ #define POLLIN 0x001 /* There is data to read. */
@@ -72,8 +111,7 @@ typedef struct ssh_pollfd_struct {
#define POLLWRBAND 0x200 /* mapped to write fds_set */ #define POLLWRBAND 0x200 /* mapped to write fds_set */
#endif #endif
#endif /* WIN32 */
typedef unsigned long int nfds_t;
#endif /* HAVE_POLL */ #endif /* HAVE_POLL */
void ssh_poll_init(void); void ssh_poll_init(void);
@@ -92,7 +130,7 @@ typedef struct ssh_poll_handle_struct *ssh_poll_handle;
* @return 0 on success, < 0 if you removed the poll object from * @return 0 on success, < 0 if you removed the poll object from
* it's poll context. * it's poll context.
*/ */
typedef int (*ssh_poll_callback)(ssh_poll_handle p, int fd, int revents, typedef int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd, int revents,
void *userdata); void *userdata);

View File

@@ -102,7 +102,7 @@ struct ssh_session_struct {
#endif #endif
char *username; char *username;
char *host; char *host;
char *bindaddr; /* TODO: check if needed */ char *bindaddr; /* bind the client to an ip addr */
char *xbanner; /* TODO: looks like it is not needed */ char *xbanner; /* TODO: looks like it is not needed */
struct ssh_list *identity; struct ssh_list *identity;
char *sshdir; char *sshdir;

View File

@@ -38,7 +38,7 @@ int ssh_socket_read(struct socket *s, void *buffer, int len);
int ssh_socket_write(struct socket *s,const void *buffer, int len); int ssh_socket_write(struct socket *s,const void *buffer, int len);
int ssh_socket_is_open(struct socket *s); int ssh_socket_is_open(struct socket *s);
int ssh_socket_fd_isset(struct socket *s, fd_set *set); int ssh_socket_fd_isset(struct socket *s, fd_set *set);
void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max); void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd);
int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len); int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len);
int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len); int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len);
int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len); int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len);

View File

@@ -41,7 +41,6 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <poll.h>
#include <unistd.h> #include <unistd.h>
#ifndef _WIN32 #ifndef _WIN32
@@ -54,6 +53,7 @@
#include "libssh/buffer.h" #include "libssh/buffer.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/keys.h" #include "libssh/keys.h"
#include "libssh/poll.h"
/* macro to check for "agent failure" message */ /* macro to check for "agent failure" message */
#define agent_failed(x) \ #define agent_failed(x) \
@@ -85,8 +85,8 @@ static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
char *b = buf; char *b = buf;
size_t pos = 0; size_t pos = 0;
ssize_t res; ssize_t res;
struct pollfd pfd; ssh_pollfd_t pfd;
int fd = ssh_socket_get_fd(s); socket_t fd = ssh_socket_get_fd(s);
pfd.fd = fd; pfd.fd = fd;
pfd.events = do_read ? POLLIN : POLLOUT; pfd.events = do_read ? POLLIN : POLLOUT;
@@ -107,7 +107,7 @@ static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
#else #else
if (errno == EAGAIN) { if (errno == EAGAIN) {
#endif #endif
(void) poll(&pfd, 1, -1); (void) ssh_poll(&pfd, 1, -1);
continue; continue;
} }
return 0; return 0;

View File

@@ -225,7 +225,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -331,7 +331,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -443,7 +443,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -561,7 +561,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -688,7 +688,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
if (username == NULL) { if (username == NULL) {
if (session->username == NULL) { if (session->username == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return rc; return rc;
} }
@@ -777,7 +777,6 @@ error:
* *
* @see ssh_userauth_kbdint() * @see ssh_userauth_kbdint()
* @see ssh_userauth_password() * @see ssh_userauth_password()
* @see ssh_options_set()
*/ */
int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
struct ssh_iterator *it; struct ssh_iterator *it;
@@ -1336,7 +1335,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
/* first time we call. we must ask for a challenge */ /* first time we call. we must ask for a challenge */
if (user == NULL) { if (user == NULL) {
if ((user = session->username) == NULL) { if ((user = session->username) == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { if (ssh_options_apply(session) < 0) {
leave_function(); leave_function();
return SSH_AUTH_ERROR; return SSH_AUTH_ERROR;
} else { } else {

View File

@@ -2160,7 +2160,7 @@ int channel_select(ssh_channel *readchans, ssh_channel *writechans,
fd_set rset; fd_set rset;
fd_set wset; fd_set wset;
fd_set eset; fd_set eset;
int fdmax = -1; socket_t max_fd = SSH_INVALID_SOCKET;
int rc; int rc;
int i; int i;
@@ -2228,24 +2228,24 @@ int channel_select(ssh_channel *readchans, ssh_channel *writechans,
for (i = 0; readchans[i] != NULL; i++) { for (i = 0; readchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) { if (!ssh_socket_fd_isset(readchans[i]->session->socket, &rset)) {
ssh_socket_fd_set(readchans[i]->session->socket, &rset, &fdmax); ssh_socket_fd_set(readchans[i]->session->socket, &rset, &max_fd);
} }
} }
for (i = 0; writechans[i] != NULL; i++) { for (i = 0; writechans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) { if (!ssh_socket_fd_isset(writechans[i]->session->socket, &wset)) {
ssh_socket_fd_set(writechans[i]->session->socket, &wset, &fdmax); ssh_socket_fd_set(writechans[i]->session->socket, &wset, &max_fd);
} }
} }
for (i = 0; exceptchans[i] != NULL; i++) { for (i = 0; exceptchans[i] != NULL; i++) {
if (!ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) { if (!ssh_socket_fd_isset(exceptchans[i]->session->socket, &eset)) {
ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &fdmax); ssh_socket_fd_set(exceptchans[i]->session->socket, &eset, &max_fd);
} }
} }
/* Here we go */ /* Here we go */
rc = select(fdmax, &rset, &wset, &eset, timeout); rc = select(max_fd, &rset, &wset, &eset, timeout);
/* Leave if select was interrupted */ /* Leave if select was interrupted */
if (rc == EINTR) { if (rc == EINTR) {
SAFE_FREE(rchans); SAFE_FREE(rchans);

View File

@@ -481,7 +481,7 @@ int ssh_service_request(ssh_session session, const char *service) {
int ssh_connect(ssh_session session) { int ssh_connect(ssh_session session) {
int ssh1 = 0; int ssh1 = 0;
int ssh2 = 0; int ssh2 = 0;
int fd = -1; socket_t fd = SSH_INVALID_SOCKET;
int ret; int ret;
if (session == NULL) { if (session == NULL) {
@@ -498,7 +498,7 @@ int ssh_connect(ssh_session session) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
if (session->fd == -1 && session->host == NULL && if (session->fd == SSH_INVALID_SOCKET && session->host == NULL &&
session->ProxyCommand == NULL) { session->ProxyCommand == NULL) {
ssh_set_error(session, SSH_FATAL, "Hostname required"); ssh_set_error(session, SSH_FATAL, "Hostname required");
leave_function(); leave_function();
@@ -512,7 +512,7 @@ int ssh_connect(ssh_session session) {
return SSH_ERROR; return SSH_ERROR;
} }
if (session->fd != -1) { if (session->fd != SSH_INVALID_SOCKET) {
fd = session->fd; fd = session->fd;
#ifndef _WIN32 #ifndef _WIN32
} else if (session->ProxyCommand != NULL) { } else if (session->ProxyCommand != NULL) {
@@ -522,7 +522,7 @@ int ssh_connect(ssh_session session) {
fd = ssh_connect_host(session, session->host, session->bindaddr, fd = ssh_connect_host(session, session->host, session->bindaddr,
session->port, session->timeout, session->timeout_usec); session->port, session->timeout, session->timeout_usec);
} }
if (fd < 0) { if (fd == SSH_INVALID_SOCKET) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }

View File

@@ -283,10 +283,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
} }
break; break;
case SOC_UNSUPPORTED: case SOC_UNSUPPORTED:
fprintf(stderr, "Unsupported option: %s, line: %d\n", keyword, count); ssh_log(session, SSH_LOG_RARE, "Unsupported option: %s, line: %d\n",
keyword, count);
break; break;
default: default:
fprintf(stderr, "ERROR - unimplemented opcode: %d\n", opcode); ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d\n",
opcode);
SAFE_FREE(x); SAFE_FREE(x);
return -1; return -1;
break; break;

View File

@@ -390,6 +390,7 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
fd_set *readfds, struct timeval *timeout) { fd_set *readfds, struct timeval *timeout) {
struct timeval zerotime; struct timeval zerotime;
fd_set localset, localset2; fd_set localset, localset2;
socket_t f;
int rep; int rep;
int set; int set;
int i; int i;
@@ -430,8 +431,8 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
/* Look into the localset for active fd */ /* Look into the localset for active fd */
set = 0; set = 0;
for (i = 0; (i < maxfd) && !set; i++) { for (f = 0; (f < maxfd) && !set; f++) {
if (FD_ISSET(i, &localset)) { if (FD_ISSET(f, &localset)) {
set = 1; set = 1;
} }
} }
@@ -493,9 +494,9 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
outchannels[j] = NULL; outchannels[j] = NULL;
FD_ZERO(&localset2); FD_ZERO(&localset2);
for (i = 0; i < maxfd; i++) { for (f = 0; f < maxfd; f++) {
if (FD_ISSET(i, readfds) && FD_ISSET(i, &localset)) { if (FD_ISSET(f, readfds) && FD_ISSET(i, &localset)) {
FD_SET(i, &localset2); FD_SET(f, &localset2);
} }
} }

View File

@@ -1077,7 +1077,7 @@ int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
} }
if (session->sshdir == NULL) { if (session->sshdir == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) { if (ssh_options_apply(session) < 0) {
return -1; return -1;
} }
} }
@@ -1145,7 +1145,7 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
} }
if (session->sshdir == NULL) { if (session->sshdir == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) { if (ssh_options_apply(session) < 0) {
return NULL; return NULL;
} }
} }
@@ -1550,7 +1550,6 @@ static int match_hashed_host(ssh_session session, const char *host,
* if host key is accepted\n * if host key is accepted\n
* SSH_SERVER_ERROR: Some error happened * SSH_SERVER_ERROR: Some error happened
* *
* \see ssh_options_set()
* \see ssh_get_pubkey_hash() * \see ssh_get_pubkey_hash()
* *
* \bug There is no current way to remove or modify an entry into the known * \bug There is no current way to remove or modify an entry into the known
@@ -1568,7 +1567,7 @@ int ssh_is_server_known(ssh_session session) {
enter_function(); enter_function();
if (session->knownhosts == NULL) { if (session->knownhosts == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) { if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_REQUEST_DENIED, ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file"); "Can't find a known_hosts file");
leave_function(); leave_function();
@@ -1687,7 +1686,7 @@ int ssh_write_knownhost(ssh_session session) {
} }
if (session->knownhosts == NULL) { if (session->knownhosts == NULL) {
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) { if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file"); ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file");
return -1; return -1;
} }

View File

@@ -554,7 +554,7 @@ char *ssh_path_expand_tilde(const char *d) {
if (lh > 0) { if (lh > 0) {
memcpy(r, h, lh); memcpy(r, h, lh);
} }
memcpy(r + lh, p, ld); memcpy(r + lh, p, ld + 1);
return r; return r;
} }
@@ -634,6 +634,7 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
} }
l = strlen(buf); l = strlen(buf);
strcat(buf + l, x); strcat(buf + l, x);
buf[i] = '\0';
SAFE_FREE(x); SAFE_FREE(x);
} }

View File

@@ -187,6 +187,9 @@ int ssh_options_set_algo(ssh_session session, int algo,
* set the hostname as the hostname is used as a key in * set the hostname as the hostname is used as a key in
* the known_host mechanism. * the known_host mechanism.
* *
* - SSH_OPTIONS_BINDADDR:
* The address to bind the client to (string).
*
* - SSH_OPTIONS_USER: * - SSH_OPTIONS_USER:
* The username for authentication (string).\n * The username for authentication (string).\n
* \n * \n
@@ -397,6 +400,18 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->fd = *x & 0xffff; session->fd = *x & 0xffff;
} }
break; break;
case SSH_OPTIONS_BINDADDR:
if (value == NULL) {
ssh_set_error_invalid(session, __FUNCTION__);
return -1;
}
q = strdup(value);
if (q == NULL) {
return -1;
}
SAFE_FREE(session->bindaddr);
session->bindaddr = q;
break;
case SSH_OPTIONS_USER: case SSH_OPTIONS_USER:
SAFE_FREE(session->username); SAFE_FREE(session->username);
if (value == NULL) { /* set default username */ if (value == NULL) { /* set default username */
@@ -1058,6 +1073,13 @@ int ssh_options_apply(ssh_session session) {
} }
} }
if (session->username == NULL) {
rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL);
if (rc < 0) {
return -1;
}
}
if (session->knownhosts == NULL) { if (session->knownhosts == NULL) {
tmp = ssh_path_expand_escape(session, "%d/known_hosts"); tmp = ssh_path_expand_escape(session, "%d/known_hosts");
} else { } else {

View File

@@ -71,28 +71,38 @@ int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
#include <sys/types.h> #include <sys/types.h>
typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int);
static poll_fn win_poll;
#ifdef _WIN32 #ifdef _WIN32
#ifndef STRICT #ifndef STRICT
#define STRICT #define STRICT
#endif #endif /* STRICT */
#include <time.h> #include <time.h>
#include <windows.h> #include <windows.h>
#include <winsock2.h> #include <winsock2.h>
#define WS2_LIBRARY "ws2_32.dll" #define WS2_LIBRARY "ws2_32.dll"
typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int);
static poll_fn win_poll;
static HINSTANCE hlib; static HINSTANCE hlib;
#else #else /* _WIN32 */
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#endif #endif /* _WIN32 */
/*
* This is a poll(2)-emulation using select for systems not providing a native
* poll implementation.
*
* Keep in mind that select is terribly inefficient. The interface is simply not
* meant to be used with maximum descriptor value greater, say, 32 or so. With
* a value as high as 1024 on Linux you'll pay dearly in every single call.
* poll() will be orders of magnitude faster.
*/
static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) { static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
fd_set readfds, writefds, exceptfds; fd_set readfds, writefds, exceptfds;
struct timeval tv, *ptv; struct timeval tv, *ptv;
@@ -110,10 +120,16 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
FD_ZERO (&exceptfds); FD_ZERO (&exceptfds);
/* compute fd_sets and find largest descriptor */ /* compute fd_sets and find largest descriptor */
for (max_fd = -1, i = 0; i < nfds; i++) { for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
if (fds[i].fd < 0) { if (fds[i].fd == SSH_INVALID_SOCKET) {
continue; continue;
} }
#ifndef _WIN32
if (fds[i].fd >= FD_SETSIZE) {
rc = -1;
break;
}
#endif
if (fds[i].events & (POLLIN | POLLRDNORM)) { if (fds[i].events & (POLLIN | POLLRDNORM)) {
FD_SET (fds[i].fd, &readfds); FD_SET (fds[i].fd, &readfds);
@@ -124,15 +140,16 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
if (fds[i].events & (POLLPRI | POLLRDBAND)) { if (fds[i].events & (POLLPRI | POLLRDBAND)) {
FD_SET (fds[i].fd, &exceptfds); FD_SET (fds[i].fd, &exceptfds);
} }
if (fds[i].fd >= max_fd && if (fds[i].fd > max_fd &&
(fds[i].events & (POLLIN | POLLOUT | POLLPRI | (fds[i].events & (POLLIN | POLLOUT | POLLPRI |
POLLRDNORM | POLLRDBAND | POLLRDNORM | POLLRDBAND |
POLLWRNORM | POLLWRBAND))) { POLLWRNORM | POLLWRBAND))) {
max_fd = fds[i].fd; max_fd = fds[i].fd;
rc = 0;
} }
} }
if (max_fd == -1) { if (max_fd == SSH_INVALID_SOCKET || rc == -1) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -162,14 +179,16 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
if (FD_ISSET(fds[i].fd, &readfds)) { if (FD_ISSET(fds[i].fd, &readfds)) {
int save_errno = errno; int save_errno = errno;
char data[64] = {0}; char data[64] = {0};
int ret;
/* support for POLLHUP */ /* support for POLLHUP */
ret = recv(fds[i].fd, data, 64, MSG_PEEK);
#ifdef _WIN32 #ifdef _WIN32
if ((recv(fds[i].fd, data, 64, MSG_PEEK) == -1) && if ((ret == -1) &&
(errno == WSAESHUTDOWN || errno == WSAECONNRESET || (errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
errno == WSAECONNABORTED || errno == WSAENETRESET)) { errno == WSAECONNABORTED || errno == WSAENETRESET)) {
#else #else
if ((recv(fds[i].fd, data, 64, MSG_PEEK) == -1) && if ((ret == -1) &&
(errno == ESHUTDOWN || errno == ECONNRESET || (errno == ESHUTDOWN || errno == ECONNRESET ||
errno == ECONNABORTED || errno == ENETRESET)) { errno == ECONNABORTED || errno == ENETRESET)) {
#endif #endif
@@ -201,10 +220,12 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
void ssh_poll_init(void) { void ssh_poll_init(void) {
poll_fn wsa_poll = NULL; poll_fn wsa_poll = NULL;
#ifdef _WIN32
hlib = LoadLibrary(WS2_LIBRARY); hlib = LoadLibrary(WS2_LIBRARY);
if (hlib != NULL) { if (hlib != NULL) {
wsa_poll = (poll_fn) GetProcAddress(hlib, "WSAPoll"); wsa_poll = (poll_fn) GetProcAddress(hlib, "WSAPoll");
} }
#endif /* _WIN32 */
if (wsa_poll == NULL) { if (wsa_poll == NULL) {
win_poll = bsd_poll; win_poll = bsd_poll;
@@ -389,7 +410,7 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
used = ctx->polls_used; used = ctx->polls_used;
for (i = 0; i < used; ) { for (i = 0; i < used; ) {
ssh_poll_handle p = ctx->pollptrs[i]; ssh_poll_handle p = ctx->pollptrs[i];
int fd = ctx->pollfds[i].fd; socket_t fd = ctx->pollfds[i].fd;
/* force poll object removal */ /* force poll object removal */
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) { if (p->cb(p, fd, POLLERR, p->cb_data) < 0) {
@@ -437,7 +458,7 @@ static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size) {
* @return 0 on success, < 0 on error * @return 0 on success, < 0 on error
*/ */
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) { int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
int fd; socket_t fd;
if (p->ctx != NULL) { if (p->ctx != NULL) {
/* already attached to a context */ /* already attached to a context */
@@ -516,7 +537,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
i++; i++;
} else { } else {
ssh_poll_handle p = ctx->pollptrs[i]; ssh_poll_handle p = ctx->pollptrs[i];
int fd = ctx->pollfds[i].fd; socket_t fd = ctx->pollfds[i].fd;
int revents = ctx->pollfds[i].revents; int revents = ctx->pollfds[i].revents;
if (p->cb(p, fd, revents, p->cb_data) < 0) { if (p->cb(p, fd, revents, p->cb_data) < 0) {

View File

@@ -129,7 +129,7 @@ ssh_bind ssh_bind_new(void) {
return NULL; return NULL;
} }
ZERO_STRUCTP(ptr); ZERO_STRUCTP(ptr);
ptr->bindfd = -1; ptr->bindfd = SSH_INVALID_SOCKET;
ptr->bindport= 22; ptr->bindport= 22;
ptr->log_verbosity = 0; ptr->log_verbosity = 0;
@@ -138,7 +138,7 @@ ssh_bind ssh_bind_new(void) {
int ssh_bind_listen(ssh_bind sshbind) { int ssh_bind_listen(ssh_bind sshbind) {
const char *host; const char *host;
int fd; socket_t fd;
if (ssh_init() < 0) { if (ssh_init() < 0) {
return -1; return -1;
@@ -185,10 +185,10 @@ void ssh_bind_fd_toaccept(ssh_bind sshbind) {
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) { int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
ssh_private_key dsa = NULL; ssh_private_key dsa = NULL;
ssh_private_key rsa = NULL; ssh_private_key rsa = NULL;
int fd = -1; socket_t fd = SSH_INVALID_SOCKET;
int i; int i;
if (sshbind->bindfd < 0) { if (sshbind->bindfd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL, ssh_set_error(sshbind, SSH_FATAL,
"Can't accept new clients on a not bound socket."); "Can't accept new clients on a not bound socket.");
return SSH_ERROR; return SSH_ERROR;
@@ -219,7 +219,7 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
} }
fd = accept(sshbind->bindfd, NULL, NULL); fd = accept(sshbind->bindfd, NULL, NULL);
if (fd < 0) { if (fd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL, ssh_set_error(sshbind, SSH_FATAL,
"Accepting a new connection: %s", "Accepting a new connection: %s",
strerror(errno)); strerror(errno));
@@ -284,7 +284,7 @@ void ssh_bind_free(ssh_bind sshbind){
close(sshbind->bindfd); close(sshbind->bindfd);
#endif #endif
} }
sshbind->bindfd = -1; sshbind->bindfd = SSH_INVALID_SOCKET;
/* options */ /* options */
SAFE_FREE(sshbind->banner); SAFE_FREE(sshbind->banner);

View File

@@ -104,7 +104,7 @@ ssh_session ssh_new(void) {
goto err; goto err;
} }
id = strdup("SSH_DIR/id_rsa"); id = strdup("%d/id_rsa");
if (id == NULL) { if (id == NULL) {
goto err; goto err;
} }
@@ -113,7 +113,7 @@ ssh_session ssh_new(void) {
goto err; goto err;
} }
id = strdup("SSH_DIR/id_dsa"); id = strdup("%d/id_dsa");
if (id == NULL) { if (id == NULL) {
goto err; goto err;
} }
@@ -122,7 +122,7 @@ ssh_session ssh_new(void) {
goto err; goto err;
} }
id = strdup("SSH_DIR/identity"); id = strdup("%d/identity");
if (id == NULL) { if (id == NULL) {
goto err; goto err;
} }

View File

@@ -29,6 +29,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>

View File

@@ -33,7 +33,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
extern const char **environ; extern char **environ;
#endif #endif
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/socket.h" #include "libssh/socket.h"
@@ -72,8 +72,9 @@ int ssh_socket_init(void) {
return -1; return -1;
} }
ssh_poll_init();
#endif #endif
ssh_poll_init();
return 0; return 0;
} }
/* /*
@@ -87,7 +88,7 @@ struct socket *ssh_socket_new(ssh_session session) {
if (s == NULL) { if (s == NULL) {
return NULL; return NULL;
} }
s->fd = -1; s->fd = SSH_INVALID_SOCKET;
s->last_errno = -1; s->last_errno = -1;
s->session = session; s->session = session;
s->in_buffer = buffer_new(); s->in_buffer = buffer_new();
@@ -129,20 +130,20 @@ int ssh_socket_unix(struct socket *s, const char *path) {
snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path); snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);
s->fd = socket(AF_UNIX, SOCK_STREAM, 0); s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s->fd < 0) { if (s->fd == SSH_INVALID_SOCKET) {
return -1; return -1;
} }
if (fcntl(s->fd, F_SETFD, 1) == -1) { if (fcntl(s->fd, F_SETFD, 1) == -1) {
close(s->fd); close(s->fd);
s->fd = -1; s->fd = SSH_INVALID_SOCKET;
return -1; return -1;
} }
if (connect(s->fd, (struct sockaddr *) &sunaddr, if (connect(s->fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) { sizeof(sunaddr)) < 0) {
close(s->fd); close(s->fd);
s->fd = -1; s->fd = SSH_INVALID_SOCKET;
return -1; return -1;
} }
@@ -162,7 +163,7 @@ void ssh_socket_close(struct socket *s){
close(s->fd); close(s->fd);
s->last_errno = errno; s->last_errno = errno;
#endif #endif
s->fd=-1; s->fd = SSH_INVALID_SOCKET;
} }
} }
@@ -184,7 +185,7 @@ socket_t ssh_socket_get_fd(struct socket *s) {
* \brief returns nonzero if the socket is open * \brief returns nonzero if the socket is open
*/ */
int ssh_socket_is_open(struct socket *s) { int ssh_socket_is_open(struct socket *s) {
return s->fd != -1; return s->fd != SSH_INVALID_SOCKET;
} }
/* \internal /* \internal
@@ -242,22 +243,22 @@ static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer,
* \brief returns nonzero if the current socket is in the fd_set * \brief returns nonzero if the current socket is in the fd_set
*/ */
int ssh_socket_fd_isset(struct socket *s, fd_set *set) { int ssh_socket_fd_isset(struct socket *s, fd_set *set) {
if(s->fd == -1) { if(s->fd == SSH_INVALID_SOCKET) {
return 0; return 0;
} }
return FD_ISSET(s->fd,set); return FD_ISSET(s->fd,set);
} }
/* \internal /* \internal
* \brief sets the current fd in a fd_set and updates the fd_max * \brief sets the current fd in a fd_set and updates the max_fd
*/ */
void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max) { void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd) {
if (s->fd == -1) if (s->fd == SSH_INVALID_SOCKET)
return; return;
FD_SET(s->fd,set); FD_SET(s->fd,set);
if (s->fd >= *fd_max) { if (s->fd >= 0 && s->fd != SSH_INVALID_SOCKET) {
*fd_max = s->fd + 1; *max_fd = s->fd + 1;
} }
} }
@@ -440,7 +441,7 @@ int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len
if (ssh_socket_is_open(session->socket)) { if (ssh_socket_is_open(session->socket)) {
r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer)); r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer));
} else { } else {
r =- 1; r = -1;
} }
if (r <= 0) { if (r <= 0) {
@@ -487,7 +488,8 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
if (!s->data_to_write) { if (!s->data_to_write) {
fd->events |= POLLOUT; fd->events |= POLLOUT;
} }
/* do not do poll if fd->events is empty, we already know the response */
if(fd->events != 0){
/* Make the call, and listen for errors */ /* Make the call, and listen for errors */
rc = ssh_poll(fd, 1, 0); rc = ssh_poll(fd, 1, 0);
if (rc < 0) { if (rc < 0) {
@@ -495,6 +497,7 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
leave_function(); leave_function();
return -1; return -1;
} }
}
if (!s->data_to_read) { if (!s->data_to_read) {
s->data_to_read = fd->revents & POLLIN; s->data_to_read = fd->revents & POLLIN;
@@ -547,7 +550,7 @@ int ssh_socket_nonblocking_flush(struct socket *s) {
buffer_get_rest_len(s->out_buffer)); buffer_get_rest_len(s->out_buffer));
} else { } else {
/* write failed */ /* write failed */
w =- 1; w = -1;
} }
if (w < 0) { if (w < 0) {