Hi,

sftp_RW_nonblock.c does not handle LIBSSH2_ERROR_EAGAIN, which causes
the password authentication to fail.  I fixed the example by taking the 
appropriate code from sftp_nonblock.c.  Note that sftp_nonblock.c does
not call select() while looping around libssh2_session_handshake(), 
libssh2_userauth_password(), libssh2_userauth_publickey_fromfile() and 
libssh2_session_disconnect() -- is that intentionally?  (the call of 
libssh2_userauth_publickey_fromfile() is dead code anyway...)

Kamil
From 19bcd604ed41540950f59944bea1913db39ae646 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <[email protected]>
Date: Mon, 24 Oct 2011 16:21:25 +0200
Subject: [PATCH] example/sftp_RW_nonblock: do not ignore LIBSSH2_ERROR_EAGAIN

Bug: https://bugzilla.redhat.com/745420
---
 example/sftp_RW_nonblock.c |   89 +++++++++++++++++++++++++++++++++++--------
 1 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/example/sftp_RW_nonblock.c b/example/sftp_RW_nonblock.c
index 8cb241f..babb48a 100644
--- a/example/sftp_RW_nonblock.c
+++ b/example/sftp_RW_nonblock.c
@@ -43,6 +43,36 @@
                                        example uses to store the downloaded
                                        file in */
 
+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;
+}
+
 int main(int argc, char *argv[])
 {
     int sock, i, auth_pw = 1;
@@ -138,36 +168,61 @@ int main(int argc, char *argv[])
 
     if (auth_pw) {
         /* We could authenticate via password */
-        if (libssh2_userauth_password(session, username, password)) {
+        while ((rc = libssh2_userauth_password(session, username, password))
+               == LIBSSH2_ERROR_EAGAIN);
+        if (rc) {
             printf("Authentication by password failed.\n");
             goto shutdown;
         }
     } else {
         /* Or by public key */
-        if (libssh2_userauth_publickey_fromfile(session, username,
-                                                "/home/username/.ssh/id_rsa.pub",
-                                                "/home/username/.ssh/id_rsa",
-                                                password)) {
+        while ((rc =
+                libssh2_userauth_publickey_fromfile(session, username,
+                                                    "/home/username/"
+                                                    ".ssh/id_rsa.pub",
+                                                    "/home/username/"
+                                                    ".ssh/id_rsa",
+                                                    password)) ==
+               LIBSSH2_ERROR_EAGAIN);
+        if (rc) {
             printf("\tAuthentication by public key failed\n");
             goto shutdown;
         }
     }
 
-    sftp_session = libssh2_sftp_init(session);
+    do {
+        sftp_session = libssh2_sftp_init(session);
 
-    if (!sftp_session) {
-        fprintf(stderr, "Unable to init SFTP session\n");
-        goto shutdown;
-    }
+        if(!sftp_session) {
+            if(libssh2_session_last_errno(session) ==
+               LIBSSH2_ERROR_EAGAIN) {
+                fprintf(stderr, "non-blocking init\n");
+                waitsocket(sock, session); /* now we wait */
+            }
+            else {
+                fprintf(stderr, "Unable to init SFTP session\n");
+                goto shutdown;
+            }
+        }
+    } while (!sftp_session);
 
     /* Request a file via SFTP */
-    sftp_handle =
-        libssh2_sftp_open(sftp_session, sftppath, LIBSSH2_FXF_READ, 0);
+    do {
+        sftp_handle = libssh2_sftp_open(sftp_session, sftppath,
+                                        LIBSSH2_FXF_READ, 0);
+
+        if (!sftp_handle) {
+            if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
+                fprintf(stderr, "Unable to open file with SFTP\n");
+                goto shutdown;
+            }
+            else {
+                fprintf(stderr, "non-blocking open\n");
+                waitsocket(sock, session); /* now we wait */
+            }
+        }
+    } while (!sftp_handle);
 
-    if (!sftp_handle) {
-        fprintf(stderr, "Unable to open file with SFTP\n");
-        goto shutdown;
-    }
     fprintf(stderr, "libssh2_sftp_open() is done, now receive data!\n");
     do {
         do {
-- 
1.7.1

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Reply via email to