diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b8da1c..a9ce285 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ endif() find_package(OpenSSL REQUIRED) 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}) file(GLOB SERVER_SRCS "src/server/*.c") set(SERVER_RECEIVER_SRCS src/server/receiver.c) diff --git a/README.md b/README.md index 8f52a59..3aaf949 100644 --- a/README.md +++ b/README.md @@ -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. ```bash +ssh user@host 'mkdir -p destination' ./build/client /path/to/source user@host:destination ``` diff --git a/src/server/server.c b/src/server/server.c index 47f512e..1485210 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -20,6 +20,16 @@ static char* authorized_root; static int authorized_root_fd = -1; 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) { size_t n = strlen(root); return strncmp(root, path, n) == 0 && (path[n] == '\0' || path[n] == '/'); @@ -233,33 +243,35 @@ int main(int argc, char* argv[]) { if (stdio_mode) { io_set_fds(STDIN_FILENO, STDOUT_FILENO); handler(STDIN_FILENO); - file_set_authorized_root(-1, NULL); - utils_set_authorized_root_fd(-1); - close(authorized_root_fd); - free(authorized_root); + release_authorization(); return 0; } g_server = server_create(port); if (!g_server) { log_message(LOG_LEVEL_ERROR, "Failed to create server"); + release_authorization(); return 1; } if (use_tls) { if (!tls_cert || !tls_key) { fprintf(stderr, "Error: --tls requires --cert and --key\n"); server_delete(&g_server); + release_authorization(); return 1; } tls_global_init(); if (!server_create_tls(g_server, tls_cert, tls_key, tls_ca)) { log_message(LOG_LEVEL_ERROR, "Failed to set up TLS"); server_delete(&g_server); + release_authorization(); return 1; } server_listen_tls(g_server, handler); } else { server_listen(g_server, handler); } + server_delete(&g_server); + release_authorization(); return 0; } #endif diff --git a/src/shared/file.c b/src/shared/file.c index fb4891e..6122d39 100644 --- a/src/shared/file.c +++ b/src/shared/file.c @@ -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, - void* old_data, unsigned long long old_size) { + void* old_data, unsigned long long old_size, bool* failed) { if (!old_data) return NULL; DeltaSignature* sig = delta_signature_create(old_data, old_size, config->delta_block_size); if (!sig) { free(old_data); + *failed = true; return NULL; } @@ -350,6 +351,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ if (!sig_data) { delta_signature_destroy(sig); free(old_data); + *failed = true; return NULL; } @@ -359,6 +361,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ if (!sig_sent) { delta_signature_destroy(sig); free(old_data); + *failed = true; return NULL; } @@ -366,6 +369,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ if (!receive_status(fd, &resp)) { delta_signature_destroy(sig); free(old_data); + *failed = true; return NULL; } @@ -374,7 +378,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ if (!delta_data) { delta_signature_destroy(sig); free(old_data); - send_status(fd, STATUS_ERROR); + *failed = true; return NULL; } @@ -385,7 +389,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ if (!raw_delta) { free(old_data); delta_signature_destroy(sig); - send_status(fd, STATUS_ERROR); + *failed = true; return NULL; } } @@ -395,7 +399,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ if (!delta) { free(old_data); delta_signature_destroy(sig); - send_status(fd, STATUS_ERROR); + *failed = true; return NULL; } @@ -406,7 +410,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ if (!new_data) { free(old_data); delta_signature_destroy(sig); - send_status(fd, STATUS_ERROR); + *failed = true; return NULL; } @@ -415,7 +419,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ free(new_data); free(old_data); delta_signature_destroy(sig); - send_status(fd, STATUS_ERROR); + *failed = true; return NULL; } @@ -427,7 +431,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ free(new_data); free(old_data); delta_signature_destroy(sig); - send_status(fd, STATUS_ERROR); + *failed = true; 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); if (!file) { - send_status(fd, STATUS_ERROR); + *failed = true; 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); if (!meta_ok) { file_destroy(file); - send_status(fd, STATUS_ERROR); + *failed = true; 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); if (file_data == NULL) { file_destroy(file); - send_status(fd, STATUS_ERROR); + *failed = true; return NULL; } @@ -472,7 +476,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ data_destroy(file_data); if (uncompressed == NULL) { file_destroy(file); - send_status(fd, STATUS_ERROR); + *failed = true; return NULL; } file_data = uncompressed; @@ -485,6 +489,7 @@ static File* receive_delta_file(int fd, const Config* config, const char* check_ delta_signature_destroy(sig); free(old_data); + *failed = true; return NULL; } @@ -492,7 +497,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) { *skipped = false; char* check_path = receive_str(fd); if (check_path == NULL) { - send_status(fd, STATUS_ERROR); 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)) || !receive_n_data(fd, &check_mtime, sizeof(check_mtime))) { free(check_path); - send_status(fd, STATUS_ERROR); return NULL; } if (config->checksum && !receive_n_data(fd, &check_checksum, sizeof(check_checksum))) { free(check_path); - send_status(fd, STATUS_ERROR); return NULL; } if (has_path_traversal(check_path)) { log_message(LOG_LEVEL_ERROR, "Path traversal detected: %s", check_path); free(check_path); - send_status(fd, STATUS_ERROR); 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); 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 */ if (delta_file) { free(full_path); free(check_path); return delta_file; } + if (delta_failed) { + free(full_path); + free(check_path); + return NULL; + } free(old_data); old_data = NULL; try_delta = false; @@ -606,7 +614,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) { free(check_path); free(full_path); if (file == NULL) { - send_status(fd, STATUS_ERROR); return NULL; } @@ -615,7 +622,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) { file->metadata = metadata_receive(fd, &meta_ok); if (!meta_ok) { file_destroy(file); - send_status(fd, STATUS_ERROR); return NULL; } } @@ -623,7 +629,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) { Data* file_data = receive_data(fd); if (file_data == NULL) { file_destroy(file); - send_status(fd, STATUS_ERROR); return NULL; } @@ -632,7 +637,6 @@ File* receive_incremental_check(int fd, const Config* config, bool* skipped) { data_destroy(file_data); if (uncompressed == NULL) { file_destroy(file); - send_status(fd, STATUS_ERROR); return NULL; } file_data = uncompressed;