Subject: Issue in reading message sent from remote process

Issue in reading message sent from remote process

From: Narayani <drop2nanni_at_gmail.com>
Date: Wed, 3 Oct 2012 08:42:39 -0700

Hi

I am facing an issue while using libssh2. I used libssh2 channel write
to write data to a remote node. But I am not sure how to access this data
in the remote node. I tried using 'read' (not libssh2 read) from stdout
but it does not work.

Please refer source code below. main.cpp is running in master node and it
sends data to MProcess.cpp which runs in remote node. I am trying to read
this data in MProcess.cpp using 'read' from stdout, but it doesnt work.

Please take a look, and let me know

/*********main.cpp**********/

#include<iostream>
#include "MNode.h"

using namespace std;

int sock;
LIBSSH2_SESSION *session;

const char *keyfile1="~/.ssh/id_rsa.pub";
const char *keyfile2="~/.ssh/id_rsa";
const char *username="username";
const char *password="password";

static void kbd_callback(const char *name, int name_len,
                         const char *instruction, int instruction_len,
                         int num_prompts,
                         const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
                         LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
                         void **abstract)
{
    (void)name;
    (void)name_len;
    (void)instruction;
    (void)instruction_len;
    if (num_prompts == 1) {
        responses[0].text = strdup(password);
        responses[0].length = strlen(password);
    }
    (void)prompts;
    (void)abstract;
} /* kbd_callback */

static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
{
    struct timeval timeout;
    int rc;
    fd_set fd;
    fd_set *writefd = NULL;
    fd_set *readfd = NULL;
    int dir;

    timeout.tv_sec = 10;
    timeout.tv_usec = 0;

    FD_ZERO(&fd);

    FD_SET(socket_fd, &fd);

    /* now make sure we wait in the correct direction */
    dir = libssh2_session_block_directions(session);

    if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
        readfd = &fd;

    if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
        writefd = &fd;

    rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);

    return rc;
}

LIBSSH2_CHANNEL * LaunchRemoteProcess(char *cmd){
   const char *hostname = "127.0.0.1";
   const char *commandline = "uptime";
   const char *username = "user";
   const char *password = "password";

     /**************************/
    unsigned long hostaddr;
    int rc, i, auth_pw = 0;
    struct sockaddr_in sin;
    const char *fingerprint;
    char *userauthlist;
    //LIBSSH2_SESSION *session;
    LIBSSH2_CHANNEL *channel;
#ifdef WIN32
    WSADATA wsadata;

    WSAStartup(MAKEWORD(2,0), &wsadata);
#endif

    /*if (argc > 1) {
        hostaddr = inet_addr(argv[1]);
    } else {
        hostaddr = htonl(0x7F000001);
    }*/
    hostaddr = inet_addr("69.91.198.171");

    //if(argc > 2) {
        username = "user";
    //}
    //if(argc > 3) {
        password = "password";
    //}

    rc = libssh2_init (0);

    if (rc != 0) {
        fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
        //return 1;
    }

    /* Ultra basic "connect to port 22 on localhost". Your code is
     * responsible for creating the socket establishing the connection
     */
    sock = socket(AF_INET, SOCK_STREAM, 0);

    sin.sin_family = AF_INET;
    sin.sin_port = htons(22);
    sin.sin_addr.s_addr = hostaddr;
    if (connect(sock, (struct sockaddr*)(&sin),
                sizeof(struct sockaddr_in)) != 0) {
        fprintf(stderr, "failed to connect!\n");
       // return -1;
    }

    /* Create a session instance and start it up. This will trade welcome
     * banners, exchange keys, and setup crypto, compression, and MAC layers
     */
    session = libssh2_session_init();

    if (libssh2_session_handshake(session, sock)) {

        fprintf(stderr, "Failure establishing SSH session\n");
       // return -1;
    }

    /* At this point we havn't authenticated. The first thing to do is check
     * the hostkey's fingerprint against our known hosts Your app may have
it
     * hard coded, may go to a file, may present it to the user, that's your
     * call
     */
    fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);

    printf("Fingerprint: ");
    for(i = 0; i < 20; i++) {
        printf("%02X ", (unsigned char)fingerprint[i]);
    }
    printf("\n");

    /* check what authentication methods are available */
    userauthlist = libssh2_userauth_list(session, username,
strlen(username));

    printf("Authentication methods: %s\n", userauthlist);
    if (strstr(userauthlist, "password") != NULL) {
        auth_pw |= 1;
    }
    if (strstr(userauthlist, "keyboard-interactive") != NULL) {
        auth_pw |= 2;
    }
    if (strstr(userauthlist, "publickey") != NULL) {
        auth_pw |= 4;
    }

    /* if we got an 4. argument we set this option if supported */
  /* if(argc > 4) {
        if ((auth_pw & 1) && !strcasecmp(argv[4], "-p")) {
            auth_pw = 1;
        }
        if ((auth_pw & 2) && !strcasecmp(argv[4], "-i")) {
            auth_pw = 2;
        }
        if ((auth_pw & 4) && !strcasecmp(argv[4], "-k")) {
            auth_pw = 4;
        }
    }*/

    if (auth_pw & 1) {
        /* We could authenticate via password */
        if (libssh2_userauth_password(session, username, password)) {

            printf("\tAuthentication by password failed!\n");
            //goto shutdown;
        } else {
            printf("\tAuthentication by password succeeded.\n");
        }
    } else if (auth_pw & 2) {
        /* Or via keyboard-interactive */
        if (libssh2_userauth_keyboard_interactive(session, username,

                                                  &kbd_callback) ) {
            printf("\tAuthentication by keyboard-interactive failed!\n");
            //goto shutdown;
        } else {
            printf("\tAuthentication by keyboard-interactive succeeded.\n");
        }
    } else if (auth_pw & 4) {
        /* Or by public key */
        if (libssh2_userauth_publickey_fromfile(session, username, keyfile1,

                                                keyfile2, password)) {
            printf("\tAuthentication by public key failed!\n");
            //goto shutdown;
        } else {
            printf("\tAuthentication by public key succeeded.\n");
        }
    } else {
        printf("No supported authentication methods found!\n");
        //goto shutdown;
    }

    /* Request a shell */
    if (!(channel = libssh2_channel_open_session(session))) {

        fprintf(stderr, "Unable to open a session\n");
        //goto shutdown;
    }

    /* Some environment variables may be set,
     * It's up to the server which ones it'll allow though
     */
    libssh2_channel_setenv(channel, "FOO", "bar");

    /* Request a terminal with 'vanilla' terminal emulation
     * See /etc/termcap for more options
     */
    if (libssh2_channel_request_pty(channel, "vanilla")) {

        fprintf(stderr, "Failed requesting pty\n");
        //goto skip_shell;
    }

    /* Open a SHELL on that pty */
    if (libssh2_channel_shell(channel)) {

        fprintf(stderr, "Unable to request shell on allocated pty\n");
        //goto shutdown;
    }
        /***********/
   return channel;
}

