[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Regarding Putty is not connecting to lib SSH server - HMAC Error


Hi

 We are using your LIBSSH server and customized it to meet our needs. Today I am trying to connect the server with putty but unfortunately I am getting the following error. To check this I have written one LIBSSH client and it seems that the LIBSSH server works fine with the custom client (which I wrote, with same kind of messages what putty is sending). Can you help us what is going wrong with putty. I am attaching both client and server code along with the keys (these keys I have collected from one my Linux server) used.

Please find the error reported and corresponding putty log.

[cid:image001.png@01CE6B85.DBA37C70]

Server Log with custom client ..,

[3] Enabling POLLOUT for socket
[3] ssh_handle_key_exchange: Actual state : 2
[3] Received banner: SSH-2.0-libssh-0.5.0
[1] SSH client banner: SSH-2.0-libssh-0.5.0
[1] Analyzing banner: SSH-2.0-libssh-0.5.0
[3] Writing on the wire a packet having 347 bytes before
[3] 347 bytes after comp + 8 padding bytes = 356 bytes packet
[3] Enabling POLLOUT for socket
[3] ssh_handle_key_exchange: Actual state : 4
[3] ssh_handle_key_exchange: Actual state : 4
[3] Packet size decrypted: 148 (0x94)
[3] Read a 148 bytes packet
[3] 6 bytes padding, 147 bytes left in buffer
[3] After padding, 141 bytes left in buffer
[3] Final size 141
[3] Type 20
[3] Dispatching handler for packet type 20
[3] Set output algorithm aes256-ctr
[3] Set input algorithm aes256-ctr
[3] ssh_handle_key_exchange: Actual state : 6
[3] Packet size decrypted: 140 (0x8c)
[3] Read a 140 bytes packet
[3] 5 bytes padding, 139 bytes left in buffer
[3] After padding, 134 bytes left in buffer
[3] Final size 134
[3] Type 30
[3] Dispatching handler for packet type 30
[3] Received SSH_MSG_KEXDH_INIT
[3] Writing on the wire a packet having 689 bytes before
[3] 689 bytes after comp + 10 padding bytes = 700 bytes packet
[3] Enabling POLLOUT for socket
[3] Writing on the wire a packet having 1 bytes before
[3] 1 bytes after comp + 10 padding bytes = 12 bytes packet
[3] SSH_MSG_NEWKEYS sent
[3] ssh_handle_key_exchange: Actual state : 6
[3] Packet size decrypted: 12 (0xc)
[3] Read a 12 bytes packet
[3] 10 bytes padding, 11 bytes left in buffer
[3] After padding, 1 bytes left in buffer
[3] Final size 1
[3] Type 21
[3] Dispatching handler for packet type 21
[2] Received SSH_MSG_NEWKEYS
[3] Enabling POLLOUT for socket
[3] ssh_handle_key_exchange: Actual state : 7
[3] Decrypting 16 bytes
[3] Packet size decrypted: 28 (0x1c)
[3] Read a 28 bytes packet
[3] Decrypting 16 bytes
[3] 10 bytes padding, 27 bytes left in buffer
[3] After padding, 17 bytes left in buffer
[3] Final size 17
[3] Type 5
[3] Dispatching handler for packet type 5
[3] Received a SERVICE_REQUEST for service ssh-userauth
[3] Sending a SERVICE_ACCEPT for service ssh-userauth
[3] Writing on the wire a packet having 17 bytes before
[3] 17 bytes after comp + 10 padding bytes = 28 bytes packet
[3] Encrypting packet with seq num: 3, len: 32
[3] Enabling POLLOUT for socket
[3] Decrypting 16 bytes
[3] Packet size decrypted: 44 (0x2c)
[3] Read a 44 bytes packet
[3] Decrypting 32 bytes
[3] 19 bytes padding, 43 bytes left in buffer
[3] After padding, 24 bytes left in buffer
[3] Final size 24
[3] Type 90
[3] Dispatching handler for packet type 90
[3] Clients wants to open a session channel
[3] Writing on the wire a packet having 17 bytes before
[3] 17 bytes after comp + 10 padding bytes = 28 bytes packet
[3] Encrypting packet with seq num: 4, len: 32
[3] Enabling POLLOUT for socket


It seems it's fine with the custom client.

/Ashish






















PNG image

Attachment: putty.log
Description: putty.log

Attachment: ssh_host_dsa_key
Description: ssh_host_dsa_key

Attachment: ssh_host_dsa_key.pub
Description: ssh_host_dsa_key.pub

Attachment: ssh_host_key.pub
Description: ssh_host_key.pub

Attachment: ssh_host_rsa_key
Description: ssh_host_rsa_key

Attachment: ssh_host_rsa_key.pub
Description: ssh_host_rsa_key.pub

/* 

ebpsshd.c compile:

gcc -g -Wall -Wstrict-prototypes -O0 -o ebpsshd `pkg-config --cflags --libs glib-2.0` -I/home/jeetu/utils/libssh/libssh-project/include ebpsshd.c -L/home/jeetu/utils/libssh/libssh-project/build/src -lssh -L/home/jeetu/utils/libssh/libssh-project/build/src/threads -lssh_threads -lgthread-2.0

*/


#include <libssh/libssh.h>
#include <libssh/server.h>
#include <libssh/callbacks.h>
//#include <unistd.h>
#include <string.h>
#include <stdio.h>
//#include <glib.h>
#include <stdlib.h>
#include <errno.h>
//#include <poll.h>
#include "poll.h"
#include <sys/types.h>
//#include <sys/socket.h>
#include <WinSock2.h>
//#include <netdb.h>
#include <fcntl.h>
#pragma comment(lib, "ws2_32.lib")
//#include "key.h" //jeetu - temporary hardcoded key

#ifndef KEYS_FOLDER	
#ifdef _WIN32
#define KEYS_FOLDER	"C:\\Users\\inrasun3\\.ssh\\"
#define AUTHORIZED_KEYS "C:\\Users\\inrasun3\\.ssh\\ssh_host_dsa_key"
#else
#define KEYS_FOLDER "/home/jeetu/tmp/" //jeetu - temporary
#define AUTHORIZED_KEYS "/home/jeetu/tmp/authorized_keys"
#endif
#endif

typedef void* gpointer;

#define MAX_X11_AUTH_PROTO_STR_SZ 18
#define MAX_X11_AUTH_COOKIE_STR_SZ 50

//jeetu - all hardcoded defines; should probably figure out how these values came to be in the orig openssh code
#define MAX_DISPLAYS 1000
#define NI_MAXSERV 32
#define NUM_SOCKS 10
#define SSH_LISTEN_BACKLOG 128


static int copy_chan_to_fd(ssh_session session,
                                           ssh_channel channel,
                                           void *data,
                                           uint32_t len,
                                           int is_stderr,
                                           void *userdata);

static void chan_close(ssh_session session, ssh_channel channel, void *userdata);
static int copy_fd_to_chan(socket_t fd, int revents, void *userdata);


typedef struct x11_session_struct
       {
       char *x11_auth_cookie;
       char *x11_auth_protocol;
       int screen_number;
       int single_connection;
       unsigned int display_number;
       } x11_session;

typedef struct x11_conn_struct
       {
       ssh_session session;
       int client_sock;
       } x11data;
       

int authenticate_user(ssh_session session);
int pubkey_auth(char *pk64);
int server_loop(ssh_session session);
int session_x11_req(ssh_session session,ssh_message message,x11_session* x11session,int *socket);
int session_setup_x11fwd(ssh_session session,x11_session* x11session,int *socket);
int x11_create_display_inet(ssh_session session,unsigned int *display_numberp, int *sockets);
int wait_for_something(ssh_session session,int socket);
static gpointer server_thread(gpointer session_data);
int exec_command(const char *command,x11_session* x11session);
//static gpointer exec_command(gpointer data);
//static gpointer process_x11_channel_events_thread(gpointer x11conndata);

ssh_channel chan=0;
ssh_session *session;
x11data **x11conndata;


/* Return Values:
 * 0 - Success
 * 1 - ssh_bind_listen failed - error listening to socket
 * 2 - ssh_bind_accept failed - error accepting a connection
 * 3 - ssh_handle_key_change failed 
 * 4 - authenticate_user failed
 */
int main(int argc, char **argv)
{    
    ssh_bind sshbind;
    int auth=0;
    int r;
    int port = 2000;
    int verbosity = SSH_LOG_PACKET;
    int session_count = 0;

    //g_thread_init(NULL);

    //ssh_threads_set_callbacks(ssh_threads_get_pthread());
    if(ssh_init() == -1)
      {
      printf("\nError initializing ssh: ssh_init() failed");
      exit(1);
      }

    sshbind=ssh_bind_new();
    session = (ssh_session *) ssh_new();

    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT,&port);
    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");

    if(ssh_bind_listen(sshbind)<0)
      {
      printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
      return 1;
      }   
 
    while(1)
         {
         session[session_count]=ssh_new();
         ssh_options_getopt(session[session_count],&argc,argv);
         r=ssh_bind_accept(sshbind,session[session_count]);
         if(r==SSH_ERROR)
           {
           printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
           return 2;
           }
         ssh_options_set(session[session_count], SSH_OPTIONS_LOG_VERBOSITY, &verbosity );
         if(ssh_handle_key_exchange(session[session_count]))
           {
           printf("ssh_handle_key_exchange: %s\n",ssh_get_error(session[session_count]));
           return 3;
           }
      
         /* public key authentication */
         auth = authenticate_user(session[session_count]);
         if(!auth)
           {
           printf("auth error: %s\n",ssh_get_error(session[session_count]));
           ssh_disconnect(session[session_count]);
           return 4;
           }
         //g_thread_create(server_thread,session[session_count],FALSE,NULL);
         session_count++;
         }
  
  
    ssh_bind_free(sshbind);
    ssh_finalize();
  
    return 0;
}

