SUPPORT-9333. Проверка подписанного сообщения, содержащего отсоединённую подпись

This commit is contained in:
Наиля Алашкова 2025-08-29 13:03:06 +03:00
parent 9d2f2be25a
commit ac08303c90
34 changed files with 2403 additions and 114 deletions

View file

@ -7,19 +7,25 @@ include_directories (
)
set (ESM_SOURCES
../src/utils/detached_sign_payload_parser.c
../src/utils/glib_utils.c
../src/utils/json_parser.c
../src/utils/jwt.c
../src/utils/logger.c
../src/utils/multipart_parser.c
)
set (HEADERS
utils/test_detached_sign_payload_parser.h
utils/test_jwt.h
utils/test_multipart_parser.h
)
set (SOURCES
main.c
utils/test_detached_sign_payload_parser.c
utils/test_jwt.c
utils/test_multipart_parser.c
"${ESM_SOURCES}"
)

View file

@ -1,4 +1,6 @@
#include "utils/test_detached_sign_payload_parser.h"
#include "utils/test_jwt.h"
#include "utils/test_multipart_parser.h"
#include <CUnit/Basic.h>
@ -11,6 +13,8 @@ int main(int arv, char** argc)
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
// jwt
CU_pSuite suite_jwt = CU_add_suite("JWTSuit", NULL, NULL);
if (NULL == suite_jwt) {
goto exit;
@ -19,6 +23,30 @@ int main(int arv, char** argc)
if (NULL == CU_ADD_TEST(suite_jwt, test_jwt_get_header_payload_and_sign)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_jwt_get_alg_from_header)) goto exit;
// multipart/form-data parser
CU_pSuite suite_multipart = CU_add_suite("MultipartSuit", NULL, NULL);
if (NULL == suite_multipart) {
goto exit;
}
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_boundary)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_boundary_failure_invalid_header)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_boundary_failure_empty_boundary)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_name)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_name_2)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_name_failure)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_filename)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_filename_2)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_multipart_get_filename_failure)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_parse_detached_sign_payload)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_parse_detached_sign_payload_failure_sign_is_missing)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_parse_detached_sign_payload_failure_data_is_missing)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_parse_detached_sign_payload_failure_extra_field)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_parse_detached_sign_payload_failure_unacceptable_content_type)) goto exit;
if (NULL == CU_ADD_TEST(suite_jwt, test_parse_detached_sign_payload_failure_invalid_header)) goto exit;
CU_basic_set_mode(CU_BRM_NORMAL);
CU_basic_run_tests();

View file

