+static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
+{
+ if(src && dst)
+ {
+ // update oxmsel
+ dst->oxmSel = src->oxmSel;
+
+ //update owner
+ memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
+
+ //update rowner
+ memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
+
+ //update deviceuuid
+ memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
+
+ //Update owned status
+ if(dst->owned != src->owned)
+ {
+ dst->owned = src->owned;
+ }
+
+#ifdef MULTIPLE_OWNER
+ if(src->mom)
+ {
+ OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
+ if(NULL == dst->mom)
+ {
+ dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
+ if(NULL != dst->mom)
+ {
+ dst->mom->mode = src->mom->mode;
+ }
+ }
+ }
+#endif //MULTIPLE_OWNER
+ }
+}
+
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+#ifdef MULTIPLE_OWNER
+/**
+ * Internal function to get number of sub-owner
+ */
+static size_t GetSubOwnerSize()
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+ size_t numberOfSubOwner = 0;
+
+ if (gDoxm && gDoxm->subOwners)
+ {
+ OicSecSubOwner_t* subowner = NULL;
+ LL_FOREACH(gDoxm->subOwners, subowner)
+ {
+ numberOfSubOwner++;
+ }
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "Numer of registered sub-owner=%d", numberOfSubOwner);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+
+ return numberOfSubOwner;
+}
+
+/**
+ * Callback function to handle MOT DTLS handshake result.
+ * @param[out] endpoint remote device information.
+ * @param[out] errorInfo CA Error information.
+ */
+void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *endpoint,
+ const CAErrorInfo_t *errorInfo)
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+ if (!endpoint || !errorInfo)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid param");
+ return;
+ }
+
+ if (!gDoxm)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__);
+ return;
+ }
+
+ if ((CA_STATUS_OK == errorInfo->result) && (true == gDoxm->owned)
+ && (OIC_PRECONFIG_PIN == gDoxm->oxmSel) && (NULL != gDoxm->mom)
+ && (OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode) && (CA_ADAPTER_TCP != endpoint->adapter))
+ {
+ OIC_LOG_V(INFO, TAG, "DTLS session established for sub-owner authentication : (%s:%d)",
+ endpoint->addr, endpoint->port);
+
+ const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(endpoint);
+ if (authenticatedSubOwnerInfo)
+ {
+ if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id,
+ authenticatedSubOwnerInfo->identity.id_length))
+ {
+ OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
+ return;
+ }
+
+ OicSecSubOwner_t* subOwnerInst = NULL;
+ LL_FOREACH(gDoxm->subOwners, subOwnerInst)
+ {
+ if(0 == memcmp(subOwnerInst->uuid.id,
+ authenticatedSubOwnerInfo->identity.id,
+ authenticatedSubOwnerInfo->identity.id_length))
+ {
+ break;
+ }
+ }
+
+ if (NULL == subOwnerInst)
+ {
+ subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
+ if (subOwnerInst)
+ {
+ char* strUuid = NULL;
+ if (OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
+ {
+ OIC_LOG(WARNING, TAG, "ConvertUuidToStr error");
+ }
+ OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
+
+ if (gMaxSubOwnerSize > GetSubOwnerSize())
+ {
+ memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
+ authenticatedSubOwnerInfo->identity.id_length);
+ LL_APPEND(gDoxm->subOwners, subOwnerInst);
+ if (!UpdatePersistentStorage(gDoxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
+ }
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Number of sub-owner exceeded : (MAX SIZE=%d)", gMaxSubOwnerSize);
+
+ //Close DTLS session
+ if (CA_STATUS_OK != CAcloseSslSession(endpoint))
+ {
+ OIC_LOG_V(ERROR, TAG, "CAcloseSslSession error for [%s:%d]", endpoint->addr, endpoint->port);
+ }
+
+ //Remove credential
+ if (OC_STACK_RESOURCE_DELETED != RemoveCredential(&subOwnerInst->uuid))
+ {
+ OIC_LOG_V(ERROR, TAG, "RemoveCredential error for [%s]", strUuid);
+ }
+
+ // TODO: How to send error to client side?
+ }
+
+ OICFree(strUuid);
+ }
+ }
+ }
+ }
+
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
+ {
+ OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
+#endif //MULTIPLE_OWNER
+#endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+
+/**
+ * Function to validate oxmsel with oxms.
+ *
+ * @param[in] supportedMethods Array of supported methods
+ * @param[in] numberOfMethods number of supported methods
+ * @param[out] selectedMethod Selected methods
+ * @return TRUE on success
+ */
+static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
+ size_t numberOfMethods, OicSecOxm_t *selectedMethod)
+{
+ bool isValidOxmsel = false;
+
+ OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
+ if (numberOfMethods == 0 || !supportedMethods)
+ {
+ OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
+ return isValidOxmsel;
+ }
+
+ for (size_t i = 0; i < numberOfMethods; i++)
+ {
+ if (*selectedMethod == supportedMethods[i])
+ {
+ isValidOxmsel = true;
+ break;
+ }
+ }
+ if (!isValidOxmsel)
+ {
+ OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
+ return isValidOxmsel;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
+
+ return isValidOxmsel;
+}
+
+static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)