Including libcurl in C project - c

This is my very first C program and I'm using this example libcurl code from their website:
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://google.com/");
#ifdef SKIP_PEER_VERIFICATION
/*
* If you want to connect to a site who isn't using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
* verification of the server's certificate. This makes the connection
* A LOT LESS SECURE.
*
* If you have a CA cert for the server stored someplace else than in the
* default bundle, then the CURLOPT_CAPATH option might come handy for
* you.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
#ifdef SKIP_HOSTNAME_VERFICATION
/*
* If the site you're connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
So in xcode I created a "group" called it curl and added all the files in the curl directory:
And now I'm getting these Build errors:
What am I doing wrong? Any advice would help, thanks!

Mac OS X comes with a copy of libcurl, so your application doesn't need its own copy.
You didn't mention the version of Xcode you're using. The following applies to 3.2, but may not work in 4.
To use the version of libcurl provided by the system, go to Project, then Add To Project. In the dialog that comes up, type /usr/lib and press enter. Find libcurl.dylib in the list of files and click Add.

For Xcode 4.5:
Click on the project in the left pane.
Click on the target.
Go to the "Build Phases" section.
Under "Link Binary with Libraries", click the plus sign.
From there you should be able to search for "libcurl.dylib".
Now when you build it should be able to link to the library.

For XCode 7, just right click on the project or group you want to put the lib in, then select Add Files to "Project Name"..., and finally find the libcurl.dylib in /usr/lib directory.

Related

I'm getting Curl error code 4 in C program but I can't figure out what is wrong

I'm new to curl library, I installed it yesterday from GitHub, I followed the steps to download it and everything seems good by checking the supported protocols; but when I'm trying to use the library in a C program to download data from a https link I get the error 4.
Supported protocols, nothing looks wrong:
curl 7.83.0-DEV (x86_64-pc-linux-gnu) libcurl/7.83.0-DEV OpenSSL/1.1.1m zlib/1.2.11
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets
But when I try to run my C program I get this:
./test https://google.com
ERROR: A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision.
The code I wrote is this:
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
void main(int argc, char *argv[])
{
CURL *curl = curl_easy_init();
int success = 0;
FILE *data = fopen("data", "wb");
if(data==NULL)
{
printf("Error making file for data to be stored.\n");
exit(1);
}
curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, data);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
success = curl_easy_perform(curl);
if(success==CURLE_OK)
printf("Download successful.\n");
else
printf("ERROR: %s\n", curl_easy_strerror(success));
fclose(data);
curl_easy_cleanup(curl);
}
type here
Someone know what is wrong??
The linked system libcurl.so runtime is another one than 7.83.0-DEV.
sudo apt intstall ibcurl4-openssl-dev
or
sudo apt intstall libcurl4-gnutls-dev

cURL crashing in release mode, not in debug

I have used cURL in my app. It works fine (no errors) in debug mode. However, if i switch code to Release build, app start crashing. I am using VC 2013
My code:
data_downloads.curl = curl_easy_init();
data_downloads.curlData = (CURL_DOWNLOADED_DATA *)malloc(sizeof(CURL_DOWNLOADED_DATA));
data_downloads.curlData->data = (char *)malloc(sizeof(char));
data_downloads.curlData->data[0] = '\0';
curl_easy_setopt(data_downloads.curl, CURLOPT_WRITEFUNCTION, &my_curl_writeCallback);
curl_easy_setopt(data_downloads.curl, CURLOPT_WRITEDATA, data_downloads->curlData);
curl_easy_setopt(data_downloads.curl, CURLOPT_VERBOSE, 1L); //tell curl to output its progress
curl_easy_setopt(data_downloads.curl, CURLOPT_URL, USER_INFO_URL);
curl_easy_setopt(data_downloads.curl, CURLOPT_COOKIEFILE, "cookie.txt");
curl_easy_perform(data_downloads.curl); //-- it crashes here
I noticed that in debug mode, VC adds some space to the stack at every of your functions. Would a function briefly be out of bounds and overwrite a few bytes of the stack, then this will not be noticed...until you compile for release.
You should further check that all libraries for the release mode are the proper ones. VC knows many library types for many models (for DLLs, multi-threaded/not, ...). Check them against the libraries for your debugging mode.
These are the issues I came across. There may be other issues.

C code for file downloading from internet using curl

I saw some c codes relative to the topic. I've tried them but only I get errors saying a heap of errors of curl.h. I googled much but couldn't find a good answer. I'm using CCS C compiler version v5.008. I really want to solve this problem soon.
I tried to compile the code from the following link.
enter link description here
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
/* 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));
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
Gives me error: "Error 119"C:\Users\Sisitha\Documents\CCS C Projects\ Testing\curl\curlbuild.h" Line 556(145,183): " Unknown non-configure build target" "
I'm on Windows 7(64bit)
Please help me to solve this matter.
Thanks!
curl uses GNU autotools to be built from source. There's a library to be built and configured, for the example program and header file, to link against. The error :
Error 119"C:\Users\Sisitha\Documents\CCS C Projects\ Testing\curl\curlbuild.h" Line 556(145,183): " Unknown non-configure build target"
Suggests that the curl.h you included, hasn't been configured, by the standard GNU ./configure; make; make install build sequence.
Curl installation instructions Install -- how to install curl

Serving multiple domains in one box with SNI

I'm using OpenSSL 0.9.8q in FreeBSD-8.2. I have 3 virtual hosts on my system and want to implement SNI to serve for all 3 of them in one server.
I have 3 separate certificates one for each, and in my ssl-server code I have to somehow find out what is the domain-name of client's request, and use the appropriate certificate file based on that. For this I wrote a function named get_ssl_servername_cb and passed it as callback function to SSL_CTX_set_tlsext_servername_callback. This way, in callback function I can get the the domain-name of the client's request.
But my problem is, this callback function is being executed after execution of SSL_accept function, but I have to choose and use the appropriate certificate before using SSL_new command, which is way before execution of SSL_accept.
So my question is, how can I use SSL_CTX_set_tlsext_servername_callback function for SNI?
but my problem is, this callback function is being executed after execution of "SSL_accept" function, but I have to choose and use the appropriate certificate before using "SSL_new" command, which is way before execution of SSL_accept.
When you start your server, you provide a default SSL_CTX. This is used for non-SNI clients, like SSLv3 clients and TLS clients that don't utilize SNI (like Windows XP). This is needed because the callback is not invoked in this situation.
Here are some examples to tickle the behavior using OpenSSL's s_client. To simulate a non-SNI client so that your get_ssl_servername_cb is not called, issue:
openssl s_client -connect localhost:8443 -ssl3 # SNI added at TLSv1
openssl s_client -connect localhost:8443 -tls1 # Windows XP client
To simulate a SNI client so that your get_ssl_servername_cb is called, issue:
openssl s_client -connect localhost:8443 -tls1 -servername localhost
You can also avoid the certificate verification errors by adding -CAfile. This is from one of my test scripts (for testing DSS/DSA certificates on localhost):
printf "GET / HTTP/1.1\r\n\r\n" | /usr/local/ssl/bin/openssl s_client \
-connect localhost:8443 -tls1 -servername localhost \
-CAfile pki/signing-dss-cert.pem
so my question is, how can I use "SSL_CTX_set_tlsext_servername_callback" function for SNI?
See the OpenSSL source code at <openssl dir>/apps/s_server.c; or see How to implement Server Name Indication(SNI) on OpenSSL in C or C++?.
In your get_ssl_servername_cb (set with SSL_CTX_set_tlsext_servername_callback), you examine the server name. One of two situations occur: you already have a SSL_CTX for the server's name, or you need to create a SSL_CTX for server's name.
Once you fetch the SSL_CTX from cache or create a new SSL_CTX, you then use SSL_set_SSL_CTX to swap in the context. There's an example of swapping in the new context in the OpenSSL source files. See the code for s_server.c (in <openssl dir>/apps/s_server.c). Follow the trail of ctx2,
Here's what it looks like in one of my projects. IsDomainInDefaultCert determines if the requested server name is provided by the default server certificate. If not, GetServerContext fetches the needed SSL_CTX. GetServerContext pulls the needed certificate out of an app-level cache; or creates it and puts it in the app-level cache (GetServerContext also asserts one reference count on the SSL_CTX so the OpenSSL library does not delete it from under the app).
static int ServerNameCallback(SSL *ssl, int *ad, void *arg)
{
UNUSED(ad);
UNUSED(arg);
ASSERT(ssl);
if (ssl == NULL)
return SSL_TLSEXT_ERR_NOACK;
const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
ASSERT(servername && servername[0]);
if (!servername || servername[0] == '\0')
return SSL_TLSEXT_ERR_NOACK;
/* Does the default cert already handle this domain? */
if (IsDomainInDefCert(servername))
return SSL_TLSEXT_ERR_OK;
/* Need a new certificate for this domain */
SSL_CTX* ctx = GetServerContext(servername);
ASSERT(ctx != NULL);
if (ctx == NULL)
return SSL_TLSEXT_ERR_NOACK;
/* Useless return value */
SSL_CTX* v = SSL_set_SSL_CTX(ssl, ctx);
ASSERT(v == ctx);
if (v != ctx)
return SSL_TLSEXT_ERR_NOACK;
return SSL_TLSEXT_ERR_OK;
}
In the code above, ad and arg are unused parameters. I don't know what ad does because I don't use it. arg can be used to pass in a context to the callback. I don't use arg either, but s_server.c uses it to print some debug information (the arg is a pointer to a BIOs tied to stderr (and a few others), IIRC).
For completeness, SSL_CTX are reference counted and they can be re-used. A newly created SSL_CTX has a count of 1, which is delegated to the OpenSSL internal caching mechanism. When you hand the SSL_CTX to a SSL object, the count increments to 2. When the SSL object calls SSL_CTX_free on the SSL_CTX, the function will decrement the reference count. If the context is expired and the reference count is 1, then the OpenSSL library will delete it from its internal cache.

