curl ssh key C++ error "Username/PublicKey combination invalid" - c++

I'm working on embedded system in C++.
I'm actualy try to connect my system on ssh to my computer host.
I use this code:
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_easy_setopt(curl, CURLOPT_URL,
"sftp://10.0.0.100/");
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_USERPWD, "root:password");
curl_easy_setopt(curl,CURLOPT_KEYPASSWD,"password");
curl_easy_setopt(curl, CURLOPT_PORT, 22);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1000);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
curl_easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE,std::string(PublicKey).c_str());
curl_easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE,std::string(PrivateKey).c_str());
curl_easy_setopt(curl, CURLOPT_SSH_AUTH_TYPES,CURLSSH_AUTH_PUBLICKEY);
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
but the result of my programme is:
Trying 10.0.0.100...
Connected to 10.0.0.100 (10.0.0.100) port 22 (#0)
SSH MD5 fingerprint: dfdaa04ed1f80caf1e588349846b7025
SSH authentication methods available: publickey,password
Using SSH public key file '/opt/appl/var/PublicKey'
Using SSH private key file '/opt/appl/var/PrivateKey'
SSH public key authentication failed: Username/PublicKey combination invalid
Authentication failure
Closing connection 0
Unfortunately i can't creat some ssh key on my system because it dosen't accept system() commandes so i directly import keys from another system.
Dose it the cause of my error?

Related

What could be reason of getting SSL connect error while posting json request to https url from Windows PC?

I am using libcurl.dll version 7.72.0.0 in Visual Studio for a C++ application.
When I am posting a JSON request to an HTTPS url on one Windows 7 PC with Service Pack 1, the request is posted successfully. But on other PC with same OS as Windows 7 Service Pack 1, I am getting response code 35 from curl_easy_perform(): SSL connect error.
What could be the reason of the same C++ code working on one Windows 7 PC and getting an error on other Windows 7 PC? Both PCs are on the same network.
Following is the C++ code:
curl_easy_setopt(curl, CURLOPT_URL, Url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
// send all data to this function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
// we pass our 'chunk' struct to the callback function
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&sResponse);
//some servers don't like requests that are made without a user-agent
// field, so we provide one
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
printf("\npostthisData=%s\n", postthis);
if (itsHTTPSRequest)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
// if we don't provide POSTFIELDSIZE, libcurl will strlen() by
// itself
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT, m_RWTimeOut );
curl_easy_setopt( curl, CURLOPT_LOW_SPEED_TIME, m_RWTimeOut);
curl_easy_setopt( curl, CURLOPT_LOW_SPEED_LIMIT, 30L);

make libcURL timeout only on connection failure

I'm using some auto-update function in my program. In case of connection failure, I would like the program to keep trying up to 15 seconds, and then announce failure. In order to achieve that, I used the following curl_easy_setopt for cURL easy option:
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15);
But then I discovered that if the download takes more than 15 seconds, the timeout error is announced.
How can I restrict the 15 seconds only to the case of failure? I.e., if there's no connection for 15 seconds?
More information
The full option list I use is the following:
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //verify ssl peer
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //verify ssl hostname
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this); //pointer to the current class as it's a GUI program
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, CurlProgress_CallbackFunc_UpdateProgress);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20);
and the call to start is done through:
CURLcode res = curl_easy_perform(curl);
If you require more information, please let me know.
Thank you.
Instead of
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20);
use
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 15);
The first line is the timeout for the connection phase. After the connection is established the timeout becomes irrelevant, but the two following lines make sure that if the average speed in a 15 second time frame drops below 1 byte per second, then the operation is aborted.
Also worth noting that curl will not try to reestablish any connection if it is dropped, because a TCP connection can still be hold if the physical connection is (temporarly) lost up until one of the sides decides to timeout.

c++ curl returns receive error when usng proxies

As the header says, I am trying to load a page with proxy using curl on c++.
I have tried the proxy with curl linux command and got a result without a password, on my code i do:
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, true);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlRead);
curl_easy_setopt(curl, CURLOPT_USERAGENT, agent);
curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, 1L);
curl_easy_setopt(curl, CURLOPT_PROXY, "<proxy IP>:80");
res = curl_easy_perform(curl);
but res returns as 56 (CURLE_RECV_ERROR) and the manual says
Failure with receiving network data.
EDIT: I have tried another proxy (also working from terminal) and now I dont get a response at all, it simply stuck.

Curl returns all ok when bad ip supplied to CURLOPT_DNS_SERVERS

