aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/libssh.h2
-rw-r--r--include/libssh/priv.h5
-rw-r--r--include/libssh/server.h76
-rw-r--r--libssh/channels.c10
-rw-r--r--libssh/client.c1
-rw-r--r--libssh/connect.c7
-rw-r--r--libssh/messages.c386
-rw-r--r--libssh/server.c6
-rw-r--r--libssh/session.c1
-rw-r--r--sample.c22
-rw-r--r--samplesshd.c86
11 files changed, 576 insertions, 26 deletions
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index 1986c8a8..e3a0b652 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -200,6 +200,8 @@ void ssh_options_set_ssh_dir(SSH_OPTIONS *opt, char *dir);
void ssh_options_set_known_hosts_file(SSH_OPTIONS *opt, char *dir);
void ssh_options_allow_ssh1(SSH_OPTIONS *opt, int allow);
void ssh_options_allow_ssh2(SSH_OPTIONS *opt, int allow);
+void ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, char *dsakey);
+void ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, char *rsakey);
/* buffer.c */
diff --git a/include/libssh/priv.h b/include/libssh/priv.h
index 1def7d45..c080762b 100644
--- a/include/libssh/priv.h
+++ b/include/libssh/priv.h
@@ -291,6 +291,8 @@ struct ssh_session {
/* server host keys */
PRIVATE_KEY *rsa_key;
PRIVATE_KEY *dsa_key;
+ /* auths accepted by server */
+ int auth_methods;
int hostkeys; /* contains type of host key wanted by client, in server impl */
};
@@ -389,7 +391,8 @@ void channel_handle(SSH_SESSION *session, int type);
CHANNEL *channel_new(SSH_SESSION *session);
void channel_default_bufferize(CHANNEL *channel, void *data, int len,
int is_stderr);
-
+u32 ssh_channel_new_id(SSH_SESSION *session);
+CHANNEL *ssh_channel_from_local(SSH_SESSION *session,u32 num);
/* options.c */
diff --git a/include/libssh/server.h b/include/libssh/server.h
index ef86febe..4b8a0f89 100644
--- a/include/libssh/server.h
+++ b/include/libssh/server.h
@@ -47,19 +47,95 @@ int ssh_accept(SSH_SESSION *session);
/* messages.c */
+#define SSH_AUTH_REQUEST 1
+#define SSH_CHANNEL_REQUEST_OPEN 2
+#define SSH_CHANNEL_REQUEST 3
+
+#define SSH_AUTH_NONE (1<<0)
+#define SSH_AUTH_PASSWORD (1<<1)
+#define SSH_AUTH_HOSTBASED (1<<2)
+#define SSH_AUTH_PUBLICKEY (1<<3)
+#define SSH_AUTH_KEYBINT (1<<4)
+#define SSH_AUTH_UNKNOWN 0
+
struct ssh_auth_request {
char *username;
int method;
char *password;
};
+
+#define SSH_CHANNEL_SESSION 1
+#define SSH_CHANNEL_TCPIP 2
+#define SSH_CHANNEL_X11 3
+#define SSH_CHANNEL_UNKNOWN 4
+struct ssh_channel_request_open {
+ int type;
+ u32 sender;
+ u32 window;
+ u32 packet_size;
+ char *originator;
+ u16 orignator_port;
+ char *destination;
+ u16 destination_port;
+};
+
+#define SSH_CHANNEL_REQUEST_PTY 1
+#define SSH_CHANNEL_REQUEST_EXEC 2
+#define SSH_CHANNEL_REQUEST_SHELL 3
+#define SSH_CHANNEL_REQUEST_ENV 4
+#define SSH_CHANNEL_REQUEST_SUBSYSTEM 5
+#define SSH_CHANNEL_REQUEST_WINDOW_CHANGE 6
+#define SSH_CHANNEL_REQUEST_UNKNOWN 7
+
+struct ssh_channel_request {
+ int type;
+ CHANNEL *channel;
+ u8 want_reply;
+ /* pty-req type specifics */
+ char *TERM;
+ u32 width;
+ u32 height;
+ u32 pxwidth;
+ u32 pxheight;
+ STRING *modes;
+
+ /* env type request */
+ char *var_name;
+ char *var_value;
+ /* exec type request */
+ char *command;
+ /* subsystem */
+ char *subsystem;
+};
+
struct ssh_message {
+ SSH_SESSION *session;
int type;
struct ssh_auth_request auth_request;
+ struct ssh_channel_request_open channel_request_open;
+ struct ssh_channel_request channel_request;
};
typedef struct ssh_message SSH_MESSAGE;
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session);
+int ssh_message_type(SSH_MESSAGE *msg);
+int ssh_message_subtype(SSH_MESSAGE *msg);
+int ssh_message_reply_default(SSH_MESSAGE *msg);
+void ssh_message_free(SSH_MESSAGE *msg);
+
+char *ssh_message_auth_user(SSH_MESSAGE *msg);
+char *ssh_message_auth_password(SSH_MESSAGE *msg);
+int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial);
+void ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods);
+
+CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg);
+
+CHANNEL *ssh_message_channel_request_channel(SSH_MESSAGE *msg);
+// returns the TERM env variable
+char *ssh_message_channel_request_pty_term(SSH_MESSAGE *msg);
+char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg);
+int ssh_message_channel_request_reply_success(SSH_MESSAGE *msg);
#endif
diff --git a/libssh/channels.c b/libssh/channels.c
index 04eeaa99..a87d338a 100644
--- a/libssh/channels.c
+++ b/libssh/channels.c
@@ -50,21 +50,21 @@ CHANNEL *channel_new(SSH_SESSION *session){
return channel;
}
-static u32 channel_new_id(SSH_SESSION *session){
+u32 ssh_channel_new_id(SSH_SESSION *session){
u32 ret=session->maxchannel;
session->maxchannel++;
return ret;
}
static int channel_open(CHANNEL *channel,char *type_c,int window,
-int maxpacket,BUFFER *payload){
+ int maxpacket,BUFFER *payload){
SSH_SESSION *session=channel->session;
STRING *type=string_from_char(type_c);
u32 foo;
int err;
packet_clear_out(session);
buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_OPEN);
- channel->local_channel=channel_new_id(session);
+ channel->local_channel=ssh_channel_new_id(session);
channel->local_maxpacket=maxpacket;
channel->local_window=window;
ssh_say(2,"creating a channel %d with %d window and %d max packet\n",
@@ -121,7 +121,7 @@ int maxpacket,BUFFER *payload){
return -1;
}
-static CHANNEL *find_local_channel(SSH_SESSION *session,u32 num){
+CHANNEL *ssh_channel_from_local(SSH_SESSION *session,u32 num){
// we assume we are always the local
CHANNEL *initchan,*channel;
initchan=session->channels;
@@ -154,7 +154,7 @@ static CHANNEL *channel_from_msg(SSH_SESSION *session){
ssh_set_error(session,SSH_FATAL,"Getting channel from message : short read");
return NULL;
}
- channel=find_local_channel(session,ntohl(chan));
+ channel=ssh_channel_from_local(session,ntohl(chan));
if(!channel)
ssh_set_error(session,SSH_FATAL,"Server specified invalid channel %d",ntohl(chan));
return channel;
diff --git a/libssh/client.c b/libssh/client.c
index 9411d5ec..42b10414 100644
--- a/libssh/client.c
+++ b/libssh/client.c
@@ -210,7 +210,6 @@ int ssh_connect(SSH_SESSION *session){
ssh_say(2,"banner : %s\n",session->serverbanner);
/* here we analyse the different protocols the server allows */
if(ssh_analyze_banner(session,&ssh1,&ssh2)){
- ssh_disconnect(session);
return -1;
}
/* here we decide which version of the protocol to use */
diff --git a/libssh/connect.c b/libssh/connect.c
index 4e1782d4..ccb704ff 100644
--- a/libssh/connect.c
+++ b/libssh/connect.c
@@ -61,12 +61,9 @@ int ssh_connect_host(SSH_SESSION *session, const char *host, const char
int s;
while(++count>1)
--count;
-#ifdef HAVE_GETHOSTBYADDR
- hp=gethostbyaddr(host,4,AF_INET);
-#endif
+
#ifdef HAVE_GETHOSTBYNAME
- if(!hp)
- hp=gethostbyname(host);
+ hp=gethostbyname(host);
#endif
if(!hp){
--count;
diff --git a/libssh/messages.c b/libssh/messages.c
new file mode 100644
index 00000000..d5f6d0bd
--- /dev/null
+++ b/libssh/messages.c
@@ -0,0 +1,386 @@
+/* messages.c */
+/*
+Copyright 2005 Aris Adamantiadis
+
+This file is part of the SSH Library
+
+The SSH Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The SSH Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the SSH Library; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* this file contains the Message parsing utilities for server programs using
+ * libssh. The main loop of the program will call ssh_message_get(session) to
+ * get messages as they come. they are not 1-1 with the protocol messages.
+ * then, the user will know what kind of a message it is and use the appropriate
+ * functions to handle it (or use the default handlers if she doesn't know what to
+ * do */
+
+#include "libssh/libssh.h"
+#include "libssh/priv.h"
+#include "libssh/server.h"
+#include "libssh/ssh2.h"
+#include <netdb.h>
+#include <string.h>
+
+static SSH_MESSAGE *message_new(SSH_SESSION *session){
+ SSH_MESSAGE *msg=malloc(sizeof(SSH_MESSAGE));
+ memset(msg,0,sizeof (*msg));
+ msg->session=session;
+ return msg;
+}
+
+static int handle_service_request(SSH_SESSION *session){
+ STRING *service;
+ char *service_c;
+ service=buffer_get_ssh_string(session->in_buffer);
+ if(!service){
+ ssh_set_error(session,SSH_FATAL,"Invalid SSH_MSG_SERVICE_REQUEST packet");
+ return -1;
+ }
+ service_c=string_to_char(service);
+ ssh_say(2,"Sending a SERVICE_ACCEPT for service %s\n",service_c);
+ free(service_c);
+ packet_clear_out(session);
+ buffer_add_u8(session->out_buffer,SSH2_MSG_SERVICE_ACCEPT);
+ buffer_add_ssh_string(session->out_buffer,service);
+ packet_send(session);
+ free(service);
+ return 0;
+}
+
+static void handle_unimplemented(SSH_SESSION *session){
+ packet_clear_out(session);
+ buffer_add_u32(session->out_buffer,htonl(session->recv_seq-1));
+ packet_send(session);
+}
+
+static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){
+ STRING *user=buffer_get_ssh_string(session->in_buffer);
+ STRING *service=buffer_get_ssh_string(session->in_buffer);
+ STRING *method=buffer_get_ssh_string(session->in_buffer);
+ SSH_MESSAGE *msg;
+ char *service_c,*method_c;
+ msg=message_new(session);
+ msg->type=SSH_AUTH_REQUEST;
+ msg->auth_request.username=string_to_char(user);
+ free(user);
+ service_c=string_to_char(service);
+ method_c=string_to_char(method);
+ ssh_say(2,"auth request for service %s, method %s for user '%s'\n",service_c,method_c,
+ msg->auth_request.username);
+ free(service_c);
+ if(!strcmp(method_c,"none")){
+ msg->auth_request.method=SSH_AUTH_NONE;
+ free(method_c);
+ return msg;
+ }
+ if(!strcmp(method_c,"password")){
+ STRING *pass;
+ u8 tmp;
+ msg->auth_request.method=SSH_AUTH_PASSWORD;
+ free(method_c);
+ buffer_get_u8(session->in_buffer,&tmp);
+ pass=buffer_get_ssh_string(session->in_buffer);
+ msg->auth_request.password=string_to_char(pass);
+ free(pass);
+ return msg;
+ }
+ msg->auth_request.method=SSH_AUTH_UNKNOWN;
+ free(method_c);
+ return msg;
+}
+
+char *ssh_message_auth_user(SSH_MESSAGE *msg){
+ return msg->auth_request.username;
+}
+
+char *ssh_message_auth_password(SSH_MESSAGE *msg){
+ return msg->auth_request.password;
+}
+
+void ssh_message_auth_set_methods(SSH_MESSAGE *msg,int methods){
+ msg->session->auth_methods=methods;
+}
+
+static int ssh_message_auth_reply_default(SSH_MESSAGE *msg,int partial){
+ char methods_c[128]="";
+ STRING *methods;
+ packet_clear_out(msg->session);
+ buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_FAILURE);
+ if(msg->session->auth_methods==0){
+ msg->session->auth_methods=SSH_AUTH_PUBLICKEY|SSH_AUTH_PASSWORD;
+ }
+ if(msg->session->auth_methods & SSH_AUTH_PUBLICKEY)
+ strcat(methods_c,"publickey,");
+ if(msg->session->auth_methods & SSH_AUTH_KEYBINT)
+ strcat(methods_c,"keyboard-interactive,");
+ if(msg->session->auth_methods & SSH_AUTH_PASSWORD)
+ strcat(methods_c,"password,");
+ if(msg->session->auth_methods & SSH_AUTH_HOSTBASED)
+ strcat(methods_c,"hostbased,");
+ methods_c[strlen(methods_c)-1]=0; // strip the comma. We are sure there is at
+ // least one word into the list
+ ssh_say(2,"Sending a auth failure. methods that can continue : %s\n",methods_c);
+ methods=string_from_char(methods_c);
+ buffer_add_ssh_string(msg->session->out_buffer,methods);
+ free(methods);
+ if(partial)
+ buffer_add_u8(msg->session->out_buffer,1);
+ else
+ buffer_add_u8(msg->session->out_buffer,0); // no partial success
+ return packet_send(msg->session);
+}
+
+int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial){
+ if(partial)
+ return ssh_message_auth_reply_default(msg,partial);
+ packet_clear_out(msg->session);
+ buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS);
+ return packet_send(msg->session);
+}
+
+static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session){
+ SSH_MESSAGE *msg=message_new(session);
+ STRING *type;
+ char *type_c;
+ u32 sender,window,packet;
+ msg->type=SSH_CHANNEL_REQUEST_OPEN;
+ type=buffer_get_ssh_string(session->in_buffer);
+ type_c=string_to_char(type);
+ ssh_say(2,"clients wants to open a %s channel\n",type_c);
+ free(type);
+ buffer_get_u32(session->in_buffer,&sender);
+ buffer_get_u32(session->in_buffer,&window);
+ buffer_get_u32(session->in_buffer,&packet);
+ msg->channel_request_open.sender=ntohl(sender);
+ msg->channel_request_open.window=ntohl(window);
+ msg->channel_request_open.packet_size=ntohl(packet);
+ if(!strcmp(type_c,"session")){
+ msg->channel_request_open.type=SSH_CHANNEL_SESSION;
+ return msg;
+ }
+ msg->channel_request_open.type=SSH_CHANNEL_UNKNOWN;
+ return msg;
+}
+
+CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg){
+ CHANNEL *chan=channel_new(msg->session);
+ chan->local_channel=ssh_channel_new_id(msg->session);
+ chan->local_maxpacket=35000;
+ chan->local_window=32000;
+ chan->remote_channel=msg->channel_request_open.sender;
+ chan->remote_maxpacket=msg->channel_request_open.packet_size;
+ chan->remote_window=msg->channel_request_open.window;
+ packet_clear_out(msg->session);
+ buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
+ buffer_add_u32(msg->session->out_buffer,htonl(chan->remote_channel));
+ buffer_add_u32(msg->session->out_buffer,htonl(chan->local_channel));
+ buffer_add_u32(msg->session->out_buffer,htonl(chan->local_window));
+ buffer_add_u32(msg->session->out_buffer,htonl(chan->local_maxpacket));
+ ssh_say(2,"Accepting a channel request_open for chan %d\n",chan->remote_channel);
+ if(packet_send(msg->session)){
+ channel_free(chan);
+ return NULL;
+ }
+ return chan;
+}
+
+static int ssh_message_channel_request_open_reply_default(SSH_MESSAGE *msg){
+ ssh_say(2,"Refusing a channel\n");
+ packet_clear_out(msg->session);
+ buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_OPEN_FAILURE);
+ buffer_add_u32(msg->session->out_buffer,htonl(msg->channel_request_open.sender));
+ buffer_add_u32(msg->session->out_buffer,htonl(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED));
+ buffer_add_u32(msg->session->out_buffer,0); // reason is an empty string
+ buffer_add_u32(msg->session->out_buffer,0); // language too
+ return packet_send(msg->session);
+}
+
+static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session){
+ u32 channel;
+ STRING *type;
+ char *type_c;
+ u8 want_reply;
+ SSH_MESSAGE *msg=message_new(session);
+ buffer_get_u32(session->in_buffer,&channel);
+ channel=ntohl(channel);
+ type=buffer_get_ssh_string(session->in_buffer);
+ buffer_get_u8(session->in_buffer,&want_reply);
+ type_c=string_to_char(type);
+ free(type);
+ ssh_say(2,"received a %s channel_request for channel %d (want_reply=%hhd)\n",
+ type_c,channel,want_reply);
+ msg->type=SSH_CHANNEL_REQUEST;
+ msg->channel_request.channel=ssh_channel_from_local(session,channel);
+ msg->channel_request.want_reply=want_reply;
+ if(!strcmp(type_c,"pty-req")){
+ STRING *term;
+ char *term_c;
+ term=buffer_get_ssh_string(session->in_buffer);
+ term_c=string_to_char(term);
+ free(term);
+ msg->channel_request.type=SSH_CHANNEL_REQUEST_PTY;
+ msg->channel_request.TERM=term_c;
+ buffer_get_u32(session->in_buffer,&msg->channel_request.width);
+ buffer_get_u32(session->in_buffer,&msg->channel_request.height);
+ buffer_get_u32(session->in_buffer,&msg->channel_request.pxwidth);
+ buffer_get_u32(session->in_buffer,&msg->channel_request.pxheight);
+ msg->channel_request.width=ntohl(msg->channel_request.width);
+ msg->channel_request.height=ntohl(msg->channel_request.height);
+ msg->channel_request.pxwidth=ntohl(msg->channel_request.pxwidth);
+ msg->channel_request.pxheight=ntohl(msg->channel_request.pxheight);
+ msg->channel_request.modes=buffer_get_ssh_string(session->in_buffer);
+ return msg;
+ }
+ if(!strcmp(type_c,"subsystem")){
+ STRING *subsys;
+ char *subsys_c;
+ subsys=buffer_get_ssh_string(session->in_buffer);
+ subsys_c=string_to_char(subsys);
+ free(subsys);
+ msg->channel_request.type=SSH_CHANNEL_REQUEST_SUBSYSTEM;
+ msg->channel_request.subsystem=subsys_c;
+ return msg;
+ }
+ if(!strcmp(type_c,"shell")){
+ msg->channel_request.type=SSH_CHANNEL_REQUEST_SHELL;
+ return msg;
+ }
+ if(!strcmp(type_c,"exec")){
+ STRING *cmd=buffer_get_ssh_string(session->in_buffer);
+ msg->channel_request.type=SSH_CHANNEL_REQUEST_EXEC;
+ msg->channel_request.command=string_to_char(cmd);
+ free(cmd);
+ return msg;
+ }
+
+ msg->channel_request.type=SSH_CHANNEL_UNKNOWN;
+ return msg;
+}
+
+char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg){
+ return msg->channel_request.subsystem;
+}
+
+int ssh_message_channel_request_reply_success(SSH_MESSAGE *msg){
+ u32 channel;
+ if(msg->channel_request.want_reply){
+ channel=msg->channel_request.channel->remote_channel;
+ ssh_say(2,"Sending a default channel_success denied to channel %d\n",channel);
+ packet_clear_out(msg->session);
+ buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_SUCCESS);
+ buffer_add_u32(msg->session->out_buffer,htonl(channel));
+ return packet_send(msg->session);
+ } else {
+ ssh_say(2,"The client doesn't want to know the request successed\n");
+ return 0;
+ }
+}
+
+static int ssh_message_channel_request_reply_default(SSH_MESSAGE *msg){
+ u32 channel;
+ if(msg->channel_request.want_reply){
+ channel=msg->channel_request.channel->remote_channel;
+ ssh_say(2,"Sending a default channel_request denied to channel %d\n",channel);
+ packet_clear_out(msg->session);
+ buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_FAILURE);
+ buffer_add_u32(msg->session->out_buffer,htonl(channel));
+ return packet_send(msg->session);
+ } else {
+ ssh_say(2,"The client doesn't want to know the request failed ! \n");
+ return 0;
+ }
+}
+
+SSH_MESSAGE *ssh_message_get(SSH_SESSION *session){
+ while(1){
+ if(packet_read(session))
+ return NULL;
+ if(packet_translate(session))
+ return NULL;
+ switch(session->in_packet.type){
+ case SSH2_MSG_SERVICE_REQUEST:
+ if(handle_service_request(session))
+ return NULL;
+ break;
+ case SSH2_MSG_IGNORE:
+ case SSH2_MSG_DEBUG:
+ break;
+ case SSH2_MSG_USERAUTH_REQUEST:
+ return handle_userauth_request(session);
+ break;
+ case SSH2_MSG_CHANNEL_OPEN:
+ return handle_channel_request_open(session);
+ break;
+ case SSH2_MSG_CHANNEL_REQUEST:
+ return handle_channel_request(session);
+ break;
+ default:
+ handle_unimplemented(session);
+ ssh_set_error(session,SSH_FATAL,"Unhandled message %d\n",session->in_packet.type);
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+int ssh_message_type(SSH_MESSAGE *msg){
+ return msg->type;
+}
+
+int ssh_message_subtype(SSH_MESSAGE *msg){
+ switch(msg->type){
+ case SSH_AUTH_REQUEST:
+ return msg->auth_request.method;
+ case SSH_CHANNEL_REQUEST_OPEN:
+ return msg->channel_request_open.type;
+ case SSH_CHANNEL_REQUEST:
+ return msg->channel_request.type;
+ }
+ return -1;
+}
+
+int ssh_message_reply_default(SSH_MESSAGE *msg){
+ switch(msg->type){
+ case SSH_AUTH_REQUEST:
+ return ssh_message_auth_reply_default(msg,0);
+ break;
+ case SSH_CHANNEL_REQUEST_OPEN:
+ return ssh_message_channel_request_open_reply_default(msg);
+ break;
+ case SSH_CHANNEL_REQUEST:
+ return ssh_message_channel_request_reply_default(msg);
+ break;
+ default:
+ ssh_say(1,"Don't know what to default reply to %d type\n",
+ msg->type);
+ break;
+ }
+ return 0;
+}
+
+void ssh_message_free(SSH_MESSAGE *msg){
+ switch(msg->type){
+ case SSH_AUTH_REQUEST:
+ if(msg->auth_request.username)
+ free(msg->auth_request.username);
+ if(msg->auth_request.password){
+ memset(msg->auth_request.password,0,strlen(msg->auth_request.password));
+ free(msg->auth_request.password);
+ }
+ break;
+ }
+ memset(msg,0,sizeof(*msg));
+ free(msg);
+}
diff --git a/libssh/server.c b/libssh/server.c
index 62294436..336aaf51 100644
--- a/libssh/server.c
+++ b/libssh/server.c
@@ -38,12 +38,8 @@ static int bind_socket(SSH_BIND *ssh_bind,char *hostname, int port) {
int opt = 1;
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);
+ hp=gethostbyname(hostname);
#endif
if(!hp){
ssh_set_error(ssh_bind,SSH_FATAL,"resolving %s: %s",hostname,hstrerror(h_errno));
diff --git a/libssh/session.c b/libssh/session.c
index 1ea071e0..ef23d03b 100644
--- a/libssh/session.c
+++ b/libssh/session.c
@@ -32,6 +32,7 @@ SSH_SESSION *ssh_new() {
memset(session,0,sizeof(SSH_SESSION));
session->next_crypto=crypto_new();
session->maxchannel=FIRST_CHANNEL;
+ session->fd=-1;
return session;
}
diff --git a/sample.c b/sample.c
index 42ae09d1..43a0b2ab 100644
--- a/sample.c
+++ b/sample.c
@@ -176,22 +176,30 @@ void shell(SSH_SESSION *session){
CHANNEL *channel;
struct termios terminal_local;
int interactive=isatty(0);
+ channel = channel_new(session);
if(interactive){
tcgetattr(0,&terminal_local);
memcpy(&terminal,&terminal_local,sizeof(struct termios));
- cfmakeraw(&terminal_local);
- tcsetattr(0,TCSANOW,&terminal_local);
- setsignal();
}
- signal(SIGTERM,do_cleanup);
- channel = channel_new(session);
- channel_open_session(channel);
+ if(channel_open_session(channel)){
+ printf("error opening channel : %s\n",ssh_get_error(session));
+ return;
+ }
chan=channel;
if(interactive){
channel_request_pty(channel);
sizechanged();
}
- channel_request_shell(channel);
+ if(channel_request_shell(channel)){
+ printf("Requesting shell : %s\n",ssh_get_error(session));
+ return;
+ }
+ if(interactive){
+ cfmakeraw(&terminal_local);
+ tcsetattr(0,TCSANOW,&terminal_local);
+ setsignal();
+ }
+ signal(SIGTERM,do_cleanup);
select_loop(session,channel);
}
diff --git a/samplesshd.c b/samplesshd.c
index d81049c5..141dc127 100644
--- a/samplesshd.c
+++ b/samplesshd.c
@@ -23,11 +23,24 @@ MA 02111-1307, USA. */
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <unistd.h>
+#include <string.h>
+
+int auth_password(char *user, char *password){
+ if(strcmp(user,"aris"))
+ return 0;
+ if(strcmp(password,"lala"))
+ return 0;
+ return 1; // authenticated
+}
+
int main(int argc, char **argv){
SSH_OPTIONS *options=ssh_options_new();
SSH_SESSION *session;
SSH_BIND *ssh_bind;
SSH_MESSAGE *message;
+ CHANNEL *chan;
+ int auth=0;
+ int sftp=0;
ssh_options_getopt(options,&argc,argv);
ssh_options_set_dsa_server_key(options,"/etc/ssh/ssh_host_dsa_key");
ssh_options_set_rsa_server_key(options,"/etc/ssh/ssh_host_rsa_key");
@@ -49,8 +62,77 @@ int main(int argc, char **argv){
}
do {
message=ssh_message_get(session);
- } while (message);
- printf("error : %s\n",ssh_get_error(session));
+ if(!message)
+ break;
+ switch(ssh_message_type(message)){
+ case SSH_AUTH_REQUEST:
+ switch(ssh_message_subtype(message)){
+ case SSH_AUTH_PASSWORD:
+ printf("User %s wants to auth with pass %s\n",
+ ssh_message_auth_user(message),
+ ssh_message_auth_password(message));
+ if(auth_password(ssh_message_auth_user(message),
+ ssh_message_auth_password(message))){
+ auth=1;
+ ssh_message_auth_reply_success(message,0);
+ break;
+ }
+ // not authenticated, send default message
+ case SSH_AUTH_NONE:
+ default:
+ ssh_message_auth_set_methods(message,SSH_AUTH_PASSWORD);
+ ssh_message_reply_default(message);
+ break;
+ }
+ break;
+ default:
+ ssh_message_reply_default(message);
+ }
+ ssh_message_free(message);
+ } while (!auth);
+ if(!auth){
+ printf("error : %s\n",ssh_get_error(session));
+ return 1;
+ }
+ do {
+ message=ssh_message_get(session);
+ if(message){
+ switch(ssh_message_type(message)){
+ case SSH_CHANNEL_REQUEST_OPEN:
+ if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
+ chan=ssh_message_channel_request_open_reply_accept(message);
+ break;
+ }
+ default:
+ ssh_message_reply_default(message);
+ }
+ ssh_message_free(message);
+ }
+ } while(message && !chan);
+ if(!chan){
+ printf("error : %s\n",ssh_get_error(session));
+ return 1;
+ }
+ do {
+ message=ssh_message_get(session);
+ if(message && ssh_message_type(message)==SSH_CHANNEL_REQUEST &&
+ ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SUBSYSTEM){
+ if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
+ sftp=1;
+ ssh_message_channel_request_reply_success(message);
+ break;
+ }
+ }
+ if(!sftp){
+ ssh_message_reply_default(message);
+ }
+ ssh_message_free(message);
+ } while (message && !sftp);
+ if(!sftp){
+ printf("error : %s\n",ssh_get_error(session));
+ return 1;
+ }
+ printf("it works !\n");
return 0;
}