SUPPORT-8592. В случае неверной подписи в ответе передается код ошибки от криптопро

This commit is contained in:
alashkova 2024-10-16 16:01:38 +03:00
parent 2f2a6efd89
commit f95975719f
3 changed files with 71 additions and 14 deletions

View file

@ -11,6 +11,12 @@
#define VERIFY_CONF_KEY_LOCATION "location"
#define VERIFY_CONF_KEY_THUMBPRINT "esia_cert_thumbprint"
#define FCGI_401_BAD_SIGNATURE_RESPONSE_FORMAT \
"Status: 401 Unauthorized" CRLF\
"Content-type: text/plain" CRLF\
CRLF\
"%s" CRLF
static const str_t VERIFY_CONF_DEFAULT_LOCATION = str_t_const("/verify");
static const int CLIENT_MAX_BODY_SIZE = 8192;
@ -29,12 +35,14 @@ typedef struct fcgi_verify_request_s {
char *content;
int content_length;
char *verify_error;
} fcgi_verify_request_t;
static fcgi_request_handler_pt fcgi_request_finalize_handler(fcgi_handler_status_t status);
static void fcgi_verify_request_clear(fcgi_verify_request_t *req_info);
static fcgi_handler_status_t verify_jwt_sign(const fcgi_verify_request_t* req_info,
static fcgi_handler_status_t verify_jwt_sign(fcgi_verify_request_t* req_info,
const verify_service_t *ctx);
@ -156,7 +164,7 @@ fcgi_verify_handler(FCGX_Request* request, void* ctx)
status = verify_jwt_sign(&req_info, ctx);
exit:
status = fcgi_request_finalize_handler(status)(request, ctx);
status = fcgi_request_finalize_handler(status)(request, &req_info);
fcgi_verify_request_clear(&req_info);
@ -164,6 +172,27 @@ exit:
return status;
}
static fcgi_handler_status_t
fcgi_401_bad_signature_handler(const FCGX_Request* request, void *ctx)
{
LOG_TRACE("fcgi_401_bad_signature_handler");
const fcgi_verify_request_t *req_info = (fcgi_verify_request_t*) ctx;
assert(req_info->verify_error != NULL);
LOG_DEBUG("response status: " FCGI_401_BAD_SIGNATURE_RESPONSE_FORMAT,
req_info->verify_error);
if (FCGX_FPrintF(request->out, FCGI_401_BAD_SIGNATURE_RESPONSE_FORMAT,
req_info->verify_error) < 0) {
LOG_ERROR("FCGX_FPrintF() failed");
return HANDLER_ERROR;
}
return HANDLER_SUCCESS;
}
static fcgi_request_handler_pt
fcgi_request_finalize_handler(fcgi_handler_status_t status)
{
@ -180,7 +209,7 @@ fcgi_request_finalize_handler(fcgi_handler_status_t status)
break;
case HANDLER_HTTP_UNAUTHORIZED:
handler = fcgi_401_unauthorized_handler;
handler = fcgi_401_bad_signature_handler;
break;
case HANDLER_HTTP_NOT_ACCEPTABLE:
@ -206,6 +235,7 @@ fcgi_verify_request_clear(fcgi_verify_request_t *req_info)
LOG_TRACE("fcgi_verify_request_clear");
free(req_info->content);
free(req_info->verify_error);
}
static int
@ -276,7 +306,7 @@ error:
}
static fcgi_handler_status_t
verify_jwt_sign(const fcgi_verify_request_t* req_info, const verify_service_t *ctx)
verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx)
{
LOG_TRACE("verify_jwt_sign enter");
@ -318,7 +348,7 @@ verify_jwt_sign(const fcgi_verify_request_t* req_info, const verify_service_t *c
}
if (cryptopro_verify(&ctx->conf->esia_cert_thumbprint, &alg, &header_payload, &sign,
&is_verified)) {
&is_verified, &req_info->verify_error)) {
goto error;
}

View file

@ -355,28 +355,51 @@ alg_id_from_str(const str_t* alg, /*out*/ ALG_ID* alg_id)
}
static void
log_verify_error()
get_verify_error(char** verify_error)
{
LOG_TRACE("get_verify_error enter");
DWORD err = cp_function_list.GetLastError();
const char* err_string;
switch (err) {
case NTE_BAD_SIGNATURE:
LOG_WARN("sign is invalid: bad signature (0x%08x)", err);
err_string = "sign is invalid: bad signature (0x%08x)";
break;
case NTE_BAD_ALGID:
LOG_WARN("sign is invalid: bad alg id (0x%08x)", err);
err_string = "sign is invalid: bad alg id (0x%08x)";
break;
default:
LOG_WARN("sign is invalid. Last error code: 0x%08x", err);
err_string = "sign is invalid. Last error code: 0x%08x";
break;
}
size_t size = strlen(err_string) + 4 /*error code*/ + 1 /*terminating null*/;
*verify_error = malloc(size);
if (*verify_error == NULL) {
LOG_ERROR("get_verify_error failed. Could not allocate memory for error string "
"(%zd bytes)", size);
return;
}
int n = snprintf(*verify_error, size, err_string, err);
if (n < 0 || (size_t)n >= size) {
LOG_ERROR("get_verify_error failed. Error occurred in concatenation err_string");
free(*verify_error);
return;
}
LOG_TRACE("get_verify_error exit");
}
int
cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *data,
const str_t *sign, bool* is_verified)
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)
{
int rc = -1;
HCERTSTORE hStoreHandle = NULL;
@ -441,7 +464,11 @@ cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *da
LOG_DEBUG("sign is valid");
*is_verified = true;
} else {
log_verify_error();
get_verify_error(verify_error);
if (*verify_error == NULL) {
goto exit;
}
LOG_WARN("%s", *verify_error);
}
rc = 0;

View file

@ -27,6 +27,6 @@ bool cryptopro_init(const char* cp_file);
int cryptopro_sign(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t *sign);
int cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *data,
const str_t *sign, bool* is_verified);
const str_t *sign, bool* is_verified, char** verify_error);
#endif // CRYPTOPRO_H_INCLUDED