fix: close remaining PR review gaps
CI / lint (pull_request) Successful in 32s
CI / sanitizers (undefined) (pull_request) Successful in 36s
CI / sanitizers (address) (pull_request) Successful in 37s
CI / fuzz-build (pull_request) Successful in 13s
CI / coverage (pull_request) Successful in 31s
CI / build-and-test (pull_request) Successful in 1m15s
CI / valgrind (pull_request) Successful in 33s
CI / lint (pull_request) Successful in 32s
CI / sanitizers (undefined) (pull_request) Successful in 36s
CI / sanitizers (address) (pull_request) Successful in 37s
CI / fuzz-build (pull_request) Successful in 13s
CI / coverage (pull_request) Successful in 31s
CI / build-and-test (pull_request) Successful in 1m15s
CI / valgrind (pull_request) Successful in 33s
This commit is contained in:
+1
-1
@@ -58,7 +58,7 @@ endif()
|
|||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
file(GLOB SHARED_SRCS "src/shared/*.c")
|
file(GLOB SHARED_SRCS "src/shared/*.c")
|
||||||
set(FILE_STORE_SRCS src/shared/file_store.c)
|
set(FILE_STORE_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/shared/file_store.c")
|
||||||
list(REMOVE_ITEM SHARED_SRCS ${FILE_STORE_SRCS})
|
list(REMOVE_ITEM SHARED_SRCS ${FILE_STORE_SRCS})
|
||||||
file(GLOB SERVER_SRCS "src/server/*.c")
|
file(GLOB SERVER_SRCS "src/server/*.c")
|
||||||
set(SERVER_RECEIVER_SRCS src/server/receiver.c)
|
set(SERVER_RECEIVER_SRCS src/server/receiver.c)
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ working directory, so use a destination below that directory unless the
|
|||||||
remote server is otherwise configured with a matching authorized root.
|
remote server is otherwise configured with a matching authorized root.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
ssh user@host 'mkdir -p destination'
|
||||||
./build/client /path/to/source user@host:destination
|
./build/client /path/to/source user@host:destination
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+16
-4
@@ -20,6 +20,16 @@ static char* authorized_root;
|
|||||||
static int authorized_root_fd = -1;
|
static int authorized_root_fd = -1;
|
||||||
static bool allow_delete;
|
static bool allow_delete;
|
||||||
|
|
||||||
|
static void release_authorization(void) {
|
||||||
|
file_set_authorized_root(-1, NULL);
|
||||||
|
utils_set_authorized_root_fd(-1);
|
||||||
|
if (authorized_root_fd >= 0)
|
||||||
|
close(authorized_root_fd);
|
||||||
|
authorized_root_fd = -1;
|
||||||
|
free(authorized_root);
|
||||||
|
authorized_root = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static bool path_is_within(const char* root, const char* path) {
|
static bool path_is_within(const char* root, const char* path) {
|
||||||
size_t n = strlen(root);
|
size_t n = strlen(root);
|
||||||
return strncmp(root, path, n) == 0 && (path[n] == '\0' || path[n] == '/');
|
return strncmp(root, path, n) == 0 && (path[n] == '\0' || path[n] == '/');
|
||||||
@@ -233,33 +243,35 @@ int main(int argc, char* argv[]) {
|
|||||||
if (stdio_mode) {
|
if (stdio_mode) {
|
||||||
io_set_fds(STDIN_FILENO, STDOUT_FILENO);
|
io_set_fds(STDIN_FILENO, STDOUT_FILENO);
|
||||||
handler(STDIN_FILENO);
|
handler(STDIN_FILENO);
|
||||||
file_set_authorized_root(-1, NULL);
|
release_authorization();
|
||||||
utils_set_authorized_root_fd(-1);
|
|
||||||
close(authorized_root_fd);
|
|
||||||
free(authorized_root);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
g_server = server_create(port);
|
g_server = server_create(port);
|
||||||
if (!g_server) {
|
if (!g_server) {
|
||||||
log_message(LOG_LEVEL_ERROR, "Failed to create server");
|
log_message(LOG_LEVEL_ERROR, "Failed to create server");
|
||||||
|
release_authorization();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (use_tls) {
|
if (use_tls) {
|
||||||
if (!tls_cert || !tls_key) {
|
if (!tls_cert || !tls_key) {
|
||||||
fprintf(stderr, "Error: --tls requires --cert and --key\n");
|
fprintf(stderr, "Error: --tls requires --cert and --key\n");
|
||||||
server_delete(&g_server);
|
server_delete(&g_server);
|
||||||
|
release_authorization();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
tls_global_init();
|
tls_global_init();
|
||||||
if (!server_create_tls(g_server, tls_cert, tls_key, tls_ca)) {
|
if (!server_create_tls(g_server, tls_cert, tls_key, tls_ca)) {
|
||||||
log_message(LOG_LEVEL_ERROR, "Failed to set up TLS");
|
log_message(LOG_LEVEL_ERROR, "Failed to set up TLS");
|
||||||
server_delete(&g_server);
|
server_delete(&g_server);
|
||||||
|
release_authorization();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
server_listen_tls(g_server, handler);
|
server_listen_tls(g_server, handler);
|
||||||
} else {
|
} else {
|
||||||
server_listen(g_server, handler);
|
server_listen(g_server, handler);
|
||||||
}
|
}
|
||||||
|
server_delete(&g_server);
|
||||||
|
release_authorization();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+24
-20
@@ -336,13 +336,14 @@ bool file_save_to_disk(const char* root_directory, const File* file, const Confi
|
|||||||
}
|
}
|
||||||
|
|
||||||
static File* receive_delta_file(int fd, const Config* config, const char* check_path,
|
static File* receive_delta_file(int fd, const Config* config, const char* check_path,
|
||||||
void* old_data, unsigned long long old_size) {
|
void* old_data, unsigned long long old_size, bool* failed) {
|
||||||
if (!old_data)
|
if (!old_data)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
DeltaSignature* sig = delta_signature_create(old_data, old_size, config->delta_block_size);
|
DeltaSignature* sig = delta_signature_create(old_data, old_size, config->delta_block_size);
|
||||||
if (!sig) {
|
if (!sig) {
|
||||||
free(old_data);
|
free(old_data);
|
||||||
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,6 +351,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
if (!sig_data) {
|
if (!sig_data) {
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
free(old_data);
|
free(old_data);
|
||||||
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,6 +361,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
if (!sig_sent) {
|
if (!sig_sent) {
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
free(old_data);
|
free(old_data);
|
||||||
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,6 +369,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
if (!receive_status(fd, &resp)) {
|
if (!receive_status(fd, &resp)) {
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
free(old_data);
|
free(old_data);
|
||||||
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +378,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
if (!delta_data) {
|
if (!delta_data) {
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
free(old_data);
|
free(old_data);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +389,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
if (!raw_delta) {
|
if (!raw_delta) {
|
||||||
free(old_data);
|
free(old_data);
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,7 +399,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
if (!delta) {
|
if (!delta) {
|
||||||
free(old_data);
|
free(old_data);
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +410,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
free(old_data);
|
free(old_data);
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +419,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
free(new_data);
|
free(new_data);
|
||||||
free(old_data);
|
free(old_data);
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +431,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
free(new_data);
|
free(new_data);
|
||||||
free(old_data);
|
free(old_data);
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,7 +450,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
|
|
||||||
File* file = file_create(check_path);
|
File* file = file_create(check_path);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +459,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
file->metadata = metadata_receive(fd, &meta_ok);
|
file->metadata = metadata_receive(fd, &meta_ok);
|
||||||
if (!meta_ok) {
|
if (!meta_ok) {
|
||||||
file_destroy(file);
|
file_destroy(file);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,7 +467,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
Data* file_data = receive_data(fd);
|
Data* file_data = receive_data(fd);
|
||||||
if (file_data == NULL) {
|
if (file_data == NULL) {
|
||||||
file_destroy(file);
|
file_destroy(file);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,7 +476,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
data_destroy(file_data);
|
data_destroy(file_data);
|
||||||
if (uncompressed == NULL) {
|
if (uncompressed == NULL) {
|
||||||
file_destroy(file);
|
file_destroy(file);
|
||||||
send_status(fd, STATUS_ERROR);
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
file_data = uncompressed;
|
file_data = uncompressed;
|
||||||
@@ -485,6 +489,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_
|
|||||||
|
|
||||||
delta_signature_destroy(sig);
|
delta_signature_destroy(sig);
|
||||||
free(old_data);
|
free(old_data);
|
||||||
|
*failed = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +497,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) {
|
|||||||
*skipped = false;
|
*skipped = false;
|
||||||
char* check_path = receive_str(fd);
|
char* check_path = receive_str(fd);
|
||||||
if (check_path == NULL) {
|
if (check_path == NULL) {
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,19 +506,16 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) {
|
|||||||
if (!receive_n_data(fd, &check_size, sizeof(check_size)) ||
|
if (!receive_n_data(fd, &check_size, sizeof(check_size)) ||
|
||||||
!receive_n_data(fd, &check_mtime, sizeof(check_mtime))) {
|
!receive_n_data(fd, &check_mtime, sizeof(check_mtime))) {
|
||||||
free(check_path);
|
free(check_path);
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (config->checksum && !receive_n_data(fd, &check_checksum, sizeof(check_checksum))) {
|
if (config->checksum && !receive_n_data(fd, &check_checksum, sizeof(check_checksum))) {
|
||||||
free(check_path);
|
free(check_path);
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_path_traversal(check_path)) {
|
if (has_path_traversal(check_path)) {
|
||||||
log_message(LOG_LEVEL_ERROR, "Path traversal detected: %s", check_path);
|
log_message(LOG_LEVEL_ERROR, "Path traversal detected: %s", check_path);
|
||||||
free(check_path);
|
free(check_path);
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,13 +583,20 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) {
|
|||||||
delta_should_attempt(old_size, check_size, config->delta_max_file_size);
|
delta_should_attempt(old_size, check_size, config->delta_max_file_size);
|
||||||
|
|
||||||
if (try_delta) {
|
if (try_delta) {
|
||||||
File* delta_file = receive_delta_file(fd, config, check_path, old_data, old_size);
|
bool delta_failed = false;
|
||||||
|
File* delta_file =
|
||||||
|
receive_delta_file(fd, config, check_path, old_data, old_size, &delta_failed);
|
||||||
old_data = NULL; /* receive_delta_file consumes the snapshot on every path */
|
old_data = NULL; /* receive_delta_file consumes the snapshot on every path */
|
||||||
if (delta_file) {
|
if (delta_file) {
|
||||||
free(full_path);
|
free(full_path);
|
||||||
free(check_path);
|
free(check_path);
|
||||||
return delta_file;
|
return delta_file;
|
||||||
}
|
}
|
||||||
|
if (delta_failed) {
|
||||||
|
free(full_path);
|
||||||
|
free(check_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
free(old_data);
|
free(old_data);
|
||||||
old_data = NULL;
|
old_data = NULL;
|
||||||
try_delta = false;
|
try_delta = false;
|
||||||
@@ -606,7 +614,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) {
|
|||||||
free(check_path);
|
free(check_path);
|
||||||
free(full_path);
|
free(full_path);
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,7 +622,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) {
|
|||||||
file->metadata = metadata_receive(fd, &meta_ok);
|
file->metadata = metadata_receive(fd, &meta_ok);
|
||||||
if (!meta_ok) {
|
if (!meta_ok) {
|
||||||
file_destroy(file);
|
file_destroy(file);
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -623,7 +629,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) {
|
|||||||
Data* file_data = receive_data(fd);
|
Data* file_data = receive_data(fd);
|
||||||
if (file_data == NULL) {
|
if (file_data == NULL) {
|
||||||
file_destroy(file);
|
file_destroy(file);
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +637,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) {
|
|||||||
data_destroy(file_data);
|
data_destroy(file_data);
|
||||||
if (uncompressed == NULL) {
|
if (uncompressed == NULL) {
|
||||||
file_destroy(file);
|
file_destroy(file);
|
||||||
send_status(fd, STATUS_ERROR);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
file_data = uncompressed;
|
file_data = uncompressed;
|
||||||
|
|||||||
Reference in New Issue
Block a user