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