Subject: [libssh2] #285: multithread calls libssh2.a error

[libssh2] #285: multithread calls libssh2.a error

From: libssh2 Trac <trac_at_libssh2.stuge.se>
Date: Tue, 11 Feb 2014 09:39:19 -0000

#285: multithread calls libssh2.a error
-----------------------------------------------------+--------------------
 Reporter: beiguan001 | Owner:
     Type: defect | Status: new
 Priority: high | Milestone: 1.4.3
Component: API | Version: 1.4.2
 Keywords: multi-thread libssh2_session_handshake | Blocked By:
   Blocks: |
-----------------------------------------------------+--------------------
 When using multiple threads, in libssh2_session_handshake abnormal.
 If you do not multi-threaded, no problem.
 How to use multi-thread calls libssh2?

 //////////// main cpp//////////

 void* work_thread(void* arg)
 {

         string ipaddr = "132.31.0.13";
         string user = "user";
         string passwd = "pass";
         int port = 22;

         Ssh2Client ssh3;
     ssh3.setHost(ipaddr.c_str(), user.c_str(), passwd.c_str(), port);
     ssh3.setTimeOut(10000L);//10s

     if(ssh3.ssh2_connect() < 0)
         cout << "Error : connect error!" << endl;

         if(ssh3.ssh2_open_session() < 0)
         {
         cout << "Error : ssh2_open_session error!" << endl;
         exit(0);
     }

 }

 int main(int argc,char* argv[])
 {
         int nthread = 1;
         pthread_t tid;

         for(int i=0;i<nthread;i++)
         {
           pthread_create(&tid,NULL,work_thread,NULL);
         }

 }

 //////////////////////Ssh2Client.cpp
 void Ssh2Client::setHost(const char *host, const char *user, const char
 *passwd, int pt)
 {
         hostname = host;
         username = user;
         password = passwd;
         port = pt;
 }

 int Ssh2Client::ssh2_connect()
 {
         int rc = 0;
         unsigned long hostaddr;
         struct sockaddr_in sin;
 #ifdef WIN32
     WSADATA wsadata;
     WSAStartup(MAKEWORD(2,0), &wsadata);
 #endif

     rc = libssh2_init(0);
     if (rc != 0)
     {

                 sprintf(errmsg, "libssh2 initialization failed (%d)\n",
 rc);
         return -1;
     }

     thread_setup();

     hostaddr = inet_addr(hostname);
     sock = socket(AF_INET, SOCK_STREAM, 0);

     sin.sin_family = AF_INET;
     sin.sin_port = htons(port);
     sin.sin_addr.s_addr = hostaddr;
     if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct
 sockaddr_in)) != 0)
     {

         sprintf(errmsg, "failed to connect!\n");
         return -1;
     }
     return 0;
 }

 int Ssh2Client::ssh2_open_session()
 {
         int rc = 0;
   size_t len;
   LIBSSH2_KNOWNHOSTS *nh;
   int type;
         const char *fingerprint;

             /* Create a session instance */
     session = libssh2_session_init();
     if (!session)
         return -1;

 // libssh2_session_set_timeout(session, timeout);

     /* tell libssh2 we want it all done non-blocking */
 // libssh2_session_set_blocking(session, block);

     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
      */
     while ((rc = libssh2_session_handshake(session, sock)) ==
            LIBSSH2_ERROR_EAGAIN);
     if (rc)
     {
         printf("File = %s, Line = %d, rc = %d\n", __FILE__, __LINE__, rc);
         sprintf(errmsg, "Failure establishing SSH session: %d\n", rc);
         return -1;
     }

     nh = libssh2_knownhost_init(session);
     if(!nh) {
         /* eeek, do cleanup here */
         return -2;
     }

     /* read all hosts from here */
     libssh2_knownhost_readfile(nh, "known_hosts",
                                LIBSSH2_KNOWNHOST_FILE_OPENSSH);

     /* store all known hosts to here */
     libssh2_knownhost_writefile(nh, "dumpfile",
                                 LIBSSH2_KNOWNHOST_FILE_OPENSSH);

     fingerprint = libssh2_session_hostkey(session, &len, &type);
     if(fingerprint) {
         struct libssh2_knownhost *host;
 #if LIBSSH2_VERSION_NUM >= 0x010206
         /* introduced in 1.2.6 */
         int check = libssh2_knownhost_checkp(nh, hostname, 22,
                                              fingerprint, len,
                                              LIBSSH2_KNOWNHOST_TYPE_PLAIN|
                                              LIBSSH2_KNOWNHOST_KEYENC_RAW,
                                              &host);
 #else
         /* 1.2.5 or older */
         int check = libssh2_knownhost_check(nh, hostname,
                                             fingerprint, len,
                                             LIBSSH2_KNOWNHOST_TYPE_PLAIN|
                                             LIBSSH2_KNOWNHOST_KEYENC_RAW,
                                             &host);
 #endif

         sprintf(errmsg, "Host check: %d, key: %s\n", check,
                 (check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
                 host->key:"<none>");

         /*****
          * At this point, we could verify that 'check' tells us the key is
          * fine or bail out.
          *****/
     }
     else {
         /* eeek, do cleanup here */
         return -3;
     }
     libssh2_knownhost_free(nh);

     if ( strlen(password) != 0 ) {
         /* We could authenticate via password */
         while ((rc = libssh2_userauth_password(session, username,
 password)) ==
                LIBSSH2_ERROR_EAGAIN);
         if (rc)
         {

             sprintf(errmsg, "Authentication by password failed.\n");
             ssh2_free_session();
             ssh2_close();
             return -1;
         }
     }
     else {
         /* Or by public key */
         char *home = getenv("HOME");
         if(home == NULL)
         {

                 sprintf(errmsg,"HOME not defined\n");
                 return -1;
         }
         char path1[1024];
         char path2[1024];
         strcat(path1,home);
         strcat(path1,"/.ssh/id_rsa.pub");
         strcat(path2,home);
         strcat(path2,"/.ssh/id_rsa");
         free(home);
         while ((rc =
 libssh2_userauth_publickey_fromfile(session,username,path1,path2,password))
 ==
                LIBSSH2_ERROR_EAGAIN);
         if (rc)
         {

             sprintf(errmsg, "\tAuthentication by public key failed\n");
             ssh2_free_session();
             ssh2_close();
             return -1;
         }
     }

                 return 0;
 }

 ///////////////////////////////////////////////////////

-- 
Ticket URL: <https://trac.libssh2.org/ticket/285>
libssh2 <https://trac.libssh2.org/>
C library for writing portable SSH2 clients
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2014-02-11