mirror of
https://dev.iopsys.eu/bbf/obuspa.git
synced 2025-12-20 11:38:46 +08:00
secure file path in upload/download
This commit is contained in:
117
src/vendor/vendor_datamodel_ext.c
vendored
117
src/vendor/vendor_datamodel_ext.c
vendored
@@ -38,6 +38,8 @@
|
||||
#include <dirent.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "usp_api.h"
|
||||
#include "usp_err_codes.h"
|
||||
@@ -62,13 +64,78 @@ static char *upload_out_args[] = { "Content", "Length", "Filesize", "Checksum",
|
||||
// cppcheck-suppress cert-STR05-C
|
||||
static char *session_start_arg[] = { "Timeout" };
|
||||
|
||||
|
||||
#if defined(OBUSPA_ENABLE_DOWNLOAD_EXT) || defined(OBUSPA_ENABLE_UPLOAD_EXT)
|
||||
static int validate_file_path(char *filename, char **filepath)
|
||||
{
|
||||
char abs_path[PATH_MAX] = {0};
|
||||
char real_path[PATH_MAX] = {0};
|
||||
|
||||
if (filename == NULL || filepath == NULL) {
|
||||
USP_LOG_Error("filename or filepath is NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int len = strlen(filename);
|
||||
if (len == 0) {
|
||||
USP_LOG_Error("Filename should not be empty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* filename should not end with '/' */
|
||||
if (filename[len - 1] == '/') {
|
||||
USP_LOG_Error("Filename should not end with /");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(abs_path, sizeof(abs_path), "/tmp/obuspa/%s", filename);
|
||||
char *tmp_p = strrchr(abs_path, '/');
|
||||
if (tmp_p == NULL) {
|
||||
USP_LOG_Error("String processing error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tmp_p = '\0';
|
||||
|
||||
/* filename should not be '.' or '..' */
|
||||
tmp_p = tmp_p + 1;
|
||||
if (strcmp(tmp_p, "..") == 0 || strcmp(tmp_p, ".") == 0) {
|
||||
USP_LOG_Error("%s could not be used as filename", tmp_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *res = realpath(abs_path, real_path);
|
||||
if (res == NULL) {
|
||||
char* errStr = strerror(errno);
|
||||
USP_LOG_Error("%s:%d (%s) %s", __FUNCTION__, __LINE__, abs_path, errStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(real_path, "/tmp/obuspa") != 0 && strncmp(real_path, "/tmp/obuspa/", 12) != 0) {
|
||||
USP_LOG_Error("%s:%d File path: (%s) can not be used", __FUNCTION__, __LINE__, real_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t size = strlen(real_path) + strlen(tmp_p) + 2;
|
||||
*filepath = (char*)USP_MALLOC(sizeof(char) * size);
|
||||
if (*filepath == NULL) {
|
||||
USP_LOG_Error("Memory allocation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(*filepath, size, "%s/%s", real_path, tmp_p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************
|
||||
* Upload functionality start
|
||||
************************************/
|
||||
#ifdef OBUSPA_ENABLE_UPLOAD_EXT
|
||||
typedef struct {
|
||||
int request_instance;
|
||||
char file_path[4096];
|
||||
char file_path[PATH_MAX];
|
||||
} file_upload_input_cond_t;
|
||||
|
||||
void *FileUploadThreadMain(void *param)
|
||||
@@ -217,6 +284,8 @@ static int upload_file_cb(dm_req_t *req, kv_vector_t *input_args,
|
||||
int instance)
|
||||
{
|
||||
int i, err;
|
||||
char *filename = NULL;
|
||||
char *real_path = NULL;
|
||||
|
||||
if (req == NULL)
|
||||
return USP_ERR_INTERNAL_ERROR;
|
||||
@@ -239,17 +308,24 @@ static int upload_file_cb(dm_req_t *req, kv_vector_t *input_args,
|
||||
cond->request_instance = instance;
|
||||
for (i = 0; i < input_args->num_entries; i++) {
|
||||
if (strcmp(input_args->vector[i].key, "Filename") == 0 && input_args->vector[i].value != NULL) {
|
||||
snprintf(cond->file_path, sizeof(cond->file_path), "/tmp/obuspa/%s", input_args->vector[i].value);
|
||||
filename = input_args->vector[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(cond->file_path) == 0) {
|
||||
if (filename == NULL || strlen(filename) == 0) {
|
||||
USP_FREE(cond);
|
||||
return USP_ERR_COMMAND_FAILURE;
|
||||
}
|
||||
|
||||
USP_LOG_Info("Filepath: %s", cond->file_path);
|
||||
if (validate_file_path(filename, &real_path) != 0) {
|
||||
USP_FREE(cond);
|
||||
return USP_ERR_COMMAND_FAILURE;
|
||||
}
|
||||
|
||||
snprintf(cond->file_path, sizeof(cond->file_path), "%s", real_path);
|
||||
USP_SAFE_FREE(real_path);
|
||||
USP_LOG_Info("Upload Filepath: %s", cond->file_path);
|
||||
|
||||
err = OS_UTILS_CreateThread("UploadFile", FileUploadThreadMain, cond);
|
||||
if (err != USP_ERR_OK) {
|
||||
@@ -324,7 +400,8 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
int i;
|
||||
char *content = NULL, *filename = NULL, *checksum = NULL;
|
||||
size_t filesize = 0, length = 0, total_frag = 1, frag_num = 1, req_id = 0;
|
||||
char file_path[4096] = {0};
|
||||
char file_path[PATH_MAX] = {0};
|
||||
char *real_path = NULL;
|
||||
FILE *fp = NULL;
|
||||
size_t file_count = 0;
|
||||
|
||||
@@ -394,6 +471,12 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
if (validate_file_path(filename, &real_path) != 0) {
|
||||
USP_ARG_Add(out, "Result", "Failed");
|
||||
USP_ARG_Add(out, "Error", "File name can not be used");
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
/* check if 15 seconds expired from the last fragment download time, then
|
||||
* cancel last download task and start a new one. */
|
||||
time_t now = time(NULL);
|
||||
@@ -410,6 +493,7 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
USP_ARG_Add(out, "Result", "Failed");
|
||||
USP_ARG_Add(out, "Error", "One download task is ongoing, please wait to finish");
|
||||
USP_LOG_Debug("%s:%d New download request rejected since one is going on", __FUNCTION__, __LINE__);
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -430,6 +514,7 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
USP_LOG_Info("%s:%d Empty file content", __FUNCTION__, __LINE__);
|
||||
remove_all_fragments();
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -440,6 +525,7 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
USP_ARG_Add(out, "Error", "Failed to write data");
|
||||
remove_all_fragments();
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -450,6 +536,7 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
last_dw_time = time(NULL);
|
||||
USP_ARG_Add(out, "Result", "Success");
|
||||
USP_ARG_Add(out, "Error", "");
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -461,6 +548,7 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
USP_ARG_Add(out, "Error", "Failed to start reassembling the package");
|
||||
remove_all_fragments();
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -495,40 +583,45 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
USP_ARG_Add(out, "Result", "Failed");
|
||||
USP_ARG_Add(out, "Error", "Failed to reassemble the package");
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
USP_LOG_Info("Download Filepath: %s", real_path);
|
||||
|
||||
size_t datalen = 0;
|
||||
snprintf(file_path, sizeof(file_path), "/tmp/obuspa/%s", filename);
|
||||
if (0 != base64_decode(frag_merge_path, &datalen, file_path)) {
|
||||
if (0 != base64_decode(frag_merge_path, &datalen, real_path)) {
|
||||
USP_LOG_Debug("%s: Failed to decode the content", __FUNCTION__);
|
||||
remove(frag_merge_path);
|
||||
USP_ARG_Add(out, "Result", "Failed");
|
||||
USP_ARG_Add(out, "Error", "Failed to decode the data");
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
remove(frag_merge_path);
|
||||
if (filesize != datalen) {
|
||||
remove(file_path);
|
||||
remove(real_path);
|
||||
char tmp[512] = {0};
|
||||
snprintf(tmp, sizeof(tmp), "Received filesize: %lu mismatched with decoded filesize:%lu", (unsigned long)filesize, (unsigned long)datalen);
|
||||
USP_LOG_Info("%s", tmp);
|
||||
USP_ARG_Add(out, "Result", "Failed");
|
||||
USP_ARG_Add(out, "Error", tmp);
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
// Calculate md5sum
|
||||
// cppcheck-suppress cert-MSC24-C
|
||||
fp = fopen(file_path, "rb");
|
||||
fp = fopen(real_path, "rb");
|
||||
if (fp == NULL) {
|
||||
USP_ARG_Add(out, "Result", "Failed");
|
||||
USP_ARG_Add(out, "Error", "Failed to get checksum");
|
||||
remove(file_path);
|
||||
remove(real_path);
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -557,14 +650,16 @@ static int download_file(kv_vector_t *in, kv_vector_t *out)
|
||||
USP_ARG_Add(out, "Result", "Failed");
|
||||
USP_ARG_Add(out, "Error", "Checksum mismatched");
|
||||
USP_LOG_Debug("%s: checksum %s not matched %s", __FUNCTION__, checksum, hash);
|
||||
remove(file_path);
|
||||
remove(real_path);
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
USP_ARG_Add(out, "Result", "Success");
|
||||
USP_ARG_Add(out, "Error", "");
|
||||
reset_download_task();
|
||||
USP_SAFE_FREE(real_path);
|
||||
|
||||
return USP_ERR_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user