I've made a multithreaded (pthread) c++ program that is configured to use a list of custom dns.
In my tests I've used google's 8.8.8.8 for good ex, and some random ip like 113.65.123.138, 13.23.123.87 to test fail. But all goes the same in both cases, successfully.
Curl was built with C-ares support, and I've tested just to be sure:
curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
cout<<endl<<"Curl version: "<< data->version <<endl
<<"AsyncDNS: "<<( data->features | CURL_VERSION_ASYNCHDNS ? "YES" : "NO" ) <<endl;
//output: Curl version: 7.30.0 \n AsyncDNS: YES
The rest of the code:
curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, thisThreadData->current_dns->dns_str.c_str());
curl_easy_setopt(curl, CURLOPT_DNS_USE_GLOBAL_CACHE,false); //thread safety
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, CONNECTION_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_to_string);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, &getUrlOutput->header);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &getUrlOutput->html);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip,deflate");
status=curl_easy_perform(curl);
I've tested the random IPs (just in case I've stumbled on some valid DNS) :
$ host google.com 113.65.123.138
;; connection timed out; no servers could be reached
$ host google.com 13.23.123.87
;; connection timed out; no servers could be reached
What am I missing ?
Update
I've tried libcurl's latest version (7.33.0) and c-ares (1.10.0) and the same outcome.
Also if I supply a wrong domain for a url it returns CURLE_HTTP_RETURNED_ERROR (22) opposed to CURLE_COULDNT_RESOLVE_HOST (6).
Update 2
Forgot to mention that I used a HTML_PROXY for the connection, and it seems that was an important aspect, see answer.
According to the curl forums, it's expected behavior as the dns is handled by the proxy.
When I am using a proxy, how do I (or can I) control
whether the target url is resolved locally or by the proxy? I have
conditions where I need both choices.
With HTTP-Proxy the client (curl) hands over the full URL to the proxy and the proxy will resolve the hostname .
If you really want to do it client-side, then you need to
first resolve the name and then "re-arrange" the URL to use IP
numericals only and set the Host: header to contain the host name you
resolved.
In my case when the proxy's DNS finds an error it returns a html formated error page with the message "host not found", html_status 503, that's why curl passed dns checks and said the domain is ok, but failed with CURLE_HTTP_RETURNED_ERROR.

How (i.e. what tool to use) to monitior headers sent by Curl (Cookie problem)

I am using Curl (libcurl) in a C++ aplication, and am unable to send cookies (I think).
I have Fiddler, TamperData and LiveHTTP Headers installed, but they are only useful for viewing browser traffic, and are (it would seem) unable of monitoring general network traffic on a machine, so when I run my machine, I cant see the header information being sent. However, when I view the page in a browser, when succesfully logged on, I can see that cookie information is being sent.
When running my app, I succesfully log onto the page, when I subsequently, try to fetch another page, the (page) data suggests that I am not logged on - i.e. "state" has somehow being lost.
My C++ code looks alright, so I dont know what is going wrong - this is why I need to:
First be able to view my machines network traffic (not just browser traffic) - which (free) tool?
Assuming I am using Curl incorrectly, whats wrong with my code? (the cookies are being retrieved and stored ok, it seems they are just not being sent with requests for some reason.
Here is the section of my class that deals with the cookie side of Http requests:
curl_easy_setopt(curl, CURLOPT_TIMEOUT, long(m_timeout));
curl_easy_setopt(curl, CURLOPT_USERAGENT,
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; WOW64; SV1; .NET CLR 2.0.50727)");
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
Is there anything wrong with the above code?
You can use Wireshark (the former Ethereal) to view all the network traffic a machine is sending and receiving.
As Sean Carpenter said, Wireshark is the right tool to view network traffic. Start a capture and use http as a filter to see only HTTP traffic. If you just want to see HTTP requests/responses sent/received by Curl, set the CURL_VERBOSE option and look at stderr: curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L).
I believe you are using Curl correctly. Compile and run the following (complete) example; you will see that, the second time you run it (when cookies.txt exists) cookies are sent to the server.
Example code:
#include <stdio.h>
#include <curl/curl.h>
int main()
{
CURL *curl;
CURLcode success;
char errbuf[CURL_ERROR_SIZE];
int m_timeout = 15;
if ((curl = curl_easy_init()) == NULL) {
perror("curl_easy_init");
return 1;
}
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, long(m_timeout));
curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com/");
curl_easy_setopt(curl, CURLOPT_USERAGENT,
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; WOW64; SV1; .NET CLR 2.0.50727)");
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
if ((success = curl_easy_perform(curl)) != 0) {
fprintf(stderr, "%s: %s\n", "curl_easy_perform", errbuf);
return 1;
}
curl_easy_cleanup(curl);
return 0;
}