Subject: Attempting to wrap sftp in Qt

Attempting to wrap sftp in Qt

From: Mark Roden <mmroden_at_gmail.com>
Date: Sun, 1 May 2011 15:21:37 -0700

Hi all,

I'm getting an error with trying to copy a file using sftp with
libssh2 from a windows 7 machine to a linux machine using libssh2.
The error number is 2, and from this thread here:
https://bugs.launchpad.net/paramiko/+bug/492238, there's a suggestion
that it might be a permissions error. But it's still a problem, and
I'm hoping for some help here.

My test code looks like this:

    SSHFunctions theFunctions;
    QString hostname = "<IPAddress>";
    QString username = "<username>";
    QString pass = "<password>";
    bool isConnected = theFunctions.StartSession(hostname, username, pass, 222);
    QVERIFY2(isConnected, "Unable to log in as <username>");

    bool isInIncoming = theFunctions.ChangeDirectory("/incoming");
    QVERIFY2(isInIncoming, "Unable to change to the incoming directory");

    //create a garbage file
    int theGarbageSize = 1024;
    QByteArray theGarbage(1024, 100);
    for (int i = 0; i < theGarbageSize; i++){
        theGarbage[i] = rand()%256;
    }
    //write the garbage to a local directory
    QFile theGarbageFile("testgarbage.txt");
    bool canOpenFile = theGarbageFile.open(QIODevice::ReadWrite |
QIODevice::Text);
    QVERIFY2(canOpenFile, "Unable to open garbage test file");

    bool wroteTestFile = theGarbageFile.write(theGarbage);
    QVERIFY2(wroteTestFile, "Unable to write to the garbage test file");

    theGarbageFile.close();
    bool wroteToTheRemote =
theFunctions.PutFile(theGarbageFile.fileName(),
"/home/audrey/incoming/garbage.txt");
    QVERIFY2(wroteToTheRemote, "Unable to put file");

Essentially, I'm creating a garbage file, going to send it, and then
retrieving it to make sure that everything's working. Logging in is
done by code that looks very similar to the example code, because it's
copied from the example code.

The line that fails is:

        sftp_handle =
            libssh2_sftp_open_ex(sftp_session,
theSendRemotePath.data(), theSendRemotePath.size(),
                          LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
                                 LIBSSH2_SFTP_S_IFREG,LIBSSH2_SFTP_OPENFILE);

and the login code looks like:

bool SFTPSession::LogIn(const QString& inHostName, const int& inPort,
                        const QString& inUsername, const QString& inPass)
{

#ifdef WIN32
    WSADATA wsadata;

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

    int sock, auth_pw = 1, rc;
    struct sockaddr_in sin;

    unsigned long hostaddr;
    //if you don't do .data on a toAscii, then you'll get some
    //garbage about Ubuntu in your strings instead
    QByteArray theHostNameArray = inHostName.toAscii();
    hostaddr = inet_addr(theHostNameArray.data());

    QByteArray theUsername = inUsername.toAscii();
    const char* username = theUsername.data();
    QByteArray thePassword = inPass.toAscii();
    const char* password = thePassword.data();

    rc = libssh2_init (0);

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

    /*
     * The application code is responsible for creating the socket
     * and establishing the connection
     */
    sock = socket(AF_INET, SOCK_STREAM, 0);

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

    /* Create a session instance
     */
    ssh_session = libssh2_session_init();

    if(!ssh_session){
        fprintf(stderr, "Unable to start ssh_session");
        return false;
    }

    /* ... start it up. This will trade welcome banners, exchange keys,
     * and setup crypto, compression, and MAC layers
     */
    rc = libssh2_session_startup(ssh_session, sock);

    if(rc) {
        fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
        return false;
    }

    /* At this point we havn't yet 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
     */
    const char* fingerprint = libssh2_hostkey_hash(ssh_session,
LIBSSH2_HOSTKEY_HASH_SHA1);

    mFingerprint.fromAscii(fingerprint, 40);

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

    if (auth_pw) {
        /* We could authenticate via password */
        if (libssh2_userauth_password(ssh_session, username, password)) {

            libssh2_session_disconnect(ssh_session, "Authentication
by password failed\n");
            libssh2_session_free(ssh_session);
            ssh_session = NULL;
            return false;
        }
    } else {
        /* Or by public key */
        if (libssh2_userauth_publickey_fromfile(ssh_session, username,

                            "/home/username/.ssh/id_rsa.pub",
                            "/home/username/.ssh/id_rsa",
                            password)) {
            libssh2_session_disconnect(ssh_session, "Authentication
by public key failed\n");
            libssh2_session_free(ssh_session);
            ssh_session = NULL;
            return false;
        }
    }

    fprintf(stderr, "libssh2_sftp_init()!\n");
    if (ssh_session == NULL){
        return false;
    }
    sftp_session = libssh2_sftp_init(ssh_session);

    if (!sftp_session) {
        libssh2_session_disconnect(ssh_session, "Unable to init SFTP
session\n");
        libssh2_session_free(ssh_session);
        return false;
    }

    /* Since we have not set non-blocking, tell libssh2 we are blocking */
    libssh2_session_set_blocking(ssh_session, 1);

    return true;
}

Any thoughts here?

Thanks!
Mark
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2011-05-02