/* returns 1 for OK, 0 for KO */
int authenticate_user(ssh_session session) 
{
    ssh_message message;
    ssh_string pubkey = NULL;
    char *pk64 = NULL;
    int signature_state = SSH_PUBLICKEY_STATE_NONE;

    do 
     {
     message = ssh_message_get(session);
     if(!message) 
       return 0;

     switch(ssh_message_type(message)) 
           {
           case SSH_REQUEST_AUTH:
                switch(ssh_message_subtype(message)) 
                      {
                      case SSH_AUTH_METHOD_PUBLICKEY:
                           pubkey = publickey_to_string(ssh_message_auth_publickey(message));
			   //pk64 = g_base64_encode((const guchar *)ssh_string_to_char(pubkey), ssh_string_len(pubkey));
			   signature_state = ssh_message_auth_publickey_state(message);
                           if(signature_state == SSH_PUBLICKEY_STATE_NONE) 
			     {
                             /* no signature */
                             ssh_message_auth_reply_pk_ok_simple(message);
                             break;
                             } 
                           else if(signature_state != SSH_PUBLICKEY_STATE_VALID) 
                             {
                             /* will be rejected later */
                             } 
                           else 
                             {
                             /* signature is good at that point */
                             if(pubkey_auth(pk64)) 
                               {
                               /* user is allowed */
                               ssh_message_auth_reply_success(message, 0);
                               ssh_message_free(message);
                               return 1;
                               }
                             }
                           /* the following is not necessary if we want only pubkey auth */
                           ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PUBLICKEY);
                           /* reject authentication */
                           ssh_message_reply_default(message);
                           break;
                      case SSH_AUTH_METHOD_PASSWORD:
                        /* handle password auth if needed */
                      default:
                           ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PUBLICKEY);
                           ssh_message_reply_default(message);
                      }
                break;
           default:
                ssh_message_reply_default(message);
           }
     ssh_message_free(message);
     }while(1);
    
    return 0;
}

