summaryrefslogtreecommitdiffstats
path: root/libopkg/opkg_download.c
diff options
context:
space:
mode:
authorpixdamix <pixdamix@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>2009-11-03 04:27:03 (EST)
committer pixdamix <pixdamix@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>2009-11-03 04:27:03 (EST)
commitb3a54f7c2d686dbec049d3788f5096c01360c5c4 (patch)
treef7a52361829f8217214e0c232aa09a35be2e5a67 /libopkg/opkg_download.c
parent99caa6bb08baa6762a09547844277f77848b76c8 (diff)
Make `curl' an instance variable and ssl support
This patch adds several new options - option ssl_ca_path /path/to/dir Tells curl to use the specified certificate directory to verify the peer. The certificates must be in PEM format, and the directory must have been processed using the c_rehash utility supplied with openssl. - option ssl_ca_file Tells curl to use the specified certificate file to verify the peer. The file may contain multiple CA certificates - option ssl_key_type Tells curl the Private key file type. Specify which type your ssl_key provided private key is. PEM (default), DER and ENG (see option ssl_engine) are recognized types. - option ssl_cert_type Tells curl what certificate type the provided certificate is in. PEM (default), DER and ENG (see option ssl_engine) are recognized types. - option ssl_key & option ssl_cert Tells curl to use the specified certificate file and private key when getting a file with HTTPS - option ssl_key_passwd Passphrase for the private key - option ssl_engine Select the OpenSSL crypto engine to use for cipher operations. - option ssl_dont_verify_peer This option explicitly allows curl to perform "insecure" SSL connections and transfers. All SSL connections are attempted to be made secure by using the CA certificate. This makes all connections considered "insecure" fail unless ssl_dont_verify_peer is used. git-svn-id: http://opkg.googlecode.com/svn/trunk@251 e8e0d7a0-c8d9-11dd-a880-a1081c7ac358
Diffstat (limited to 'libopkg/opkg_download.c')
-rw-r--r--libopkg/opkg_download.c182
1 files changed, 152 insertions, 30 deletions
diff --git a/libopkg/opkg_download.c b/libopkg/opkg_download.c
index ee8dc08..33019d8 100644
--- a/libopkg/opkg_download.c
+++ b/libopkg/opkg_download.c
@@ -17,20 +17,25 @@
General Public License for more details.
*/
#include "config.h"
+
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
+
+#if defined(HAVE_SSLCURL) || defined(HAVE_OPENSSL)
+#include <openssl/conf.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#endif
+
#if defined(HAVE_GPGME)
#include <gpgme.h>
#elif defined(HAVE_OPENSSL)
#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/hmac.h>
-
#endif
#include "includes.h"
@@ -44,10 +49,22 @@
#include "str_util.h"
#include "opkg_defines.h"
+#if defined(HAVE_OPENSSL) || defined(HAVE_SSLCURL)
+static void openssl_init(void);
+#endif
#ifdef HAVE_OPENSSL
static X509_STORE *setup_verify(opkg_conf_t *conf, char *CAfile, char *CApath);
-static void init_openssl(void);
+#endif
+
+#ifdef HAVE_CURL
+/*
+ * Make curl an instance variable so we don't have to instanciate it
+ * each time
+ */
+static CURL *curl = NULL;
+static void opkg_curl_cleanup(void);
+static CURL *opkg_curl_init(opkg_conf_t *conf, curl_progress_func cb, void *data);
#endif
int opkg_download(opkg_conf_t *conf, const char *src,
@@ -99,27 +116,12 @@ int opkg_download(opkg_conf_t *conf, const char *src,
CURLcode res;
FILE * file = fopen (tmp_file_location, "w");
- curl = curl_easy_init ();
+ curl = opkg_curl_init (conf, cb, data);
if (curl)
{
curl_easy_setopt (curl, CURLOPT_URL, src);
curl_easy_setopt (curl, CURLOPT_WRITEDATA, file);
- curl_easy_setopt (curl, CURLOPT_NOPROGRESS, (cb == NULL));
- if (cb)
- {
- curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, data);
- curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, cb);
- }
- curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
- if (conf->http_proxy || conf->ftp_proxy)
- {
- char *userpwd;
- sprintf_alloc (&userpwd, "%s:%s", conf->proxy_user,
- conf->proxy_passwd);
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, userpwd);
- free (userpwd);
- }
+
res = curl_easy_perform (curl);
fclose (file);
if (res)
@@ -129,10 +131,8 @@ int opkg_download(opkg_conf_t *conf, const char *src,
opkg_message(conf, OPKG_ERROR, "Failed to download %s. \nerror detail: %s\n", src, curl_easy_strerror(res));
free(tmp_file_location);
free(src_basec);
- curl_easy_cleanup (curl);
return res;
}
- curl_easy_cleanup (curl);
}
else
@@ -396,7 +396,7 @@ opkg_verify_file (opkg_conf_t *conf, char *text_file, char *sig_file)
// Sig check failed by default !
int status = -1;
- init_openssl();
+ openssl_init();
// Set-up the key store
if(!(store = setup_verify(conf, conf->signature_ca_file, conf->signature_ca_path))){
@@ -454,6 +454,21 @@ verify_file_end:
}
+#if defined(HAVE_OPENSSL) || defined(HAVE_SSLCURL)
+static void openssl_init(void){
+ static int init = 0;
+
+ if(!init){
+ OPENSSL_config(NULL);
+ OpenSSL_add_all_algorithms();
+ ERR_load_crypto_strings();
+ init = 1;
+ }
+}
+
+#endif
+
+
#if defined HAVE_OPENSSL
static X509_STORE *setup_verify(opkg_conf_t *conf, char *CAfile, char *CApath){
X509_STORE *store = NULL;
@@ -509,13 +524,120 @@ end:
}
-static void init_openssl(void){
- static int init = 0;
+#endif
+
+#ifdef HAVE_CURL
+static void opkg_curl_cleanup(void){
+ if(curl != NULL){
+ curl_easy_cleanup (curl);
+ curl = NULL;
+ }
+}
+
+static CURL *opkg_curl_init(opkg_conf_t *conf, curl_progress_func cb, void *data){
+
+ if(curl == NULL){
+ curl = curl_easy_init();
+
+#ifdef HAVE_SSLCURL
+ openssl_init();
+
+ if (conf->ssl_engine) {
+
+ /* use crypto engine */
+ if (curl_easy_setopt(curl, CURLOPT_SSLENGINE, conf->ssl_engine) != CURLE_OK){
+ opkg_message(conf, OPKG_ERROR, "can't set crypto engine: '%s'\n",
+ conf->ssl_engine);
+
+ opkg_curl_cleanup();
+ return NULL;
+ }
+ /* set the crypto engine as default */
+ if (curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L) != CURLE_OK){
+ opkg_message(conf, OPKG_ERROR, "can't set crypto engine as default\n");
+
+ opkg_curl_cleanup();
+ return NULL;
+ }
+ }
+
+ /* cert & key can only be in PEM case in the same file */
+ if(conf->ssl_key_passwd){
+ if (curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, conf->ssl_key_passwd) != CURLE_OK)
+ {
+ opkg_message(conf, OPKG_DEBUG, "Failed to set key password\n");
+ }
+ }
+
+ /* sets the client certificate and its type */
+ if(conf->ssl_cert_type){
+ if (curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, conf->ssl_cert_type) != CURLE_OK)
+ {
+ opkg_message(conf, OPKG_DEBUG, "Failed to set certificate format\n");
+ }
+ }
+ /* SSL cert name isn't mandatory */
+ if(conf->ssl_cert){
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, conf->ssl_cert);
+ }
+
+ /* sets the client key and its type */
+ if(conf->ssl_key_type){
+ if (curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, conf->ssl_key_type) != CURLE_OK)
+ {
+ opkg_message(conf, OPKG_DEBUG, "Failed to set key format\n");
+ }
+ }
+ if(conf->ssl_key){
+ if (curl_easy_setopt(curl, CURLOPT_SSLKEY, conf->ssl_key) != CURLE_OK)
+ {
+ opkg_message(conf, OPKG_DEBUG, "Failed to set key\n");
+ }
+ }
+
+ /* Should we verify the peer certificate ? */
+ if(conf->ssl_dont_verify_peer){
+ /*
+ * CURLOPT_SSL_VERIFYPEER default is nonzero (curl => 7.10)
+ */
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+
+ /* certification authority file and/or path */
+ if(conf->ssl_ca_file){
+ curl_easy_setopt(curl, CURLOPT_CAINFO, conf->ssl_ca_file);
+ }
+ if(conf->ssl_ca_path){
+ curl_easy_setopt(curl, CURLOPT_CAPATH, conf->ssl_ca_path);
+ }
+#endif
+
+ curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
+ if (conf->http_proxy || conf->ftp_proxy)
+ {
+ char *userpwd;
+ sprintf_alloc (&userpwd, "%s:%s", conf->proxy_user,
+ conf->proxy_passwd);
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, userpwd);
+ free (userpwd);
+ }
+
+ /* add curl cleanup callback */
+ if(!atexit(opkg_curl_cleanup)){
+ opkg_message(conf,OPKG_DEBUG, "Failed to register atexit curl cleanup function\n");
+ }
- if(!init){
- OpenSSL_add_all_algorithms();
- ERR_load_crypto_strings();
- init = 1;
}
+
+ curl_easy_setopt (curl, CURLOPT_NOPROGRESS, (cb == NULL));
+ if (cb)
+ {
+ curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, data);
+ curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, cb);
+ }
+
+ return curl;
+
}
#endif