...
 
Commits (8)
FROM debian:stable
FROM debian:unstable
ENV HOME=/root
......
......@@ -25,6 +25,7 @@ libupdater_MODULES := \
embed_types \
events \
subprocess \
download \
journal \
locks \
picosat \
......
This diff is collapsed.
/*
* Copyright 2018, CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This file is part of the turris updater.
*
* Updater is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Updater is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Updater. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UPDATER_DOWNLOAD_H
#define UPDATER_DOWNLOAD_H
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <event2/event.h>
#include <curl/curl.h>
#include "logging.h"
struct download_i;
// Download manager object
struct downloader {
struct event_base *ebase; // libevent base
CURLM *cmulti; // Curl multi instance
struct event *ctimer; // Timer used by curl
struct download_i **instances; // Registered instances
size_t i_size, i_allocated; // instances size and allocated size
int pending; // Number of still not downloaded instances
struct download_i *failed; // Latest failed instance (used internally)
};
// Download options (additional options configuring security and more)
struct download_opts {
long timeout; // Download timeout (including download retries)
long connect_timeout; // Timeout for single connection
int retries; // Number of full download retries
bool follow_redirect; // If HTTP request 3xx should be followed
bool ssl_verify; // If SSL should be verified
bool ocsp; // If OCSP should be used for certificate verification
const char *cacert_file; // Path to custom CA certificate bundle
const char *capath; // Path to directory containing CA certificates
const char *crl_file; // Path to custom CA crl
};
enum download_output_type {
DOWN_OUT_T_FILE,
DOWN_OUT_T_BUFFER
};
// Download instance. Identifier of single download.
struct download_i {
bool done; // What ever is download finished
bool success; // If download was successful. Not valid if done is false.
char error[CURL_ERROR_SIZE]; // error message if download fails
int retries; // Number of reties we have
struct downloader *downloader; // parent downloader
enum download_output_type out_t; // What output this instance utilizes
union {
struct {
int fd; // File descriptor
char *fpath; // Path to output file
} *file; // Used when writing to file
struct {
uint8_t *data; // Buffer for output data
size_t size; // Amount of downloaded data
} *buff; // Used when writing to buffer
} out; // Output data
CURL *curl; // easy curl session
};
// Initialize new download manager
// parallel: Number of possible parallel downloadings
// Returns new instance of downloader
struct downloader *downloader_new(int parallel);
// Free given instance of downloader
void downloader_free(struct downloader*) __attribute__((nonnull));
// Run downloader and download all registered URLs
// return: NULL on success otherwise pointer to download instance that failed.
struct download_i *downloader_run(struct downloader*) __attribute__((nonnull));
// Remove all download instances from downloader
void downloader_flush(struct downloader*) __attribute__((nonnull));
// Set default values for download_opts
// opts: Allocated instance of download options to be set to defaults
// Note: strings in download_opts are set to NULL and previous values are NOT
// freed.
void download_opts_def(struct download_opts *opts) __attribute__((nonnull));
// Register given URL to be downloaded to file.
// url: URL data are downloaded from
// output_path: Path where data are going to be stored (written to)
// opts: Download options (does not have to exist during instance existence)
// Returns download instance
struct download_i *download_file(struct downloader *downloader, const char *url,
const char *output_path, const struct download_opts *opts)
__attribute__((nonnull(1, 2, 3, 4)));
// Register given URL to be downloaded to temporally file. Output file path is
// generated using mkstemp function.
// url: URL data are downloaded from
// output_template: Template for path where data are going to be stored (written
// to). Passed string has to end with XXXXXX and is modified to contain used
// path. This string should be freed only after download instance is freed.
// opts: Download options (does not have to exist during instance existence)
// Returns download instance
struct download_i *download_temp_file(struct downloader *downloader,
const char *url, char *output_template, const struct download_opts *opts)
__attribute__((nonnull(1, 2, 3, 4)));
// Register given URL to be downloaded to internal buffer.
// url: URL data are downloaded from
// opts: Download options (does not have to exist during instance existence)
// Returns download instance
struct download_i *download_data(struct downloader *downloader, const char *url,
const struct download_opts *opts) __attribute__((nonnull(1, 2, 3)));
// Free download instance
void download_i_free(struct download_i*) __attribute__((nonnull));
// This is same as download_i_free but where download_i_free just frees downloaded
// buffer, this passes it to caller. Instance is freed the same way as in case of
// download_i_free but data buffer has to be freed later by caller.
// In other words this overtakes allocated buffer and frees rest of instance.
// This can be called only on instance that was created by download_data.
void download_i_collect_data(struct download_i*, uint8_t **data, size_t *size);
#endif
......@@ -154,11 +154,6 @@ enum log_level log_level_get(const char *level) {
return LL_UNKNOWN;
}
static const char *type_string[] = {
[LST_PKG_SCRIPT] = "pkg-script",
[LST_HOOK] = "hook"
};
// log_subproc cookie
struct c_log_subproc {
bool err; // Is this out or err
......
......@@ -19,7 +19,9 @@
#ifndef UPDATER_LOGGING_H
#define UPDATER_LOGGING_H
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
......
......@@ -23,6 +23,7 @@
#include "logging.h"
#include "subprocess.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
......@@ -41,6 +42,22 @@ bool dump2file (const char *file, const char *text) {
return true;
}
char *readfile(const char *file) {
FILE *f = fopen(file, "r");
if (!f) {
ERROR("Read of file \"%s\" failed: %s", file, strerror(errno));
return NULL;
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *ret = malloc(fsize + 1);
fread(ret, fsize, 1, f);
fclose(f);
ret[fsize] = 0;
return ret;
}
static int exec_dir_filter(const struct dirent *de) {
// ignore system paths and accept only files
return strcmp(de->d_name, ".") && strcmp(de->d_name, "..") && de->d_type == DT_REG;
......
......@@ -30,6 +30,10 @@
// Writes given text to file. Be aware that no information about failure is given.
bool dump2file (const char *file, const char *text) __attribute__((nonnull,nonnull));
// Read content of whole file and return it as string
// Returned memory has to be freed by used.
char *readfile(const char *file) __attribute__((nonnull));
// Executes all executable files in given directory
void exec_hook(const char *dir, const char *message) __attribute__((nonnull));
......
......@@ -10,6 +10,7 @@ C_TESTS := \
events \
util \
subprocess \
download \
interpreter
LUA_TESTS := \
......@@ -56,7 +57,7 @@ LUA_AUTOLOAD := $(filter-out 01_stacktraceplus 07_dumper,$(patsubst a_%.lua,%,$(
define DO_C_TEST
BINARIES_NOTARGET += tests/ctest-$(1)
ctest-$(1)_MODULES += $(1) ctest
ctest-$(1)_MODULES += $(1) ctest test_data
ctest-$(1)_SYSTEM_LIBS += m rt
ctest-$(1)_PKG_CONFIGS += check
ctest-$(1)_LOCAL_LIBS += updater
......
......@@ -62,3 +62,28 @@ function test_cleanup_unregister()
assert_false(cleanup_unregister(cleanup_local))
assert_false(cleaned);
end
-- Test if we correctly recognize closures
function test_cleanup_local()
local cl_a = false
local cl_b = false
local function new_clean(is_a)
local function lclean()
if is_a then
cl_a = true
else
cl_b = true
end
end
cleanup_register(lclean)
return lclean
end
local f_a = new_clean(true)
local f_b = new_clean(false)
cleanup_run(f_a)
assert_true(cl_a)
assert_false(cl_b)
cleanup_run(f_b)
assert_true(cl_b)
end
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
This diff is collapsed.
-----BEGIN CERTIFICATE-----
MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA
MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w
ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw
MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU
T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b
wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX
/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0
77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP
uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx
p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx
Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2
TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W
G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw
vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY
EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1
2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw
DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf
gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS
FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0
V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P
XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I
i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t
TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91
09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky
Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ
AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj
1oxx
-----END CERTIFICATE-----
/*
* Copyright 2018-2019, CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This file is part of the turris updater.
*
* Updater is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Updater is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Updater. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ctest.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../src/lib/download.h"
#include "test_data.h"
START_TEST(downloader_empty) {
struct downloader *d = downloader_new(1);
ck_assert_ptr_null(downloader_run(d));
downloader_free(d);
}
END_TEST
// Test simple download from http with redirect to https and Let's encrypt certificate
START_TEST(simple_download) {
struct downloader *d = downloader_new(1);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
struct download_i *inst = download_data(d, HTTP_LOREM_IPSUM_SHORT, &opts);
ck_assert_ptr_null(downloader_run(d));
ck_assert_uint_eq(LOREM_IPSUM_SHORT_SIZE, inst->out.buff->size);
ck_assert_str_eq(LOREM_IPSUM_SHORT, (char *)inst->out.buff->data);
downloader_free(d);
}
END_TEST
// Test download to file. Otherwise it's same test as in case of simple_download.
START_TEST(file_download) {
struct downloader *d = downloader_new(1);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
char *file = aprintf("%s/updater-download.txt", get_tmpdir());
ck_assert_ptr_nonnull(download_file(d, HTTP_LOREM_IPSUM_SHORT, file, &opts));
ck_assert_ptr_null(downloader_run(d));
char *str = readfile(file);
ck_assert(str);
ck_assert_uint_eq(LOREM_IPSUM_SHORT_SIZE, strlen(str));
ck_assert_str_eq(LOREM_IPSUM_SHORT, str);
free(str);
unlink(file);
downloader_free(d);
}
END_TEST
// Test download to temporally file. We download different data to different
// files to test that having same template we end up with two different files.
START_TEST(temp_file_download) {
struct downloader *d = downloader_new(2);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
const char *tmpdir = get_tmpdir();
char *file1 = aprintf("%s/updater-download-temp-XXXXXX", tmpdir);
char *file2 = aprintf("%s/updater-download-temp-XXXXXX", tmpdir);
ck_assert_str_eq(file1, file2); // Templates are same
ck_assert_ptr_nonnull(download_temp_file(d, HTTP_LOREM_IPSUM_SHORT, file1, &opts));
ck_assert_ptr_nonnull(download_temp_file(d, HTTP_LOREM_IPSUM, file2, &opts));
ck_assert_str_ne(file1, file2); // Paths are not same
ck_assert_ptr_null(downloader_run(d));
char *str = readfile(file1);
ck_assert(str);
ck_assert_uint_eq(LOREM_IPSUM_SHORT_SIZE, strlen(str));
ck_assert_str_eq(LOREM_IPSUM_SHORT, str);
free(str);
char *lorem_ipsum_file = FILE_LOREM_IPSUM;
char *big_content = readfile(lorem_ipsum_file);
size_t big_size = strlen(big_content);
str = readfile(file2);
ck_assert(str);
ck_assert_uint_eq(big_size, strlen(str));
ck_assert_str_eq(big_content, str);
free(str);
free(big_content);
unlink(file1);
unlink(file2);
downloader_free(d);
}
END_TEST
// Test that we can have multiple downloads and that all are downloaded
// Half of them are small file and half of them are bigger ones
// This test requires min. 20MB of memory.
START_TEST(multiple_downloads) {
struct downloader *d = downloader_new(4);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
const size_t cnt = 32;
struct download_i *insts[cnt];
for (size_t i = 0; i < cnt; i++) {
if (i % 2)
insts[i] = download_data(d, HTTP_LOREM_IPSUM_SHORT, &opts);
else
insts[i] = download_data(d, HTTP_LOREM_IPSUM, &opts);
}
ck_assert_ptr_null(downloader_run(d));
char *lorem_ipsum_file = FILE_LOREM_IPSUM;
char *big_content = readfile(lorem_ipsum_file);
size_t big_size = strlen(big_content);
for (size_t i = 0; i < cnt; i++) {
if (i % 2) {
ck_assert_uint_eq(LOREM_IPSUM_SHORT_SIZE, insts[i]->out.buff->size);
ck_assert_str_eq(LOREM_IPSUM_SHORT, (char *)insts[i]->out.buff->data);
} else {
ck_assert_uint_eq(big_size, insts[i]->out.buff->size);
ck_assert_str_eq(big_content, (char *)insts[i]->out.buff->data);
}
}
free(big_content);
downloader_free(d);
}
END_TEST
// Test failure if we access non-existent url
START_TEST(invalid) {
struct downloader *d = downloader_new(1);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
struct download_i *inst = download_data(d, HTTP_APPLICATION_TEST "/invalid", &opts);
ck_assert_ptr_eq(downloader_run(d), inst);
downloader_free(d);
}
END_TEST
// Test that even if one of download fail that all other will be downloaded
START_TEST(invalid_continue) {
struct downloader *d = downloader_new(4);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
const size_t cnt = 3;
struct download_i *insts[cnt];
for (size_t i = 0; i < cnt; i++)
insts[i] = download_data(d, HTTP_LOREM_IPSUM_SHORT, &opts);
struct download_i *fail_inst = download_data(d, HTTP_APPLICATION_TEST "/invalid", &opts);
ck_assert_ptr_eq(downloader_run(d), fail_inst);
ck_assert_ptr_null(downloader_run(d));
for (size_t i = 0; i < cnt; i++) {
ck_assert_uint_eq(LOREM_IPSUM_SHORT_SIZE, insts[i]->out.buff->size);
ck_assert_str_eq(LOREM_IPSUM_SHORT, (char *)insts[i]->out.buff->data);
}
downloader_free(d);
}
END_TEST
// Test certification pinning
START_TEST(cert_pinning) {
struct downloader *d = downloader_new(1);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
opts.cacert_file = FILE_LETS_ENCRYPT_ROOTS;
opts.capath = "/dev/null";
struct download_i *inst = download_data(d, HTTP_LOREM_IPSUM_SHORT, &opts);
ck_assert_ptr_null(downloader_run(d));
ck_assert_uint_eq(LOREM_IPSUM_SHORT_SIZE, inst->out.buff->size);
ck_assert_str_eq(LOREM_IPSUM_SHORT, (char *)inst->out.buff->data);
downloader_free(d);
}
END_TEST
// Test failure if we try invalid certificate
START_TEST(cert_invalid) {
struct downloader *d = downloader_new(1);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
opts.cacert_file = FILE_OPENTRUST_CA_G1;
opts.capath = "/dev/null";
struct download_i *inst = download_data(d, HTTP_LOREM_IPSUM_SHORT, &opts);
ck_assert_ptr_eq(downloader_run(d), inst);
downloader_free(d);
}
END_TEST
// Test that we are able to overtake buffer
START_TEST(collect_data) {
struct downloader *d = downloader_new(1);
ck_assert_ptr_null(downloader_run(d));
struct download_opts opts;
download_opts_def(&opts);
struct download_i *inst = download_data(d, HTTP_LOREM_IPSUM_SHORT, &opts);
ck_assert_ptr_null(downloader_run(d));
uint8_t *data;
size_t size;
download_i_collect_data(inst, &data, &size);
ck_assert_uint_eq(LOREM_IPSUM_SHORT_SIZE, size);
ck_assert_str_eq(LOREM_IPSUM_SHORT, (char *)data);
free(data);
downloader_free(d);
}
END_TEST
Suite *gen_test_suite(void) {
Suite *result = suite_create("Download");
TCase *down = tcase_create("download");
tcase_set_timeout(down, 30);
tcase_add_test(down, downloader_empty);
tcase_add_test(down, simple_download);
tcase_add_test(down, multiple_downloads);
tcase_add_test(down, file_download);
tcase_add_test(down, temp_file_download);
tcase_add_test(down, invalid);
tcase_add_test(down, invalid_continue);
tcase_add_test(down, cert_pinning);
tcase_add_test(down, cert_invalid);
tcase_add_test(down, collect_data);
suite_add_tcase(result, down);
return result;
}
/*
* Copyright 2018-2019, CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This file is part of the turris updater.
*
* Updater is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Updater is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Updater. If not, see <http://www.gnu.org/licenses/>.
*/
#include "test_data.h"
#include <stdlib.h>
const char *get_tmpdir() {
const char *tmpdir = getenv("TMPDIR");
if (!tmpdir)
tmpdir = "/tmp";
return tmpdir;
}
const char *get_sdir() {
const char *sdir = getenv("S");
if (!sdir)
sdir = ".";
return sdir;
}
/*
* Copyright 2019, CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This file is part of the turris updater.
*
* Updater is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Updater is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Updater. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../src/lib/util.h"
#ifndef UPDATER_TEST_DATA_H
#define UPDATER_TEST_DATA_H
const char *get_tmpdir();
const char *get_sdir();
#define HTTP_APPLICATION_TEST "http://applications-test.turris.cz"
#define HTTPS_APPLICATION_TEST "https://applications-test.turris.cz"
// Lorem Ipsum
#define LOREM_IPSUM_SHORT "lorem ipsum\n"
#define LOREM_IPSUM_SHORT_SIZE 12
#define HTTP_LOREM_IPSUM_SHORT ( HTTP_APPLICATION_TEST "/li.txt" )
#define HTTP_LOREM_IPSUM ( HTTP_APPLICATION_TEST "/lorem_ipsum.txt" )
#define HTTPS_LOREM_IPSUM_SHORT ( HTTPS_APPLICATION_TEST "/li.txt" )
#define HTTPS_LOREM_IPSUM ( HTTPS_APPLICATION_TEST "/lorem_ipsum.txt" )
#define FILE_LOREM_IPSUM_SHORT aprintf("%s/tests/data/lorem_ipsum_short.txt", get_sdir())
#define FILE_LOREM_IPSUM aprintf("%s/tests/data/lorem_ipsum.txt", get_sdir())
// Certificates
#define FILE_LETS_ENCRYPT_ROOTS aprintf("%s/tests/data/lets_encrypt_roots.pem", get_sdir())
#define URI_FILE_LETS_ENCRYPT_ROOTS aprintf("file://%s/tests/data/lets_encrypt_roots.pem", get_sdir())
#define FILE_OPENTRUST_CA_G1 aprintf("%s/tests/data/opentrust_ca_g1.pem", get_sdir())
#define URI_FILE_OPENTRUST_CA_G1 aprintf("file://%s/tests/data/opentrust_ca_g1.pem", get_sdir())
#endif