int pubkey_auth(char* pk64)
{
    char header[100],key[300],footer[100];
    int ret = 0;
    FILE *fp;

    fp = fopen(AUTHORIZED_KEYS,"r");
    if(fp == NULL)
      {
      fprintf(stderr,"\nCould not open authorized_keys file %s\n",AUTHORIZED_KEYS);
      return 0;
      }

    while(fgetc(fp) != EOF)
         {
         header[0] = '\0';
         key[0] = '\0';
         footer[0] = '\0';
         fscanf(fp,"%s %s %s\n",header,key,footer);
         printf("\nkey = %s\n",key);
         if(strcmp(pk64,key) == 0)
           {
           ret = 1;
           break;
           }
         }

    fclose(fp);
    return ret;
}


static gpointer server_thread(gpointer session_data)
{
    ssh_message message;
    int message_subtype = 0;
    int message_type = 0;
    int ret = 0;
    ssh_session session = (ssh_session) session_data;
    x11_session x11session;
    int socket;

    do 
     {
     message=ssh_message_get(session);
     if(message)
       {
       message_type = ssh_message_type(message);
       message_subtype = ssh_message_subtype(message);

       switch(message_type)
             {		
	     case SSH_REQUEST_CHANNEL_OPEN:
                  if(message_subtype == SSH_CHANNEL_SESSION)
                    {
		    printf("\nSSH_CHANNEL_SESSION");
                    chan=ssh_message_channel_request_open_reply_accept(message);
                    }
		  break;
	     case SSH_REQUEST_CHANNEL:
		  printf("\nSSH_REQUEST_CHANNEL subtype = %d",message_subtype);
		  /*if(message_subtype == SSH_CHANNEL_REQUEST_X11)
		    {
		    printf("\nSSH_CHANNEL_REQUEST_X11");
		    if(session_x11_req(session,message,&x11session,&socket) != 1)
                      {
                      printf("\nsession_x11_req error");
                      ssh_message_reply_default(message);
                      ssh_disconnect(session);
                      return NULL;
                      }
                    else
		      ssh_message_channel_request_reply_success(message);
		    }*/
		  if(message_subtype == SSH_CHANNEL_REQUEST_ENV)
		    {		   
		    printf("\nSSH_CHANNEL_REQUEST_ENV");
		    ssh_message_channel_request_reply_success(message);
		    }
		  if(message_subtype == SSH_CHANNEL_REQUEST_EXEC)
		    {
		    printf("\nSSH_CHANNEL_REQUEST_EXEC command = %s\n",ssh_message_channel_request_command(message));
                    ret = exec_command(ssh_message_channel_request_command(message),&x11session);
                    if(ret == 0)
                      {
                      printf("\nserver_loop: unable to exec command\n");
                      }
                    ssh_message_channel_request_reply_success(message);		
                    wait_for_something(session,socket);
                    ssh_disconnect(session);
		    return NULL; /* Aris's hack */   
		    }
		  break;		    
	     default:
                  ssh_message_reply_default(message);
	     }
       ssh_message_free(message);
       }
     } while(1);

     return NULL;
}

