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_LOCATION "location"
#define VERIFY_CONF_KEY_THUMBPRINT "esia_cert_thumbprint" #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 str_t VERIFY_CONF_DEFAULT_LOCATION = str_t_const("/verify");
static const int CLIENT_MAX_BODY_SIZE = 8192; static const int CLIENT_MAX_BODY_SIZE = 8192;
@ -29,12 +35,14 @@ typedef struct fcgi_verify_request_s {
char *content; char *content;
int content_length; int content_length;
char *verify_error;
} fcgi_verify_request_t; } fcgi_verify_request_t;
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 void fcgi_verify_request_clear(fcgi_verify_request_t *req_info); 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); const verify_service_t *ctx);
@ -156,7 +164,7 @@ fcgi_verify_handler(FCGX_Request* request, void* ctx)
status = verify_jwt_sign(&req_info, ctx); status = verify_jwt_sign(&req_info, ctx);
exit: exit:
status = fcgi_request_finalize_handler(status)(request, ctx); status = fcgi_request_finalize_handler(status)(request, &req_info);
fcgi_verify_request_clear(&req_info); fcgi_verify_request_clear(&req_info);
@ -164,6 +172,27 @@ exit:
return status; 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 static fcgi_request_handler_pt
fcgi_request_finalize_handler(fcgi_handler_status_t status) fcgi_request_finalize_handler(fcgi_handler_status_t status)
{ {
@ -180,7 +209,7 @@ fcgi_request_finalize_handler(fcgi_handler_status_t status)
break; break;
case HANDLER_HTTP_UNAUTHORIZED: case HANDLER_HTTP_UNAUTHORIZED:
handler = fcgi_401_unauthorized_handler; handler = fcgi_401_bad_signature_handler;
break; break;
case HANDLER_HTTP_NOT_ACCEPTABLE: 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"); LOG_TRACE("fcgi_verify_request_clear");
free(req_info->content); free(req_info->content);
free(req_info->verify_error);
} }
static int static int
@ -276,7 +306,7 @@ error:
} }
static fcgi_handler_status_t 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"); 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, if (cryptopro_verify(&ctx->conf->esia_cert_thumbprint, &alg, &header_payload, &sign,
&is_verified)) { &is_verified, &req_info->verify_error)) {
goto error; goto error;
} }

View file

@ -355,28 +355,51 @@ alg_id_from_str(const str_t* alg, /*out*/ ALG_ID* alg_id)
} }
static void static void
log_verify_error() get_verify_error(char** verify_error)
{ {
LOG_TRACE("get_verify_error enter");
DWORD err = cp_function_list.GetLastError(); DWORD err = cp_function_list.GetLastError();
const char* err_string;
switch (err) { switch (err) {
case NTE_BAD_SIGNATURE: case NTE_BAD_SIGNATURE:
LOG_WARN("sign is invalid: bad signature (0x%08x)", err); err_string = "sign is invalid: bad signature (0x%08x)";
break; break;
case NTE_BAD_ALGID: 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; break;
default: default:
LOG_WARN("sign is invalid. Last error code: 0x%08x", err); err_string = "sign is invalid. Last error code: 0x%08x";
break; 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 int
cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *data, 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)
{ {
int rc = -1; int rc = -1;
HCERTSTORE hStoreHandle = NULL; 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"); LOG_DEBUG("sign is valid");
*is_verified = true; *is_verified = true;
} else { } else {
log_verify_error(); get_verify_error(verify_error);
if (*verify_error == NULL) {
goto exit;
}
LOG_WARN("%s", *verify_error);
} }
rc = 0; 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_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, 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 #endif // CRYPTOPRO_H_INCLUDED