curl: Set fallback CA paths in swupd_curl_init()

Curl initialization were split in 2 different functions, swupd_curl_init(),
that creates the curl handles and swupd_curl_check_network() that checks the
network and set alternative CA paths, if needed.

Merging those two functions in one to perform all curl initialization all at
once.

Also fixes:
 - Fix cases where curl was used before calling swupd_curl_check_network() and
   then the correct CA path wasn't set.
 - Don't use #ifdef FALLBACK_CAPATHS because FALLBACK_CAPATHS is always defined.
   It's set to an empty string if fallback ca paths are disabled.
 - Don't use extra memory to duplicate content of FALLBACK_CAPATHS and store
   it in a global.
This commit is contained in:
Otavio Pontes
2018-07-13 16:15:41 -07:00
committed by Matthew Johnson
parent b00fedecbe
commit cd406409f8
12 changed files with 59 additions and 142 deletions
-6
View File
@@ -53,12 +53,6 @@ int list_installable_bundles()
int current_version;
bool mix_exists;
int ret = swupd_curl_check_network();
if (ret) {
fprintf(stderr, "Error: Network issue, unable to download manifest\n");
return ret;
}
current_version = get_current_version(path_prefix);
if (current_version < 0) {
fprintf(stderr, "Error: Unable to determine current OS version\n");
-6
View File
@@ -139,12 +139,6 @@ static int check_update()
}
swupd_curl_init();
int ret = swupd_curl_check_network();
if (ret) {
fprintf(stderr, "Error: Network issue, unable to check for update\n");
return ret;
}
read_versions(&current_version, &server_version, path_prefix);
if (server_version < 0) {
+56 -92
View File
@@ -48,10 +48,8 @@
static CURL *curl = NULL;
/* these are used to handle alternative trust locations */
static char *capath;
static char **fallback_capaths;
static char fallback_capaths_no;
/* alternative CA Path */
static char *capath = NULL;
/* Pretty print curl return status */
static void swupd_curl_strerror(CURLcode curl_ret)
@@ -59,9 +57,50 @@ static void swupd_curl_strerror(CURLcode curl_ret)
fprintf(stderr, "Curl error: (%d) %s\n", curl_ret, curl_easy_strerror(curl_ret));
}
static int check_connection(const char *test_capath)
{
CURLcode curl_ret;
curl_ret = curl_easy_setopt(curl, CURLOPT_URL, version_url);
if (curl_ret != CURLE_OK) {
return -1;
}
curl_ret = curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
if (curl_ret != CURLE_OK) {
return -1;
}
if (test_capath) {
curl_ret = curl_easy_setopt(curl, CURLOPT_CAPATH, test_capath);
if (curl_ret != CURLE_OK) {
return -1;
}
}
curl_ret = curl_easy_perform(curl);
switch (curl_ret) {
case CURLE_OK:
return 0;
case CURLE_SSL_CACERT:
fprintf(stderr, "Error: unable to verify server SSL certificate\n");
return -EBADCERT;
default:
swupd_curl_strerror(curl_ret);
/* something bad, stop */
return -1;
}
}
int swupd_curl_init(void)
{
CURLcode curl_ret;
char *str;
char *tok;
char *ctx;
int ret;
struct stat st;
curl_ret = curl_global_init(CURL_GLOBAL_ALL);
if (curl_ret != CURLE_OK) {
@@ -76,20 +115,13 @@ int swupd_curl_init(void)
return -1;
}
#ifdef FALLBACK_CAPATHS
/* parse and initialize CA paths. */
{
char *str = strdup(FALLBACK_CAPATHS);
char *tok;
char *ctx;
struct stat st;
int i;
int sz = 1;
fallback_capaths = (char **)malloc(sz * sizeof(char *));
fallback_capaths[0] = NULL;
i = 1;
ret = check_connection(NULL);
if (ret == 0) {
return 0;
}
if (FALLBACK_CAPATHS[0]) {
str = strdup_or_die(FALLBACK_CAPATHS);
for (tok = strtok_r(str, ":", &ctx); tok; tok = strtok_r(NULL, ":", &ctx)) {
if (stat(tok, &st)) {
continue;
@@ -97,87 +129,16 @@ int swupd_curl_init(void)
if ((st.st_mode & S_IFMT) != S_IFDIR) {
continue;
}
if (i == sz) {
sz <<= 1;
fallback_capaths = (char **)realloc(fallback_capaths, sz * sizeof(char *));
}
fallback_capaths[i] = strdup(tok);
i++;
}
fallback_capaths_no = i;
free_string(&str);
}
#else
fallback_capaths = (char **)malloc(sizeof(char *));
fallback_capaths[0] = NULL;
fallback_capaths_no = 1;
#endif
return 0;
}
int swupd_curl_check_network(void)
{
CURLcode curl_ret;
int ret = -1;
int i;
CURL *c;
static int has_network = 0;
if (has_network) {
return 0;
}
if (!curl) {
return -1;
}
c = curl_easy_duphandle(curl);
if (!c) {
return -1;
}
for (i = 0; i < fallback_capaths_no; i++) {
curl_easy_reset(c);
curl_ret = curl_easy_setopt(c, CURLOPT_URL, version_url);
if (curl_ret != CURLE_OK) {
goto cleanup;
}
curl_ret = curl_easy_setopt(c, CURLOPT_NOBODY, 1L);
if (curl_ret != CURLE_OK) {
goto cleanup;
}
if (i) { /* first element represents default CApath, means no explicit setting */
curl_ret = curl_easy_setopt(c, CURLOPT_CAPATH, fallback_capaths[i]);
if (curl_ret != CURLE_OK) {
ret = check_connection(tok);
if (ret == 0) {
capath = strdup_or_die(tok);
break;
}
}
curl_ret = curl_easy_perform(c);
switch (curl_ret) {
case CURLE_OK:
capath = fallback_capaths[i];
ret = 0;
has_network = 1;
goto cleanup;
case CURLE_SSL_CACERT:
fprintf(stderr, "Error: unable to verify server SSL certificate\n");
ret = EBADCERT;
break;
default:
swupd_curl_strerror(curl_ret);
/* something bad, stop */
goto cleanup;
}
free_string(&str);
}
cleanup:
curl_easy_cleanup(c);
return ret;
}
@@ -187,6 +148,9 @@ void swupd_curl_deinit(void)
curl_easy_cleanup(curl);
}
curl = NULL;
free_string(&capath);
curl_global_cleanup();
}
-6
View File
@@ -472,12 +472,6 @@ static int retrieve_manifests(int current, int version, char *component, struct
}
free_string(&filename);
ret = swupd_curl_check_network();
if (ret) {
ret = -ret;
goto out;
}
string_or_die(&dir, "%s/%i", state_dir, version);
ret = mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if ((ret != 0) && (errno != EEXIST)) {
-5
View File
@@ -109,11 +109,6 @@ int download_subscribed_packs(struct list *subs, struct manifest *mom, bool requ
unsigned int list_length = list_len(subs);
unsigned int complete = 0;
int ret = swupd_curl_check_network();
if (ret) {
return -ret;
}
fprintf(stderr, "Downloading packs...\n");
iter = list_head(subs);
while (iter) {
-6
View File
@@ -870,12 +870,6 @@ int search_main(int argc, char **argv)
return ret;
}
ret = swupd_curl_check_network();
if (ret) {
fprintf(stderr, "Error: Network issue, unable to proceed with update\n");
goto clean_exit;
}
if (!init) {
fprintf(stderr, "Searching for '%s'\n\n", search_string);
}
-1
View File
@@ -295,7 +295,6 @@ extern int update_device_latest_version(int version);
extern int swupd_curl_init(void);
extern void swupd_curl_deinit(void);
extern int swupd_curl_check_network(void);
extern double swupd_query_url_content_size(char *url);
extern CURLcode swupd_download_file_start(struct file *file);
extern CURLcode swupd_download_file_complete(CURLcode curl_ret, struct file *file);
-6
View File
@@ -236,12 +236,6 @@ static int main_update()
clock_gettime(CLOCK_MONOTONIC_RAW, &ts_start);
grabtime_start(&times, "Main Update");
ret = swupd_curl_check_network();
if (ret) {
fprintf(stderr, "Error: Network issue, unable to proceed with update\n");
goto clean_curl;
}
mix_exists = check_mix_exists();
fprintf(stderr, "Update started.\n");
-6
View File
@@ -706,12 +706,6 @@ int verify_main(int argc, char **argv)
fprintf(stderr, "Verifying version %i\n", version);
ret = swupd_curl_check_network();
if (ret) {
fprintf(stderr, "Error: Network issue, unable to download manifest\n");
goto clean_and_exit;
}
read_subscriptions(&subs);
/*
-5
View File
@@ -147,11 +147,6 @@ int check_versions(int *current_version,
int requested_version,
char *path_prefix)
{
if (swupd_curl_check_network()) {
return -1;
}
read_versions(current_version, server_version, path_prefix);
if (*current_version < 0) {
@@ -1,2 +1,2 @@
Unable to get latest version for install
Error: Fix did not fully succeed
Curl error: (37) Couldn't read a file:// file
Failed verify initialization, exiting now.
@@ -5,7 +5,7 @@ load "../../swupdlib"
@test "verify install using latest with missing version file on server" {
run sudo sh -c "$SWUPD verify $SWUPD_OPTS --install -m latest"
check_lines "$output"
check_lines "$(echo "$output" | uniq)"
}
# vi: ft=sh ts=8 sw=2 sts=2 et tw=80