simplereenroll for EST client using libCurl - c

I'm trying to develop an EST client program in C using libcurl, to perform simpleenroll and simplereenroll. As of now, I was able to retrieve the certificate using ./well-known/est/simpleenroll., but I'm have a problem performing ./well-known/est/simplereenroll
url = self.url_prefix + '/simplereenroll'
auth = (self.username, self.password)
headers = {'Content-Type': 'application/pkcs10'}
content = est.request.post(url, csr, auth=auth, headers=headers,
verify=self.implicit_trust_anchor_cert_path,
cert=cert)
pem = self.pkcs7_to_pem(content)
I was referring this python code where I could see the certificate being passed for simplereenroll operation. I don't know how to implement the same using libcurl.
Below mentioned is the portion of libcurl code which I'm using to perform the simpleenroll.
/*SIMPLEENROLL
*
*/
if (res = curl_easy_setopt(curl,CURLOPT_URL,"https://localhost:4443/.well-known/est/simpleenroll")!=CURLE_OK)
{
fprintf(stderr,"curl_easy_setopt() failed: %s\n",curl_easy_strerror(res));
return 1;
}
struct curl_slist* slist = NULL;
slist = curl_slist_append(slist, "Content-Type: application/pkcs10");
curl_easy_setopt(curl,CURLOPT_USERPWD,"estuser:estpwd")
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, CSR);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, CSR_LEN);
if((res = curl_easy_perform(curl))!=CURLE_OK)
{
fprintf(stderr,"curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
return 1;
}
The above code will return a client certificate from server. Now I need to perform simplereenroll where I need to provide this certificate.

curl_easy_setopt(curl, CURLOPT_SSLKEY, client_key);
curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert);
curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);

Related

Use curl with a webpage with no security protocol

I have a webpage: 10.1.1.165 that I am trying to get the data off of. I have built this program in linux and it works fine, however, when developing for windows systems I am running into an issue.
if (filename.substr(filename.length() - 4, 4) == "html" || filename.substr(filename.length() - 3, 3) == "htm")
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
string s;
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, filename.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
if (gLogger->isDebug()) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout/1000);
//curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); //remove this to disable verbose output
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK)
{
while (res == CURLE_OPERATION_TIMEDOUT)
{
res = curl_easy_perform(curl);
}
if (res != CURLE_OK)
{
gLogger->error("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
return -1;
}
}
curl_easy_cleanup(curl);
On my linux system, this works perfectly. On my Windows system I get: curl_easy_perform() failed: Unsupported protocol. If I go to my webpage 10.1.1.165 I see that it is being hosted with NO security. I have no way of changing how that webpage is being hosted.
Per this resource: https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html
By default libcurl will accept all protocols
Does anyone know why curl doesn't like me grabbing this webpage on windows? And if so, what settings might I have to adjust?
I have solved my issue by switching to curl-7.55.1. Previously I was using curl-7.68.0. I'm not sure if the functionality was removed or if using it is more involved.

LibCurl : Upload file to azure blob storage and Authorization

I have to check the network upload speed as well as upload a file in azure blob storage.
Initially I have tried with some sample HTTP servers to check the network speed and it's working. But when I am trying to send the file to azure blob storage HTTP endpoint, I am not sure how to use the SAS token for the authentication or the username and password will be enough to do the authentication and proceed with further procedure.
I have attached the code I have written , Please give some examples or reliable link for the authentication with SAS token and file upload.
size_t uploadspeed()
{
CURL *curl;
CURLcode res;
FILE *hd_src;
struct stat file_info;
curl_off_t fsize;
size_t speed_upload, total_time1;
hd_src = fopen("bbb.txt", "rb");
curl = curl_easy_init();
if(curl) {
int old_stdout = dup(2);
freopen("/dev/null" , "w+" , stderr);
FILE *f = fopen("target.txt", "wb");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, f);
curl_easy_setopt(curl, CURLOPT_URL,
"AZURE_URL");
curl_easy_setopt(curl, CURLOPT_USERPWD, "A:B");
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,(curl_off_t)file_info.st_size);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
fclose(stderr);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else {
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed_upload);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time1);
}
curl_easy_cleanup(curl);
fclose(hd_src);
curl_global_cleanup();
return speed_upload;
}
}
Sumana, sorry for the late response, you should consider looking at this documentation
Here's an example using SAS with block blob using C#:
string sasUri = "https://storagesample.blob.core.windows.net/sample-container/" +
"sampleBlob.txt?sv=2015-07-08&sr=b&sig=39Up9JzHkxhUIhFEjEH9594DJxe7w6cIRCg0V6lCGSo%3D" +
"&se=2016-10-18T21%3A51%3A37Z&sp=rcw";
CloudBlockBlob blob = new CloudBlockBlob(new Uri(sasUri));
// Create operation: Upload a blob with the specified name to the container.
// If the blob does not exist, it will be created. If it does exist, it will be overwritten.
try
{
MemoryStream msWrite = new MemoryStream(Encoding.UTF8.GetBytes(blobContent));
msWrite.Position = 0;
using (msWrite)
{
await blob.UploadFromStreamAsync(msWrite);
}
Console.WriteLine("Create operation succeeded for SAS {0}", sasUri);
Console.WriteLine();
}
catch (StorageException e)
{
if (e.RequestInformation.HttpStatusCode == 403)
{
Console.WriteLine("Create operation failed for SAS {0}", sasUri);
Console.WriteLine("Additional error information: " + e.Message);
Console.WriteLine();
}
else
{
Console.WriteLine(e.Message);
Console.ReadLine();
throw;
}
}
Let me know if this helps.

