diff options
-rw-r--r-- | configure.ac | 41 | ||||
-rw-r--r-- | libopkg/Makefile.am | 2 | ||||
-rw-r--r-- | libopkg/opkg_conf.c | 22 | ||||
-rw-r--r-- | libopkg/opkg_conf.h | 16 | ||||
-rw-r--r-- | libopkg/opkg_download.c | 182 |
5 files changed, 231 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac index 579a105..95233b5 100644 --- a/configure.ac +++ b/configure.ac @@ -15,6 +15,9 @@ for top_builddir in . .. ../.. $ac_auxdir $ac_auxdir/..; do test -f $top_builddir/configure && break done +# large file support can be useful for gpgme +AC_SYS_LARGEFILE + # Checks for programs AC_PROG_AWK @@ -55,8 +58,44 @@ AC_ARG_ENABLE(openssl, [want_openssl="$enableval"], [want_openssl="no"]) if test "x$want_openssl" = "xyes"; then - PKG_CHECK_MODULES(OPENSSL, openssl) AC_DEFINE(HAVE_OPENSSL, 1, [Define if you want OpenSSL support]) + NEED_SSL_LIBS="yes" +fi + +# check for libssl-curl +AC_ARG_ENABLE(ssl-curl, + AC_HELP_STRING([--enable-ssl-curl], [Enable certificate authentication with curl + [[default="$default_sslcurl"]] ]), + [want_sslcurl="$enableval"], [want_sslcurl="yes"]) + +if test "x$want_curl" = "xyes" -a "x$want_sslcurl" = "xyes"; then + AC_DEFINE(HAVE_CURL, 1, [Define if you want CURL support]) + AC_DEFINE(HAVE_SSLCURL, 1, [Define if you want certificate authentication with curl]) + NEED_SSL_LIBS="yes" +fi + +if test "x$NEED_SSL_LIBS" = "xyes"; then + AC_MSG_CHECKING([if openssl is available]) + + PKG_CHECK_MODULES(OPENSSL, openssl, [:], [:]) + if test "x$OPENSSL_LIBS" != "x"; then + AC_MSG_RESULT(yes) + else + OPENSSL_LIBS="-lcrypto -lssl" + dnl If pkg-config fails, run compile/link test. + AC_TRY_LINK([ +#include <openssl/opensslv.h> +], [ +return OPENSSL_VERSION_NUMBER; ], + [ + AC_MSG_RESULT(yes) + + ], [ + AC_MSG_RESULT(no) + AC_MSG_ERROR(OpenSSL not found) + ]) + fi + AC_SUBST(OPENSSL_LIBS) fi diff --git a/libopkg/Makefile.am b/libopkg/Makefile.am index 28fdeb9..555b0e5 100644 --- a/libopkg/Makefile.am +++ b/libopkg/Makefile.am @@ -40,7 +40,7 @@ libopkg_la_SOURCES = \ $(opkg_cmd_sources) $(opkg_db_sources) \ $(opkg_util_sources) $(opkg_list_sources) -libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS) +libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) # make sure we only export symbols that are for public use libopkg_la_LDFLAGS = -export-symbols-regex "^opkg_.*" diff --git a/libopkg/opkg_conf.c b/libopkg/opkg_conf.c index 2739861..4ea15d6 100644 --- a/libopkg/opkg_conf.c +++ b/libopkg/opkg_conf.c @@ -79,6 +79,17 @@ int opkg_init_options_array(const opkg_conf_t *conf, opkg_option_t **options) { "signature_ca_file", OPKG_OPT_TYPE_STRING, &conf->signature_ca_file }, { "signature_ca_path", OPKG_OPT_TYPE_STRING, &conf->signature_ca_path }, #endif +#if defined(HAVE_SSLCURL) && defined(HAVE_CURL) + { "ssl_engine", OPKG_OPT_TYPE_STRING, &conf->ssl_engine }, + { "ssl_cert", OPKG_OPT_TYPE_STRING, &conf->ssl_cert }, + { "ssl_cert_type", OPKG_OPT_TYPE_STRING, &conf->ssl_cert_type }, + { "ssl_key", OPKG_OPT_TYPE_STRING, &conf->ssl_key }, + { "ssl_key_type", OPKG_OPT_TYPE_STRING, &conf->ssl_key_type }, + { "ssl_key_passwd", OPKG_OPT_TYPE_STRING, &conf->ssl_key_passwd }, + { "ssl_ca_file", OPKG_OPT_TYPE_STRING, &conf->ssl_ca_file }, + { "ssl_ca_path", OPKG_OPT_TYPE_STRING, &conf->ssl_ca_path }, + { "ssl_dont_verify_peer", OPKG_OPT_TYPE_BOOL, &conf->ssl_dont_verify_peer }, +#endif { NULL } }; @@ -376,6 +387,17 @@ void opkg_conf_deinit(opkg_conf_t *conf) opkg_conf_free_string(&conf->signature_ca_path); #endif +#if defined(HAVE_SSLCURL) + opkg_conf_free_string(&conf->ssl_engine); + opkg_conf_free_string(&conf->ssl_cert); + opkg_conf_free_string(&conf->ssl_cert_type); + opkg_conf_free_string(&conf->ssl_key); + opkg_conf_free_string(&conf->ssl_key_type); + opkg_conf_free_string(&conf->ssl_key_passwd); + opkg_conf_free_string(&conf->ssl_ca_file); + opkg_conf_free_string(&conf->ssl_ca_path); +#endif + if (conf->verbosity > 1) { int i; hash_table_t *hashes[] = { diff --git a/libopkg/opkg_conf.h b/libopkg/opkg_conf.h index 4bd50e5..ecfe9ea 100644 --- a/libopkg/opkg_conf.h +++ b/libopkg/opkg_conf.h @@ -75,6 +75,22 @@ struct opkg_conf int noaction; char *cache; +#ifdef HAVE_SSLCURL + /* some options could be used by + * wget if curl support isn't builtin + * If someone want to try... + */ + char *ssl_engine; + char *ssl_cert; + char *ssl_cert_type; + char *ssl_key; + char *ssl_key_type; + char *ssl_key_passwd; + char *ssl_ca_file; + char *ssl_ca_path; + int ssl_dont_verify_peer; +#endif + /* proxy options */ char *http_proxy; char *ftp_proxy; 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 |