@ -0,0 +1,169 @@
#include "test_detached_sign_payload_parser.h"
#include "utils/detached_sign_payload_parser.h"
#include <CUnit/Basic.h>
static const str_t HEADER = str_t_const(
"multipart/form-data; boundary=---------------------------9051914041544843365972754266"
);
static const str_t INVALID_HEADER = str_t_const(
"multipart/form-data; boundary=--invalid_boundary--"
);
static const str_t BODY = str_t_const(
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"data\"; filename=\"a.txt\"\r\n" \
"Content-Type: application/octet-stream\r\n" \
"\r\n" \
"This is a data." \
"\r\n" \
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"sign\"; filename=\"a.txt.sig\"\r\n" \
"Content-Type: application/octet-stream\r\n" \
"\r\n" \
"This is a sign." \
"\r\n" \
"-----------------------------9051914041544843365972754266--"
);
static const str_t BODY_WITHOUT_SIGN = str_t_const(
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"data\"; filename=\"a.txt\"\r\n" \
"Content-Type: application/octet-stream\r\n" \
"\r\n" \
"This is a data." \
"\r\n" \
"-----------------------------9051914041544843365972754266--"
);
static const str_t BODY_WITHOUT_DATA = str_t_const(
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"sign\"; filename=\"a.txt.sig\"\r\n" \
"Content-Type: application/octet-stream\r\n" \
"\r\n" \
"This is a sign." \
"\r\n" \
"-----------------------------9051914041544843365972754266--"
);
static const str_t BODY_EXTRA_FIELD = str_t_const(
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"data\"; filename=\"a.txt\"\r\n" \
"Content-Type: application/octet-stream\r\n" \
"\r\n" \
"This is a data." \
"\r\n" \
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"sign\"; filename=\"a.txt.sig\"\r\n" \
"Content-Type: application/octet-stream\r\n" \
"\r\n" \
"This is a sign." \
"\r\n" \
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"extra\"; filename=\"extra.txt\"\r\n" \
"Content-Type: application/octet-stream\r\n" \
"\r\n" \
"This is an extra field." \
"\r\n" \
"-----------------------------9051914041544843365972754266--"
);
static const str_t BODY_UNACCEPTABLE_CONTENT_TYPE = str_t_const(
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"data\"; filename=\"a.txt\"\r\n" \
"Content-Type: text/plain\r\n" \
"\r\n" \
"This is a data." \
"\r\n" \
"-----------------------------9051914041544843365972754266\r\n" \
"Content-Disposition: form-data; name=\"sign\"; filename=\"a.txt.sig\"\r\n" \
"Content-Type: text/plain\r\n" \
"\r\n" \
"This is a sign." \
"\r\n" \
"-----------------------------9051914041544843365972754266--"
);
void test_parse_detached_sign_payload()
{
str_t data = str_t_null;
str_t sign = str_t_null;
int rc = parse_detached_sign_payload(HEADER.data, BODY.data, BODY.len, &data, &sign);
CU_ASSERT_EQUAL(rc, 0);
CU_ASSERT_NSTRING_EQUAL(data.data, "This is a data.", data.len);
CU_ASSERT_NSTRING_EQUAL(sign.data, "This is a sign.", sign.len);
}
void test_parse_detached_sign_payload_failure_sign_is_missing()
{
int rc;
str_t data = str_t_null;
str_t sign = str_t_null;
rc = parse_detached_sign_payload(HEADER.data, BODY_WITHOUT_SIGN.data, BODY_WITHOUT_SIGN.len, &data, &sign);
CU_ASSERT_NOT_EQUAL(rc, 0);
CU_ASSERT_EQUAL(data.data, NULL);
CU_ASSERT_EQUAL(data.len, 0);
CU_ASSERT_EQUAL(sign.data, NULL);
CU_ASSERT_EQUAL(sign.len, 0);
}
void test_parse_detached_sign_payload_failure_data_is_missing()
{
int rc;
str_t data = str_t_null;
str_t sign = str_t_null;
rc = parse_detached_sign_payload(HEADER.data, BODY_WITHOUT_DATA.data, BODY_WITHOUT_DATA.len, &data, &sign);
CU_ASSERT_NOT_EQUAL(rc, 0);
CU_ASSERT_EQUAL(data.data, NULL);
CU_ASSERT_EQUAL(data.len, 0);
CU_ASSERT_EQUAL(sign.data, NULL);
CU_ASSERT_EQUAL(sign.len, 0);
}
void test_parse_detached_sign_payload_failure_extra_field()
{
int rc;
str_t data = str_t_null;
str_t sign = str_t_null;
rc = parse_detached_sign_payload(HEADER.data, BODY_EXTRA_FIELD.data, BODY_EXTRA_FIELD.len, &data, &sign);
CU_ASSERT_NOT_EQUAL(rc, 0);
CU_ASSERT_EQUAL(data.data, NULL);
CU_ASSERT_EQUAL(data.len, 0);
CU_ASSERT_EQUAL(sign.data, NULL);
CU_ASSERT_EQUAL(sign.len, 0);
}
void test_parse_detached_sign_payload_failure_unacceptable_content_type()
{
int rc;
str_t data = str_t_null;
str_t sign = str_t_null;
rc = parse_detached_sign_payload(HEADER.data, BODY_UNACCEPTABLE_CONTENT_TYPE.data,
BODY_UNACCEPTABLE_CONTENT_TYPE.len, &data, &sign);
CU_ASSERT_NOT_EQUAL(rc, 0);
CU_ASSERT_EQUAL(data.data, NULL);
CU_ASSERT_EQUAL(data.len, 0);
CU_ASSERT_EQUAL(sign.data, NULL);
CU_ASSERT_EQUAL(sign.len, 0);
}
void test_parse_detached_sign_payload_failure_invalid_header()
{
int rc;
str_t data = str_t_null;
str_t sign = str_t_null;
rc = parse_detached_sign_payload(INVALID_HEADER.data, BODY.data, BODY.len, &data, &sign);
CU_ASSERT_NOT_EQUAL(rc, 0);
CU_ASSERT_EQUAL(data.data, NULL);
CU_ASSERT_EQUAL(data.len, 0);
CU_ASSERT_EQUAL(sign.data, NULL);
CU_ASSERT_EQUAL(sign.len, 0);
}

