From 9d1dcab555ee5ac390a04e659185979da5e0f973 Mon Sep 17 00:00:00 2001 From: Oleksii Beketov Date: Wed, 13 Mar 2019 13:04:52 +0200 Subject: [PATCH] Asynchronous User Confirm API for asynchronous user confirmation added https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/373 (cherry picked from adaebd8edd926ae3ddc34f9a21edc793af7b0c1f) Change-Id: I17d91e07793c2108ccaeb702e440d5d0c64f317c Signed-off-by: Oleksii Beketov Signed-off-by: DoHyun Pyun --- resource/c_common/octhread/include/octhread.h | 14 +- resource/c_common/octhread/src/posix/octhread.c | 15 ++ resource/csdk/security/include/oxmverifycommon.h | 41 +++++ .../provisioning/sample/sampleserver_mfg.cpp | 17 +- resource/csdk/security/src/doxmresource.c | 171 +++++++++++++++++++-- resource/csdk/security/src/oxmverifycommon.c | 59 +++++++ 6 files changed, 297 insertions(+), 20 deletions(-) diff --git a/resource/c_common/octhread/include/octhread.h b/resource/c_common/octhread/include/octhread.h index 95728d1..8f96de8 100644 --- a/resource/c_common/octhread/include/octhread.h +++ b/resource/c_common/octhread/include/octhread.h @@ -59,7 +59,8 @@ typedef enum OC_THREAD_INVALID = 3, OC_THREAD_WAIT_FAILURE = 4, OC_THREAD_INVALID_PARAMETER = 5, - OC_THREAD_CANCEL_FAILURE = 6 + OC_THREAD_CANCEL_FAILURE = 6, + OC_THREAD_DETACH_FAILURE = 7 } OCThreadResult_t; /** @@ -103,6 +104,17 @@ OCThreadResult_t oc_thread_free(oc_thread t); */ OCThreadResult_t oc_thread_wait(oc_thread t); +/** + * Detach the thread + * + * @param[in] t The thread to be detached + * @return OCThreadResult_t An enumeration of possible outcomes + * @retval OC_THREAD_SUCCESS If the thread successfully detached + * @retval OC_THREAD_DETACH_FAILURE If a problem occured while detaching + * + */ +OCThreadResult_t oc_thread_detach(oc_thread t); + #ifdef __TIZEN__ /** * Cancel the thread without block diff --git a/resource/c_common/octhread/src/posix/octhread.c b/resource/c_common/octhread/src/posix/octhread.c index 2e9781a..4a0ca43 100644 --- a/resource/c_common/octhread/src/posix/octhread.c +++ b/resource/c_common/octhread/src/posix/octhread.c @@ -176,6 +176,21 @@ OCThreadResult_t oc_thread_wait(oc_thread t) return res; } +OCThreadResult_t oc_thread_detach(oc_thread t) +{ + OCThreadResult_t res = OC_THREAD_SUCCESS; +#ifndef __TIZENRT__ + oc_thread_internal *threadInfo = (oc_thread_internal*) t; + int detachres = pthread_detach(threadInfo->thread); + if (0 != detachres) + { + OIC_LOG_V(ERROR, TAG, "Failed to detach thread with error %d", detachres); + res = OC_THREAD_DETACH_FAILURE; + } +#endif + return res; +} + #ifdef __TIZEN__ OCThreadResult_t oc_thread_cancel(oc_thread t) { diff --git a/resource/csdk/security/include/oxmverifycommon.h b/resource/csdk/security/include/oxmverifycommon.h index bab6aa2..ecf50a6 100644 --- a/resource/csdk/security/include/oxmverifycommon.h +++ b/resource/csdk/security/include/oxmverifycommon.h @@ -84,6 +84,17 @@ typedef struct UserConfirmContext } UserConfirmContext_t; /** + * Context for getting user confirmation + */ +typedef struct UserAsyncConfirmContext +{ + UserConfirmCallback callback; + void * context; + bool userConfirmResult; + bool userConfirm; +} UserAsyncConfirmContext_t; + +/** * Context for notifying user input state */ typedef struct InputStateContext @@ -108,11 +119,21 @@ void* UnsetDisplayNumCB(); void SetUserConfirmCB(void * ptr, UserConfirmCallback userConfirmCB); /** + * Set asynchronous callback for getting user confirmation + */ +void SetAsyncUserConfirmCB(void * ptr, UserConfirmCallback userConfirmCB); + +/** * Unset Callback for getting user confirmation */ void* UnsetUserConfirmCB(); /** + * Unset asynchronous callback for getting user confirmation + */ +void* UnsetAsyncUserConfirmCB(); + +/** * Set Callback for notifying user input state */ void SetInputStateCB(void * ptr, UserConfirmCallback userConfirmCB); @@ -145,10 +166,30 @@ OCStackResult VerifyOwnershipTransfer(uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LE VerifyOptionBitmask_t verifyOption); /** + * Call the Asynchronius Callback for Verifying Ownership Transfer process. + */ +OCStackResult VerifyUserConfirm(); + +/** + * Get user asynchronous verification result + */ +void GetAsyncVerifyUserResult(bool * result, bool * confirm); + +/** * Call the Callback for notifying user input state */ OCStackResult NotifyInputState(void); +/** + * Callback to set user confirmation result. + * + * @param ctx Asynchronous confirmation context. + * @param confirmed User confirmation result. + * + * @retVal ::OC_STACK_OK + */ +OCStackResult SendUserConfirm(bool confirmed); + #ifdef __cplusplus } #endif diff --git a/resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp b/resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp index a1923fe..88ff489 100644 --- a/resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp +++ b/resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp @@ -406,9 +406,8 @@ void handleSigInt(int signum) } } -OCStackResult confirmCB(void * ctx) +OCStackResult confirmCB_thread() { - OC_UNUSED(ctx); for (;;) { int userConfirm; @@ -424,17 +423,27 @@ OCStackResult confirmCB(void * ctx) } if (1 == userConfirm) { + SendUserConfirm(true); break; } else if (0 == userConfirm) { - return OC_STACK_USER_DENIED_REQ; + SendUserConfirm(false); + break; } printf(" Entered Wrong Number. Please Enter Again\n"); } return OC_STACK_OK; } +OCStackResult confirmCB(void * ctx) +{ + OC_UNUSED(ctx); + pthread_t threadId; + pthread_create (&threadId, NULL, &confirmCB_thread, NULL); + return OC_STACK_OK; +} + void confirmNoCertCB(CACertificateVerificationStatus_t status) { if (CA_CERTIFICATE_VERIFY_SUCCESS_MUTUAL == status) @@ -499,7 +508,7 @@ int main(int argc, char **argv) // Initialize Persistent Storage for SVR database OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink, NULL, NULL}; - SetUserConfirmCB(NULL, confirmCB); + SetAsyncUserConfirmCB(NULL, confirmCB); SetInformOxmSelCB(informOxmSelCB); CAsetCertificateVerificationCallback(confirmNoCertCB); diff --git a/resource/csdk/security/src/doxmresource.c b/resource/csdk/security/src/doxmresource.c index 320425f..811fa89 100644 --- a/resource/csdk/security/src/doxmresource.c +++ b/resource/csdk/security/src/doxmresource.c @@ -49,6 +49,8 @@ #include "pinoxmcommon.h" #include "oxmverifycommon.h" #include "octhread.h" +#include "oic_time.h" +#include "oic_string.h" #if defined(__WITH_DTLS__) || defined (__WITH_TLS__) #include "pkix_interface.h" @@ -95,6 +97,9 @@ static OicSecDoxm_t *gDoxm = NULL; static oc_mutex g_mutexDoxm = NULL; static bool g_isDoxmNull = false; static OCResourceHandle gDoxmHandle = NULL; +static oc_mutex g_mutexWait; +static oc_thread g_waitConfirmThreadId; +oc_cond g_condWait; static InformOxmSelectedCallback_t g_InformOxmSelectedCallback = NULL; static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS; @@ -1096,6 +1101,122 @@ void UnsetInformOxmSelCB() OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); } +#if defined(__WITH_DTLS__) || defined (__WITH_TLS__) +static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest); + +void * WaitConfirm(OCEntityHandlerRequest * ehRequest) +{ + bool confirmResult = false, confirmState = false; + + oc_mutex_lock(g_mutexWait); + oc_cond_wait(g_condWait, g_mutexWait); + oc_cond_free(g_condWait); + oc_mutex_free(g_mutexWait); + + GetAsyncVerifyUserResult(&confirmResult, &confirmState); + if (confirmResult == true) + { + gConfirmState = CONFIRM_STATE_ACCEPTED; + HandleDoxmPostRequest(ehRequest); + return NULL; + } + else + { + gConfirmState = CONFIRM_STATE_DENIED; + HandleDoxmPostRequest(ehRequest); + return NULL; + } +} + +static OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest) +{ + OIC_LOG(INFO, TAG, "Copying received request for slow response"); + + if (!entityHandlerRequest) + { + OIC_LOG_V(ERROR, TAG, "%s: entityHandlerRequest is NULL", __func__); + return NULL; + } + + OCEntityHandlerRequest *copyOfRequest = + (OCEntityHandlerRequest *)OICMalloc(sizeof(OCEntityHandlerRequest)); + if(!copyOfRequest) + { + OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure"); + return NULL; + } + + memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest)); + + if (entityHandlerRequest->query) + { + copyOfRequest->query = OICStrdup(entityHandlerRequest->query); + if(!copyOfRequest->query) + { + OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure"); + OICFree(copyOfRequest); + return NULL; + } + } + + if (entityHandlerRequest->payload) + { + copyOfRequest->payload = + (OCSecurityPayload *)OICMalloc(sizeof(OCSecurityPayload)); + if(!copyOfRequest->payload) + { + OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure"); + OICFree(copyOfRequest->query); + OICFree(copyOfRequest); + return NULL; + } + + if (((OCSecurityPayload *)copyOfRequest->payload)->securityData && + ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize) + { + ((OCSecurityPayload *)copyOfRequest->payload)->securityData = + (uint8_t *)OICMalloc(((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize); + if(!((OCSecurityPayload *)copyOfRequest->payload)->securityData) + { + OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure"); + OICFree(copyOfRequest->payload); + OICFree(copyOfRequest->query); + OICFree(copyOfRequest); + return NULL; + } + + memcpy(((OCSecurityPayload *)copyOfRequest->payload)->securityData, + ((OCSecurityPayload *)entityHandlerRequest->payload)->securityData, + ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize); + + ((OCSecurityPayload *)(copyOfRequest->payload))->payloadSize = + ((OCSecurityPayload *)(entityHandlerRequest->payload))->payloadSize; + + memcpy(((OCSecurityPayload *)copyOfRequest->payload)->securityData, + ((OCSecurityPayload *)entityHandlerRequest->payload)->securityData, + ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize); + } + + copyOfRequest->payload->type = entityHandlerRequest->payload->type; + copyOfRequest->messageID = entityHandlerRequest->messageID; + } + + // Ignore vendor specific header options for example + copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0; + copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL; + + if (copyOfRequest) + { + OIC_LOG(INFO, TAG, "Copied client request"); + } + else + { + OIC_LOG(ERROR, TAG, "Error copying client request"); + } + return copyOfRequest; +} +#endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__) + static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest) { OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request"); @@ -1473,25 +1594,45 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe #if defined(__WITH_DTLS__) || defined (__WITH_TLS__) else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel) { - //Get user confirmation - if (false == newDoxm->owned && - false == isDuplicatedMsg && - memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0) + if (CONFIRM_STATE_ACCEPTED != gConfirmState && CONFIRM_STATE_DENIED != gConfirmState) { - gConfirmMsgId = ehRequest->messageID; - gConfirmState = CONFIRM_STATE_WAIT; - if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM)) + //Get user confirmation + if (false == newDoxm->owned && + false == isDuplicatedMsg && + memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0) { - ehRet = OC_EH_NOT_ACCEPTABLE; - gConfirmState = CONFIRM_STATE_DENIED; - goto exit; - } - else - { - ehRet = OC_EH_OK; - gConfirmState = CONFIRM_STATE_ACCEPTED; + gConfirmMsgId = ehRequest->messageID; + gConfirmState = CONFIRM_STATE_WAIT; + + if (OC_STACK_OK != VerifyUserConfirm()) + { + if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM)) + { + ehRet = OC_EH_NOT_ACCEPTABLE; + gConfirmState = CONFIRM_STATE_DENIED; + goto exit; + } + } + else + { + OCEntityHandlerRequest * ehRequestCopy = CopyRequest(ehRequest); + VERIFY_NON_NULL(TAG, ehRequestCopy, ERROR); + + g_condWait = oc_cond_new(); + g_mutexWait = oc_mutex_new(); + if (oc_thread_new (&g_waitConfirmThreadId, WaitConfirm, ehRequestCopy)) + { + oc_thread_detach(g_waitConfirmThreadId); + } + return OC_EH_SLOW; + } } } + else if (CONFIRM_STATE_DENIED == gConfirmState) + { + ehRet = OC_EH_NOT_ACCEPTABLE; + goto exit; + } //Save the owner's UUID to derive owner credential memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)); diff --git a/resource/csdk/security/src/oxmverifycommon.c b/resource/csdk/security/src/oxmverifycommon.c index b8470e9..8f5f946 100644 --- a/resource/csdk/security/src/oxmverifycommon.c +++ b/resource/csdk/security/src/oxmverifycommon.c @@ -25,6 +25,7 @@ #include "srmresourcestrings.h" #include "cainterface.h" #include "oxmverifycommon.h" +#include "octhread.h" #define TAG "OIC_VERIFY_COMMON" @@ -32,7 +33,9 @@ static VerifyOptionBitmask_t gVerifyOption = (DISPLAY_NUM | USER_CONFIRM); static DisplayNumContext_t gDisplayNumContext = { .callback = NULL, .context = NULL }; static UserConfirmContext_t gUserConfirmContext = { .callback = NULL, .context = NULL }; +static UserAsyncConfirmContext_t gUserAsyncConfirmContext = { .callback = NULL, .context = NULL, .userConfirm = false, .userConfirmResult = false }; static InputStateContext_t gInputStateContext = { .callback = NULL, .context = NULL }; +extern oc_cond g_condWait; void SetDisplayNumCB(void * ptr, DisplayNumCallback displayNumCB) { @@ -149,6 +152,62 @@ OCStackResult VerifyOwnershipTransfer(uint8_t mutualVerifNum [MUTUAL_VERIF_NUM_L return OC_STACK_OK; } +OCStackResult VerifyUserConfirm() +{ + OIC_LOG(DEBUG, TAG, "IN VerifyUserConfirm"); + OIC_LOG_V(DEBUG, TAG, "gVerifyOption: %d", (int) gVerifyOption); + if (gVerifyOption) + { + if (!gUserAsyncConfirmContext.callback) + { + OIC_LOG(ERROR, TAG, "Callback to get user confirmation not registered"); + return OC_STACK_ERROR; + } + OIC_LOG(DEBUG, TAG, "calling userAsyncConfirmCallback"); + gUserAsyncConfirmContext.callback(&gUserAsyncConfirmContext); + } + OIC_LOG(DEBUG, TAG, "OUT VerifyUserConfirm"); + return OC_STACK_OK; +} + +void GetAsyncVerifyUserResult(bool * result, bool * confirm) +{ + *result = gUserAsyncConfirmContext.userConfirmResult; + *confirm = gUserAsyncConfirmContext.userConfirm; + return; +} + +void SetAsyncUserConfirmCB(void * ptr, UserConfirmCallback userConfirmCB) +{ + OIC_LOG(DEBUG, TAG, "IN SetAsyncUserConfirmCB"); + if (NULL == userConfirmCB) + { + OIC_LOG(ERROR, TAG, "Failed to set callback to confirm mutualVerifNum"); + return; + } + gUserAsyncConfirmContext.callback = userConfirmCB; + gUserAsyncConfirmContext.context = ptr; + OIC_LOG(DEBUG, TAG, "OUT SetAsyncUserConfirmCB"); +} + +void* UnsetAsyncUserConfirmCB() +{ + OIC_LOG(DEBUG, TAG, "IN UnsetAsyncUserConfirmCB"); + void *prevctx = gUserAsyncConfirmContext.context; + gUserAsyncConfirmContext.callback = NULL; + gUserAsyncConfirmContext.context = NULL; + OIC_LOG(DEBUG, TAG, "OUT UnsetAsyncUserConfirmCB"); + return prevctx; +} + +OCStackResult SendUserConfirm(bool confirmed) +{ + gUserAsyncConfirmContext.userConfirmResult = confirmed; + gUserAsyncConfirmContext.userConfirm = true; + oc_cond_signal(g_condWait); + return OC_STACK_OK; +} + OCStackResult NotifyInputState(void) { OIC_LOG_V(DEBUG, TAG, "IN %s", __func__); -- 2.7.4