Skip to content
This repository has been archived by the owner on Jun 25, 2019. It is now read-only.

Commit

Permalink
CVE: work around libcurl-native CA cert file bug
Browse files Browse the repository at this point in the history
This works around the failing CVE database update because of
a failed SSL certificate check caused by the invalid file path
embedded in libcurl (https://bugzilla.yoctoproject.org/show_bug.cgi?id=9883)

isafw.py ensures that ca-certificates-native is installed and then
instructs plugins to use that ca-certificate.crt file. This is only
needed for the cve-check-tool, but gets set up for all plugins just in
case.

That path is then passed through to the patched cve-check-tool, which
overrides the default (and broken) path in libcurl.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
  • Loading branch information
pohly committed Jul 6, 2016
1 parent 190e5c2 commit d844f37
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 3 deletions.
13 changes: 11 additions & 2 deletions classes/isafw.bbclass
Expand Up @@ -23,7 +23,7 @@ ISAFW_LA_PLUGIN_IMAGE_BLACKLIST ?= ""

# First, code to handle scanning each recipe that goes into the build

do_analysesource[depends] += "cve-check-tool-native:do_populate_sysroot"
do_analysesource[depends] += "cve-check-tool-native:do_populate_sysroot ca-certificates-native:do_populate_sysroot"
do_analysesource[depends] += "rpm-native:do_populate_sysroot"
do_analysesource[depends] += "python-lxml-native:do_populate_sysroot"
do_analysesource[nostamp] = "1"
Expand Down Expand Up @@ -173,7 +173,7 @@ python analyse_image() {
imageSecurityAnalyser.process_filesystem(fs)
}

do_rootfs[depends] += "checksec-native:do_populate_sysroot"
do_rootfs[depends] += "checksec-native:do_populate_sysroot ca-certificates-native:do_populate_sysroot"
do_rootfs[depends] += "prelink-native:do_populate_sysroot"
do_rootfs[depends] += "python-lxml-native:do_populate_sysroot"
analyse_image[fakeroot] = "1"
Expand All @@ -184,6 +184,15 @@ def isafw_init(isafw, d):

isafw_config = isafw.ISA_config()
isafw_config.proxy = d.getVar('HTTP_PROXY', True)
# Override the builtin default in curl-native (used by cve-check-tool-native)
# because that default is a path that may not be valid: when curl-native gets
# installed from sstate, we end up with the sysroot path as it was on the
# original build host, which is not necessarily the same path used now
# (see https://bugzilla.yoctoproject.org/show_bug.cgi?id=9883).
#
# Can't use ${sysconfdir} here, it already includes ${STAGING_DIR_NATIVE}
# when the current recipe is native.
isafw_config.cacert = d.expand('${STAGING_DIR_NATIVE}/etc/ssl/certs/ca-certificates.crt')
if not isafw_config.proxy :
isafw_config.proxy = d.getVar('http_proxy', True)
bb.debug(1, 'isafw: proxy is %s' % isafw_config.proxy)
Expand Down
1 change: 1 addition & 0 deletions lib/isafw/isafw.py
Expand Up @@ -105,6 +105,7 @@ class ISA_config:
plugin_whitelist = "" # comma separated list of plugins to whitelist
plugin_blacklist = "" # comma separated list of plugins to blacklist
proxy = "" # proxy settings
cacert = None # If set, a CA certificate file that replaces the system default one
reportdir = "" # location of produced reports
logdir = "" # location of produced logs
timestamp = "" # timestamp of the build provided by build system
Expand Down
3 changes: 3 additions & 0 deletions lib/isafw/isaplugins/ISA_cve_plugin.py
Expand Up @@ -39,6 +39,7 @@ class ISA_CVEChecker:

def __init__(self, ISA_config):
self.proxy = ISA_config.proxy
self.cacert = ISA_config.cacert
self.reportdir = ISA_config.reportdir
self.timestamp = ISA_config.timestamp
self.logfile = ISA_config.logdir + "/isafw_cvelog"
Expand Down Expand Up @@ -162,6 +163,8 @@ def process_report_type(self, rtype):
if self.proxy:
args += "https_proxy=%s http_proxy=%s " % (self.proxy, self.proxy)
args += "cve-check-tool "
if self.cacert:
args += "--cacert '%s' " % self.cacert
if rtype != "html":
args += "-c "
rtype = "csv"
Expand Down
4 changes: 3 additions & 1 deletion recipes-devtools/cve-check-tool/cve-check-tool_5.6.4.bb
Expand Up @@ -6,7 +6,9 @@ SECTION = "Development/Tools"
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=e8c1458438ead3c34974bc0be3a03ed6"

SRC_URI = "https://github.com/ikeydoherty/${BPN}/releases/download/v${PV}/${BP}.tar.xz"
SRC_URI = "https://github.com/ikeydoherty/${BPN}/releases/download/v${PV}/${BP}.tar.xz \
file://curl-allow-overriding-default-CA-certificate-file.patch \
"

SRC_URI[md5sum] = "c5f4247140fc9be3bf41491d31a34155"
SRC_URI[sha256sum] = "b8f283be718af8d31232ac1bfc10a0378fb958aaaa49af39168f8acf501e6a5b"
Expand Down
@@ -0,0 +1,205 @@
From 8ccce4f14e62fc118cc76c06c064bbbe8e5e9485 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Wed, 6 Jul 2016 09:49:12 +0200
Subject: [PATCH] curl: allow overriding default CA certificate file

Similar to curl, --cacert can now be used in cve-check-tool and
cve-check-update to override the default CA certificate file. Useful
in cases where the system default is unsuitable (for example,
out-dated) or broken (as in OE's current native libcurl, which embeds
a path string from one build host and then uses it on another although
the right path may have become something different).

Upstream-Status: Submitted [https://github.com/ikeydoherty/cve-check-tool/pull/45]

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
---
src/library/cve-check-tool.h | 1 +
src/library/fetch.c | 9 ++++++++-
src/library/fetch.h | 2 +-
src/main.c | 5 ++++-
src/update-main.c | 4 +++-
src/update.c | 10 +++++-----
src/update.h | 2 +-
7 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/src/library/cve-check-tool.h b/src/library/cve-check-tool.h
index e4bb5b1..f89eade 100644
--- a/src/library/cve-check-tool.h
+++ b/src/library/cve-check-tool.h
@@ -43,6 +43,7 @@ typedef struct CveCheckTool {
bool bugs; /**<Whether bug tracking is enabled */
GHashTable *mapping; /**<CVE Mapping */
const char *output_file; /**<Output file, if any */
+ const char *cacert_file; /**<Non-default SSL certificate file, if any */
} CveCheckTool;

/**
diff --git a/src/library/fetch.c b/src/library/fetch.c
index 06d4b30..ed9bca9 100644
--- a/src/library/fetch.c
+++ b/src/library/fetch.c
@@ -37,7 +37,7 @@ static size_t write_func(void *ptr, size_t size, size_t nmemb, struct fetch_t *f
return fwrite(ptr, size, nmemb, f->f);
}

-FetchStatus fetch_uri(const char *uri, const char *target, bool verbose)
+FetchStatus fetch_uri(const char *uri, const char *target, bool verbose, const char *cacert_file)
{
FetchStatus ret = FETCH_STATUS_FAIL;
CURLcode res;
@@ -50,6 +50,13 @@ FetchStatus fetch_uri(const char *uri, const char *target, bool verbose)
return ret;
}

+ if (cacert_file) {
+ res = curl_easy_setopt(curl, CURLOPT_CAINFO, cacert_file);
+ if (res != CURLE_OK) {
+ goto bail;
+ }
+ }
+
if (stat(target, &st) == 0) {
res = curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
if (res != CURLE_OK) {
diff --git a/src/library/fetch.h b/src/library/fetch.h
index 70c3779..bc3355e 100644
--- a/src/library/fetch.h
+++ b/src/library/fetch.h
@@ -28,7 +28,7 @@ typedef enum {
* @param verbose Whether to be verbose
* @return A FetchStatus, indicating the operation taken
*/
-FetchStatus fetch_uri(const char *uri, const char *target, bool verbose);
+FetchStatus fetch_uri(const char *uri, const char *target, bool verbose, const char *cacert_file);

/**
* Attempt to extract the given gzipped file
diff --git a/src/main.c b/src/main.c
index 8e6f158..fbf1c95 100644
--- a/src/main.c
+++ b/src/main.c
@@ -280,6 +280,7 @@ static bool csv_mode = false;
static char *modified_stamp = NULL;
static gchar *mapping_file = NULL;
static gchar *output_file = NULL;
+static gchar *cacert_file = NULL;

static GOptionEntry _entries[] = {
{ "not-patched", 'n', 0, G_OPTION_ARG_NONE, &hide_patched, "Hide patched/addressed CVEs", NULL },
@@ -294,6 +295,7 @@ static GOptionEntry _entries[] = {
{ "csv", 'c', 0, G_OPTION_ARG_NONE, &csv_mode, "Output CSV formatted data only", NULL },
{ "mapping", 'M', 0, G_OPTION_ARG_STRING, &mapping_file, "Path to a mapping file", NULL},
{ "output-file", 'o', 0, G_OPTION_ARG_STRING, &output_file, "Path to the output file (output plugin specific)", NULL},
+ { "cacert", 'C', 0, G_OPTION_ARG_STRING, &cacert_file, "Path to the combined SSL certificates file (system default is used if not set)", NULL},
{ .short_name = 0 }
};

@@ -492,6 +494,7 @@ int main(int argc, char **argv)

quiet = csv_mode || !no_html;
self->output_file = output_file;
+ self->cacert_file = cacert_file;

if (!csv_mode && self->output_file) {
quiet = false;
@@ -530,7 +533,7 @@ int main(int argc, char **argv)
if (status) {
fprintf(stderr, "Update of db forced\n");
cve_db_unlock();
- if (!update_db(quiet, db_path->str)) {
+ if (!update_db(quiet, db_path->str, self->cacert_file)) {
fprintf(stderr, "DB update failure\n");
goto cleanup;
}
diff --git a/src/update-main.c b/src/update-main.c
index 2379cfa..c52d9d0 100644
--- a/src/update-main.c
+++ b/src/update-main.c
@@ -43,11 +43,13 @@ the Free Software Foundation; either version 2 of the License, or\n\
static gchar *nvds = NULL;
static bool _show_version = false;
static bool _quiet = false;
+static const char *_cacert_file = NULL;

static GOptionEntry _entries[] = {
{ "nvd-dir", 'd', 0, G_OPTION_ARG_STRING, &nvds, "NVD directory in filesystem", NULL },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &_show_version, "Show version", NULL },
{ "quiet", 'q', 0, G_OPTION_ARG_NONE, &_quiet, "Run silently", NULL },
+ { "cacert", 'C', 0, G_OPTION_ARG_STRING, &_cacert_file, "Path to the combined SSL certificates file (system default is used if not set)", NULL},
{ .short_name = 0 }
};

@@ -88,7 +90,7 @@ int main(int argc, char **argv)
goto end;
}

- if (update_db(_quiet, db_path->str)) {
+ if (update_db(_quiet, db_path->str, _cacert_file)) {
ret = EXIT_SUCCESS;
} else {
fprintf(stderr, "Failed to update database\n");
diff --git a/src/update.c b/src/update.c
index 30fbe96..7c4d635 100644
--- a/src/update.c
+++ b/src/update.c
@@ -266,7 +266,7 @@ static inline void update_end(int fd, const char *update_fname, bool ok)
}

static int do_fetch_update(int year, const char *db_dir, CveDB *cve_db,
- bool db_exist, bool verbose)
+ bool db_exist, bool verbose, const char *cacert_file)
{
const char nvd_uri[] = URI_PREFIX;
autofree(cve_string) *uri_meta = NULL;
@@ -330,14 +330,14 @@ refetch:
}

/* Fetch NVD META file */
- st = fetch_uri(uri_meta->str, nvdcve_meta->str, verbose);
+ st = fetch_uri(uri_meta->str, nvdcve_meta->str, verbose, cacert_file);
if (st == FETCH_STATUS_FAIL) {
fprintf(stderr, "Failed to fetch %s\n", uri_meta->str);
return -1;
}

/* Fetch NVD XML file */
- st = fetch_uri(uri_data_gz->str, nvdcve_data_gz->str, verbose);
+ st = fetch_uri(uri_data_gz->str, nvdcve_data_gz->str, verbose, cacert_file);
switch (st) {
case FETCH_STATUS_FAIL:
fprintf(stderr, "Failed to fetch %s\n", uri_data_gz->str);
@@ -390,7 +390,7 @@ refetch:
return 0;
}

-bool update_db(bool quiet, const char *db_file)
+bool update_db(bool quiet, const char *db_file, const char *cacert_file)
{
autofree(char) *db_dir = NULL;
autofree(CveDB) *cve_db = NULL;
@@ -460,7 +460,7 @@ bool update_db(bool quiet, const char *db_file)
int y = i > year ? -1 : i;
int rc;

- rc = do_fetch_update(y, db_dir, cve_db, db_exist, !quiet);
+ rc = do_fetch_update(y, db_dir, cve_db, db_exist, !quiet, cacert_file);
switch (rc) {
case 0:
continue;
diff --git a/src/update.h b/src/update.h
index b8e9911..ceea0c3 100644
--- a/src/update.h
+++ b/src/update.h
@@ -15,7 +15,7 @@ cve_string *get_db_path(const char *path);

int update_required(const char *db_file);

-bool update_db(bool quiet, const char *db_file);
+bool update_db(bool quiet, const char *db_file, const char *cacert_file);


/*
--
2.1.4

0 comments on commit d844f37

Please sign in to comment.