View file

@ -0,0 +1,11 @@
#ifndef TEST_DETACHED_SIGN_PAYLOAD_PARSER_H
#define TEST_DETACHED_SIGN_PAYLOAD_PARSER_H
void test_parse_detached_sign_payload();
void test_parse_detached_sign_payload_failure_sign_is_missing();
void test_parse_detached_sign_payload_failure_data_is_missing();
void test_parse_detached_sign_payload_failure_extra_field();
void test_parse_detached_sign_payload_failure_unacceptable_content_type();
void test_parse_detached_sign_payload_failure_invalid_header();
#endif // TEST_DETACHED_SIGN_PAYLOAD_PARSER_H

View file

@ -0,0 +1,149 @@
#include "test_multipart_parser.h"
#include "utils/multipart_parser.h"
#include "utils/str_t.h"
#include <CUnit/Basic.h>
static const str_t BOUNDARY = str_t_const(
"---------------------------9051914041544843365972754266"
);
static const str_t CONTENT_TYPE_HEADER = str_t_const(
"multipart/form-data; boundary=---------------------------9051914041544843365972754266"
);
static const str_t INVALID_CONTENT_TYPE_HEADER = str_t_const(
"multipart/form-data;"
);
static const str_t INVALID_CONTENT_TYPE_HEADER_EMPTY_BOUNDARY = str_t_const(
"multipart/form-data; boundary="
);
static const str_t FIELD_NAME = str_t_const(
"data"
);
static const str_t FILENAME = str_t_const(
"Название файла.txt"
);
static const str_t CONTENT_DISPOSITION_HEADER = str_t_const(
"Content-Disposition: form-data; name=\"data\"; filename=\"Название файла.txt\""
);
static const str_t CONTENT_DISPOSITION_HEADER_2 = str_t_const(
"Content-Disposition: form-data;filename=\"Название файла.txt\";name=\"data\";"
);
static const str_t CONTENT_DISPOSITION_HEADER_WITHOUT_NAME = str_t_const(
"Content-Disposition: form-data; filename=\"Название файла.txt\""
);
static const str_t CONTENT_DISPOSITION_HEADER_WITHOUT_FILENAME = str_t_const(
"Content-Disposition: form-data; name=\"data\""
);
void test_multipart_get_boundary()
{
const char *b = NULL;
size_t b_len = 0;
b = multipart_get_boundary(CONTENT_TYPE_HEADER.data, &b_len);
CU_ASSERT_NOT_EQUAL_FATAL(b, NULL);
CU_ASSERT_EQUAL(b_len, BOUNDARY.len);
CU_ASSERT_NSTRING_EQUAL(b, BOUNDARY.data, b_len);
}
void test_multipart_get_boundary_failure_invalid_header()
{
const char *b = NULL;
size_t b_len = 0;
b = multipart_get_boundary(INVALID_CONTENT_TYPE_HEADER.data, &b_len);
CU_ASSERT_EQUAL_FATAL(b, NULL);
CU_ASSERT_EQUAL(b_len, 0);
}
void test_multipart_get_boundary_failure_empty_boundary()
{
const char *b = NULL;
size_t b_len = 0;
b = multipart_get_boundary(INVALID_CONTENT_TYPE_HEADER_EMPTY_BOUNDARY.data, &b_len);
CU_ASSERT_EQUAL_FATAL(b, NULL);
CU_ASSERT_EQUAL(b_len, 0);
}
void test_multipart_get_name()
{
size_t name_len = 0;
const char *name = NULL;
name = multipart_get_name(CONTENT_DISPOSITION_HEADER.data, CONTENT_DISPOSITION_HEADER.len,
&name_len);
CU_ASSERT_NOT_EQUAL_FATAL(name, NULL);
CU_ASSERT_EQUAL(name_len, FIELD_NAME.len);
CU_ASSERT_NSTRING_EQUAL(name, FIELD_NAME.data, name_len);
}
void test_multipart_get_name_2()
{
size_t name_len = 0;
const char *name = NULL;
name = multipart_get_name(CONTENT_DISPOSITION_HEADER_2.data, CONTENT_DISPOSITION_HEADER_2.len,
&name_len);
CU_ASSERT_NOT_EQUAL_FATAL(name, NULL);
CU_ASSERT_EQUAL(name_len, FIELD_NAME.len);
CU_ASSERT_NSTRING_EQUAL(name, FIELD_NAME.data, name_len);
}
void test_multipart_get_name_failure()
{
size_t name_len = 0;
const char *name = NULL;
name = multipart_get_name(CONTENT_DISPOSITION_HEADER_WITHOUT_NAME.data,
CONTENT_DISPOSITION_HEADER_WITHOUT_NAME.len,
&name_len);
CU_ASSERT_EQUAL_FATAL(name, NULL);
CU_ASSERT_EQUAL(name_len, 0);
}
void test_multipart_get_filename()
{
size_t filename_len = 0;
const char *filename = NULL;
filename = multipart_get_filename(CONTENT_DISPOSITION_HEADER.data, CONTENT_DISPOSITION_HEADER.len,
&filename_len);
CU_ASSERT_NOT_EQUAL_FATAL(filename, NULL);
CU_ASSERT_EQUAL(filename_len, FILENAME.len);
CU_ASSERT_NSTRING_EQUAL(filename, FILENAME.data, filename_len);
}
void test_multipart_get_filename_2()
{
size_t filename_len = 0;
const char *filename = NULL;
filename = multipart_get_filename(CONTENT_DISPOSITION_HEADER_2.data, CONTENT_DISPOSITION_HEADER_2.len,
&filename_len);
CU_ASSERT_NOT_EQUAL_FATAL(filename, NULL);
CU_ASSERT_EQUAL(filename_len, FILENAME.len);
CU_ASSERT_NSTRING_EQUAL(filename, FILENAME.data, filename_len);
}
void test_multipart_get_filename_failure()
{
size_t filename_len = 0;
const char *filename = NULL;
filename = multipart_get_filename(CONTENT_DISPOSITION_HEADER_WITHOUT_FILENAME.data,
CONTENT_DISPOSITION_HEADER_WITHOUT_FILENAME.len,
&filename_len);
CU_ASSERT_EQUAL_FATAL(filename, NULL);
CU_ASSERT_EQUAL(filename_len, 0);
}

View file

@ -0,0 +1,18 @@
#ifndef TEST_MULTIPART_PARSER_H_INCLUDED
#define TEST_MULTIPART_PARSER_H_INCLUDED
void test_multipart_get_boundary();
void test_multipart_get_boundary_failure_invalid_header();
void test_multipart_get_boundary_failure_empty_boundary();
void test_multipart_get_name();
void test_multipart_get_name_2();
void test_multipart_get_name_failure();
void test_multipart_get_filename();
void test_multipart_get_filename_2();
void test_multipart_get_filename_failure();
#endif // TEST_MULTIPART_PARSER_H_INCLUDED