libcurl POST request failing - c++

I am trying to mimic the behavior of a python program using libcurl and getting rejected by the server. As near as I can tell, this is an issue with how the file is being handled. Here is the python code:
import requests
savedTextFile = open('filepath/file.txt', 'rw')
myPostRequest = requests.post("https://mywebserver.com/ws/v1/layers/template/lines2", headers={"API-Key":"source:1111111111"}, files={'file': savedTextFile}, verify=False)
The libcurl/C++ code I have currently is:
CURL* curl; //our curl object
struct curl_httppost* formpost=NULL;
struct curl_httppost* lastptr=NULL;
struct curl_slist* headerlist=NULL;
curl_global_init(CURL_GLOBAL_ALL); //pretty obvious
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "file", // required ?
CURLFORM_FILE, dbFile.c_str(), // makes this part a file upload part
CURLFORM_CONTENTTYPE, "application/octet-stream", // generic binary
CURLFORM_END);
curl = curl_easy_init();
const int MediumBufferSize = 256;
char sApiKeyHeaderLine[MediumBufferSize];
sprintf_s(sApiKeyHeaderLine, MediumBufferSize, "API-Key:%s", api.c_str());
headerlist = curl_slist_append((struct curl_slist*) headerlist, sApiKeyHeaderLine);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_URL, full_url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //tell curl to output its progress
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
Not sure what im missing.Here is the DOS console output:
* About to connect() to 54.219.209.180 port 443 (#1)
* Trying 54.219.209.180...
* Adding handle: conn: 0x490140
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 1 (0x490140) send_pipe: 1, recv_pipe: 0
* Connected to 54.219.209.180 (54.219.209.180) port 443 (#1)
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 1/3)
* schannel: disable server certificate revocation checks
* schannel: using IP address, SNI is being disabled by disabling the servername check against the subject names in server certificates.
* schannel: verifyhost setting prevents Schannel from comparing the supplied tar get name with the subject names in server certificates. Also disables SNI.
* schannel: sending initial handshake data: sending 90 bytes...
* schannel: sent initial handshake data: sent 90 bytes
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 2/3)
* schannel: encrypted data buffer: offset 797 length 4096
* schannel: sending next handshake data: sending 326 bytes...
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 2/3)
* schannel: encrypted data buffer: offset 59 length 4096
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 3/3)
* schannel: incremented credential handle refcount = 1
* schannel: stored credential handle in session cache
> POST /ws/v1/layers/template/lines1 HTTP/1.1 Host: 54.219.209.180 Accept: */* LatLongo-API-Key:source:1234567890
Content-Length: 35023 Expect: 100-continue Content-Type: multipart/form-data; boundary=------------------------3e5310b06e42 8f31
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 16384
* schannel: encrypted data got 245
* schannel: encrypted data buffer: offset 245 length 16384
* schannel: decrypted data length: 209
* schannel: decrypted data added: 209
* schannel: decrypted data cached: offset 209 length 16384
* schannel: decrypted data buffer: offset 209 length 16384
* schannel: decrypted data returned 209
* schannel: decrypted data buffer: offset 0 length 16384
< HTTP/1.1 400 BAD REQUEST
< Date: Thu, 09 Jan 2014 04:04:59 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
* Server gunicorn/18.0 is not blacklisted
< Server: gunicorn/18.0
* HTTP error before end of send, stop sending
< POST form invalid
* Closing connection 1
* schannel: shutting down SSL/TLS connection with 54.219.209.180 port 443
* schannel: clear security context handle
* schannel: decremented credential handle refcount = 0

Related

SSL certificate expiration date on Windows

Can anybody provide me a C++ implementation rather simple to get SSL certificate expiration date. I have been looking online for past many hours, couldn't find anything so far. Currently I am using libcpr, and it doesn't seem to have any way to get it. I tried using the "curl" command, but that also doesn't seem to have that particular information in the output on Windows OS. The same command give the "expire date" in the output if I run it in GitBash, but not in the windows command prompt. I am new to C++.
The command below and output is from GitBash.
$ curl --insecure -vvI https://www.example.com
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
* Server certificate:
* subject: C=US; ST=California; L=Los Angeles;
O=Internet▒Corporation▒for▒Assigned▒Names▒and▒Numbers; CN=www.example.org
* start date: Mar 14 00:00:00 2022 GMT
* expire date: Mar 14 23:59:59 2023 GMT <-------- **********
* issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
* SSL certificate verify result: unable to get local issuer certificate (20),
continuing anyway.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* h2h3 [:method: HEAD]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: www.example.com]
* h2h3 [user-agent: curl/7.83.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x16d9a46c1d0)
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection #0 to host www.example.com left intact
Any help would be appriciated!!
Thanks
I suggest you to refer to the code in this issue:
ASN1_TIME *expires = X509_get_notAfter(cert.get());
// Construct another ASN1_TIME for the unix epoch, get the difference
// between them and use that to calculate a unix timestamp representing
// when the cert expires
ASN1_TIME_ptr epoch(ASN1_TIME_new(), ASN1_STRING_free);
ASN1_TIME_set_string(epoch.get(), "700101000000");
int days, seconds;
ASN1_TIME_diff(&days, &seconds, epoch.get(), expires);
time_t expire_timestamp = (days * 24 * 60 * 60) + seconds;
std::cout << "Expiration timestamp:" << std::endl;
std::cout << expire_timestamp << std::endl;
std::cout << std::endl;

How to download compressed files using the curl C API?

I want to download a compressed file from a URL using libcurl C API. I have the following code:
// CurlGet.h
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <curl/curl.h>
struct memory {
char *response;
size_t size;
};
size_t callBackWrite(void *data, size_t size, size_t nmemb, void *userp) {
size_t written = fwrite(data, size, nmemb, (FILE *) userp);
return written;
}
int curlGetC(const char *url, const char* output_filename) {
CURL *curl_handle;
curl_global_init(CURL_GLOBAL_ALL);
/* init the curl session */
curl_handle = curl_easy_init();
if (!curl_handle) {
throw std::logic_error("You no curl");
}
/* set URL to get here */
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
/* Switch on full protocol/debug output while testing */
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
/* disable progress meter, set to 0L to enable it */
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L);
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, callBackWrite);
/* open the file */
FILE *f = fopen(output_filename, "wb");
if (!f) {
throw std::invalid_argument("You no got file");
}
/* write the page body to this file handle */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, f);
/* get it! */
curl_easy_perform(curl_handle);
/* close the header file */
fclose(f);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return 0;
}
Then using this code to download a web page works as expected but downloading an omex file (which is actually just a zip file with the omex extension name) does not:
#include "CurlGet.h"
#include <iostream>
// works as expected
std::string url1 = "https://isocpp.org/wiki/faq/mixing-c-and-cpp";
std::string output_filename1 = "/mnt/d/libsemsim/semsim/example.html";
curlGetC(url1_.c_str(), output_filename1_.c_str());
// downloaded file is 0 bytes.
std::string url2 = "https://auckland.figshare.com/ndownloader/files/17432333";
std::string output_filename2 = "/mnt/d/libsemsim/semsim/example.omex";
curlGetC(url2_.c_str(), output_filename2_.c_str());
Could anybody suggest how to modify my code to get it to download the compressed file?
edit : Showing the verbose traces:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 52.48.88.255...
* TCP_NODELAY set
* Connected to auckland.figshare.com (52.48.88.255) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=GB; L=London; O=figshare LLP; CN=*.figshare.com
* start date: Mar 20 00:00:00 2019 GMT
* expire date: Jul 9 12:00:00 2020 GMT
* subjectAltName: host "auckland.figshare.com" matched cert's "*.figshare.com"
* issuer: C=US; O=DigiCert Inc; CN=DigiCert SHA2 Secure Server CA
* SSL certificate verify ok.
> GET /ndownloader/files/17432333 HTTP/1.1
Host: auckland.figshare.com
Accept: */*
< HTTP/1.1 302 Found
< Date: Sun, 12 Apr 2020 10:43:10 GMT
< Content-Type: application/octet-stream
< Content-Length: 0
< Connection: keep-alive
< Server: nginx
< X-Storage-Protocol: https
< X-Filename: BIOMD0000000204_new.omex
< Location: https://objectext.auckland.ac.nz/figshare/17432333/BIOMD0000000204_new.omex
< X-Storage-Host: objectext.auckland.ac.nz
< X-Storage-File: 17432333/BIOMD0000000204_new.omex
< X-Storage-Bucket: figshare
< Content-Disposition: attachment;filename=BIOMD0000000204_new.omex
< Cache-Control: no-cache, no-store
< Set-Cookie: fig_tracker_client=0975a192-4ec5-4a63-a800-c598eb7ca6b5; Max-Age=31536000; Path=/; expires=Mon, 12-Apr-2021 10:43:10 GMT; secure; HttpOnly
< X-Robots-Tag: noindex
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Strict-Transport-Security: max-age=31536000; includeSubDomains;
< Cache-Control: public, must-revalidate, proxy-revalidate
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, OPTIONS
< Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Range
< Access-Control-Expose-Headers: Location,Accept-Ranges,Content-Encoding,Content-Length,Content-Range
<
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
* Connection #0 to host auckland.figshare.com left intact
This really has nothing to do with the fact that the traget file is compressed. Zip files are archives whose components are compressed individually; it is not possible to decompress a zip file into a single meaningful object. That's different from gzipped tar archives, for example. (However it is not generally desirable for a user agent to automatically decompress a .tgz file into a .tar file, even though it could.)
Your problem stems from the fact that you didn't provide the full URI for the file. The web server responded by sending a redirect (302) return code. That tells the user agent to make a new request for the resource, using the URI provided in the Location response header.
You need to tell libcurl to follow redirects.
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
302 redirects differ from 301 redirects in that the redirection is marked as temporary. The 301 return code suggests to the user agent that it should remember the redirection and not attempt to use the original URL in the future. A 302 response should not be cached; it might, for example, be used to provide the location of what is currently the most recent version of a resource.
here is (probably) what happened:
You sent a request without the Accept-Encoding header, the server (foolishly, imo) assumed that since you didn't specify any specific transfer encodings, you probably support gzip.. (sounds stupid, i know, but the proper way to say "i dont support any transfer encodings" is to send the header Accept-Encoding: identity, but you didn't do that), and the server decided to answer with Content-Encoding: gzip, which your code ignored. what happens next is that gzip-compressed data was saved in your "output_filename".
to tell curl to automatically deal with encodings (which is the easiest solution, the vast majority of the time), just set CURLOPT_ACCEPT_ENCODING to emptystring, this tells curl to attempt to do the tansfer compressed, and automatically decompress the response before writing it:
curl_easy_setopt(curl_handle, CURLOPT_ACCEPT_ENCODING, "");
that should fix your problem. now curl will send a header looking like Accept-Encoding: gzip, deflate, br (the exact compression algorithms sent will depend on what your libcurl was compiled to support), and the server will choose 1 of those encodings, or if the server doesn't support any of the encodings your libcurl supports, the server should send the data uncompressed,
and curl in turn will auto-decompress the data before sending it to CURLOPT_WRITEFUNCTION
you can find relevant documentation here: https://curl.haxx.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html

How to send JSON data to a REST API?

I'm sending data to a Wordpress site with the WooCommerce plugin installed using libcurl in C++ and the WooCommerce REST API. The data seems to get sent but the expected result is not shown on the website. The purpose of it is to update (modify) the product. My code is based on the WooCommerce documentation, found here.
I have managed to get the CURLOPT_VERBOSE text from the program in a separate txt file.
Here is my C++ code using cURL :
std::string URL = main_domain + "wp-json/wc/v3/products/" + product_id + "?consumer_key=" + consumer_key + "&consumer_secret=" + consumer_secret;
curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
headers = curl_slist_append(headers, "Accept:application/json");
headers = curl_slist_append(headers, "Content-Type:application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
// log file
FILE* filep = fopen("logfichier.txt", "w");
std::string toUpdate = "{\"id\":\"" + product_id + ",\"name\":\"" + product_name + "\",\"description\":\"" + product_description + "\",\"price\":\"" + product_price + "\"}";
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl) {
readBuffer = "";
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, toUpdate.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, toUpdate.length());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_STDERR, filep);
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK) {
// error handling and cleanup
}
else {
// code and cleanup
}
}
else {
// error handling and cleanup
}
I've literally put every header found on the internet that seemed relevant to what i'm trying to acomplish in my code.
Here is the returned debug text :
* STATE: INIT => CONNECT handle 0x10870278; line 1428 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x10870278; line 1464 (connection #0)
* Trying 192.XX.XX.XX...
* TCP_NODELAY set
* STATE: WAITRESOLVE => WAITCONNECT handle 0x10870278; line 1545 (connection #0)
* Connected to mywebsite.com (192.XX.XX.XX) port 443 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x10870278; line 1599 (connection #0)
* Marked for [keep alive]: HTTP default
* schannel: SSL/TLS connection with mywebsite.com port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 176 bytes...
// (here was just a bunch of connexion attemps log text...)
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with mywebsite.com port 443 (step 3/3)
* schannel: stored credential handle in session cache
* STATE: PROTOCONNECT => DO handle 0x10870278; line 1634 (connection #0)
> PUT /wp-json/wc/v3/products/111867?consumer_key=(the actual key)&consumer_secret=(the actual secret) HTTP/1.1
Host: mywebsite.com
Transfer-Encoding: chunked
Accept:application/json
Content-Type:application/json
charsets: utf-8
4b
* upload completely sent off: 82 out of 75 bytes
* STATE: DO => DO_DONE handle 0x10870278; line 1696 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x10870278; line 1823 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x10870278; line 1838 (connection #0)
* schannel: client wants to read 16384 bytes
* schannel: encdata_buffer resized 17408
* schannel: encrypted data buffer: offset 0 length 17408
// (a few decrypting data attempts...)
* schannel: decrypted data returned 536
* schannel: decrypted data buffer: offset 0 length 16384
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Date: Tue, 18 Jun 2019 15:27:42 GMT
* Server Apache is not blacklisted
< Server: Apache
< X-Robots-Tag: noindex
< Link: <https://mywebsite.com/wp-json/>; rel="https://api.w.org/"
< X-Content-Type-Options: nosniff
< Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages
< Access-Control-Allow-Headers: Authorization, Content-Type
< Expires: Wed, 11 Jan 1984 05:00:00 GMT
< Cache-Control: no-transform, no-cache, must-revalidate, max-age=0
< Allow: GET, POST, PUT, PATCH, DELETE
< Transfer-Encoding: chunked
< Content-Type: application/json; charset=UTF-8
<
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 835 length 17408
// (a few decrypting data attempts...)
* schannel: decrypted data returned 1986
* schannel: decrypted data buffer: offset 0 length 16384
* STATE: PERFORM => DONE handle 0x10870278; line 2011 (connection #0)
* multi_done
* Connection #0 to host axanti.info left intact
I took out a few redundant part from the original text and kept what I think is the main piece of information. It seems that my JSON data is actually sent to the server but the intended result doesn't show up on my website (a product should be modified but it's actually not).
Is there any way this code could be wrong ? Or is the problem on the server side ? Because I litteraly apply the same stuff that is mentioned in the official documentation.
Looks like your payload if off. The id portion is redundant, as you're already specifying the product to update via the URL, so you can drop that. Additionally, you're attempting to set the price incorrectly. Per the REST docs, you need to use the regular_price attribute instead of price (price is read only). The proper payload should look like this:
{
name: 'My product name',
description: 'my product description',
regular_price' : '3.50',
}

Google cloud functions : All criteria for calling Http triggered cloud functions from outside cloud project (browser or c# client)

I have written Google cloud function (HTTP trigger). It tests successfully within the google cloud interface. Now I need to call it from Unity Game (C# .Net core).
First I tried to run it from browser. I took URL shown in Google cloud function interface. It does not work. I do not get stackdriver log (it does not even hit the URL?).
Is it because it needs oauth 2.0 token?
I am creating Http request , embedding JSON
request.ContentType = "application/json";
request.Method = "POST";
request.Headers["Authorization"] = "Bearer " + token;
//token obtained from oauth 2.0 JWT call
byte[] JsonContentBytes = Encoding.UTF8.GetBytes(strjsonReqContent);
// my Json object. requestJSON.ToString());
request.ContentLength = JsonContentBytes.Length;
Here I tried with Oauth 2.0 token as well. (It works for storage API. My service account for cloud function has project editor access)
I saw one post about using cloud function from outside the cloud project. It did not solve my problem.
Please let me know all the criteria for using cloud functions from outside the cloud project.
EDIT1:
Thanks for the suggestion. Here is the log from Curl execution. I am not used to web debugging. Please suggest what should I check further. I could make out that it is 'Bad Request'. The URL is the one I picked from cloud function console.
>curl -v -X POST https://us-central1- myproject.cloudfunctions.net/myfunctiontest -H "Content-Type:application/json" -d '{"username":"myemail#mydomain.com","password":"password1"}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 172.217.163.174...
* TCP_NODELAY set
* Connected to us-central1-myproject.cloudfunctions.net (172.217.163.174) port 443 (#0)
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 212 bytes...
* schannel: sent initial handshake data: sent 212 bytes
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 4096
* schannel: encrypted data buffer: offset 4096 length 4096
* schannel: encrypted data length: 4028
* schannel: encrypted data buffer: offset 4028 length 4096
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 5052 length 5052
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 6076 length 6076
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 7100 length 7100
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 8124 length 8124
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 317
* schannel: encrypted data buffer: offset 8441 length 9148
* schannel: sending next handshake data: sending 93 bytes...
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 284
* schannel: encrypted data buffer: offset 284 length 9148
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 3/3)
* schannel: stored credential handle in session cache
> POST /logontest HTTP/1.1
> Host: us-central1-myproject.cloudfunctions.net
> User-Agent: curl/7.55.1
> Accept: */*
> Content-Type:application/json
> Content-Length: 59
>
* upload completely sent off: 59 out of 59 bytes
* schannel: client wants to read 102400 bytes
* schannel: encdata_buffer resized 103424
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: encrypted data got 506
* schannel: encrypted data buffer: offset 506 length 103424
* schannel: decrypted data length: 477
* schannel: decrypted data added: 477
* schannel: decrypted data cached: offset 477 length 102400
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: decrypted data buffer: offset 477 length 102400
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 477
* schannel: decrypted data buffer: offset 0 length 102400
< HTTP/1.1 400 Bad Request
< Content-Type: text/html
< Function-Execution-Id: qyx8g4vv8hn1
< X-Cloud-Trace-Context: 6f8012ea791b4a0f900ac4b84debaf5f;o=1
< Date: Thu, 02 May 2019 13:23:14 GMT
< Server: Google Frontend
< Content-Length: 192
< Alt-Svc: quic=":443"; ma=2592000; v="46,44,43,39"
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>The browser (or proxy) sent a request that this server could not
understand.</p>
* Connection #0 to host us-central1-myproject.cloudfunctions.net left intact
The 'bad request' may not be due to URL since I took from the cloud function UI. Please suggest how I should proceed. Thanks.