/*
int session_x11_req(ssh_session session,ssh_message message,x11_session* x11session,int *socket)
{
    int ret = 1;
    FILE* fpxauth;
    char xauth_path[] = "/usr/bin/xauth";
    char strxauth_exec[200]; //jeetu - buffer size sufficient?; xauth path name may be larger; ideally not fixed

    x11session->x11_auth_protocol = NULL;
    x11session->x11_auth_cookie = NULL;

    x11session->x11_auth_protocol = malloc(MAX_X11_AUTH_PROTO_STR_SZ+2);
    strncpy(x11session->x11_auth_protocol,ssh_message_channel_request_x11_auth_protocol(message),MAX_X11_AUTH_PROTO_STR_SZ+1);
    x11session->x11_auth_protocol[MAX_X11_AUTH_PROTO_STR_SZ] = '\0';
    if(strncmp(x11session->x11_auth_protocol,"MIT-MAGIC-COOKIE-1",MAX_X11_AUTH_PROTO_STR_SZ+1) == 0)
      { 
      x11session->x11_auth_cookie = malloc(MAX_X11_AUTH_COOKIE_STR_SZ+2);
      strncpy(x11session->x11_auth_cookie,ssh_message_channel_request_x11_auth_cookie(message),MAX_X11_AUTH_COOKIE_STR_SZ+1);
      x11session->x11_auth_cookie[MAX_X11_AUTH_COOKIE_STR_SZ] = '\0';
      x11session->screen_number = ssh_message_channel_request_x11_screen_number(message);
      x11session->single_connection = ssh_message_channel_request_x11_single_connection(message);
      }
    else
      return 0;

    ret = session_setup_x11fwd(session,x11session,socket);
    if(ret == 0)
      {
      printf("\nsession_setup_x11fwd failed");
      return 0;
      }

    printf("\nx11_auth_protocol=%s\nx11_auth_cookie=%s\nscreen_number = %d\nsingle_connection =  %d\ndisplay_number = %d\n",x11session->x11_auth_protocol,x11session->x11_auth_cookie,x11session->screen_number,x11session->single_connection,x11session->display_number);

    snprintf(strxauth_exec,199,"%s remove :%d",xauth_path,x11session->display_number);
    printf("\nstrxauth_exec = %s",strxauth_exec);

    fpxauth = popen(strxauth_exec,"r");
    if(fpxauth == NULL)
      return 0;
    pclose(fpxauth);

    strxauth_exec[0] = '\0';
    snprintf(strxauth_exec,199,"%s add unix:%d %s %s",xauth_path,x11session->display_number,x11session->x11_auth_protocol,x11session->x11_auth_cookie);
    printf("\nstrxauth_exec = %s",strxauth_exec);

    fpxauth = popen(strxauth_exec,"r");
    if(fpxauth == NULL)
      return 0;
    pclose(fpxauth);

    return ret;
}



int session_setup_x11fwd(ssh_session session,x11_session* x11session,int *socket)
{
    int ret = 1;

    ret = x11_create_display_inet(session,&x11session->display_number,socket);
    if(ret == 0)
      {
      printf("\nx11_create_display_inet failed");
      return 0;
      }

    return ret;
}

int x11_create_display_inet(ssh_session session,unsigned int *display_numberp, int *sockets)
{
    int ret = 1;
    int display_num = 0,sock = 0,num_socks = 0;
    unsigned int port = 0;
    struct addrinfo hints, *ai, *aitop;
    char strport[NI_MAXSERV];
    int gaierr,n,socks[NUM_SOCKS];
    static int x11_display_offset = 10; //jeetu - temporarily hardcoded here

    printf("\nx11_create_display_inet: x11_display_offset = %d\n",x11_display_offset);    
    for(display_num = x11_display_offset; display_num < MAX_DISPLAYS; display_num++)
       {
       port = 6000 + display_num;
       hints.ai_family = AF_INET;
       hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE;
       hints.ai_socktype = SOCK_STREAM;
       hints.ai_protocol = 0;
       //snprintf(strport, sizeof strport, "%d", port);
	   sprintf(strport, "%d", port);
       if((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0)
	 {
         printf("\ngetaddrinfo: %s",gai_strerror(gaierr));
         return 0;
         }

       for(ai = aitop; ai; ai = ai->ai_next)
          {
	  if(ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
	    continue;
          sock = socket(ai->ai_family, ai->ai_socktype,ai->ai_protocol);
	  if(sock < 0)
            {
	    if((errno != EINVAL) && (errno != EAFNOSUPPORT))
              {
	      printf("\nsocket error: %s", strerror(errno));
	      freeaddrinfo(aitop);
	      return 0;
	      }
            else
              {
	      printf("\nx11_create_display_inet: Socket family %d not supported",ai->ai_family);
	      continue;
              }
            }
//          if(ai->ai_family == AF_INET6)
//	    sock_set_v6only(sock);
//	  if(x11_use_localhost)
//	    channel_set_reuseaddr(sock);
	  if(bind(sock, ai->ai_addr, ai->ai_addrlen) < 0)
            {
	    printf("bind port %d: %s", port, strerror(errno));
            close(sock);
            for(n = 0; n < num_socks; n++) 
               {
	       close(socks[n]);
	       }
            num_socks = 0;
            break;
            }
          socks[num_socks++] = sock;
	  if(num_socks == NUM_SOCKS)
	    break;
          }
       freeaddrinfo(aitop);
       if(num_socks > 0)
	 break;
       }    

    if(display_num >= MAX_DISPLAYS) 
      {
      printf("\nFailed to allocate internet-domain X11 display socket.");
      return 0;
      }
 
    // Start listening for connections on the socket. 
    for(n = 0; n < num_socks; n++) 
       {
       sock = socks[n];
       *(sockets+n) = sock;
       if(listen(sock, SSH_LISTEN_BACKLOG) < 0) 
         {
	 printf("\nlisten: %s", strerror(errno));
	 close(sock);
	 return 0;
	 }
       }

    *display_numberp = display_num;
    x11_display_offset++;
    return ret;
}
*/