Peer to Peer linux authentication in C

I have two embedded systems running Angstrom Linux that are connected via a Ethernet cross-over cable. I'm developing a C program that will allow the two systems to communicate with each other.
When the two computers talk to each other they first need to verify the identity of the other and encrypt the connection. I'm trying to use openssl to accomplish the authentication and encryption but I'm not totally sure what to do.
All the peer to peer questions are related to other languages or aren't related to openssl.
I’ve been trying to modify the code from An Introduction to OpenSSL Programming http://www.linuxjournal.com/article/4822 to get my embedded systems working, but haven’t been successful. The in the SSL_CTX *initialize_ctx which is in common.c and also load_dh_params(ctx,file) in server.c seem to be the problem areas. Here is my code for common.c with some of my modifications.
SSL_CTX *initialize_ctx(keyfile,password)
char *keyfile;
char *password;
{
SSL_METHOD *meth;
SSL_CTX *ctx;
char buffer[200];
if (!bio_err)
{
/* Global system initialization*/
SSL_library_init();
SSL_load_error_strings();
/* An error write context */
bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
}
debuglocation(__LINE__,__FILE__);
/* Set up a SIGPIPE handler */
signal(SIGPIPE,sigpipe_handle);
/* Create our context*/
meth=SSLv23_method();
ctx=SSL_CTX_new(meth);
debuglocation(__LINE__,__FILE__);
/* Load our keys and certificates*/
// if (!(SSL_CTX_use_certificate_chain_file(ctx,keyfile)))
// berr_exit("Can't read certificate file");
debuglocation(__LINE__,__FILE__);
pass=password;
/* TODO need to put a password on the key*/
//SSL_CTX_set_default_passwd_cb(ctx,password_cb);
//if (!(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM)))
//http://www.openssl.org/docs/ssl/SSL_CTX_use_certificate.html#NOTES
if(!(SSL_CTX_use_RSAPrivateKey_file(ctx,"private.pem", SSL_FILETYPE_PEM)))
berr_exit("Can't read priveate rsa");
debuglocation(__LINE__,__FILE__);
//berr_exit("Can't read key file");
// /* Load the CAs we trust*/
// if (!(SSL_CTX_load_verify_locations(ctx,
// CA_LIST,0)))
// berr_exit("Can't read CA list");
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
SSL_CTX_set_verify_depth(ctx,1);
#endif
return ctx;
}
And here is the server.c
void load_dh_params(ctx,file)
SSL_CTX *ctx;
char *file;
{
DH *ret=0;
BIO *bio;
//http://www.openssl.org/docs/crypto/BIO_s_file.html
// opens a file just like fopen with the second parameter as the type of open. Here it is read 'r'.
if ((bio=BIO_new_file(file,"r")) == NULL)
berr_exit("Couldn't open DH file");
//http://www.openssl.org/docs/crypto/pem.html
ret=PEM_read_bio_DHparams(bio,NULL,NULL,
NULL);
BIO_free(bio);
if(SSL_CTX_set_tmp_dh(ctx,ret)<0)
berr_exit("Couldn't set DH parameters");
}
My debuglocation function looks like this.
int debuglocation(int line, char * file)
{
static char c = 'A';
printf("Made it to line %d in %s call it %c\n",line,file, c);
c++;
return 0;
}
So when I run all that I get from the server.
2535:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1075:
And this from the client.
SSL connect error
2616:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:596:
Also I’m not sure what ssl commands to use to make the needed certificates.
It seemed like RSA would work well if both the embedded devices had one public and one priviate key, so I tried following http://www.devco.net/archives/2006/02/13/public_-_private_key_encryption_using_openssl.php
and made a script to make them for me.
openssl genrsa -out private.pem 1024
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
Thanks in advance for the help. If you need more information please let me know. I think that answers to this question could be really helpful to anyone developing in C for an embedded system who needs some authentication.
Anthony
As the user that runs the comm process, do ssh_keygen.
Append the public part of the output, id_rsa.pub, to the ~/.ssh/authorized_keys on the other machine. Now you can run remote programs using ssh without logging in.
Edit. I suggested the above because of the hassle of working with certs. You need to have a trust store, correct directory permissions, etc. I think the first thing you're missing is loading the data on trusted certificates. See the link on how to do that. It's easier to check the authorization using the command line tools in openssl then to debug your program and get the SSL set up at the same time.
I ended up using ssh rather than trying to use openssl. It did make life much simpler. Maybe when I have more time I will figure it out the other way.

Resources