cURL / Mailing Lists / curl-library / Single Mail

curl-library

SFTP Public-Key Authentication

From: Saddam Quirem <SQuirem_at_fbdfrozen.com>
Date: Thu, 11 Jul 2013 20:28:14 +0000

I've been trying to upload a file using SFTP with libcurl using public-key
 authentication, but have had no luck.

In my `/etc/ssh/sshd_config` file I have turned off password authentication and
enabled public-key and RSA authentication. I have created a public and private key
 pair in my `$HOME/.ssh` directory (id_rsa + id_rsa.pub) and copied `id_rsa.pub`
 as the `authorized_keys` file. From the shell I am able to log in automatically without
 needing to enter a passphrase/password.

However, my program which uploads a file via SFTP using libcurl does not work.
 Below is the SFTP upload code I'm using:

#include <cstdlib>
#include <cstdio>
#include <sstream>
#include <curl/curl.h>

using namespace std;

// libcurl Read/Write Callback Functions
size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream){
        curl_off_t nread;
        size_t retcode = fread(ptr, size, nmemb, (FILE*)stream);
        nread = (curl_off_t)retcode;
        return retcode;
}

int main(void){

    // Networking Contexts
    CURL *curlUp; // cURL upload context
    CURLcode res; // Error code

    FILE *memstream; // Memory stream
    stringstream file_sstream; // C++ string stream
        char buffer[BUFSIZ]; // C string

    // Initialize cURL context
    curl_global_init(CURL_GLOBAL_DEFAULT);
    if(!(curlUp = curl_easy_init())){
        fprintf(stderr, "ERROR: cURL Context Initialization\n");
        exit(EXIT_FAILURE);
    }

    // Set URL encoding
    curl_easy_setopt(curlUp, CURLOPT_URL, "sftp://localhost/~/output");
    curl_easy_setopt(curlUp, CURLOPT_USERNAME, "squirem");

    // Other options
    curl_easy_setopt(curlUp, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(curlUp, CURLOPT_NOSIGNAL, 1L);

    // Set our own read/write functions
    curl_easy_setopt(curlUp, CURLOPT_READFUNCTION, read_callback);

    // Set SSH options
    curl_easy_setopt(curlUp, CURLOPT_SSH_AUTH_TYPES, CURLSSH_AUTH_PUBLICKEY);
    curl_easy_setopt(curlUp, CURLOPT_SSH_PUBLIC_KEYFILE, "home/squirem/.ssh/id_rsa.pub");
    curl_easy_setopt(curlUp, CURLOPT_SSH_PRIVATE_KEYFILE, "home/squirem/.ssh/id_rsa");
    curl_easy_setopt(curlUp, CURLOPT_SSH_KNOWNHOSTS, "/home/squirem/.ssh/known_hosts");
    curl_easy_setopt(curlUp, CURLOPT_KEYPASSWD, "mypasswd");

    // Enable uploading
    curl_easy_setopt(curlUp, CURLOPT_UPLOAD, 1L);

    file_sstream << "Why" << "\n";
    file_sstream << "Won't" << "\n";
    file_sstream << "This" << "\n";
    file_sstream << "Work!" << "\n";
                                
    // Test for buffer overflow
    if(file_sstream.str().length() >= BUFSIZ){
        fprintf(stderr, "ERROR: NetworkThread Invalid Readouts String\n");
        return EXIT_FAILURE;
    }

    // Copy over string
    snprintf(buffer, BUFSIZ, "%s", file_sstream.str().c_str());

    // Open readouts string as file
    memstream = fmemopen(buffer,BUFSIZ,"r");

    // Pass readouts string stream to callback function
    curl_easy_setopt(curlUp, CURLOPT_READDATA, memstream);

    // Upload File
    if((res=curl_easy_perform(curlUp)) != CURLE_OK){
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                      curl_easy_strerror(res));
    }
    fclose(memstream);

    curl_easy_cleanup(curlUp); // End cURL upload session
    curl_global_cleanup(); // Global libcurl cleanup

        return 0;
}

The application prints out the following error:

    * About to connect() to localhost port 22 (#0)
    * Trying ::1... * connected
    * Connected to localhost (::1) port 22 (#0)
    * SSH host check: 0, key: bunchOfGibberish
    * SSH authentication methods available: publickey,gssapi-keyex,gssapi-with-mic
    * Using ssh public key file home/squirem/.ssh/id_rsa.pub
    * Using ssh private key file home/squirem/.ssh/id_rsa
    * SSH public key authentication failed: Unable to open public key file
    * Authentication failure
    * Closing connection #0
    * Login denied
    curl_easy_perform() failed: Login denied

The code compiles with g++ as is. I'm thinking one of my options is incorrect,
or I'm missing one.

Any help would be appreciated.
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2013-07-12