/*
int wait_for_something(ssh_session session,int socket)
{
    fd_set infds, testfds;
    struct timeval tv = { 15, 0 };
    int maxfds = 0;
    int nready;
    int client_sock, cli_len;
    struct sockaddr_in cli_addr;
    ssh_event event;
    short events;
    ssh_channel chan_x11=0;

    struct ssh_channel_callbacks_struct cb = 
	{
    	.channel_data_function = copy_chan_to_fd,
    	.channel_eof_function = chan_close,
    	.channel_close_function = chan_close,
	.userdata = NULL 
	};
    
    FD_ZERO(&infds);
    FD_SET(socket, &infds);
    printf("\nwait_for_something: socket = %d\n",socket);
    maxfds = socket;    

    testfds = infds;
    printf("\nwait_for_something: before select\n");
    tv.tv_sec = 15;
    nready = select(maxfds + 1, &testfds, NULL, NULL, &tv);
    if(nready == -1)
      {
      printf("\nselect error: %s\n",strerror(errno));
      }
    if(nready > 0)
      {
      printf("\nwait_for_something: nready > 0");
      if(FD_ISSET(socket, &testfds))
        {
        printf("\nFD_ISSET\n");
        cli_len = sizeof (cli_addr);
	bzero((char *) &cli_addr, sizeof (cli_addr));	
	client_sock = accept(socket, (struct sockaddr *) &cli_addr, (socklen_t *) &cli_len);
        printf("\nclient_sock = %d",client_sock);
        chan_x11 = ssh_channel_new(session);
        if(ssh_channel_open_x11(chan_x11,"127.0.0.1",client_sock) == SSH_ERROR)
          {
          printf("ssh_channel_open_x11 error : %s\n",ssh_get_error(chan_x11));
          return 0;
          }
        else
          printf("\nssh_channel_open_x11\n");

        cb.userdata = &client_sock;
        ssh_callbacks_init(&cb);
        ssh_set_channel_callbacks(chan_x11, &cb);
	events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
        event = ssh_event_new();
        if(event == NULL) 
          {
          printf("Couldn't get a event\n");
          return 0;
          }
        else
          printf("\nevent != NULL");

        if(ssh_event_add_fd(event, client_sock, events, copy_fd_to_chan, chan_x11) != SSH_OK) 
          {
          printf("Couldn't add an fd to the event\n");
	  return 0;
          }
        else
          printf("\nAdded fd to event");

        if(ssh_event_add_session(event, session) != SSH_OK) 
          {
          printf("Couldn't add the session to the event\n");
          return 0;
          }
        else
          printf("\nadded the session to the event\n");
  
        do {
           ssh_event_dopoll(event, 1000);
           } while(!ssh_channel_is_closed(chan_x11));
        printf("\nssh_channel_open_x11: channel closed\n");
//             ssh_event_remove_fd(event, client_sock);
//             ssh_event_remove_session(event, data->session);
//             ssh_event_free(event);
        }
      }
    printf("\nexiting wait_for_something\n");
    return 1;
}
*/

