0 votes
by (160 points)

Hi Lukas,

Unfortunately I may have the following problem. We recently added the following code to our client application, which you'll recall makes calls to libssh2 library to speak with the rebex server:

sftp = libssh2_sftp_init(session);
if (!sftp)  { (error handling) }

if (scanner_stats)
{
       **s = libssh2_sftp_statvfs (sftp, "/", strlen("/"), scanner_stats);**
   if(s != 0) { (error handling) }
}

if (sftp)
{
libssh2_sftp_shutdown(sftp);
}

The problematic code is the bolded call to libssh2_sftp_statvfs(). When I look at the logs for the Rebex server (available here: https://app.box.com/s/32vddysqz87q6h38hw22e32t0de3cwzz), I see:

2023-05-22 16:00:24.745 VERBOSE FileServer(1)[20] SSH: Session 1: Sent packet SSHMSGCHANNEL_DATA (61 bytes).
2023-05-22 16:00:24.745 LEVEL0 FileServer(1)[20] SSH: Sent packet data:
0000 |5E-00-00-00-01-00-00-00 34-00-00-00-30-65-00-00| ^.......4...0e..
0010 |00-00-00-00-00-08-00-00 00-1F-45-78-74-65-6E-64| ..........Extend
0020 |65-64-20-72-65-71-75-65 73-74-20-6E-6F-74-20-73| ed request not s
0030 |75-70-70-6F-72-74-65-64 2E-00-00-00-00 | upported.....

When this happens, the call into the libssh2 library doesn't return/hangs. Would you think this is a problem with the rebex server's code in some regard?

Yours,

Ron

1 Answer

0 votes
by (1.2k points)

Hello Ron,
I have tried to reproduce the issue but I could not. When I run this code it fails with expected message Failed to get SFTP statistics: -31. (the hardcoded values are for test.rebex.net test server)
I am on Arch Linux using
kernel 6.3.2
glibc 2.37
libssh2 1.10.0-3

compiled with gcc sftp_test.c -lssh2 -o sftp_test

#include <libssh2.h>
#include <libssh2_sftp.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() {
    // Initialize libssh2
    int rc = libssh2_init(0);
    if (rc != 0) {
        fprintf(stderr, "Failed to initialize libssh2: %d\n", rc);
        return 1;
    }

    // Connect to the remote host
    LIBSSH2_SESSION *session = libssh2_session_init();
    if (!session) {
        fprintf(stderr, "Failed to create session\n");
        return 1;
    }

    // Set up your connection details
    const char *host = "194.108.117.16";
    int port = 22;
    const char *username = "demo";
    const char *password = "password";

    // Create a socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        fprintf(stderr, "Failed to create socket\n");
        return 1;
    }

    // Set up the remote host address
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    if (inet_pton(AF_INET, host, &(server_addr.sin_addr)) <= 0) {
        fprintf(stderr, "Invalid address or address not supported\n");
        return 1;
    }

    // Connect to the remote host
    if (connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
        fprintf(stderr, "Failed to connect to the remote host\n");
        return 1;
    }

    // Attach the socket to the libssh2 session
    rc = libssh2_session_startup(session, sock);
    if (rc != 0) {
        fprintf(stderr, "Failed to establish SSH connection: %d\n", rc);
        return 1;
    }

    // Authenticate with the remote host using password
    rc = libssh2_userauth_password(session, username, password);
    if (rc != 0) {
        fprintf(stderr, "Failed to authenticate: %d\n", rc);
        return 1;
    }

    // Open an SFTP session
    LIBSSH2_SFTP *sftp_session = libssh2_sftp_init(session);
    if (!sftp_session) {
        fprintf(stderr, "Failed to initialize SFTP session\n");
        return 1;
    }


    LIBSSH2_SFTP_STATVFS scanner_stats;
    rc = libssh2_sftp_statvfs(sftp_session, "/", strlen("/"), &scanner_stats);
    if (rc != 0) {
        fprintf(stderr, "Failed to get SFTP statistics: %d\n", rc);
        libssh2_sftp_shutdown(sftp_session);
        return 1;
    }


    // Close the SFTP session
    libssh2_sftp_shutdown(sftp_session);

    // Disconnect from the remote host
    libssh2_session_disconnect(session, "Normal shutdown");
    libssh2_session_free(session);

    // Clean up libssh2
    libssh2_exit();

    return 0;
}

Alexandr Pleskot

by (160 points)
Hello Alexandr,

