curl-library
curl_easy_perform() fails with "Problem with the SSL CA cert (path? access rights?)" after first time calling this routine
Date: Sun, 10 Mar 2013 07:44:33 -0400
Hi,
I'll appreciate it very much if anyone in the team can resolve this issue.
I believe it is a bug in libcurl:
Here are the information:
Platform: 64bit Red Hat Enterprise Linux Server release 6.1
libcurl version: curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/
3.12.9.0 zlib/1.2.3 libidn/1.18 libssh2/1.2.2
Useful Information:
1. we dynamically load libcurl routines by using dlopen() and dlsym(), see
code below
2. we call a set of libcurl routines, setopt CURLOPT_SSL_VERIFYPEER and
CURLOPT_SSL_VERIFYHOST to 0L
3. it fails with "Problem with the SSL CA cert (path? access rights?)"
after the 1st call to httpPostData() routine (see code below).
4. We don't/cannot use curl_global_init() because our code is thread-safe,
and it crashes if we use this routine.
5. when you use this code, please modify the url, prot#, username/password
to your area.
However, if we don't do dlopen/dlsym() and statically link libcurl instead,
it works fine, see code below:
===== beginning of make file for dynamic load ====
cc -g -ldl -o post_d dbfetch_libcurl_post_dynamic.c
===== end of make file for dynamic load ====
====== beginning of c file for dynamic load ====
/* $Id: dbfetch_libcurl_get.c -1 $
* ======================================================================
*
* Example dbfetch client in C using libcurl and HTTP POST.
*
* ======================================================================
*/
/* Include libraries */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define _GNU_SOURCE
#include <dlfcn.h>
#include <curl/curl.h>
struct string {
char *ptr;
size_t len;
};
void init_string(struct string *s)
{
s->len = 0;
s->ptr = malloc(s->len+1);
if (s->ptr == NULL)
{
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = realloc(s->ptr, new_len+1);
if (s->ptr == NULL)
{
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return size*nmemb;
}
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
static int first_time=1;
char outfilename[FILENAME_MAX] = "body_post.out";
static FILE *outfile;
size_t written;
if (first_time) {
first_time = 0;
outfile = fopen(outfilename,"w");
if (outfile == NULL) {
return -1;
}
fprintf(stderr,"The body is <%s>\n",outfilename);
}
written = fwrite(ptr,size,nmemb,outfile);
return written;
}
int httpPostData(char **xmlOut)
{
/* Exit status to return */
int exitStatus = 0;
/* Endpoint for dbfetch service to be used for POST */
const char* endpointUrl = "
https://l2se0060.lss.emc.com:8443/univmax/restapi/performance/Array/metrics"
;
char userpwd[40]="smc:smc";
const char body[800];
void* handle = dlopen("/usr/lib64/libcurl.so", RTLD_LAZY | RTLD_NOW);
if (handle == NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
return 1;
}
CURL* (*DLcurl_easy_init)();
DLcurl_easy_init = (CURL* (*)())dlsym(handle,"curl_easy_init");
if ( DLcurl_easy_init== NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
// !!!it is not thread-safe, CANNOT use it
//
/*CURLcode (*DLcurl_global_init)(long);
DLcurl_global_init = (CURLcode (*)(long))dlsym(handle, "curl_global_init");
if (DLcurl_global_init==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}*/
CURLcode (*DLcurl_easy_setopt)(CURL *, CURLoption , ...);
DLcurl_easy_setopt = (CURLcode (*)(CURL *, CURLoption , ...))dlsym(handle,
"curl_easy_setopt");
if (DLcurl_easy_setopt==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
struct curl_slist * (*DLcurl_slist_append)(struct curl_slist *, const char* );
DLcurl_slist_append = (struct curl_slist * (*)(struct curl_slist *, const
char * ))dlsym(handle, "curl_slist_append");
if (DLcurl_slist_append==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
CURLcode (*DLcurl_easy_perform)(CURL * );
DLcurl_easy_perform = (CURLcode (*)(CURL * ))dlsym(handle,
"curl_easy_perform");
if (DLcurl_easy_perform==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
const char * (*DLcurl_easy_strerror)(CURLcode );
DLcurl_easy_strerror = (const char * (*)(CURLcode ))dlsym(handle,
"curl_easy_strerror");
if (DLcurl_easy_strerror==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
void (*DLcurl_slist_free_all)(struct curl_slist * );
DLcurl_slist_free_all = (void (*)(struct curl_slist * ))dlsym(handle,
"curl_slist_free_all");
if (DLcurl_slist_free_all==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
void (*DLcurl_easy_cleanup)(CURL * );
DLcurl_easy_cleanup = (void (*)(CURL * ))dlsym(handle, "curl_easy_cleanup");
if (DLcurl_easy_cleanup==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
void (*DLcurl_easy_reset)(CURL * );
DLcurl_easy_reset = (void (*)(CURL * ))dlsym(handle, "curl_easy_reset");
if (DLcurl_easy_reset==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}
// !!!! It is not thread-safe
/*void (*DLcurl_global_cleanup)(void);
DLcurl_global_cleanup = (void (*)(void ))dlsym(handle,
"curl_global_cleanup");
if (DLcurl_global_cleanup==NULL)
{
const char * dl = dlerror();
printf("Error = %s\n", dl);
}*/
strcpy(body, "{\n\"arrayParam\": {\n\"startDate\" :
\"1361887800000\",\n\"endDate\" : \"1362495000000\",\n\"symmetrixId\" :
\"000195600138\",\n\"metrics\" : [\"IO_RATE\", \"HIT_PER_SEC\",
\"PERCENT_HIT\", \"WP\"]}}");
/* Construct resource POST data */
int postDataLen = strlen(body) + 26;
char* postData = (char*)malloc(sizeof(char) * (postDataLen));
if(postData == NULL) {
printf("Error: unable to allocate memory for POST data\n");
}
strcpy(postData, body);
printf("-------postData: %s\n\n", postData);
/* Initialise libcurl */
// !!!! It is not thread-safe, we CANNOT use it
// It works fine if we use this to init this program, however,
// We cannot use it because it is not thread-safe in our software!!!!
//
/*CURLcode globalHandle = DLcurl_global_init(CURL_GLOBAL_ALL);
if (globalHandle)
{
printf("DLcurl_global_init fails");
return 1;
}*/
char* curlErrStr = (char*)malloc(CURL_ERROR_SIZE);
/* Get a curl handle */
CURL* curlHandle = DLcurl_easy_init();
if(curlHandle)
{
struct string s;
init_string(&s);
DLcurl_easy_setopt(curlHandle, CURLOPT_ERRORBUFFER, curlErrStr);
/* Set the endpoint to send the POST to */
CURLcode curlErr0 = DLcurl_easy_setopt(curlHandle, CURLOPT_URL,
endpointUrl);
if(curlErr0) {
printf("CURLOPT_URL...%s\n", DLcurl_easy_strerror(curlErr0));
}
CURLcode curlErr3 = DLcurl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYPEER,
0);
if(curlErr3) {
printf("CURLOPT_SSL_VERIFYPEER...%s\n", DLcurl_easy_strerror(curlErr3));
}
CURLcode curlErr38 = DLcurl_easy_setopt(curlHandle, CURLOPT_VERBOSE, 1);
if(curlErr38) {
printf("CURLOPT_VERBOSE...%s\n", DLcurl_easy_strerror(curlErr38));
}
CURLcode curlErr4 = DLcurl_easy_setopt(curlHandle, CURLOPT_CAINFO, 0);
if(curlErr4) {
printf("CURLOPT_CAINFO...%s\n", DLcurl_easy_strerror(curlErr4));
}
CURLcode curlErr5 = DLcurl_easy_setopt(curlHandle, CURLOPT_CAPATH, 0);
if(curlErr5) {
printf("CURLOPT_CAPATH...%s\n", DLcurl_easy_strerror(curlErr5));
}
CURLcode curlErr6 = DLcurl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYHOST,
0);
if(curlErr6) {
printf("CURLOPT_SSL_VERIFYHOST...%s\n", DLcurl_easy_strerror(curlErr6));
}
struct curl_slist *headers=NULL;
headers = DLcurl_slist_append(headers, "Content-Type:
application/json\nAccept: application/xml");
CURLcode curlErr7 = DLcurl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER,
headers);
if(curlErr7) {
printf("CURLOPT_HTTPHEADER...%s\n", DLcurl_easy_strerror(curlErr7));
}
CURLcode curlErr8 = DLcurl_easy_setopt(curlHandle, CURLOPT_USERPWD,
userpwd);
if(curlErr8) {
printf("CURLOPT_USERPWD...%s\n", DLcurl_easy_strerror(curlErr8));
}
/* Specify the POST data */
CURLcode curlErr9 = DLcurl_easy_setopt(curlHandle, CURLOPT_POSTFIELDS,
postData);
if(curlErr9) {
printf("CURLOPT_POSTFIELDS...%s\n", DLcurl_easy_strerror(curlErr9));
}
CURLcode curlErr10 = DLcurl_easy_setopt(curlHandle,
CURLOPT_WRITEFUNCTION,&writefunc);
if(curlErr10) {
printf("CURLOPT_WRITEFUNCTION...%s\n", DLcurl_easy_strerror(curlErr10));
}
CURLcode curlErr11 = DLcurl_easy_setopt(curlHandle, CURLOPT_WRITEDATA,&s);
if(curlErr11) {
printf("CURLOPT_WRITEDATA...%s\n", DLcurl_easy_strerror(curlErr11));
}
//curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION,&write_data);
/* Execute the POST, response goes to STDOUT */
CURLcode curlErr = DLcurl_easy_perform(curlHandle);
/* Report any errors */
if(curlErr) {
printf("...%s\n", DLcurl_easy_strerror(curlErr));
}
*xmlOut = malloc(strlen(s.ptr)+1);
if (*xmlOut == NULL)
{
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
*xmlOut[0] = '\0';
strncpy(*xmlOut, s.ptr, s.len);
free(s.ptr);
DLcurl_easy_reset(curlHandle);
/* free the header list */
DLcurl_slist_free_all(headers);
/* Clean-up libcurl */
DLcurl_easy_cleanup(curlHandle);
//DLcurl_global_cleanup();
}
else {
exitStatus = 1;
}
free(curlErrStr);
free(postData);
int cl = dlclose(handle);
if (cl != 0)
{
printf("Error\n");
}
/* Return the exit status */
return exitStatus;
}
int main(int argc, char* argv[])
{
int exitStatus = 0;
char * xmlOut;
int r;
for (r=0; r < 5; r++)
{
httpPostData(&xmlOut);
printf("%s...", xmlOut);
free (xmlOut);
getchar();
printf("=============");
}
return exitStatus;
}
====== end of c file for dynamic load ====
====== beginning of make file for static link =====
cc -g -o post_s dbfetch_libcurl_post_static.c /usr/lib64/libcurl.so
====== end of make file for static link =====
====== beginning of c file for static link ====
/* $Id: dbfetch_libcurl_get.c -1 $
* ======================================================================
*
* Example dbfetch client in C using libcurl and HTTP POST.
*
* ======================================================================
*/
/* Include libraries */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <curl/curl.h>
struct string {
char *ptr;
size_t len;
};
void init_string(struct string *s)
{
s->len = 0;
s->ptr = malloc(s->len+1);
if (s->ptr == NULL)
{
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = realloc(s->ptr, new_len+1);
if (s->ptr == NULL)
{
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return size*nmemb;
}
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
static int first_time=1;
char outfilename[FILENAME_MAX] = "body_post.out";
static FILE *outfile;
size_t written;
if (first_time) {
first_time = 0;
outfile = fopen(outfilename,"w");
if (outfile == NULL) {
return -1;
}
fprintf(stderr,"The body is <%s>\n",outfilename);
}
written = fwrite(ptr,size,nmemb,outfile);
return written;
}
int httpPostData(char **xmlOut)
{
/* Exit status to return */
int exitStatus = 0;
/* Endpoint for dbfetch service to be used for POST */
const char* endpointUrl = "
https://l2se0060.lss.emc.com:8443/univmax/restapi/performance/Array/metrics"
;
char userpwd[40]="smc:smc";
const char body[800];
strcpy(body, "{\n\"arrayParam\": {\n\"startDate\" :
\"1361887800000\",\n\"endDate\" : \"1362495000000\",\n\"symmetrixId\" :
\"000195600138\",\n\"metrics\" : [\"IO_RATE\", \"HIT_PER_SEC\",
\"PERCENT_HIT\", \"WP\"]}}");
/* Construct resource POST data */
int postDataLen = strlen(body) + 26;
char* postData = (char*)malloc(sizeof(char) * (postDataLen));
if(postData == NULL) {
printf("Error: unable to allocate memory for POST data\n");
}
strcpy(postData, body);
printf("-------postData: %s\n\n", postData);
/* Initialise libcurl */
/*CURLcode globalHandle = DLcurl_global_init(CURL_GLOBAL_ALL);
if (globalHandle)
{
printf("DLcurl_global_init fails");
return 1;
}*/
char* curlErrStr = (char*)malloc(CURL_ERROR_SIZE);
/* Get a curl handle */
CURL* curlHandle = curl_easy_init();
if(curlHandle) {
struct string s;
init_string(&s);
curl_easy_setopt(curlHandle, CURLOPT_ERRORBUFFER, curlErrStr);
/* Set the endpoint to send the POST to */
CURLcode curlErr0 = curl_easy_setopt(curlHandle, CURLOPT_URL, endpointUrl);
if(curlErr0) {
printf("CURLOPT_URL...%s\n", curl_easy_strerror(curlErr0));
}
CURLcode curlErr3 = curl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYPEER, 0);
if(curlErr3) {
printf("CURLOPT_SSL_VERIFYPEER...%s\n", curl_easy_strerror(curlErr3));
}
CURLcode curlErr4 = curl_easy_setopt(curlHandle, CURLOPT_CAINFO, 0);
if(curlErr4) {
printf("CURLOPT_CAINFO...%s\n", curl_easy_strerror(curlErr4));
}
CURLcode curlErr5 = curl_easy_setopt(curlHandle, CURLOPT_CAPATH, 0);
if(curlErr5) {
printf("CURLOPT_CAPATH...%s\n", curl_easy_strerror(curlErr5));
}
CURLcode curlErr6 = curl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYHOST, 0);
if(curlErr6) {
printf("CURLOPT_SSL_VERIFYHOST...%s\n", curl_easy_strerror(curlErr6));
}
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type:
application/json\nAccept: application/xml");
CURLcode curlErr7 = curl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER,
headers);
if(curlErr7) {
printf("CURLOPT_HTTPHEADER...%s\n", curl_easy_strerror(curlErr7));
}
CURLcode curlErr8 = curl_easy_setopt(curlHandle, CURLOPT_USERPWD, userpwd);
if(curlErr8) {
printf("CURLOPT_USERPWD...%s\n", curl_easy_strerror(curlErr8));
}
/* Specify the POST data */
CURLcode curlErr9 = curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDS,
postData);
if(curlErr9) {
printf("CURLOPT_POSTFIELDS...%s\n", curl_easy_strerror(curlErr9));
}
CURLcode curlErr10 = curl_easy_setopt(curlHandle,
CURLOPT_WRITEFUNCTION,&writefunc);
if(curlErr10) {
printf("CURLOPT_WRITEFUNCTION...%s\n", curl_easy_strerror(curlErr10));
}
CURLcode curlErr11 = curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA,&s);
if(curlErr11) {
printf("CURLOPT_WRITEDATA...%s\n", curl_easy_strerror(curlErr11));
}
//curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION,&write_data);
/* Execute the POST, response goes to STDOUT */
CURLcode curlErr = curl_easy_perform(curlHandle);
/* Report any errors */
if(curlErr) {
printf("...%s\n", curl_easy_strerror(curlErr));
}
*xmlOut = malloc(strlen(s.ptr)+1);
if (*xmlOut == NULL)
{
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
*xmlOut[0] = '\0';
strncpy(*xmlOut, s.ptr, s.len);
//printf("%d..%d..%s\n", s.len, strlen(s.ptr), s.ptr);
free(s.ptr);
curl_easy_reset(curlHandle);
/* free the header list */
curl_slist_free_all(headers);
/* Clean-up libcurl */
curl_easy_cleanup(curlHandle);
//DLcurl_global_cleanup();
}
else {
exitStatus = 1;
}
free(curlErrStr);
free(postData);
/* Return the exit status */
return exitStatus;
}
int main(int argc, char* argv[])
{
int exitStatus = 0;
char * xmlOut;
int r;
for (r=0; r < 5; r++)
{
httpPostData(&xmlOut);
printf("%s...", xmlOut);
free (xmlOut);
getchar();
printf("=============");
}
return exitStatus;
}
====== end of c file for static link ====
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2013-03-10