static int copy_fd_to_chan(socket_t fd, int revents, void *userdata) 
{
    ssh_channel chan = (ssh_channel)userdata;
    char buf[2048];
    int sz = 0;
    buf[0] = '\0';    

    if(!chan) {
        close(fd);
        return -1;
    }
    if(revents & POLLIN) {
        sz = read(fd, buf, 2048);        
        if(sz == 0)
          {
          ssh_channel_close(chan);
          close(fd);
          sz = -1;
          }
        if(sz > 0) {
            ssh_channel_write(chan, buf, sz);
        }
    }
    if(revents & POLLHUP) {
        ssh_channel_close(chan);
        sz = -1;
    }
    return sz;
}


static int copy_chan_to_fd(ssh_session session,
                                           ssh_channel channel,
                                           void *data,
                                           uint32_t len,
                                           int is_stderr,
                                           void *userdata) 
{
    int fd = *(int*)userdata;
    int sz;
    (void)session;
    (void)channel;
    (void)is_stderr;

    sz = write(fd, data, len);

    return sz;
}

static void chan_close(ssh_session session, ssh_channel channel, void *userdata) 
{
    int fd = *(int*)userdata;
    (void)session;
    (void)channel;

    close(fd);
}


int exec_command(const char *command,x11_session* x11session)
//static gpointer exec_command(gpointer data)
{
    FILE *fpcmd;
    char str_exec[256]; //jeetu - buffer size sufficient?; command name may be larger; ideally not fixed
//    char *env[256] = {"DISPLAY=:10",NULL};
//    char *argv[256] = {"/bin/sh","-c","xcalc",NULL};

    str_exec[0] = '\0';
//    snprintf(str_exec,199,"%s -display :%d",command,x11session->display_number);
    //snprintf(str_exec,256,"/bin/sh -c \"export DISPLAY=:%d;%s\"",x11session->display_number,command);
	//sprintf(str_exec, "/bin/sh -c \"export DISPLAY=:%d;%s\"", x11session->display_number,command);
   // fpcmd = popen(str_exec,"r");
    if(fpcmd == NULL)
      return 0;
//    execve("/bin/sh",argv,env);    

    return 1;
//    return NULL;
}