I regret that I didn't mention that I'm running on/using the Windows (.NET 4.5.2) version of Rebex.  I might also mention that we have not been keeping up with the libssh2 library changes; we're using version 1.4.2, so that may be where the real problem lies.

Thank you for looking into this for us.

Ron
by (1.2k points)
Hello Ron,

can I ask you how the script I sent behaved in your enviroment (with your version of libssh). Or how did your code behave with new version of libssh (if it compiles).

Alexandr Pleskot
by (160 points)
The script I used (slightly different than yours, reproduced below), with the old version of LibSSH2 acted the same way as our other code, which is to say, it hangs.

I used the same script with the latest version of LibSSH2 (1.10.0) and OpenSSL (version 3.1.0) and it returns a -31 value (LIBSSH2_ERROR_SFTP_PROTOCOL) from libssh2_sftp_statvfs, and an 8 from a subsequent call to libssh2_sftp_last_error, meaning Operation Unsupported.

All of these were run as 32-bit x86 executables/DLLs.

Here's the version of the script I used:

// Libssh2Test.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <libssh2.h>
#include <libssh2_sftp.h>
#include <stdio.h>
#include <string.h>
#include <ws2tcpip.h>
#if asfd
#include <socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

int main() {
    // Initialize libssh2
    int rc = libssh2_init(0);
    if (rc != 0) {
        fprintf(stderr, "Failed to initialize libssh2: %d\n", rc);
        return 1;
    }

    // Connect to the remote host
    LIBSSH2_SESSION* session = libssh2_session_init();
    if (!session) {
        fprintf(stderr, "Failed to create session\n");
        return 1;
    }

    // Set up your connection details
    const char* host = "10.124.100.37";
    int port = 22;
    const char* username = "laser";
    const char* password = "password";

    WORD wVersionRequested = MAKEWORD(2, 2);
    WSADATA wsaData;
    auto errWSAStartup = WSAStartup(wVersionRequested, &wsaData);
    if (errWSAStartup != 0)
    {
        printf("WSAStartup failed with error: %d\n", errWSAStartup);  // Tell the user that we could not find a usable Winsock DLL.
        return 1;
    }

    // Create a socket
    auto sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        auto error = WSAGetLastError();
        fprintf(stderr, "Failed to create socket %d\n", error);
        return 1;
    }

    // Set up the remote host address
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    if (inet_pton(AF_INET, host, &(server_addr.sin_addr)) <= 0) {
        fprintf(stderr, "Invalid address or address not supported\n");
        return 1;
    }

    // Connect to the remote host
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        fprintf(stderr, "Failed to connect to the remote host\n");
        return 1;
    }

    // Attach the socket to the libssh2 session
    rc = libssh2_session_startup(session, sock);
    if (rc != 0) {
        fprintf(stderr, "Failed to establish SSH connection: %d\n", rc);
        return 1;
    }

    // Authenticate with the remote host using password
    auto    rc2 = libssh2_userauth_password(session, username, password);
    if (rc2 != 0) {
        fprintf(stderr, "Failed to authenticate: %d\n", rc);
        return 1;
    }

    // Open an SFTP session
    LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session);
    if (!sftp_session) {
        fprintf(stderr, "Failed to initialize SFTP session\n");
        return 1;
    }


    LIBSSH2_SFTP_STATVFS scanner_stats;
    rc = libssh2_sftp_statvfs(sftp_session, "/", strlen("/"), &scanner_stats);
    if (rc != 0) {
        unsigned long lastError = 0;
        if (rc == LIBSSH2_ERROR_SFTP_PROTOCOL)
        {
            lastError = libssh2_sftp_last_error(sftp_session);
        }
        fprintf(stderr, "Failed to get SFTP statistics: %d %ld\n", rc, lastError);
        libssh2_sftp_shutdown(sftp_session);
        return 1;
    }


    // Close the SFTP session
    libssh2_sftp_shutdown(sftp_session);

    // Disconnect from the remote host
    libssh2_session_disconnect(session, "Normal shutdown");
    libssh2_session_free(session);

    // Clean up libssh2
    libssh2_exit();

    WSACleanup();
    return 0;
}

extern "C" { FILE __iob_func[3] = { *stdin,*stdout,*stderr }; }
by (1.2k points)
The hanging appears to be a flaw within the previous iteration of libssh2.
The "unsupported operation" error occurs because the component currently lacks this particular extension, although there are plans for its implementation in the future.
by (160 points)
Yes, it does.

Thanks for your help.
...