diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2005-08-10 13:22:52 +0000 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2005-08-10 13:22:52 +0000 |
commit | 96a99bab7853998ec8c23da6bcb9ffb10855705d (patch) | |
tree | 25a79efb0fbcddb346fb65a4cdb554e78c7bec3b | |
parent | 5c26ae735483d140f802d58b1872b2fe9468d219 (diff) | |
download | libssh-96a99bab7853998ec8c23da6bcb9ffb10855705d.tar.gz libssh-96a99bab7853998ec8c23da6bcb9ffb10855705d.tar.xz libssh-96a99bab7853998ec8c23da6bcb9ffb10855705d.zip |
The kex works, the client authentifies (with password) then it's possible to choose a subsystem. The channels don't completely work.
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@7 7dcaeef0-15fb-0310-b436-a5af3365683c
-rw-r--r-- | include/libssh/libssh.h | 2 | ||||
-rw-r--r-- | include/libssh/priv.h | 5 | ||||
-rw-r--r-- | include/libssh/server.h | 76 | ||||
-rw-r--r-- | libssh/channels.c | 10 | ||||
-rw-r--r-- | libssh/client.c | 1 | ||||
-rw-r--r-- | libssh/connect.c | 7 | ||||
-rw-r--r-- | libssh/messages.c | 386 | ||||
-rw-r--r-- | libssh/server.c | 6 | ||||
-rw-r--r-- | libssh/session.c | 1 | ||||
-rw-r--r-- | sample.c | 22 | ||||
-rw-r--r-- | samplesshd.c | 86 |
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; } @@ -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; } |