int wait_for_something(ssh_session session,int socket)
{
    fd_set infds, testfds;
    struct timeval tv = { 15, 0 };
    int maxfds = 0;
    int nready;
    int x11datacount = 0;
    int client_sock,cli_len;
    struct sockaddr_in cli_addr;

    x11conndata = malloc(sizeof(x11data)); //jeetu - memory to be freed

    while(1)
         {
         FD_ZERO(&infds);
         FD_SET(socket, &infds);
         printf("\nwait_for_something: socket = %d\n",socket);
         maxfds = socket;    

         testfds = infds;
         printf("\nwait_for_something: before select\n");
         tv.tv_sec = 15;
         nready = select(maxfds + 1, &testfds, NULL, NULL, &tv);
         if(nready == -1)
           {
           printf("\nselect error: %s\n",strerror(errno));
           }
         if(nready > 0)
           {
           printf("\nwait_for_something: nready > 0");
           if(FD_ISSET(socket, &testfds))
             {
             printf("\nFD_ISSET\n");
             x11conndata[x11datacount] = malloc(sizeof(x11data));
             cli_len = sizeof (cli_addr);
	     //bzero((char *) &cli_addr, sizeof (cli_addr));	
	     client_sock = accept(socket, (struct sockaddr *) &cli_addr,  &cli_len);
             printf("\nclient_sock = %d",client_sock);
             x11conndata[x11datacount]->session = session;
             x11conndata[x11datacount]->client_sock = client_sock;
             //g_thread_create(process_x11_channel_events_thread,x11conndata[x11datacount],FALSE,NULL);
             x11datacount++;
             }
           }
         }
    printf("\nexiting wait_for_something\n");
    return 1;
}

/*
static gpointer process_x11_channel_events_thread(gpointer x11conndata)
{
    ssh_event event;
    short events;
    ssh_channel chan_x11=0;
    int client_sock;
    x11data *data = (x11data *) x11conndata;

    struct ssh_channel_callbacks_struct cb = 
	{
    	.channel_data_function = copy_chan_to_fd,
    	.channel_eof_function = chan_close,
    	.channel_close_function = chan_close,
	.userdata = NULL 
	};

    client_sock = data->client_sock;
    chan_x11 = ssh_channel_new(data->session);
    if(ssh_channel_open_x11(chan_x11,"127.0.0.1",client_sock) == SSH_ERROR)
      {
      printf("ssh_channel_open_x11 error : %s\n",ssh_get_error(chan_x11));
      return NULL;
      }
    else
      printf("\nssh_channel_open_x11\n");

    cb.userdata = &client_sock;
    ssh_callbacks_init(&cb);
    ssh_set_channel_callbacks(chan_x11, &cb);
    events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
    event = ssh_event_new();
    if(event == NULL) 
      {
      printf("Couldn't get a event\n");
      return NULL;
      }
    else
      printf("\nevent != NULL");

    if(ssh_event_add_fd(event, client_sock, events, copy_fd_to_chan, chan_x11) != SSH_OK) 
      {
      printf("Couldn't add an fd to the event\n");
      return NULL;
      }
    else
      printf("\nAdded fd to event");

    if(ssh_event_add_session(event, data->session) != SSH_OK) 
      {
      printf("Couldn't add the session to the event\n");
      return NULL;
      }
    else
      printf("\nadded the session to the event\n");
 
    do {
       ssh_event_dopoll(event, 1000);
       } while(!ssh_channel_is_closed(chan_x11));
    printf("\nssh_channel_open_x11: channel closed\n");
//             ssh_event_remove_fd(event, client_sock);
//             ssh_event_remove_session(event, data->session);
//             ssh_event_free(event);

    return NULL;
}
*/
#include <iostream>

using namespace std;

#include"libssh/libssh.h"
#include"libssh/server.h"
#include"libssh/callbacks.h"
#include"libssh/legacy.h"
#include"libssh/sftp.h"
#include"libssh/ssh2.h"

#include <string.h>
#include <ctype.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <io.h>
//#include <unistd.h>

int verify_knownhost(ssh_session session);
char *getpass(char *data);
int interactive_shell_session(ssh_channel channel);

const int port = 2000;//22010;

