Skip to content

Commit c92904b

Browse files
better server response to authorization error cases
1 parent e6bb65b commit c92904b

2 files changed

Lines changed: 192 additions & 53 deletions

File tree

src/wh_server.c

Lines changed: 183 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
#include "wolfhsm/wh_message_comm.h"
4444
#include "wolfhsm/wh_message_nvm.h"
4545
#include "wolfhsm/wh_message_auth.h"
46+
#if defined(WOLFHSM_CFG_CERTIFICATE_MANAGER) && !defined(WOLFHSM_CFG_NO_CRYPTO)
47+
#include "wolfhsm/wh_message_cert.h"
48+
#endif /* WOLFHSM_CFG_CERTIFICATE_MANAGER && !WOLFHSM_CFG_NO_CRYPTO */
4649

4750
/* Server API's */
4851
#include "wolfhsm/wh_server.h"
@@ -319,6 +322,171 @@ static int _wh_Server_HandlePkcs11Request(whServerContext* server,
319322
return rc;
320323
}
321324

325+
/* Helper to format an authorization error response for any group/action.
326+
* All response structures have int32_t rc as the first field.
327+
* Returns the response size to send. */
328+
static uint16_t _wh_Server_FormatAuthErrorResponse(uint16_t magic, uint16_t group,
329+
uint16_t action, int32_t error_code, void* resp_packet)
330+
{
331+
uint16_t resp_size = sizeof(int32_t); /* Minimum: just the rc field */
332+
333+
if (resp_packet == NULL) {
334+
return 0;
335+
}
336+
337+
/* Write error code to first int32_t (rc field) - all responses start with this */
338+
*(int32_t*)resp_packet = (int32_t)wh_Translate32(magic, (uint32_t)error_code);
339+
340+
switch (group) {
341+
case WH_MESSAGE_GROUP_AUTH:
342+
/* Auth group has some responses larger than SimpleResponse */
343+
switch (action) {
344+
case WH_MESSAGE_AUTH_ACTION_LOGIN:
345+
{
346+
whMessageAuth_LoginResponse resp = {0};
347+
resp.rc = error_code;
348+
resp.user_id = WH_USER_ID_INVALID;
349+
resp.permissions = 0;
350+
wh_MessageAuth_TranslateLoginResponse(magic, &resp,
351+
(whMessageAuth_LoginResponse*)resp_packet);
352+
resp_size = sizeof(resp);
353+
break;
354+
}
355+
case WH_MESSAGE_AUTH_ACTION_USER_ADD:
356+
{
357+
whMessageAuth_UserAddResponse resp = {0};
358+
resp.rc = error_code;
359+
resp.user_id = WH_USER_ID_INVALID;
360+
wh_MessageAuth_TranslateUserAddResponse(magic, &resp,
361+
(whMessageAuth_UserAddResponse*)resp_packet);
362+
resp_size = sizeof(resp);
363+
break;
364+
}
365+
case WH_MESSAGE_AUTH_ACTION_USER_GET:
366+
{
367+
whMessageAuth_UserGetResponse resp = {0};
368+
resp.rc = error_code;
369+
resp.user_id = WH_USER_ID_INVALID;
370+
memset(resp.permissions, 0, sizeof(resp.permissions));
371+
wh_MessageAuth_TranslateUserGetResponse(magic, &resp,
372+
(whMessageAuth_UserGetResponse*)resp_packet);
373+
resp_size = sizeof(resp);
374+
break;
375+
}
376+
default:
377+
{
378+
/* Use SimpleResponse for other auth actions */
379+
whMessageAuth_SimpleResponse resp = {0};
380+
resp.rc = error_code;
381+
wh_MessageAuth_TranslateSimpleResponse(magic, &resp,
382+
(whMessageAuth_SimpleResponse*)resp_packet);
383+
resp_size = sizeof(resp);
384+
break;
385+
}
386+
}
387+
break;
388+
389+
case WH_MESSAGE_GROUP_NVM:
390+
/* NVM group - some actions have larger responses than SimpleResponse */
391+
switch (action) {
392+
case WH_MESSAGE_NVM_ACTION_INIT:
393+
{
394+
whMessageNvm_InitResponse resp = {0};
395+
resp.rc = error_code;
396+
resp.servernvm_id = 0;
397+
resp.clientnvm_id = 0;
398+
wh_MessageNvm_TranslateInitResponse(magic, &resp,
399+
(whMessageNvm_InitResponse*)resp_packet);
400+
resp_size = sizeof(resp);
401+
break;
402+
}
403+
case WH_MESSAGE_NVM_ACTION_GETAVAILABLE:
404+
{
405+
whMessageNvm_GetAvailableResponse resp = {0};
406+
resp.rc = error_code;
407+
resp.avail_size = 0;
408+
resp.reclaim_size = 0;
409+
resp.avail_objects = 0;
410+
resp.reclaim_objects = 0;
411+
wh_MessageNvm_TranslateGetAvailableResponse(magic, &resp,
412+
(whMessageNvm_GetAvailableResponse*)resp_packet);
413+
resp_size = sizeof(resp);
414+
break;
415+
}
416+
case WH_MESSAGE_NVM_ACTION_LIST:
417+
{
418+
whMessageNvm_ListResponse resp = {0};
419+
resp.rc = error_code;
420+
resp.count = 0;
421+
resp.id = 0;
422+
wh_MessageNvm_TranslateListResponse(magic, &resp,
423+
(whMessageNvm_ListResponse*)resp_packet);
424+
resp_size = sizeof(resp);
425+
break;
426+
}
427+
case WH_MESSAGE_NVM_ACTION_GETMETADATA:
428+
{
429+
whMessageNvm_GetMetadataResponse resp = {0};
430+
resp.rc = error_code;
431+
resp.id = 0;
432+
resp.access = 0;
433+
resp.flags = 0;
434+
resp.len = 0;
435+
memset(resp.label, 0, sizeof(resp.label));
436+
wh_MessageNvm_TranslateGetMetadataResponse(magic, &resp,
437+
(whMessageNvm_GetMetadataResponse*)resp_packet);
438+
resp_size = sizeof(resp);
439+
break;
440+
}
441+
case WH_MESSAGE_NVM_ACTION_READ:
442+
{
443+
whMessageNvm_ReadResponse resp = {0};
444+
resp.rc = error_code;
445+
wh_MessageNvm_TranslateReadResponse(magic, &resp,
446+
(whMessageNvm_ReadResponse*)resp_packet);
447+
resp_size = sizeof(resp);
448+
break;
449+
}
450+
default:
451+
{
452+
/* Use SimpleResponse for other NVM actions */
453+
whMessageNvm_SimpleResponse resp = {0};
454+
resp.rc = error_code;
455+
wh_MessageNvm_TranslateSimpleResponse(magic, &resp,
456+
(whMessageNvm_SimpleResponse*)resp_packet);
457+
resp_size = sizeof(resp);
458+
break;
459+
}
460+
}
461+
break;
462+
463+
#if defined(WOLFHSM_CFG_CERTIFICATE_MANAGER) && !defined(WOLFHSM_CFG_NO_CRYPTO)
464+
case WH_MESSAGE_GROUP_CERT:
465+
/* Cert group - use SimpleResponse for all actions */
466+
{
467+
whMessageCert_SimpleResponse resp = {0};
468+
resp.rc = error_code;
469+
wh_MessageCert_TranslateSimpleResponse(magic, &resp,
470+
(whMessageCert_SimpleResponse*)resp_packet);
471+
resp_size = sizeof(resp);
472+
}
473+
break;
474+
#endif /* WOLFHSM_CFG_CERTIFICATE_MANAGER && !WOLFHSM_CFG_NO_CRYPTO */
475+
476+
default:
477+
/* For other groups, use minimum size (just rc field).
478+
* Most response structures have int32_t rc as first field, so clients
479+
* should be able to read at least the error code. If a group needs
480+
* special handling, it can be added above. */
481+
/* Error code already written above */
482+
resp_size = sizeof(int32_t);
483+
break;
484+
}
485+
486+
return resp_size;
487+
}
488+
489+
322490
int wh_Server_HandleRequestMessage(whServerContext* server)
323491
{
324492
uint16_t magic = 0;
@@ -359,23 +527,21 @@ int wh_Server_HandleRequestMessage(whServerContext* server)
359527
if (server->auth != NULL) {
360528
rc = wh_Auth_CheckRequestAuthorization(server->auth, group, action);
361529
if (rc != WH_ERROR_OK) {
362-
/* Authorization failed - send error response to client but keep server running */
363-
int32_t error_response = (int32_t)WH_AUTH_PERMISSION_ERROR;
364-
uint16_t resp_size = sizeof(error_response);
365-
366-
/* Translate the error response for endian conversion */
367-
error_response = (int32_t)wh_Translate32(magic, (uint32_t)error_response);
368-
369-
/* Send error response to client */
370-
do {
371-
rc = wh_CommServer_SendResponse(server->comm, magic, kind, seq,
372-
resp_size, &error_response);
373-
} while (rc == WH_ERROR_NOTREADY);
374-
375-
/* Log the authorization failure */
376-
WH_LOG_ON_ERROR_F(&server->log, WH_LOG_LEVEL_ERROR, WH_AUTH_PERMISSION_ERROR,
377-
"Authorization failed for (group=%d, action=%d, seq=%d)",
378-
group, action, seq);
530+
/* Authorization failed - format and send error response to client */
531+
int32_t error_code = (int32_t)WH_AUTH_PERMISSION_ERROR;
532+
uint16_t resp_size = _wh_Server_FormatAuthErrorResponse(magic, group,
533+
action, error_code, data);
534+
535+
/* Send error response to client */
536+
do {
537+
rc = wh_CommServer_SendResponse(server->comm, magic, kind, seq,
538+
resp_size, data);
539+
} while (rc == WH_ERROR_NOTREADY);
540+
541+
/* Log the authorization failure */
542+
WH_LOG_ON_ERROR_F(&server->log, WH_LOG_LEVEL_ERROR, WH_AUTH_PERMISSION_ERROR,
543+
"Authorization failed for (group=%d, action=%d, seq=%d)",
544+
group, action, seq);
379545

380546
return rc;
381547
}

test/wh_test_auth.c

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ static int _whTest_Auth_BadArgs(void)
346346
whAuthConfig config;
347347
whAuthPermissions perms;
348348
whUserId user_id = WH_USER_ID_INVALID;
349+
int32_t server_rc = 0;
349350

350351
memset(&ctx, 0, sizeof(ctx));
351352
memset(&config, 0, sizeof(config));
@@ -366,9 +367,9 @@ static int _whTest_Auth_BadArgs(void)
366367
WH_TEST_ASSERT_RETURN(rc == WH_ERROR_BADARGS);
367368
rc = wh_Auth_Login(&ctx, 0, WH_AUTH_METHOD_PIN, "user", "pin", 3, NULL);
368369
WH_TEST_ASSERT_RETURN(rc == WH_ERROR_BADARGS);
369-
rc = wh_Auth_LoginRequest(NULL, 0, WH_AUTH_METHOD_PIN, "user", "pin", 3, &loggedIn);
370+
rc = wh_Client_AuthLoginRequest(NULL, WH_AUTH_METHOD_PIN, "user", "pin", 3);
370371
WH_TEST_ASSERT_RETURN(rc == WH_ERROR_BADARGS);
371-
rc = wh_Auth_LoginResponse(NULL, &loggedIn, &user_id, &perms);
372+
rc = wh_Client_AuthLoginResponse(NULL, &server_rc, &user_id, &perms);
372373
WH_TEST_ASSERT_RETURN(rc == WH_ERROR_BADARGS);
373374

374375
rc = wh_Auth_Logout(NULL, 1);
@@ -768,12 +769,7 @@ int whTest_AuthDeleteUser(whClientContext* client)
768769
server_rc = 0;
769770
_whTest_Auth_UserDeleteOp(client, 1, &server_rc);
770771
/* Should fail authorization - not logged in */
771-
/* Note: This may fail if backend permission checks are not fully implemented */
772-
if (server_rc == WH_ERROR_ACCESS) {
773-
WH_TEST_PRINT(" Authorization check working (expected)\n");
774-
} else {
775-
WH_TEST_PRINT(" Note: Authorization check may not be fully implemented\n");
776-
}
772+
WH_TEST_ASSERT_RETURN(server_rc != WH_ERROR_OK);
777773

778774
return WH_TEST_SUCCESS;
779775
}
@@ -878,12 +874,7 @@ int whTest_AuthSetPermissions(whClientContext* client)
878874
server_rc = 0;
879875
_whTest_Auth_UserSetPermsOp(client, user_id, new_perms, &server_rc);
880876
/* Should fail authorization - not logged in */
881-
/* Note: This may fail if backend permission checks are not fully implemented */
882-
if (server_rc == WH_ERROR_ACCESS) {
883-
WH_TEST_PRINT(" Authorization check working (expected)\n");
884-
} else {
885-
WH_TEST_PRINT(" Note: Authorization check may not be fully implemented\n");
886-
}
877+
WH_TEST_ASSERT_RETURN(server_rc != WH_ERROR_OK);
887878

888879
/* Cleanup */
889880
server_rc = 0;
@@ -1004,12 +995,7 @@ int whTest_AuthRequestAuthorization(whClientContext* client)
1004995
_whTest_Auth_UserAddOp(client, "testuser5", perms, WH_AUTH_METHOD_PIN,
1005996
"test", 4, &server_rc, &temp_id);
1006997
/* Should fail authorization - not logged in */
1007-
/* Note: This may fail if backend permission checks are not fully implemented */
1008-
if (server_rc == WH_ERROR_ACCESS) {
1009-
WH_TEST_PRINT(" Authorization check working (expected)\n");
1010-
} else {
1011-
WH_TEST_PRINT(" Note: Authorization check may not be fully implemented\n");
1012-
}
998+
WH_TEST_ASSERT_RETURN(server_rc != WH_ERROR_OK);
1013999

10141000
/* Test 2: Operation when logged in and allowed */
10151001
WH_TEST_PRINT(" Test: Operation when logged in and allowed\n");
@@ -1063,12 +1049,7 @@ int whTest_AuthRequestAuthorization(whClientContext* client)
10631049
_whTest_Auth_UserAddOp(client, "testuser7", perms, WH_AUTH_METHOD_PIN,
10641050
"test", 4, &server_rc, &temp_id2);
10651051
/* Should fail authorization - user doesn't have permissions */
1066-
/* Note: This may fail if backend permission checks are not fully implemented */
1067-
if (server_rc == WH_ERROR_ACCESS) {
1068-
WH_TEST_PRINT(" Authorization check working (expected)\n");
1069-
} else {
1070-
WH_TEST_PRINT(" Note: Authorization check may not be fully implemented\n");
1071-
}
1052+
WH_TEST_ASSERT_RETURN(server_rc != WH_ERROR_OK);
10721053

10731054
/* Test 4: Logged in as different user and allowed */
10741055
WH_TEST_PRINT(" Test: Logged in as different user and allowed\n");
@@ -1106,11 +1087,7 @@ int whTest_AuthRequestAuthorization(whClientContext* client)
11061087
temp_id3 = WH_USER_ID_INVALID;
11071088
_whTest_Auth_UserAddOp(client, "testuser8", perms, WH_AUTH_METHOD_PIN,
11081089
"test", 4, &server_rc, &temp_id3);
1109-
if (server_rc == WH_ERROR_ACCESS) {
1110-
WH_TEST_PRINT(" Authorization check working (expected)\n");
1111-
} else {
1112-
WH_TEST_PRINT(" Note: Authorization check may not be fully implemented\n");
1113-
}
1090+
WH_TEST_ASSERT_RETURN(server_rc != WH_ERROR_OK);
11141091

11151092
/* Test 5: Logged in as different user and not allowed */
11161093
WH_TEST_PRINT(" Test: Logged in as different user and not allowed\n");
@@ -1129,11 +1106,7 @@ int whTest_AuthRequestAuthorization(whClientContext* client)
11291106
temp_id3 = WH_USER_ID_INVALID;
11301107
_whTest_Auth_UserAddOp(client, "testuser9", perms, WH_AUTH_METHOD_PIN,
11311108
"test", 4, &server_rc, &temp_id3);
1132-
if (server_rc == WH_ERROR_ACCESS) {
1133-
WH_TEST_PRINT(" Authorization check working (expected)\n");
1134-
} else {
1135-
WH_TEST_PRINT(" Note: Authorization check may not be fully implemented\n");
1136-
}
1109+
WH_TEST_ASSERT_RETURN(server_rc != WH_ERROR_OK);
11371110

11381111
/* Cleanup */
11391112
_whTest_Auth_LogoutOp(client, logged_in_id, &server_rc);

0 commit comments

Comments
 (0)