Merge remote-tracking branch 'origin/feature/8821_add_generate_uuid' into develop
This commit is contained in:
commit
dc2790043e
14 changed files with 385 additions and 37 deletions
|
|
@ -51,6 +51,7 @@ SET (DEP_LIBS
|
||||||
-ldl
|
-ldl
|
||||||
-ljson-glib-1.0
|
-ljson-glib-1.0
|
||||||
-lgobject-2.0
|
-lgobject-2.0
|
||||||
|
-luuid
|
||||||
)
|
)
|
||||||
|
|
||||||
# JSON-GLIB
|
# JSON-GLIB
|
||||||
|
|
@ -120,10 +121,12 @@ ADD_EXECUTABLE (${PROJECT_NAME}
|
||||||
${UTILS_DIR}/gconf_file.c
|
${UTILS_DIR}/gconf_file.c
|
||||||
${UTILS_DIR}/glib_utils.c
|
${UTILS_DIR}/glib_utils.c
|
||||||
${UTILS_DIR}/json_parser.c
|
${UTILS_DIR}/json_parser.c
|
||||||
|
${UTILS_DIR}/json_writer.c
|
||||||
${UTILS_DIR}/jwt.c
|
${UTILS_DIR}/jwt.c
|
||||||
${UTILS_DIR}/library.c
|
${UTILS_DIR}/library.c
|
||||||
${UTILS_DIR}/logger.c
|
${UTILS_DIR}/logger.c
|
||||||
${UTILS_DIR}/str_t.c
|
${UTILS_DIR}/str_t.c
|
||||||
|
${UTILS_DIR}/uuid.c
|
||||||
${FCGISRV_DIR}/fcgi_map.c
|
${FCGISRV_DIR}/fcgi_map.c
|
||||||
${FCGISRV_DIR}/fcgi_server.c
|
${FCGISRV_DIR}/fcgi_server.c
|
||||||
${FCGISRV_DIR}/fcgi_thread.c
|
${FCGISRV_DIR}/fcgi_thread.c
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ RUN apt-get update \
|
||||||
make \
|
make \
|
||||||
gcc \
|
gcc \
|
||||||
gcc10 \
|
gcc10 \
|
||||||
libjson-glib libjson-glib-devel
|
libjson-glib libjson-glib-devel \
|
||||||
|
libuuid libuuid-devel
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
COPY src src
|
COPY src src
|
||||||
|
|
@ -33,7 +34,7 @@ ENV TZ=Europe/Moscow
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get -y install glib2 libfcgi libjson-glib \
|
&& apt-get -y install glib2 libfcgi libjson-glib libuuid \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -f /var/cache/apt/*.bin \
|
&& rm -f /var/cache/apt/*.bin \
|
||||||
&& rm -f /var/lib/apt/lists/update* \
|
&& rm -f /var/lib/apt/lists/update* \
|
||||||
|
|
|
||||||
16
README.md
16
README.md
|
|
@ -7,8 +7,9 @@
|
||||||
### Подпись данных
|
### Подпись данных
|
||||||
|
|
||||||
Приложение принимает POST-запрос по протоколу FastCGI (Content-Type: text/plain).
|
Приложение принимает POST-запрос по протоколу FastCGI (Content-Type: text/plain).
|
||||||
Подписывает строку, полученную в теле запроса.
|
C помощью аппаратного ДСЧ генерирует state - набор случайных символов, генерируется по стандарту UUID.
|
||||||
В ответе возвращает подпись в формате urlSafeBase64 (Content-Type: text/plain).
|
В строку, полученную в теле запроса, добавляет state.
|
||||||
|
В ответе возвращает подпись полученной строки в формате urlSafeBase64 (параметр "signature") и сгенерированный state (параметр "state") (Content-Type: application/json).
|
||||||
|
|
||||||
Пример выполнения запроса:
|
Пример выполнения запроса:
|
||||||
```
|
```
|
||||||
|
|
@ -24,12 +25,15 @@ $ /opt/cprocsp/bin/amd64/curl -v http://127.0.0.1/sign -H "Content-Type: text/pl
|
||||||
>
|
>
|
||||||
< HTTP/1.1 200 OK
|
< HTTP/1.1 200 OK
|
||||||
< Server: nginx/1.24.0
|
< Server: nginx/1.24.0
|
||||||
< Date: Fri, 16 Aug 2024 07:33:13 GMT
|
< Date: Tue, 20 Aug 2024 12:00:25 GMT
|
||||||
< Content-Type: text/plain
|
< Content-Type: application/json
|
||||||
< Transfer-Encoding: chunked
|
< Transfer-Encoding: chunked
|
||||||
< Connection: keep-alive
|
< Connection: keep-alive
|
||||||
<
|
<
|
||||||
urlSafeBase64_of_signed_string_test
|
{
|
||||||
|
"signature": "urlSafeBase64_of_signed_string_test_with_state",
|
||||||
|
"state": "7c327cb7-7916-4255-bc46-85fbc5ad7d5f"
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Проверка подписи маркера доступа
|
### Проверка подписи маркера доступа
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
#include "fcgisrv/fcgi_utils.h"
|
#include "fcgisrv/fcgi_utils.h"
|
||||||
|
|
||||||
#include "utils/cryptopro.h"
|
#include "utils/cryptopro.h"
|
||||||
|
#include "utils/json_writer.h"
|
||||||
|
#include "utils/uuid.h"
|
||||||
|
|
||||||
#define SIGN_CONF_SECTION "sign"
|
#define SIGN_CONF_SECTION "sign"
|
||||||
#define SIGN_CONF_KEY_LOCATION "location"
|
#define SIGN_CONF_KEY_LOCATION "location"
|
||||||
|
|
@ -10,9 +12,9 @@
|
||||||
#define SIGN_CONF_KEY_SIGN_CERT_PASSWORD "sign_cert_password"
|
#define SIGN_CONF_KEY_SIGN_CERT_PASSWORD "sign_cert_password"
|
||||||
|
|
||||||
#define FCGI_OK_RESPONSE_FORMAT \
|
#define FCGI_OK_RESPONSE_FORMAT \
|
||||||
"Content-type: text/plain" CRLF\
|
"Content-type: application/json" CRLF\
|
||||||
CRLF\
|
CRLF\
|
||||||
"%.*s" CRLF
|
"%s" CRLF
|
||||||
|
|
||||||
static const str_t SIGN_CONF_DEFAULT_LOCATION = str_t_const("/sign");
|
static const str_t SIGN_CONF_DEFAULT_LOCATION = str_t_const("/sign");
|
||||||
|
|
||||||
|
|
@ -30,7 +32,7 @@ typedef struct fcgi_sign_request_s {
|
||||||
char *content;
|
char *content;
|
||||||
int content_length;
|
int content_length;
|
||||||
|
|
||||||
str_t signed_content;
|
char *response;
|
||||||
|
|
||||||
} fcgi_sign_request_t;
|
} fcgi_sign_request_t;
|
||||||
|
|
||||||
|
|
@ -38,7 +40,7 @@ static void fcgi_sign_request_clear(fcgi_sign_request_t *req_info);
|
||||||
|
|
||||||
static fcgi_request_handler_pt fcgi_request_finalize_handler(fcgi_handler_status_t status);
|
static fcgi_request_handler_pt fcgi_request_finalize_handler(fcgi_handler_status_t status);
|
||||||
|
|
||||||
static int sign_content(const sign_service_t *hsign, fcgi_sign_request_t *req_info);
|
static int sign_client_secret(const sign_service_t *hsign, fcgi_sign_request_t *req_info);
|
||||||
|
|
||||||
int
|
int
|
||||||
sign_conf_load(sign_conf_t *conf, const conf_file_context_t conf_file)
|
sign_conf_load(sign_conf_t *conf, const conf_file_context_t conf_file)
|
||||||
|
|
@ -182,7 +184,7 @@ fcgi_sign_handler(FCGX_Request* request, void* ctx)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sign_content(hsign, &req_info)) {
|
if (sign_client_secret(hsign, &req_info)) {
|
||||||
status = HANDLER_ERROR;
|
status = HANDLER_ERROR;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +206,9 @@ fcgi_sign_request_clear(fcgi_sign_request_t *req_info)
|
||||||
LOG_TRACE("fcgi_sign_request_clear");
|
LOG_TRACE("fcgi_sign_request_clear");
|
||||||
|
|
||||||
free(req_info->content);
|
free(req_info->content);
|
||||||
str_t_clear(&(req_info->signed_content));
|
free(req_info->response);
|
||||||
|
|
||||||
|
memset(req_info, 0, sizeof(fcgi_sign_request_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static fcgi_handler_status_t
|
static fcgi_handler_status_t
|
||||||
|
|
@ -214,11 +218,9 @@ fcgi_ok_handler(const FCGX_Request* request, void *ctx)
|
||||||
|
|
||||||
const fcgi_sign_request_t *req_info = (fcgi_sign_request_t*) ctx;
|
const fcgi_sign_request_t *req_info = (fcgi_sign_request_t*) ctx;
|
||||||
|
|
||||||
LOG_DEBUG("response status: " FCGI_OK_RESPONSE_FORMAT,
|
LOG_DEBUG("response status: " FCGI_OK_RESPONSE_FORMAT, req_info->response);
|
||||||
(int) req_info->signed_content.len, req_info->signed_content.data);
|
|
||||||
|
if (FCGX_FPrintF(request->out, FCGI_OK_RESPONSE_FORMAT, req_info->response) < 0) {
|
||||||
if (FCGX_FPrintF(request->out, FCGI_OK_RESPONSE_FORMAT,
|
|
||||||
(int) req_info->signed_content.len, req_info->signed_content.data) < 0) {
|
|
||||||
LOG_ERROR("FCGX_FPrintF() failed");
|
LOG_ERROR("FCGX_FPrintF() failed");
|
||||||
return HANDLER_ERROR;
|
return HANDLER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
@ -233,10 +235,13 @@ fcgi_request_finalize_handler(fcgi_handler_status_t status)
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case HANDLER_SUCCESS:
|
case HANDLER_SUCCESS:
|
||||||
case HANDLER_HTTP_OK:
|
|
||||||
handler = fcgi_ok_handler;
|
handler = fcgi_ok_handler;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HANDLER_HTTP_OK:
|
||||||
|
handler = fcgi_200_ok_handler;
|
||||||
|
break;
|
||||||
|
|
||||||
case HANDLER_HTTP_BAD_REQUEST:
|
case HANDLER_HTTP_BAD_REQUEST:
|
||||||
handler = fcgi_400_bad_request_handler;
|
handler = fcgi_400_bad_request_handler;
|
||||||
break;
|
break;
|
||||||
|
|
@ -259,23 +264,128 @@ fcgi_request_finalize_handler(fcgi_handler_status_t status)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sign_content(const sign_service_t *hsign, fcgi_sign_request_t *req_info)
|
generate_client_secret(const fcgi_sign_request_t *req_info, const char *state,
|
||||||
|
/*out*/ str_t *secret)
|
||||||
{
|
{
|
||||||
LOG_TRACE("sign_content enter");
|
LOG_TRACE("generate_client_secret enter");
|
||||||
|
|
||||||
str_t content = {
|
size_t secret_size = req_info->content_length + strlen(state);
|
||||||
.data = req_info->content,
|
|
||||||
.len = req_info->content_length
|
|
||||||
};
|
|
||||||
|
|
||||||
if (cryptopro_sign(&hsign->cryptopro_ctx, &content, &req_info->signed_content)) {
|
secret->data = malloc(secret_size);
|
||||||
|
if (secret->data == NULL) {
|
||||||
|
LOG_ERROR("Could not allocate memory for client_secret (%zd bytes)", secret_size);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_TRACE("sign_content exit");
|
int len = snprintf(secret->data, secret_size, req_info->content, state);
|
||||||
|
if (len < 0 || (size_t)len >= secret_size) {
|
||||||
|
LOG_ERROR("Could not concatenate client_secret");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
secret->len = len;
|
||||||
|
|
||||||
|
LOG_TRACE("generate_client_secret exit");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
LOG_ERROR("sign_content exit with error");
|
str_t_clear(secret);
|
||||||
|
LOG_ERROR("generate_client_secret exit with error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
generate_response(const char *signature, const char *state)
|
||||||
|
{
|
||||||
|
JsonBuilder *jbuilder;
|
||||||
|
char *response;
|
||||||
|
|
||||||
|
LOG_TRACE("generate_response enter");
|
||||||
|
|
||||||
|
jbuilder = json_builder_new();
|
||||||
|
if (jbuilder == NULL) {
|
||||||
|
LOG_ERROR("json_builder_new failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_builder_begin_object(jbuilder) == NULL) {
|
||||||
|
LOG_ERROR("json_builder_begin_object failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_write_member_string(jbuilder, "signature", signature)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_write_member_string(jbuilder, "state", state)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_builder_end_object(jbuilder) == NULL) {
|
||||||
|
LOG_ERROR("json_builder_end_object failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
response = json_write_to_str(jbuilder);
|
||||||
|
|
||||||
|
g_object_unref(jbuilder);
|
||||||
|
|
||||||
|
LOG_TRACE("generate_response exit");
|
||||||
|
return response;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (jbuilder != NULL) {
|
||||||
|
g_object_unref(jbuilder);
|
||||||
|
}
|
||||||
|
LOG_ERROR("generate_response exit with error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sign_client_secret(const sign_service_t *hsign, fcgi_sign_request_t *req_info)
|
||||||
|
{
|
||||||
|
str_t secret = str_t_null;
|
||||||
|
char *state = NULL;
|
||||||
|
str_t signature = str_t_null;
|
||||||
|
|
||||||
|
LOG_TRACE("sign_client_secret enter");
|
||||||
|
|
||||||
|
state = generate_uuid4();
|
||||||
|
if (state == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generate_client_secret(req_info, state, &secret)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cryptopro_sign(&hsign->cryptopro_ctx, &secret, &signature)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(str_t_is_null_terminated(signature));
|
||||||
|
|
||||||
|
req_info->response = generate_response(signature.data, state);
|
||||||
|
|
||||||
|
if (req_info->response == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("state: '%s'", state);
|
||||||
|
LOG_DEBUG("client secret: '%.*s'", (int) secret.len, secret.data);
|
||||||
|
LOG_DEBUG("response: '%s'", req_info->response);
|
||||||
|
|
||||||
|
str_t_clear(&secret);
|
||||||
|
free(state);
|
||||||
|
str_t_clear(&signature);
|
||||||
|
|
||||||
|
LOG_TRACE("sign_client_secret exit");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
str_t_clear(&secret);
|
||||||
|
free(state);
|
||||||
|
str_t_clear(&signature);
|
||||||
|
LOG_ERROR("sign_client_secret exit with error");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -31,6 +31,7 @@ capi_function_list_init(library_t *lib, capi_function_list_t *fl)
|
||||||
LIBRARY_RESOLVE(fl->CertGetCertificateChain, lib, "CertGetCertificateChain");
|
LIBRARY_RESOLVE(fl->CertGetCertificateChain, lib, "CertGetCertificateChain");
|
||||||
LIBRARY_RESOLVE(fl->CertVerifyCertificateChainPolicy, lib, "CertVerifyCertificateChainPolicy");
|
LIBRARY_RESOLVE(fl->CertVerifyCertificateChainPolicy, lib, "CertVerifyCertificateChainPolicy");
|
||||||
LIBRARY_RESOLVE(fl->CertFreeCertificateChain, lib, "CertFreeCertificateChain");
|
LIBRARY_RESOLVE(fl->CertFreeCertificateChain, lib, "CertFreeCertificateChain");
|
||||||
|
LIBRARY_RESOLVE(fl->CryptGenRandom, lib, "CryptGenRandom");
|
||||||
|
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashW");
|
LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashW");
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,13 @@ DECLARE_FN(WINADVAPI,
|
||||||
CERT_FREE_CERTIFICATE_CHAIN,
|
CERT_FREE_CERTIFICATE_CHAIN,
|
||||||
(PCCERT_CHAIN_CONTEXT pChainContext));
|
(PCCERT_CHAIN_CONTEXT pChainContext));
|
||||||
|
|
||||||
|
DECLARE_FN(WINADVAPI,
|
||||||
|
BOOL,
|
||||||
|
CRYPT_GEN_RANDOM,
|
||||||
|
(HCRYPTPROV hProv,
|
||||||
|
DWORD dwLen,
|
||||||
|
BYTE *pbBuffer));
|
||||||
|
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
#define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_W_FN
|
#define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_W_FN
|
||||||
#define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_W_FN
|
#define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_W_FN
|
||||||
|
|
@ -233,6 +240,7 @@ typedef struct {
|
||||||
CERT_GET_CERTIFICATE_CHAIN_FN CertGetCertificateChain;
|
CERT_GET_CERTIFICATE_CHAIN_FN CertGetCertificateChain;
|
||||||
CERT_VERIFY_CERTIFICATE_CHAIN_POLICY_FN CertVerifyCertificateChainPolicy;
|
CERT_VERIFY_CERTIFICATE_CHAIN_POLICY_FN CertVerifyCertificateChainPolicy;
|
||||||
CERT_FREE_CERTIFICATE_CHAIN_FN CertFreeCertificateChain;
|
CERT_FREE_CERTIFICATE_CHAIN_FN CertFreeCertificateChain;
|
||||||
|
CRYPT_GEN_RANDOM_FN CryptGenRandom;
|
||||||
|
|
||||||
} capi_function_list_t;
|
} capi_function_list_t;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cp_function_list.CryptAcquireCertificatePrivateKey(
|
if (!cp_function_list.CryptAcquireCertificatePrivateKey(
|
||||||
pSignerCert,
|
pSignerCert,
|
||||||
CRYPT_ACQUIRE_SILENT_FLAG,
|
CRYPT_ACQUIRE_SILENT_FLAG,
|
||||||
NULL,
|
NULL,
|
||||||
&hCryptProv,
|
&hCryptProv,
|
||||||
|
|
@ -695,3 +695,36 @@ exit:
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cryptopro_gen_random(unsigned char* data, size_t len)
|
||||||
|
{
|
||||||
|
HCRYPTPROV hCryptProv = 0;
|
||||||
|
|
||||||
|
LOG_TRACE("cryptopro_gen_random enter");
|
||||||
|
|
||||||
|
if (!cp_function_list.CryptAcquireContext(&hCryptProv, NULL, CP_KC1_GR3410_2001_PROV,
|
||||||
|
PROV_GOST_2001_DH, CRYPT_VERIFYCONTEXT)) {
|
||||||
|
LOG_ERROR("CryptAcquireContext() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cp_function_list.CryptGenRandom(hCryptProv, len, data)) {
|
||||||
|
LOG_ERROR("CryptGenRandom() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp_function_list.CryptReleaseContext(hCryptProv, 0);
|
||||||
|
|
||||||
|
LOG_TRACE("cryptopro_gen_random exit");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (hCryptProv) {
|
||||||
|
cp_function_list.CryptReleaseContext(hCryptProv, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_ERROR("cryptopro_gen_random exit with error. Last error code: 0x%08x",
|
||||||
|
cp_function_list.GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
@ -29,4 +29,6 @@ int cryptopro_sign(const cryptopro_context_t *ctx, const str_t *data, /*out*/ st
|
||||||
int cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *data,
|
int cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *data,
|
||||||
const str_t *sign, bool* is_verified, char** verify_error);
|
const str_t *sign, bool* is_verified, char** verify_error);
|
||||||
|
|
||||||
|
int cryptopro_gen_random(unsigned char* data, size_t len);
|
||||||
|
|
||||||
#endif // CRYPTOPRO_H_INCLUDED
|
#endif // CRYPTOPRO_H_INCLUDED
|
||||||
|
|
|
||||||
48
src/utils/json_writer.c
Normal file
48
src/utils/json_writer.c
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "json_writer.h"
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
char *
|
||||||
|
json_write_to_str(JsonBuilder *builder)
|
||||||
|
{
|
||||||
|
char *out;
|
||||||
|
|
||||||
|
LOG_TRACE("json_write_to_str enter");
|
||||||
|
|
||||||
|
JsonNode *jnode = json_builder_get_root(builder);
|
||||||
|
if (jnode == NULL) {
|
||||||
|
LOG_ERROR("json_builder_get_root failed");
|
||||||
|
LOG_ERROR("json_write_to_str exit with error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = json_to_string(jnode, FALSE);
|
||||||
|
|
||||||
|
json_node_unref(jnode);
|
||||||
|
|
||||||
|
LOG_TRACE("json_write_to_str exit");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
json_write_member_string(JsonBuilder *builder, const char *member_name, const char *value)
|
||||||
|
{
|
||||||
|
LOG_TRACE("json_write_member_string enter");
|
||||||
|
|
||||||
|
if (json_builder_set_member_name(builder, member_name) == NULL) {
|
||||||
|
LOG_ERROR("json_builder_set_member_name failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_builder_add_string_value(builder, value) == NULL) {
|
||||||
|
LOG_ERROR("json_builder_add_string_value failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_TRACE("json_write_member_string exit");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
LOG_ERROR("json_write_member_string exit with error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
13
src/utils/json_writer.h
Normal file
13
src/utils/json_writer.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef JSON_WRITER_H_INCLUDED
|
||||||
|
#define JSON_WRITER_H_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include <json-glib/json-glib.h>
|
||||||
|
|
||||||
|
|
||||||
|
char* json_write_to_str(JsonBuilder *builder);
|
||||||
|
|
||||||
|
int json_write_member_string(JsonBuilder *builder, const char *member_name, const char *value);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JSON_WRITER_H_INCLUDED
|
||||||
116
src/utils/uuid.c
Normal file
116
src/utils/uuid.c
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
#include "uuid.h"
|
||||||
|
|
||||||
|
#include "cryptopro.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
|
struct uuid {
|
||||||
|
uint32_t time_low;
|
||||||
|
uint16_t time_mid;
|
||||||
|
uint16_t time_hi_and_version;
|
||||||
|
uint16_t clock_seq;
|
||||||
|
uint8_t node[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
uuid_unpack(const uuid_t in, struct uuid *uu)
|
||||||
|
{
|
||||||
|
const uint8_t *ptr = in;
|
||||||
|
uint32_t tmp;
|
||||||
|
|
||||||
|
tmp = *ptr++;
|
||||||
|
tmp = (tmp << 8) | *ptr++;
|
||||||
|
tmp = (tmp << 8) | *ptr++;
|
||||||
|
tmp = (tmp << 8) | *ptr++;
|
||||||
|
uu->time_low = tmp;
|
||||||
|
|
||||||
|
tmp = *ptr++;
|
||||||
|
tmp = (tmp << 8) | *ptr++;
|
||||||
|
uu->time_mid = tmp;
|
||||||
|
|
||||||
|
tmp = *ptr++;
|
||||||
|
tmp = (tmp << 8) | *ptr++;
|
||||||
|
uu->time_hi_and_version = tmp;
|
||||||
|
|
||||||
|
tmp = *ptr++;
|
||||||
|
tmp = (tmp << 8) | *ptr++;
|
||||||
|
uu->clock_seq = tmp;
|
||||||
|
|
||||||
|
memcpy(uu->node, ptr, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
uuid_pack(const struct uuid *uu, uuid_t ptr)
|
||||||
|
{
|
||||||
|
uint32_t tmp;
|
||||||
|
unsigned char *out = ptr;
|
||||||
|
|
||||||
|
tmp = uu->time_low;
|
||||||
|
out[3] = (unsigned char) tmp;
|
||||||
|
tmp >>= 8;
|
||||||
|
out[2] = (unsigned char) tmp;
|
||||||
|
tmp >>= 8;
|
||||||
|
out[1] = (unsigned char) tmp;
|
||||||
|
tmp >>= 8;
|
||||||
|
out[0] = (unsigned char) tmp;
|
||||||
|
|
||||||
|
tmp = uu->time_mid;
|
||||||
|
out[5] = (unsigned char) tmp;
|
||||||
|
tmp >>= 8;
|
||||||
|
out[4] = (unsigned char) tmp;
|
||||||
|
|
||||||
|
tmp = uu->time_hi_and_version;
|
||||||
|
out[7] = (unsigned char) tmp;
|
||||||
|
tmp >>= 8;
|
||||||
|
out[6] = (unsigned char) tmp;
|
||||||
|
|
||||||
|
tmp = uu->clock_seq;
|
||||||
|
out[9] = (unsigned char) tmp;
|
||||||
|
tmp >>= 8;
|
||||||
|
out[8] = (unsigned char) tmp;
|
||||||
|
|
||||||
|
memcpy(out+10, uu->node, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
generate_uuid4()
|
||||||
|
{
|
||||||
|
char *uuid;
|
||||||
|
uuid_t buf;
|
||||||
|
uuid_t out;
|
||||||
|
struct uuid uu;
|
||||||
|
|
||||||
|
LOG_TRACE("generate_uuid enter");
|
||||||
|
|
||||||
|
uuid = malloc(UUID_STR_LEN);
|
||||||
|
if (uuid == NULL) {
|
||||||
|
LOG_ERROR("Could not allocate memory fot uuid (%d bytes)", UUID_STR_LEN);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cryptopro_gen_random(buf, sizeof(buf))) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid_unpack(buf, &uu);
|
||||||
|
|
||||||
|
uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
|
||||||
|
uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
|
||||||
|
|
||||||
|
uuid_pack(&uu, out);
|
||||||
|
|
||||||
|
LOG_DEBUG("uuid_type: %d, uuid_variant: %d", uuid_type(out), uuid_variant(out));
|
||||||
|
|
||||||
|
uuid_unparse(out, uuid);
|
||||||
|
|
||||||
|
LOG_TRACE("generate_uuid exit");
|
||||||
|
return uuid;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(uuid);
|
||||||
|
LOG_ERROR("generate_uuid exit with error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
7
src/utils/uuid.h
Normal file
7
src/utils/uuid.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef UUID_H_INCLUDED
|
||||||
|
#define UUID_H_INCLUDED
|
||||||
|
|
||||||
|
// generates uuid version 4
|
||||||
|
char* generate_uuid4();
|
||||||
|
|
||||||
|
#endif // UUID_H_INCLUDED
|
||||||
|
|
@ -18,7 +18,7 @@ cd -
|
||||||
1. Установить зависимости для сборки приложения:
|
1. Установить зависимости для сборки приложения:
|
||||||
``` bash
|
``` bash
|
||||||
apt-get install cmake gcc gcc10
|
apt-get install cmake gcc gcc10
|
||||||
apt-get install glib2-devel libfcgi-devel libjson-glib libjson-glib-devel
|
apt-get install glib2-devel libfcgi-devel libjson-glib libjson-glib-devel libuuid libuuid-devel
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Собрать приложение из исходников:
|
2. Собрать приложение из исходников:
|
||||||
|
|
|
||||||
|
|
@ -162,10 +162,9 @@ chown -R ervu:ervu /var/opt/cprocsp/keys/ervu/key_cont.000/
|
||||||
## Установка и настройка ervu-sign-module
|
## Установка и настройка ervu-sign-module
|
||||||
|
|
||||||
1. Установить зависимости для запуска приложения:
|
1. Установить зависимости для запуска приложения:
|
||||||
|
``` bash
|
||||||
```bash
|
apt-get install glib2 libfcgi libjson-glib libuuid
|
||||||
apt-get install glib2 libfcgi libjson-glib
|
```
|
||||||
```
|
|
||||||
|
|
||||||
2. Скопировать исполняемый файл:
|
2. Скопировать исполняемый файл:
|
||||||
|
|
||||||
|
|
@ -249,11 +248,14 @@ chown -R ervu:ervu /var/opt/cprocsp/keys/ervu/key_cont.000/
|
||||||
< HTTP/1.1 200 OK
|
< HTTP/1.1 200 OK
|
||||||
< Server: nginx/1.24.0
|
< Server: nginx/1.24.0
|
||||||
< Date: Tue, 20 Aug 2024 12:00:25 GMT
|
< Date: Tue, 20 Aug 2024 12:00:25 GMT
|
||||||
< Content-Type: text/plain
|
< Content-Type: application/json
|
||||||
< Transfer-Encoding: chunked
|
< Transfer-Encoding: chunked
|
||||||
< Connection: keep-alive
|
< Connection: keep-alive
|
||||||
<
|
<
|
||||||
REFlyzGQrCjX9DvA7hWwN9vf5kPqBxcG4TLYnXUHnAS9_G-sLAFvaJei2OhxpaWNraHbOv_mMsM_bcDsXWiC0Q
|
{
|
||||||
|
"signature": "urlSafeBase64_of_signed_string_test_with_state",
|
||||||
|
"state": "7c327cb7-7916-4255-bc46-85fbc5ad7d5f"
|
||||||
|
}
|
||||||
* Connection #0 to host 127.0.0.1 left intact
|
* Connection #0 to host 127.0.0.1 left intact
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue