Verified Commit 310154c9 authored by Karel Koci's avatar Karel Koci 🤘

Implement URI in C

This is C implementation of URI with configuration inheritance and
ability to have relative URIs.
parent e0b80042
......@@ -26,6 +26,7 @@ libupdater_MODULES := \
events \
subprocess \
download \
uri \
journal \
locks \
picosat \
......@@ -42,9 +43,9 @@ endif
libupdater_MODULES_3RDPARTY := picosat-965/picosat
libupdater_PKG_CONFIGS := $(LUA_NAME) libevent libcurl libcrypto
libupdater_PKG_CONFIGS := $(LUA_NAME) libevent libcurl libcrypto liburiparser
# Workaround, lua.pc doesn't containd -ldl, even when it uses dlopen
libupdater_SO_LIBS += dl
libupdater_SO_LIBS += dl b64
LIB_DOCS := \
journal \
......
This diff is collapsed.
This diff is collapsed.
......@@ -33,6 +33,7 @@
#include <dirent.h>
#include <signal.h>
#include <poll.h>
#include <b64/cdecode.h>
bool dump2file (const char *file, const char *text) {
FILE *f = fopen(file, "w");
......@@ -68,6 +69,19 @@ bool statfile(const char *file, int mode) {
return !access(file, mode);
}
char *writetempfile(char *buf, size_t len) {
char *fpath = strdup("/tmp/updater-temp-XXXXXX");
FILE *f = fdopen(mkstemp(fpath), "w");
if (!f) {
ERROR("Opening temporally file failed: %s", strerror(errno));
free(fpath);
return NULL;
}
ASSERT_MSG(fwrite(buf, 1, len, f) == len, "Not all data were written to temporally file.");
fclose(f);
return fpath;
}
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;
......@@ -94,6 +108,37 @@ void exec_hook(const char *dir, const char *message) {
free(namelist);
}
static bool base64_is_valid_char(const char c) {
return \
(c >= '0' && c <= '9') || \
(c >= 'A' && c <= 'Z') || \
(c >= 'a' && c <= 'z') || \
(c == '+' || c == '/' || c == '=');
}
unsigned base64_valid(const char *data) {
// TODO this is only minimal verification, we should do more some times in future
int check_off = 0;
while (data[check_off] != '\0')
if (!base64_is_valid_char(data[check_off++]))
return check_off;
return 0;
}
void base64_decode(const char *data, uint8_t **buf, size_t *len) {
size_t data_len = strlen(data);
size_t buff_len = (data_len * 3 / 4) + 2;
*buf = malloc(sizeof(uint8_t) * buff_len);
base64_decodestate s;
base64_init_decodestate(&s);
int cnt = base64_decode_block(data, data_len, (char*)*buf, &s);
ASSERT(cnt >= 0);
*len = cnt;
ASSERT_MSG((*len + 1) < buff_len, "Output buffer was too small, this should not happen!");
(*buf)[*len] = '\0'; // Terminate this with \0 so if it is string it can be used as such
}
static bool cleanup_registered = false;
static struct {
size_t size, allocated;
......
......@@ -34,6 +34,10 @@ bool dump2file (const char *file, const char *text) __attribute__((nonnull,nonnu
// 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));
// Write buffer to temporally file
// This function returns path to file. It is your responsibility to both free
// returned memory and to unlink created file. On error NULL is returned.
char *writetempfile(char *buf, size_t len) __attribute__((nonnull));
// Returns true if file exists and is accessible in given mode
// Mode is bitwise OR of one or more of R_OK, W_OK, and X_OK.
......@@ -42,6 +46,17 @@ bool statfile(const char *file, int mode);
// Executes all executable files in given directory
void exec_hook(const char *dir, const char *message) __attribute__((nonnull));
// Verify if given data are encoded in base64 format (this is only minimal check,
// not complete one)
// It returns 0 if data are valid base64 format, it returns index+1 of problematic
// character otherwise.
unsigned base64_valid(const char *data);
// Decode given string as a base64 encoded data
// This function allocates buffer of appropriate size to buf argument and sets
// size of that buffer to len.
void base64_decode(const char *data, uint8_t **buf, size_t *len) __attribute__((nonnull));
// Using these functions you can register/unregister cleanup function. Note that
// they are called in reverse order of insertion. This is implemented using atexit
// function.
......
......@@ -13,6 +13,7 @@ C_TESTS := \
multiwrite \
subprocess \
download \
uri \
interpreter
LUA_TESTS := \
......
untrusted comment: signed by key d1ce0a8a82748a7d
RWTRzgqKgnSKfdqpDwFH38I6mh/mZ5nY217B7HnK/pVpKcCXChlIpnFO3efg1oWpzVNoTAEpwUBKoJrsMKnHQcyzJRP7MwnyJwM=
untrusted comment: signed by key 40e1ae405379ec08
RWRA4a5AU3nsCJKIEn7D9jhxUwdmZHXO7HwZyk0Nll3JsZ5EwW+UNvKBxHtvRX1SjW2/tIEaAKTvKvBizyCbCxyZ+4WVIaL5ZwQ=
untrusted comment: signed by key d1ce0a8a82748a7d
RWTRzgqKgnSKfWNUOILK11/029kM//cg35tabJam/feiEoh7NnVOCYuw359MSlTLSi+Ps6e6knkRNFOYhffwxJnp1hxvmGd21go=
untrusted comment: signed by key 40e1ae405379ec08
RWRA4a5AU3nsCLXe1YSgPcXb//GXQvhKB5k3iKvyzNlzflGrprYQzsxr/BA7KrgmfWUOWzwrpOX8Mj8lu8VzKxp9Db0iIwsfsgg=
untrusted comment: public key d1ce0a8a82748a7d
RWTRzgqKgnSKfdqpsPOfAewplIqDU7hfosnrrCdZV+So2l0bf+8OY48P
untrusted comment: private key d1ce0a8a82748a7d
RWRCSwAAAADEKeeLg5fDx1bTCQht/ka02y9AITsYvsXRzgqKgnSKfSioAlXENe5YgVqL+9ayDaM+hIOC+OCkEAwBU7OiRY5D2qmw858B7CmUioNTuF+iyeusJ1lX5KjaXRt/7w5jjw8=
untrusted comment: public key 40e1ae405379ec08
RWRA4a5AU3nsCKCGsa4DMtQDVXExF7nD0P04NhpASPDPggEyQuWjlwXG
untrusted comment: private key 40e1ae405379ec08
RWRCSwAAAAA4H2GXztRnpM4PiYWrbThcJ/Yj+lKLwJVA4a5AU3nsCJC4Yq5ZMvM4TMuLhb2zqB/n8+DhlzrC/mAL6dOCZApnoIaxrgMy1ANVcTEXucPQ/Tg2GkBI8M+CATJC5aOXBcY=
......@@ -36,6 +36,14 @@ const char *get_sdir();
#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())
// Signatures
#define USIGN_KEY_1_PUB (aprintf("%s/tests/data/usign.key1.pub", get_sdir()))
#define USIGN_KEY_2_PUB (aprintf("%s/tests/data/usign.key2.pub", get_sdir()))
#define SIG_1_LOREM_IPSUM (aprintf("%s/tests/data/lorem_ipsum.txt.sig", get_sdir()))
#define SIG_2_LOREM_IPSUM (aprintf("%s/tests/data/lorem_ipsum.txt.sig2", get_sdir()))
#define SIG_1_LOREM_IPSUM_SHORT (aprintf("%s/tests/data/lorem_ipsum_short.txt.sig", get_sdir()))
#define SIG_2_LOREM_IPSUM_SHORT (aprintf("%s/tests/data/lorem_ipsum_short.txt.sig2", 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())
......
This diff is collapsed.
......@@ -20,6 +20,25 @@
#include <stdbool.h>
#include "../src/lib/util.h"
#define BASE64_PLAIN "Hello\n"
#define BASE64_ENCOD "SGVsbG8K"
START_TEST(base64_is_valid) {
ck_assert_int_eq(0, base64_valid(BASE64_ENCOD));
ck_assert_int_eq(5, base64_valid("SGvs$bG8L"));
}
END_TEST
START_TEST(base64) {
uint8_t *result;
size_t result_len;
base64_decode(BASE64_ENCOD, &result, &result_len);
ck_assert_int_eq(6, result_len);
ck_assert_str_eq(BASE64_PLAIN, (char*)result);
free(result);
}
END_TEST
static int cleaned;
static void cleanup_func(void *data) {
......@@ -85,6 +104,8 @@ Suite *gen_test_suite(void) {
Suite *result = suite_create("Util");
TCase *util = tcase_create("util");
tcase_set_timeout(util, 30);
tcase_add_test(util, base64_is_valid);
tcase_add_test(util, base64);
tcase_add_test(util, cleanup_multi);
tcase_add_test(util, cleanup_single);
tcase_add_test(util, cleanup_by_data);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment