mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-02 01:17:52 +03:00
Beginning of the SSH_BIND implementation
hack for errors handling so it supports an Object-oriented kind of errors (generic for ssh_bind and ssh_session data types) git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@3 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
@@ -91,8 +91,8 @@ typedef u_int8_t u8;
|
|||||||
#define SSH_EINTR 3
|
#define SSH_EINTR 3
|
||||||
|
|
||||||
|
|
||||||
char *ssh_get_error(SSH_SESSION *session);
|
char *ssh_get_error(void *error);
|
||||||
int ssh_get_error_code(SSH_SESSION *session);
|
int ssh_get_error_code(void *error);
|
||||||
void ssh_say(int priority,char *format,...);
|
void ssh_say(int priority,char *format,...);
|
||||||
void ssh_set_verbosity(int num);
|
void ssh_set_verbosity(int num);
|
||||||
|
|
||||||
|
|||||||
@@ -223,12 +223,23 @@ struct channel_struct {
|
|||||||
int blocking;
|
int blocking;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct error_struct {
|
||||||
|
/* error handling */
|
||||||
|
int error_code;
|
||||||
|
char error_buffer[ERROR_BUFFERLEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ssh_session {
|
struct ssh_session {
|
||||||
|
struct error_struct error;
|
||||||
int fd;
|
int fd;
|
||||||
SSH_OPTIONS *options;
|
SSH_OPTIONS *options;
|
||||||
char *serverbanner;
|
char *serverbanner;
|
||||||
char *clientbanner;
|
char *clientbanner;
|
||||||
int protoversion;
|
int protoversion;
|
||||||
|
int server;
|
||||||
|
int client;
|
||||||
u32 send_seq;
|
u32 send_seq;
|
||||||
u32 recv_seq;
|
u32 recv_seq;
|
||||||
/* status flags */
|
/* status flags */
|
||||||
@@ -272,9 +283,6 @@ struct ssh_session {
|
|||||||
int exec_channel_opened; /* version 1 only. more
|
int exec_channel_opened; /* version 1 only. more
|
||||||
info in channels1.c */
|
info in channels1.c */
|
||||||
|
|
||||||
/* error handling */
|
|
||||||
int error_code;
|
|
||||||
char error_buffer[ERROR_BUFFERLEN];
|
|
||||||
/* keyb interactive data */
|
/* keyb interactive data */
|
||||||
struct ssh_kbdint *kbdint;
|
struct ssh_kbdint *kbdint;
|
||||||
int version; /* 1 or 2 */
|
int version; /* 1 or 2 */
|
||||||
@@ -294,7 +302,7 @@ void ssh_cleanup(SSH_SESSION *session);
|
|||||||
|
|
||||||
|
|
||||||
/* errors.c */
|
/* errors.c */
|
||||||
void ssh_set_error(SSH_SESSION *session,int code,char *descr,...);
|
void ssh_set_error(void *error,int code,char *descr,...);
|
||||||
|
|
||||||
/* in dh.c */
|
/* in dh.c */
|
||||||
/* DH key generation */
|
/* DH key generation */
|
||||||
@@ -360,12 +368,15 @@ void channel_handle(SSH_SESSION *session, int type);
|
|||||||
CHANNEL *channel_new(SSH_SESSION *session);
|
CHANNEL *channel_new(SSH_SESSION *session);
|
||||||
void channel_default_bufferize(CHANNEL *channel, void *data, int len,
|
void channel_default_bufferize(CHANNEL *channel, void *data, int len,
|
||||||
int is_stderr);
|
int is_stderr);
|
||||||
|
|
||||||
|
|
||||||
/* options.c */
|
/* options.c */
|
||||||
void options_free(SSH_OPTIONS *opt);
|
|
||||||
|
void ssh_options_free(SSH_OPTIONS *opt);
|
||||||
/* this function must be called when no specific username has been asked. it has to guess it */
|
/* this function must be called when no specific username has been asked. it has to guess it */
|
||||||
int options_default_username(SSH_OPTIONS *opt);
|
int ssh_options_default_username(SSH_OPTIONS *opt);
|
||||||
int options_default_ssh_dir(SSH_OPTIONS *opt);
|
int ssh_options_default_ssh_dir(SSH_OPTIONS *opt);
|
||||||
int options_default_known_hosts_file(SSH_OPTIONS *opt);
|
int ssh_options_default_known_hosts_file(SSH_OPTIONS *opt);
|
||||||
|
|
||||||
/* buffer.c */
|
/* buffer.c */
|
||||||
void buffer_add_ssh_string(BUFFER *buffer,STRING *string);
|
void buffer_add_ssh_string(BUFFER *buffer,STRING *string);
|
||||||
|
|||||||
@@ -20,12 +20,28 @@ MA 02111-1307, USA. */
|
|||||||
|
|
||||||
#ifndef SERVER_H
|
#ifndef SERVER_H
|
||||||
#define SERVER_H
|
#define SERVER_H
|
||||||
/* the client banner doesn't say hey! look i'm a client ! */
|
|
||||||
#include "libssh/libssh.h"
|
#include "libssh/libssh.h"
|
||||||
|
#include "libssh/priv.h"
|
||||||
#define SERVERBANNER CLIENTBANNER
|
#define SERVERBANNER CLIENTBANNER
|
||||||
|
|
||||||
int bind_socket();
|
struct ssh_bind_struct {
|
||||||
int listen_socket(int s);
|
struct error_struct error;
|
||||||
int accept_socket(int s);
|
int bindfd;
|
||||||
|
SSH_OPTIONS *options;
|
||||||
|
int blocking;
|
||||||
|
int toaccept;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ssh_bind_struct SSH_BIND;
|
||||||
|
|
||||||
|
SSH_BIND *ssh_bind_new();
|
||||||
|
void ssh_bind_set_options(SSH_BIND *ssh_bind, SSH_OPTIONS *options);
|
||||||
|
int ssh_bind_listen(SSH_BIND *ssh_bind);
|
||||||
|
void ssh_bind_set_blocking(SSH_BIND *ssh_bind,int blocking);
|
||||||
|
int ssh_bind_get_fd(SSH_BIND *ssh_bind);
|
||||||
|
int ssh_bind_set_toaccept(SSH_BIND *ssh_bind);
|
||||||
|
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,20 +27,23 @@ MA 02111-1307, USA. */
|
|||||||
static int verbosity;
|
static int verbosity;
|
||||||
|
|
||||||
/* ssh_set_error registers an error with a description. the error code is the class of error, and description is obvious.*/
|
/* ssh_set_error registers an error with a description. the error code is the class of error, and description is obvious.*/
|
||||||
void ssh_set_error(SSH_SESSION *session,int code,char *descr,...){
|
void ssh_set_error(void *error,int code,char *descr,...){
|
||||||
va_list va;
|
struct error_struct *err= error;
|
||||||
va_start(va,descr);
|
va_list va;
|
||||||
vsnprintf(session->error_buffer,ERROR_BUFFERLEN,descr,va);
|
va_start(va,descr);
|
||||||
va_end(va);
|
vsnprintf(err->error_buffer,ERROR_BUFFERLEN,descr,va);
|
||||||
session->error_code=code;
|
va_end(va);
|
||||||
|
err->error_code=code;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ssh_get_error(SSH_SESSION *session){
|
char *ssh_get_error(void *error){
|
||||||
return session->error_buffer;
|
struct error_struct *err=error;
|
||||||
|
return err->error_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_get_error_code(SSH_SESSION *session){
|
int ssh_get_error_code(void *error){
|
||||||
return session->error_code;
|
struct error_struct *err=error;
|
||||||
|
return err->error_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssh_say(int priority, char *format,...){
|
void ssh_say(int priority, char *format,...){
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ SSH_OPTIONS *ssh_options_new(){
|
|||||||
option->fd=-1;
|
option->fd=-1;
|
||||||
option->ssh2allowed=1;
|
option->ssh2allowed=1;
|
||||||
option->ssh1allowed=0;
|
option->ssh1allowed=0;
|
||||||
|
option->bindport=22;
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ MA 02111-1307, USA. */
|
|||||||
/* from times to times, you need to serve your friends */
|
/* from times to times, you need to serve your friends */
|
||||||
/* and, perhaps, ssh connections. */
|
/* and, perhaps, ssh connections. */
|
||||||
|
|
||||||
#ifdef WITH_SERVER
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -37,39 +35,91 @@ MA 02111-1307, USA. */
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "libssh/libssh.h"
|
#include "libssh/libssh.h"
|
||||||
#include "libssh/server.h"
|
#include "libssh/server.h"
|
||||||
|
static int bind_socket(char *hostname, int port) {
|
||||||
int bind_socket() {
|
|
||||||
struct sockaddr_in myaddr;
|
struct sockaddr_in myaddr;
|
||||||
int opt = 1;
|
int opt = 1;
|
||||||
int s = socket(PF_INET, SOCK_STREAM, 0);
|
int s = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
struct hostent *hp=NULL;
|
||||||
|
#ifdef HAVE_GETHOSTBYADDR
|
||||||
|
hp=gethostbyaddr(hostname,4,AF_INET);
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GETHOSTBYNAME
|
||||||
|
if(!hp)
|
||||||
|
hp=gethostbyname(hostname);
|
||||||
|
#endif
|
||||||
|
if(!hp){
|
||||||
|
close(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&myaddr, 0, sizeof(myaddr));
|
memset(&myaddr, 0, sizeof(myaddr));
|
||||||
myaddr.sin_family = AF_INET;
|
memcpy(&myaddr.sin_addr,hp->h_addr,hp->h_length);
|
||||||
myaddr.sin_port = htons(2222);
|
myaddr.sin_family=hp->h_addrtype;
|
||||||
|
myaddr.sin_port = htons(port);
|
||||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||||
if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) {
|
if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) {
|
||||||
ssh_set_error(NULL, SSH_FATAL, "%s", strerror(errno));
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* ok, bound */
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int listen_socket(int socket) {
|
SSH_BIND *ssh_bind_new(){
|
||||||
int i = listen(socket, 1);
|
SSH_BIND *ptr=malloc(sizeof(SSH_BIND));
|
||||||
if (i < 0)
|
memset(ptr,0,sizeof(*ptr));
|
||||||
ssh_set_error(NULL, SSH_FATAL, "listening on %d : %s",
|
ptr->bindfd=-1;
|
||||||
strerror(errno));
|
return ptr;
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int accept_socket(int socket) {
|
void ssh_bind_set_options(SSH_BIND *ssh_bind, SSH_OPTIONS *options){
|
||||||
int i = accept(socket, NULL, NULL);
|
ssh_bind->options=options;
|
||||||
if (i < 0)
|
|
||||||
ssh_set_error(NULL, SSH_FATAL, "accepting client on socket %d : %s",
|
|
||||||
strerror(errno));
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ssh_bind_listen(SSH_BIND *ssh_bind){
|
||||||
|
char *host;
|
||||||
|
int fd;
|
||||||
|
if(!ssh_bind->options)
|
||||||
|
return -1;
|
||||||
|
host=ssh_bind->options->bindaddr;
|
||||||
|
if(!host)
|
||||||
|
host="0.0.0.0";
|
||||||
|
fd=bind_socket(host,ssh_bind->options->bindport);
|
||||||
|
if(fd<0)
|
||||||
|
return -1;
|
||||||
|
ssh_bind->bindfd=fd;
|
||||||
|
if(listen(fd,10)<0){
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssh_bind_set_blocking(SSH_BIND *ssh_bind, int blocking){
|
||||||
|
ssh_bind->blocking=blocking?1:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssh_bind_get_fd(SSH_BIND *ssh_bind){
|
||||||
|
return ssh_bind->bindfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssh_bind_fd_toaccept(SSH_BIND *ssh_bind){
|
||||||
|
ssh_bind->toaccept=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind){
|
||||||
|
SSH_SESSION *session;
|
||||||
|
if(ssh_bind->bindfd<0)
|
||||||
|
return NULL;
|
||||||
|
int fd=accept(ssh_bind->bindfd,NULL,NULL);
|
||||||
|
if(fd<0)
|
||||||
|
return NULL;
|
||||||
|
session=ssh_new(ssh_options_copy(ssh_bind->options));
|
||||||
|
session->server=1;
|
||||||
|
session->fd=fd;
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
SSH_SESSION *getserver(SSH_OPTIONS * options) {
|
SSH_SESSION *getserver(SSH_OPTIONS * options) {
|
||||||
int socket;
|
int socket;
|
||||||
@@ -105,8 +155,8 @@ int server_set_kex(SSH_SESSION * session) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(server,0,sizeof(KEX));
|
memset(server,0,sizeof(KEX));
|
||||||
/* the program might ask for a specific cookie to be sent. useful for server
|
// the program might ask for a specific cookie to be sent. useful for server
|
||||||
debugging */
|
// debugging
|
||||||
if (options->wanted_cookie)
|
if (options->wanted_cookie)
|
||||||
memcpy(server->cookie, options->wanted_cookie, 16);
|
memcpy(server->cookie, options->wanted_cookie, 16);
|
||||||
else
|
else
|
||||||
@@ -125,4 +175,5 @@ int server_set_kex(SSH_SESSION * session) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_SERVER */
|
*/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user