Setting up Curl for FTPS on Windows 10 Visual studio 2017

I am trying to set up Curl for use with FTPS on Visual Studio 2017 (Community) on Windows 10, but i keep getting strange errors (errors included in the different things i have tried). I currently have Curl working for FTPS on Mac and i dont need it on Linux at the moment.
Things i have tried:
Downloading the binaries at Curls Download Page
To set up Curl for MacOs, all i had to do was download the MacOs binary and link it, so this is where i started for setting up Curl for Windows. On downloading a binary, however, it only included the .dll. It was missing headers and .lib files. I tried downloading about 5 other binaries, each of which was missing at least one essential file.
Installing through vcpkg
After failing to get the binaries, i realized that Curl is probably on vcpkg. I ran
./vcpkg install curl from vcpkg master. After compiling for a few minutes, it succeeded. I then went to my project and linked it to curl, with a test ftps transfer. This is the example from Curls Example page
#include <stdio.h>
#include <curl/curl.h>
/* <DESC>
* Get a single file from an FTP server.
* </DESC>
*/
struct FtpFile {
const char *filename;
FILE *stream;
};
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
struct FtpFile *out = (struct FtpFile *)stream;
if(out && !out->stream) {
/* open file for writing */
out->stream = fopen(out->filename, "wb");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
int main(void)
{
CURL *curl;
CURLcode res;
struct FtpFile ftpfile = {
"C:\Users\myUser\Desktop\file.png", /* name to store the file as if successful */
NULL
};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/*
* You better replace the URL with one that works!
*/
curl_easy_setopt(curl, CURLOPT_URL,
"ftp://my.ip.adress.here/path/to/file.png"); //Not actual address
/* Define our callback to get called when there's data to be written */
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);
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
//Extra options to enable ssl (not included in example)
curl_easy_setopt(FTPAgent,CURLOPT_USE_SSL,CURLUSESSL_ALL);
curl_easy_setopt(FTPAgent,CURLOPT_SSL_VERIFYPEER,0L);
curl_easy_setopt(FTPAgent,CURLOPT_USERNAME,"Username"); //Not actual username
curl_easy_setopt(FTPAgent,CURLOPT_PASSWORD,"Password"); //Not actual password for obvious reasons
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
if(CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}
if(ftpfile.stream)
fclose(ftpfile.stream); /* close the local file */
curl_global_cleanup();
return 0;
}
The project compiled and ran, but when it tried to download the file, an error appeared in the debug console saying Curl is not compatible with the FTPS protocol. It is intentional that i am using Explicit FTPS, because that is what i configured my server to accept, and i can connect to it using Explicit FTPS from Curl on Mac and from FileZilla from mac and windows. If anyone knows how to fix this, please lmk. For the time being i have given up using curl through vcpkg
Compiling Source Code
I saved this for last, since i was unable to find any instructions for building Curl, but eventually i found This and followed the instructions in the answer, with the version of curl used there to eliminate any variables, other than the fact that i am on VS2017 not VS2013. the second time i did this, i had someone watch me do it to make sure i did all the steps correctly, so i am about 90% sure i did these instructions correctly. After completing the instructions, i used the same code as above. It compiled and ran with no errors, but whenever i try to download a file of any significant size (im not quite sure the cutoff, but a 4kb file works and 78kb file doesnt) it says failed to decrypt data need more data about 20 times then hangs:
* Trying my.ip.adress.here...
* TCP_NODELAY set
* Connected to my.ip.adress.here (my.ip.adress.here) port 21 (#0)
< 220 (vsFTPd 2.2.2)
> AUTH SSL
< 234 Proceed with negotiation.
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 1/3)
* schannel: disabled server certificate revocation checks
* schannel: using IP address, SNI is not supported by OS.
* schannel: sending initial handshake data: sending 147 bytes...
* schannel: sent initial handshake data: sent 147 bytes
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 2/3)
* schannel: encrypted data got 1034
* schannel: encrypted data buffer: offset 1034 length 4096
* schannel: a client certificate has been requested
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 2/3)
* schannel: encrypted data buffer: offset 1034 length 4096
* schannel: sending next handshake data: sending 349 bytes...
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 2/3)
* schannel: encrypted data got 250
* schannel: encrypted data buffer: offset 250 length 4096
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 3/3)
* schannel: stored credential handle in session cache
> USER Username
* schannel: client wants to read 16384 bytes
* schannel: encdata_buffer resized 17408
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 85
* schannel: encrypted data buffer: offset 85 length 17408
* schannel: decrypted data length: 34
* schannel: decrypted data added: 34
* schannel: decrypted data cached: offset 34 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 34 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 34
* schannel: decrypted data buffer: offset 0 length 16384
< 331 Please specify the password.
> PASS Password
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 69
* schannel: encrypted data buffer: offset 69 length 17408
* schannel: decrypted data length: 23
* schannel: decrypted data added: 23
* schannel: decrypted data cached: offset 23 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 23 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 23
* schannel: decrypted data buffer: offset 0 length 16384
< 230 Login successful.
> PBSZ 0
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 69
* schannel: encrypted data buffer: offset 69 length 17408
* schannel: decrypted data length: 20
* schannel: decrypted data added: 20
* schannel: decrypted data cached: offset 20 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 20 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 20
* schannel: decrypted data buffer: offset 0 length 16384
< 200 PBSZ set to 0.
> PROT P
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 69
* schannel: encrypted data buffer: offset 69 length 17408
* schannel: decrypted data length: 23
* schannel: decrypted data added: 23
* schannel: decrypted data cached: offset 23 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 23 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 23
* schannel: decrypted data buffer: offset 0 length 16384
< 200 PROT now Private.
> PWD
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 53
* schannel: encrypted data buffer: offset 53 length 17408
* schannel: decrypted data length: 9
* schannel: decrypted data added: 9
* schannel: decrypted data cached: offset 9 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 9 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 9
* schannel: decrypted data buffer: offset 0 length 16384
< 257 "/"
* Entry path is '/'
> CWD path
* ftp_perform ends with SECONDARY: 0
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 85
* schannel: encrypted data buffer: offset 85 length 17408
* schannel: decrypted data length: 37
* schannel: decrypted data added: 37
* schannel: decrypted data cached: offset 37 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 37 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 37
* schannel: decrypted data buffer: offset 0 length 16384
< 250 Directory successfully changed.
> CWD to
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 85
* schannel: encrypted data buffer: offset 85 length 17408
* schannel: decrypted data length: 37
* schannel: decrypted data added: 37
* schannel: decrypted data cached: offset 37 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 37 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 37
* schannel: decrypted data buffer: offset 0 length 16384
< 250 Directory successfully changed.
> EPSV
* Connect data stream passively
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 101
* schannel: encrypted data buffer: offset 101 length 17408
* schannel: decrypted data length: 48
* schannel: decrypted data added: 48
* schannel: decrypted data cached: offset 48 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 48 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 48
* schannel: decrypted data buffer: offset 0 length 16384
< 229 Entering Extended Passive Mode (|||1040|).
* Trying my.ip.adress.here...
* TCP_NODELAY set
* Connecting to my.ip.adress.here (my.ip.adress.here) port 1040
* Connected to my.ip.adress.here (my.ip.adress.here) port 21 (#0)
> TYPE I
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 85
* schannel: encrypted data buffer: offset 85 length 17408
* schannel: decrypted data length: 31
* schannel: decrypted data added: 31
* schannel: decrypted data cached: offset 31 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 31 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 31
* schannel: decrypted data buffer: offset 0 length 16384
< 200 Switching to Binary mode.
> SIZE file.png
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 53
* schannel: encrypted data buffer: offset 53 length 17408
* schannel: decrypted data length: 11
* schannel: decrypted data added: 11
* schannel: decrypted data cached: offset 11 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 11 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 11
* schannel: decrypted data buffer: offset 0 length 16384
< 213 84381
> RETR file.png
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 117
* schannel: encrypted data buffer: offset 117 length 17408
* schannel: decrypted data length: 68
* schannel: decrypted data added: 68
* schannel: decrypted data cached: offset 68 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 68 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 68
* schannel: decrypted data buffer: offset 0 length 16384
< 150 Opening BINARY mode data connection for 001.png (84381 bytes).
* Maxdownload = -1
* Getting file with size: 84381
* Doing the SSL/TLS handshake on the data stream
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 1/3)
* schannel: re-using existing credential handle
* schannel: incremented credential handle refcount = 3
* schannel: using IP address, SNI is not supported by OS.
* schannel: sending initial handshake data: sending 307 bytes...
* schannel: sent initial handshake data: sent 307 bytes
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 2/3)
* schannel: encrypted data got 129
* schannel: encrypted data buffer: offset 129 length 4096
* schannel: sending next handshake data: sending 75 bytes...
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with my.ip.adress.here port 21 (step 3/3)
* schannel: client wants to read 16384 bytes
* schannel: encdata_buffer resized 17408
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 10220
* schannel: encrypted data buffer: offset 10220 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 10220 length 17408
* schannel: encrypted data got 4380
* schannel: encrypted data buffer: offset 14600 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 14600 length 17408
* schannel: encrypted data got 1460
* schannel: encrypted data buffer: offset 16060 length 17408
* schannel: decrypted data length: 15872
* schannel: decrypted data added: 15872
* schannel: decrypted data cached: offset 15872 length 16384
* schannel: encrypted data length: 135
* schannel: encrypted data cached: offset 135 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 15872
* schannel: decrypted data buffer: offset 0 length 16384
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 135 length 17408
* schannel: encrypted data got 16060
* schannel: encrypted data buffer: offset 16195 length 17408
* schannel: decrypted data length: 15872
* schannel: decrypted data added: 15872
* schannel: decrypted data cached: offset 15872 length 16384
* schannel: encrypted data length: 270
* schannel: encrypted data cached: offset 270 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 15872
* schannel: decrypted data buffer: offset 0 length 16384
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 270 length 17408
* schannel: encrypted data got 16060
* schannel: encrypted data buffer: offset 16330 length 17408
* schannel: decrypted data length: 15872
* schannel: decrypted data added: 15872
* schannel: decrypted data cached: offset 15872 length 16384
* schannel: encrypted data length: 405
* schannel: encrypted data cached: offset 405 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 15872
* schannel: decrypted data buffer: offset 0 length 16384
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 405 length 17408
* schannel: encrypted data got 14600
* schannel: encrypted data buffer: offset 15005 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 15005 length 17408
* schannel: encrypted data got 2403
* schannel: encrypted data buffer: offset 17408 length 17408
* schannel: decrypted data length: 15872
* schannel: decrypted data added: 15872
* schannel: decrypted data cached: offset 15872 length 16384
* schannel: encrypted data length: 1483
* schannel: encrypted data cached: offset 1483 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 15872
* schannel: decrypted data buffer: offset 0 length 16384
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 1483 length 17408
* schannel: encrypted data got 15925
* schannel: encrypted data buffer: offset 17408 length 17408
* schannel: decrypted data length: 2048
* schannel: decrypted data added: 2048
* schannel: decrypted data cached: offset 2048 length 16384
* schannel: encrypted data length: 15307
* schannel: encrypted data cached: offset 15307 length 17408
* schannel: failed to decrypt data, need more data
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 2048
* schannel: decrypted data buffer: offset 0 length 16384
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 15307 length 17408
* schannel: encrypted data got 2101
* schannel: encrypted data buffer: offset 17408 length 17408
* schannel: decrypted data length: 16384
* schannel: decrypted data added: 16384
* schannel: decrypted data cached: offset 16384 length 16384
* schannel: encrypted data length: 971
* schannel: encrypted data cached: offset 971 length 17408
* schannel: encrypted data buffer: offset 971 length 17408
* schannel: decrypted data buffer: offset 16384 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 16384
* schannel: decrypted data buffer: offset 0 length 16384
* schannel: client wants to read 2461 bytes
* schannel: encrypted data buffer: offset 971 length 17408
* schannel: encrypted data got 1599
* schannel: encrypted data buffer: offset 2570 length 17408
* schannel: decrypted data length: 2461
* schannel: decrypted data added: 2461
* schannel: decrypted data cached: offset 2461 length 16384
* schannel: encrypted data length: 53
* schannel: encrypted data cached: offset 53 length 17408
* schannel: encrypted data buffer: offset 53 length 17408
* schannel: decrypted data buffer: offset 2461 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 2461
* schannel: decrypted data buffer: offset 0 length 16384
Again, i replaced the IP, Username, and Password with dummy values for obvious reasons.
Notes:
HTTPS works with method 3 (did not try it with method 2 so i dont know if it works) Curl successfully performed an https get request on both my server and google.
I am assuming the problem is with my installation of curl, or with my code, but it is possible that it is with my server because i do not have another ftps server to test it against. I do know i can do ftps with my server from Curl on Mac, and from Filezilla on mac and windows.
I tried method 2 three times, and method 3 two times.
If there is any more information that i can provide, let me know. Thank you for any help you might have. I will be so happy if i get this working after a week...