int main(void)
{
    ssh_session session;
	int iError;
	char *password;
	ssh_channel channel;

	iError = ssh_init();

	if(iError == SSH_ERROR)
	{
		cout<<"Error Libssh init failed";
		return 0;
	}

	session = ssh_new();

	if(session == NULL)
	{
		cout<<"Session is null";
		return 0;
	}

	ssh_options_set(session, SSH_OPTIONS_HOST, "127.0.0.1");
	ssh_options_set(session, SSH_OPTIONS_PORT, &port);

	if(iError < 0)
	{
		cout<<"ssh set options failed "<<ssh_get_error(session);
		return 0;
	}

	iError = ssh_connect(session);

	if(iError < 0 )
	{
		printf("Error while connecting to server at local host %s", ssh_get_error(session));
		return 0;
	}

	//iError = verify_knownhost(session);
	// Verify the server's identity
	// For the source code of verify_knowhost(), check previous example
	if (verify_knownhost(session) < 0)
	{
		ssh_disconnect(session);
		ssh_free(session);
		exit(-1);
	}

	//request for Service request
	iError = ssh_service_request(session, "ssh-userauth");

	if(iError == -1)
	{
		printf("Error while sending ssh_service_request %s", ssh_get_error(session));
		return 0;
	}

	channel = ssh_channel_new(session);
	if (channel == NULL)
		return SSH_ERROR;
	
	iError = ssh_channel_open_session(channel);
	if (iError != SSH_OK)
	{
		ssh_channel_free(channel);
		return iError;
	}
	
	//request a channel
	interactive_shell_session(channel);

	 // Authenticate ourselves
	password = getpass("Password: ");
	iError = ssh_userauth_password(session, NULL, password);
	if (iError != SSH_AUTH_SUCCESS)
	{
		fprintf(stderr, "Error authenticating with password: %s\n", ssh_get_error(session));
		ssh_disconnect(session);
		ssh_free(session);
		exit(-1);
	}

	Sleep(10000);

	ssh_disconnect(session);
	ssh_free(session);

	return 0;
}

int verify_knownhost(ssh_session session)
{
int state, hlen;
  unsigned char *hash = NULL;
  char *hexa;
  char buf[10];
  state = ssh_is_server_known(session);
  hlen = ssh_get_pubkey_hash(session, &hash);
  if (hlen < 0)
    return -1;
  switch (state)
  {
    case SSH_SERVER_KNOWN_OK:
      break; /* ok */
    case SSH_SERVER_KNOWN_CHANGED:
      fprintf(stderr, "Host key for server changed: it is now:\n");
      ssh_print_hexa("Public key hash", hash, hlen);
      fprintf(stderr, "For security reasons, connection will be stopped\n");
      free(hash);
      return -1;
    case SSH_SERVER_FOUND_OTHER:
      fprintf(stderr, "The host key for this server was not found but an other"
        "type of key exists.\n");
      fprintf(stderr, "An attacker might change the default server key to"
        "confuse your client into thinking the key does not exist\n");
      free(hash);
      return -1;
    case SSH_SERVER_FILE_NOT_FOUND:
      fprintf(stderr, "Could not find known host file.\n");
      fprintf(stderr, "If you accept the host key here, the file will be"
       "automatically created.\n");
      /* fallback to SSH_SERVER_NOT_KNOWN behavior */
    case SSH_SERVER_NOT_KNOWN:
      hexa = ssh_get_hexa(hash, hlen);
      fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
      fprintf(stderr, "Public key hash: %s\n", hexa);
      free(hexa);
      if (fgets(buf, sizeof(buf), stdin) == NULL)
      {
        free(hash);
        return -1;
      }
      //if (strncasecmp(buf, "yes", 3) != 0)
      //{
        //free(hash);
        //return -1;
      //}
      if (ssh_write_knownhost(session) < 0)
      {
        fprintf(stderr, "Error %s\n", strerror(errno));
        free(hash);
        return -1;
      }
      break;
    case SSH_SERVER_ERROR:
      fprintf(stderr, "Error %s", ssh_get_error(session));
      free(hash);
      return -1;
  }
  free(hash);
  return 0;
}


char *getpass(char *data)
{
	char *pData = new char[50];
	//cout<<data;
	gets(pData);

	return pData;
}

int interactive_shell_session(ssh_channel channel)
{
  int rc;
  char buffer[256];
  int nbytes;
  rc = ssh_channel_request_pty(channel);
  if (rc != SSH_OK) 
	  return rc;
  rc = ssh_channel_change_pty_size(channel, 80, 24);
  if (rc != SSH_OK) 
	  return rc;
  rc = ssh_channel_request_shell(channel);
  if (rc != SSH_OK) 
	  return rc;
  while (ssh_channel_is_open(channel) &&
         !ssh_channel_is_eof(channel))
  {
    nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
    if (nbytes < 0)
      return SSH_ERROR;
    if (nbytes > 0)
      write(1, buffer, nbytes);	
  }
  return rc;
}

Archive administrator: postmaster@lists.cynapses.org