int main(){

 MNode *m = new MNode;
 LIBSSH2_CHANNEL *channel;
 int bytecount = 0;
 int rc;
 printf("main");
 //channel = E
 char *cmd= "Mprocess";
 //cout<<"Into remote proc exec"<endl;
 channel = LaunchRemoteProcess(cmd);
 if (channel == NULL) {

         fprintf(stderr, "No channel");
         //goto shutdown;
    }
 //cout<<"exec done"<<endl;
 printf("exec done\n");

 m->channel = channel;

 if (m->channel == NULL) {

          fprintf(stderr, "No channel");
          //goto shutdown;
    }

    printf("starting exec\n");
    while( (channel = libssh2_channel_open_session(session)) == NULL &&
            libssh2_session_last_error(session,NULL,NULL,0) ==
            LIBSSH2_ERROR_EAGAIN )
     {
         waitsocket(sock, session);
     }
     if( channel == NULL )
     {
         fprintf(stderr,"Error\n");
         exit( 1 );
     }
     while( (rc = libssh2_channel_exec(channel, cmd)) ==
            LIBSSH2_ERROR_EAGAIN )
     {
         waitsocket(sock, session);
     }
     if( rc != 0 )
     {
         fprintf(stderr,"Error\n");
         exit( 1 );
    }
     printf( "Mprocess launched and now will send a message\n" );

 m->sendMessage();

    //channel = LaunchRemoteProcess(cmd);
    /**************/
        for( ;; )
     {
         /* loop until we block */
         int rc;
         do
         {
             char buffer[0x4000];
             rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
             if( rc > 0 )
             {
                 int i;
                 bytecount += rc;
                 fprintf(stderr, "We read:\n");
                 for( i=0; i < rc; ++i )
                     fputc( buffer[i], stderr);
                 fprintf(stderr, "\n");
             }
             else {
                 if( rc != LIBSSH2_ERROR_EAGAIN )
                     /* no need to output this for the EAGAIN case */
                     fprintf(stderr, "libssh2_channel_read returned %d\n",
rc);
             }
         }
         while( rc > 0 );

         /* this is due to blocking that would occur otherwise so we loop on
            this condition */
         if( rc == LIBSSH2_ERROR_EAGAIN )
         {
                printf("Waiting for message \n");
             waitsocket(sock, session);
         }
         else
             break;
    }

 return 0;

}

/*****************************************************************************************************************************************/

/***************MNode.h*******************/

#include "libssh2_config.h"
#include <libssh2.h>

#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif

#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>

//#define BUFSIZE 32000
#define BUFSIZE 320

class MNode
{
 //private:
 //string hostName;
 //int pid;

 //LIBSSH2_CHANNEL *channel;
 public :
 LIBSSH2_CHANNEL *channel;
 void sendMessage(){
   // int bufsize = BUFSIZE;
  int i;
        char buffer[BUFSIZE];
        for (i = 0; i < BUFSIZE; i++)
            buffer[i] = 'A';
        printf("Into lib write \n");
        if (channel == NULL) {

           fprintf(stderr, "No mNode channel");
           //goto shutdown;
    }
        int n = libssh2_channel_write_ex(channel, 0, buffer,
sizeof(buffer));
 libssh2_channel_flush_ex( channel, 0 );
        printf("%d \n",n);

 }
 void receiveMessage(){
 }

};
/**********************************************************************************************************************************/

/**********MProcess.cpp**************/

/*#include<iostream>
#include<string.h>
using namespace std;
int main(){
  std::string s;
printf("Into remote proc exec");

 while(true) {
  getline( cin, s );

     fprintf(stderr,"%s",s.c_str());
     break;
    // flag=false;
  }
  //write(1,buffer,sizeof(buffer));
   // printf("test Nani");
 return 0;
}
*/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include<string>
#include<iostream>
using namespace std;
int main()
{
  char s[320];
  printf("Into remote proc exec\n");
  bzero(s,320);
    printf("message\n");
    fflush( stdout );
    read( 0, s, 20 );
    printf( "read 20 bytes\n" );
    fflush( stdout );
    return 0;
}

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2012-10-03