cURL / Mailing Lists / curl-library / Single Mail

curl-library

curl_easy_perform() fails with "Problem with the SSL CA cert (path? access rights?)" after first time calling this routine

From: cnm marketing <cnn.marketing_at_gmail.com>
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