keep-alive curl C htttps POST

With this code I am sending strings to a webserver using libcurl and write the data to a MySQL (is done at the webserver).
My Problem is that for every call of this function the program starts a new key exchange with the webserver. I would like to have a persistant connection to the Server.
I searched here and web already and didnt find any satisfying solutions.
Multi-handler and forced keep alive still open a new connection.
Following is my Code to establish an SSL Connection:
CURL *curl;
CURLcode res;
res = curl_global_init(CURL_GLOBAL_DEFAULT); // Check for errors
if(res != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed: %s\n",
curl_easy_strerror(res));
return 1;
}
// curl handler
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, STRING);
curl_easy_setopt(curl, CURLOPT_URL, "https://IP/something/something.php");
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //verbose output activated
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: application/json"); // type JSON
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
// cleanup
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
is Answered by Daniel Stenberg here, which is a similar/the same question.
Re-use the same curl handle in subsequent requests! Don't call curl_easy_cleanup(curl) and curl_easy_init() again between them.
So the Solution is to call curl_easy_cleanup(curl) and curl_easy_init() only once.

curl wsdl soap error - mismatched Actions between sender and receiver

I am trying to post the curl based soap request to url using c API's. My libcurl version is curl 7.30.0 (i686-pc-linux-gnu) libcurl/7.30.0 OpenSSL/1.0.0 zlib/1.2.5.I am receiving the below error.Also below code i am using to post the request.i am using correct soap action aswell "GetAuthToken", Why this error is happening while posting the request.Thanks in advance.
Error:
The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)
Request:
123456789
url:
http://x.xx.xx.xxx:20003/HIMS/SecurityService/?wsdl
Sample code:
int main()
{
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
FILE *out_fd = (FILE *) 0;
char errorbuf[300]="",filename[32]="Response.txt";
char errmsg[256];
int Timeout=120;
int buffer_size = 0;
char urlbuff[100]="";
char buff[128] = "http://x.xx.xx.xxx:20003/HIMS/SecurityService/?wsdl";
memset(urlbuff,0,sizeof(urlbuff));
curl = curl_easy_init();
buffer_size = strlen(buffer);
if(curl)
{
out_fd = fopen (filename, "w");
curl_easy_setopt(curl, CURLOPT_FILE, out_fd);
headers = curl_slist_append(headers, "Content-type:text/xml;charset=utf-8; SOAPAction=GetAuthToken");
sprintf(urlbuff,"%s",buff);
curl_easy_setopt(curl, CURLOPT_URL, urlbuff);
Timeout=2000;
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, buffer_size);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, Timeout);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER,errmsg);
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
fclose(out_fd);
if(CURLE_OK != res)
{
printf("\nerrorbuf:%s:%d\n",errorbuf,res);
return -1;
}
return 0;
}
}
Assuming you have created a valid soap envelope for this request. In your code, you missed to define a POST request with your curl.
curl_easy_setopt(curl, CURLOPT_POST, 1L);

c libcurl piping HTTP GET and PUT

I want to make some kind of migrations for virtual hosts in XCP.
At the moment I do it by downloading the file with HTTP GET and then uploading it to another host with HTTP PUT, here is example of downloading
curl = curl_easy_init();
//Auto escape user password
password = curl_easy_escape(curl, XEN.user_passwd, 0);
snprintf(api_req, sizeof(api_req), "http://%s:%s#%s/export?uuid=%s",
XEN.user_name, password, XEN.host_ip, uuid);
curl_free(password);
puts(api_req);
TASK_LOG(api_req);
curl_download=TRUE;
curl_easy_setopt(curl, CURLOPT_URL, api_req);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, xva_export);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
// Install the callback function
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curl_progress_func);
//And....go!
run_progress_bar = TRUE;
//g_timeout_add_seconds(1, (GSourceFunc)update_progress_bar, 0);
res = curl_easy_perform(curl);
And uploading, if needed
curl = curl_easy_init();
//Auto escape user password
char *password = curl_easy_escape(curl, XEN.user_passwd, 0);
snprintf(api_req, sizeof(api_req), "http://%s:%s#%s/import",XEN.user_name, password, XEN.host_ip);
curl_free(password);
puts(api_req);
TASK_LOG(api_req);
curl_upload=TRUE;
g_timeout_add_seconds(1, (GSourceFunc) update_progress_bar, 0);
abort_flag = 0;
curl_easy_setopt(curl, CURLOPT_URL, api_req);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, export_read_callback);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_PUT, 1L);
curl_easy_setopt(curl, CURLOPT_READDATA, xva);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,(curl_off_t)file_info.st_size);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
// Install the callback function
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curl_progress_func);
puts("Upload started");
TASK_LOG("Upload started");
CURLcode res = curl_easy_perform(curl);
I just wonder if it possible to pipe traffic directly from one machine to another without downloading it?
You are using curl to download the file locally and then upload it.
Why not directly copy the file from source to destination using scp?

Resources