X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fprovisioning%2Fsrc%2Fsecureresourceprovider.c;h=3a8f242c76e663153d313f038e3bd705caf6ce62;hb=e3a136f22d2c08a237b7b949d914a9f299fea3d8;hp=1a2a65ad6cb56351d0d345e45104f39760c2d928;hpb=5109759af99f93abeb467de0732867d2413d12eb;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/provisioning/src/secureresourceprovider.c b/resource/csdk/security/provisioning/src/secureresourceprovider.c index 1a2a65a..3a8f242 100644 --- a/resource/csdk/security/provisioning/src/secureresourceprovider.c +++ b/resource/csdk/security/provisioning/src/secureresourceprovider.c @@ -17,10 +17,13 @@ * limitations under the License. * * *****************************************************************/ +#include "iotivity_config.h" #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif #include "ocprovisioningmanager.h" #include "secureresourceprovider.h" @@ -42,7 +45,7 @@ #include "utlist.h" #include "ocpayload.h" -#ifdef __WITH_X509__ +#ifdef __WITH_DTLS__ #include "crlresource.h" #endif // WITH_X509__ @@ -133,6 +136,7 @@ struct UnlinkData { //Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID) const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s"; +const char * SRP_FORM_DELETE_CREDENTIAL_TCP = "coaps+tcp://[%s]:%d%s?%s=%s"; // Structure to carry remove APIs data to callback. typedef struct RemoveData RemoveData_t; @@ -197,9 +201,9 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNU OIC_LOG(INFO, TAG, "provisionCredentialCB2 called"); if (clientResponse) { - if(OC_STACK_RESOURCE_CREATED == clientResponse->result) + if(OC_STACK_RESOURCE_CHANGED == clientResponse->result) { - registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED, 2); + registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, 2); OCStackResult res = PDMLinkDevices(&credData->deviceInfo1->doxm->deviceID, &credData->deviceInfo2->doxm->deviceID); if (OC_STACK_OK != res) @@ -249,10 +253,10 @@ static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNU const OCProvisionResultCB resultCallback = credData->resultCallback; if (clientResponse) { - if (OC_STACK_RESOURCE_CREATED == clientResponse->result) + if (OC_STACK_RESOURCE_CHANGED == clientResponse->result) { // send credentials to second device - registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED,1); + registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED,1); OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData, provisionCredentialCB2); DeleteCredList(credInfo); @@ -356,7 +360,7 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred, return OC_STACK_OK; } -#ifdef __WITH_X509__ +#if defined(__WITH_DTLS__) || defined(__WITH_TLS__) /** * Structure to carry certificate data to callback. */ @@ -372,19 +376,6 @@ struct CertificateData }; /** - * Structure to carry CRL provision API data to callback. - */ -typedef struct CRLData CRLData_t; -struct CRLData -{ - void *ctx; /**< Pointer to user context.**/ - const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/ - OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/ - OCProvisionResult_t *resArr; /**< Result array.**/ - int numOfResults; /**< Number of results in result array.**/ -}; - -/** * Internal function to update result in result array. */ static void registerResultForCertProvisioning(CertData_t *certData, @@ -399,142 +390,6 @@ static void registerResultForCertProvisioning(CertData_t *certData, } /** - * Internal Function to store results in result array during ACL provisioning. - */ -static void registerResultForCRLProvisioning(CRLData_t *crlData, - OCStackResult stackresult) -{ - OIC_LOG_V(INFO, TAG, "Inside registerResultForCRLProvisioning crlData->numOfResults is %d\n", - crlData->numOfResults); - memcpy(crlData->resArr[(crlData->numOfResults)].deviceId.id, - crlData->deviceInfo->doxm->deviceID.id, UUID_LENGTH); - crlData->resArr[(crlData->numOfResults)].res = stackresult; - ++(crlData->numOfResults); -} - - -/** - * Callback handler of SRPProvisionCRL. - * - * @param[in] ctx ctx value passed to callback from calling function. - * @param[in] UNUSED handle to an invocation - * @param[in] clientResponse Response from queries to remote servers. - * @return OC_STACK_DELETE_TRANSACTION to delete the transaction - * and OC_STACK_KEEP_TRANSACTION to keep it. - */ -static OCStackApplicationResult SRPProvisionCRLCB(void *ctx, OCDoHandle UNUSED, - OCClientResponse *clientResponse) -{ - OIC_LOG_V(INFO, TAG, "Inside SRPProvisionCRLCB."); - (void)UNUSED; - VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION); - CRLData_t *crlData = (CRLData_t*)ctx; - OCProvisionResultCB resultCallback = crlData->resultCallback; - - if (clientResponse) - { - if(OC_STACK_RESOURCE_CREATED == clientResponse->result) - { - registerResultForCRLProvisioning(crlData, OC_STACK_RESOURCE_CREATED); - ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults, - crlData->resArr, - false); - OICFree(crlData->resArr); - OICFree(crlData); - return OC_STACK_DELETE_TRANSACTION; - } - } - registerResultForCRLProvisioning(crlData, OC_STACK_ERROR); - ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults, - crlData->resArr, - true); - OIC_LOG_V(ERROR, TAG, "SRPProvisionCRLCB received Null clientResponse"); - OICFree(crlData->resArr); - OICFree(crlData); - return OC_STACK_DELETE_TRANSACTION; -} - -OCStackResult SRPProvisionCRL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, - OicSecCrl_t *crl, OCProvisionResultCB resultCallback) -{ - VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM); - VERIFY_NON_NULL(TAG, crl, ERROR, OC_STACK_INVALID_PARAM); - VERIFY_NON_NULL(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK); - - OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload)); - if (!secPayload) - { - OIC_LOG(ERROR, TAG, "Failed to memory allocation"); - return OC_STACK_NO_MEMORY; - } - - secPayload->base.type = PAYLOAD_TYPE_SECURITY; - OCStackResult res = CrlToCBORPayload(crl, &secPayload->securityData, &secPayload->payloadSize); - if((OC_STACK_OK != res) && (NULL == secPayload->securityData)) - { - OICFree(secPayload); - OIC_LOG(ERROR, TAG, "Failed to BinToCrlJSON"); - return OC_STACK_NO_MEMORY; - } - OIC_LOG(DEBUG, TAG, "Created payload for CRL:"); - OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize); - - char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0}; - if(!PMGenerateQuery(true, - selectedDeviceInfo->endpoint.addr, - selectedDeviceInfo->securePort, - selectedDeviceInfo->connType, - query, sizeof(query), OIC_RSRC_CRL_URI)) - { - OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query"); - OCPayloadDestroy((OCPayload *)secPayload); - return OC_STACK_ERROR; - } - OIC_LOG_V(DEBUG, TAG, "Query=%s", query); - - OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL}; - cbData.cb = &SRPProvisionCRLCB; - CRLData_t *crlData = (CRLData_t *) OICCalloc(1, sizeof(CRLData_t)); - if (crlData == NULL) - { - OCPayloadDestroy((OCPayload *)secPayload); - OIC_LOG(ERROR, TAG, "Unable to allocate memory"); - return OC_STACK_NO_MEMORY; - } - - crlData->deviceInfo = selectedDeviceInfo; - crlData->resultCallback = resultCallback; - crlData->numOfResults=0; - crlData->ctx = ctx; - - crlData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t)); - if (crlData->resArr == NULL) - { - OCPayloadDestroy((OCPayload *)secPayload); - OIC_LOG(ERROR, TAG, "Unable to allocate memory"); - return OC_STACK_NO_MEMORY; - } - - cbData.context = (void *)crlData; - cbData.cd = NULL; - OCMethod method = OC_REST_POST; - OCDoHandle handle = NULL; - OIC_LOG(DEBUG, TAG, "Sending CRL info to resource server"); - - OCStackResult ret = OCDoResource(&handle, method, query, - &selectedDeviceInfo->endpoint, (OCPayload*)secPayload, - selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0); - - if (ret != OC_STACK_OK) - { - OICFree(crlData->resArr); - OICFree(crlData); - } - - return ret; -} - -/** * Internal function for handling credential generation and sending cretificate credential. * * @param[in] cred Instance of cred resource. @@ -617,9 +472,9 @@ static OCStackApplicationResult provisionCertCB(void *ctx, OCDoHandle UNUSED, OIC_LOG(INFO, TAG, "provisionCertCred called"); if (clientResponse) { - if(OC_STACK_RESOURCE_CREATED == clientResponse->result) + if(OC_STACK_RESOURCE_CHANGED == clientResponse->result) { - registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CREATED); + registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CHANGED); ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults, certData->resArr, false); @@ -638,7 +493,198 @@ static OCStackApplicationResult provisionCertCB(void *ctx, OCDoHandle UNUSED, OICFree(certData); return OC_STACK_DELETE_TRANSACTION; } -#endif // __WITH_X509__ + +OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId, + const OCProvisionDev_t *selectedDeviceInfo, OCProvisionResultCB resultCallback) +{ + OIC_LOG(INFO, TAG, "In SRPProvisionTrustCertChain"); + VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK); + if (SIGNED_ASYMMETRIC_KEY != type || NULL == type) + { + OIC_LOG(INFO, TAG, "Invalid key type"); + return OC_STACK_INVALID_PARAM; + } + + OicSecCred_t *trustCertChainCred = GetCredResourceDataByCredId(credId); + if(NULL == trustCertChainCred) + { + OIC_LOG(ERROR, TAG, "Can not find matched Trust Cert. Chain."); + return OC_STACK_NO_RESOURCE; + } + + OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload)); + if(!secPayload) + { + OIC_LOG(ERROR, TAG, "Failed to memory allocation"); + return OC_STACK_NO_MEMORY; + } + secPayload->base.type = PAYLOAD_TYPE_SECURITY; + int secureFlag = 0; + if(OC_STACK_OK != CredToCBORPayload(trustCertChainCred, &secPayload->securityData, &secPayload->payloadSize, secureFlag)) + { + OCPayloadDestroy((OCPayload *)secPayload); + OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload"); + return OC_STACK_NO_MEMORY; + } + OIC_LOG(DEBUG, TAG, "Created payload for Cred:"); + OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize); + + char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0}; + if(!PMGenerateQuery(true, + selectedDeviceInfo->endpoint.addr, + selectedDeviceInfo->securePort, + selectedDeviceInfo->connType, + query, sizeof(query), OIC_RSRC_CRED_URI)) + { + OIC_LOG(ERROR, TAG, "SRPProvisionTrustCertChain : Failed to generate query"); + return OC_STACK_ERROR; + } + OIC_LOG_V(DEBUG, TAG, "Query=%s", query); + + OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL}; + cbData.cb = &provisionCertCB; + CertData_t *certData = (CertData_t *) OICCalloc(1, sizeof(CertData_t)); + if (NULL == certData) + { + OIC_LOG(ERROR, TAG, "Memory allocation problem"); + return OC_STACK_NO_MEMORY; + } + certData->deviceInfo = selectedDeviceInfo; + certData->resultCallback = resultCallback; + certData->credInfo = NULL; //credInfo not used in the response handler + certData->numOfResults=0; + certData->ctx = ctx; + + int noOfRiCalls = 1; + certData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t)); + if (certData->resArr == NULL) + { + OICFree(certData); + OCPayloadDestroy((OCPayload *)secPayload); + OIC_LOG(ERROR, TAG, "Unable to allocate memory"); + return OC_STACK_NO_MEMORY; + } + cbData.context = (void *)certData; + cbData.cd = NULL; + OCMethod method = OC_REST_POST; + OCDoHandle handle = NULL; + OIC_LOG(DEBUG, TAG, "Sending Cred info to resource server"); + OCStackResult ret = OCDoResource(&handle, method, query, + &selectedDeviceInfo->endpoint, (OCPayload*)secPayload, + selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OICFree(certData->resArr); + OICFree(certData); + } + + VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR); + return OC_STACK_OK; +} + +OCStackResult SRPSaveTrustCertChain(uint8_t *trustCertChain, size_t chainSize, + OicEncodingType_t encodingType, uint16_t *credId) +{ + OIC_LOG(DEBUG, TAG, "IN SRPSaveTrustCertChain"); + VERIFY_NON_NULL(TAG, trustCertChain, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(TAG, credId, ERROR, OC_STACK_INVALID_PARAM); + + OCStackResult res = OC_STACK_ERROR; + + OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred)); + VERIFY_NON_NULL(TAG, cred, ERROR, OC_STACK_NO_MEMORY); + + memcpy(cred->subject.id, &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN); + + cred->credUsage= (char *)OICCalloc(1, strlen(TRUST_CA)+1 ); + VERIFY_NON_NULL(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY); + OICStrcpy(cred->credUsage, strlen(TRUST_CA) + 1, TRUST_CA) ; + + cred->credType = SIGNED_ASYMMETRIC_KEY; + + if (encodingType == OIC_ENCODING_PEM) + { + cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize + 1); + VERIFY_NON_NULL(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY); + cred->optionalData.len = chainSize + 1; + } + else + { + cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize); + VERIFY_NON_NULL(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY); + cred->optionalData.len = chainSize; + } + memcpy(cred->optionalData.data, trustCertChain, chainSize); + cred->optionalData.encoding = encodingType; + + res = AddCredential(cred); + if(res != OC_STACK_OK) + { + DeleteCredList(cred); + return res; + } + *credId = cred->credId; + + OIC_LOG(DEBUG, TAG, "OUT SRPSaveTrustCertChain"); + + return res; +} + + +OCStackResult SRPSaveOwnCertChain(OicSecCert_t * cert, OicSecKey_t * key, uint16_t *credId) +{ + OIC_LOG_V(DEBUG, TAG, "In %s", __func__); + VERIFY_NON_NULL(TAG, cert, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(TAG, cert->data, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(TAG, key, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(TAG, key->data, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(TAG, credId, ERROR, OC_STACK_INVALID_PARAM); + + OCStackResult res = OC_STACK_ERROR; + + OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred)); + VERIFY_NON_NULL(TAG, cred, ERROR, OC_STACK_NO_MEMORY); + + OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__); + + if (OC_STACK_OK != GetDoxmDeviceID(&cred->subject)) + { + OIC_LOG(ERROR, TAG, "Cann't get the device id(GetDoxmDeviceID)"); + } + + cred->credUsage= (char *)OICCalloc(1, strlen(PRIMARY_CERT)+1 ); + VERIFY_NON_NULL(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY); + OICStrcpy(cred->credUsage, strlen(PRIMARY_CERT) + 1, PRIMARY_CERT) ; + + cred->credType = SIGNED_ASYMMETRIC_KEY; + + OicSecCert_t *publicData = &cred->publicData; + publicData->data = (uint8_t *)OICCalloc(1, cert->len); + VERIFY_NON_NULL(TAG, publicData->data, ERROR, OC_STACK_NO_MEMORY); + memcpy(publicData->data, cert->data, cert->len); + publicData->len = cert->len; + + OicSecKey_t *privateData = &cred->privateData; + privateData->data = (uint8_t *)OICCalloc(1, key->len); + VERIFY_NON_NULL(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY); + memcpy(privateData->data, key->data, key->len); + privateData->len = key->len; + privateData->encoding = key->encoding; + + res = AddCredential(cred); + if(res != OC_STACK_OK) + { + DeleteCredList(cred); + return res; + } + *credId = cred->credId; + + OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); + + return res; +} +#endif // __WITH_DTLS__ || __WITH_TLS__ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize, const OCProvisionDev_t *pDev1, @@ -750,50 +796,6 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR); return res; } -#ifdef __WITH_X509__ - case SIGNED_ASYMMETRIC_KEY: - { - const OCProvisionDev_t *firstDevice = pDev1; - OicSecCred_t *cred = NULL; - OCStackResult res = PMGenerateCertificateCredentials(&provTooldeviceID, - &firstDevice->doxm->deviceID,&cred); - VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR); - OIC_LOG(INFO, TAG, "Certificate credentials generated successfully"); - CertData_t *certData = (CertData_t *) OICCalloc(1, sizeof(CertData_t)); - if (NULL == certData) - { - OICFree(cred); - OIC_LOG(ERROR, TAG, "Memory allocation problem"); - return OC_STACK_NO_MEMORY; - } - - certData->deviceInfo = firstDevice; - certData->ctx = ctx; - certData->credInfo = cred; - certData->numOfResults = 0; - certData->resultCallback = resultCallback; - - certData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t)); - if (NULL == certData->resArr) - { - DeleteCredList(cred); - OICFree(certData); - OIC_LOG(ERROR, TAG, "Memory allocation problem"); - return OC_STACK_NO_MEMORY; - } - - res = provisionCertCred(cred, firstDevice, certData, &provisionCertCB); - if (OC_STACK_OK != res) - { - OICFree(certData->resArr); - OICFree(certData); - } - DeleteCredList(cred); - OIC_LOG_V(INFO, TAG, "provisionCertCredentials returned: %d",res); - - return res; - } -#endif default: { OIC_LOG(ERROR, TAG, "Invalid option."); @@ -837,9 +839,9 @@ static OCStackApplicationResult SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED, if (clientResponse) { - if(OC_STACK_RESOURCE_CREATED == clientResponse->result) + if(OC_STACK_RESOURCE_CHANGED == clientResponse->result) { - registerResultForACLProvisioning(aclData, OC_STACK_RESOURCE_CREATED); + registerResultForACLProvisioning(aclData, OC_STACK_RESOURCE_CHANGED); ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults, aclData->resArr, false); @@ -865,6 +867,25 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI VERIFY_NON_NULL(TAG, acl, ERROR, OC_STACK_INVALID_PARAM); VERIFY_NON_NULL(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK); + // if rowneruuid is empty, set it to device ID + OicUuid_t emptyOwner = {.id = {0} }; + if (memcmp(&(acl->rownerID.id), &emptyOwner, UUID_IDENTITY_SIZE) == 0) + { + OIC_LOG(DEBUG, TAG, "Set Rowner to PT's deviceId, because Rowner of ACL is empty"); + OicUuid_t oicUuid; + + if (OC_STACK_OK == GetDoxmDeviceID(&oicUuid)) + { + memcpy(&(acl->rownerID.id), &oicUuid, UUID_IDENTITY_SIZE); + } + else + { + OIC_LOG(DEBUG, TAG, "Failed to set Rowner to PT's deviceID\ + becuase it failed to retrieve Doxm DeviceID"); + return OC_STACK_ERROR; + } + } + OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload)); if(!secPayload) { @@ -878,6 +899,9 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload"); return OC_STACK_NO_MEMORY; } + OIC_LOG(DEBUG, TAG, "Created payload for ACL:"); + OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize); + char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0}; if(!PMGenerateQuery(true, selectedDeviceInfo->endpoint.addr, @@ -964,7 +988,7 @@ static OCStackApplicationResult SRPProvisionDirectPairingCB(void *ctx, OCDoHandl if (clientResponse) { - if(OC_STACK_RESOURCE_CREATED == clientResponse->result) + if(OC_STACK_RESOURCE_CHANGED == clientResponse->result) { registerResultForDirectPairingProvisioning(pconfData, OC_STACK_OK); ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults, @@ -1137,7 +1161,14 @@ static OCStackResult SendDeleteCredentialRequest(void* ctx, char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0}; int snRet = 0; //coaps://0.0.0.0:5684/oic/sec/cred?subjectid=(Canonical ENCODED UUID) - snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, destDev->endpoint.addr, + char *srpUri = SRP_FORM_DELETE_CREDENTIAL; +#ifdef __WITH_TLS__ + if(CA_ADAPTER_TCP == destDev->endpoint.adapter) + { + srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP; + } +#endif + snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, destDev->endpoint.addr, destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID); OICFree(subID); if (snRet < 0) @@ -1172,17 +1203,75 @@ static OCStackResult SendDeleteCredentialRequest(void* ctx, return ret; } -/** - * Callback handler of unlink second device. - * - * @param[in] ctx ctx value passed to callback from calling function. - * @param[in] handle handle to an invocation - * @param[in] clientResponse Response from queries to remote servers. - * @return OC_STACK_DELETE_TRANSACTION to delete the transaction and - * OC_STACK_KEEP_TRANSACTION to keep it. - */ -static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle, - OCClientResponse *clientResponse) +static OCStackResult SendDeleteACLRequest(void* ctx, + OCClientResponseHandler respHandler, + const OCProvisionDev_t* revokedDev, + const OCProvisionDev_t* destDev) +{ + OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest"); + + if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev) + { + return OC_STACK_INVALID_PARAM; + } + + char *subID = NULL; + OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID); + if(OC_STACK_OK != ret) + { + OIC_LOG(ERROR, TAG, "SendDeleteACLRequest : Failed to canonical UUID encoding"); + return OC_STACK_ERROR; + } + + char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0}; + int snRet = 0; + //coaps://0.0.0.0:5684/oic/sec/acl?subjectuuid=(Canonical ENCODED UUID) + snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, destDev->endpoint.addr, + destDev->securePort, OIC_RSRC_ACL_URI, OIC_JSON_SUBJECTID_NAME, subID); + OICFree(subID); + if (snRet < 0) + { + OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error (snprintf) %d\n", snRet); + return OC_STACK_ERROR; + } + else if ((size_t)snRet >= sizeof(reqBuf)) + { + OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Truncated (snprintf) %d\n", snRet); + return OC_STACK_ERROR; + } + + OCCallbackData cbData; + memset(&cbData, 0, sizeof(cbData)); + cbData.context = ctx; + cbData.cb = respHandler; + cbData.cd = NULL; + OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf); + + OIC_LOG(DEBUG, TAG, "Sending remove ACL request to resource server"); + + ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf, + &destDev->endpoint, NULL, + CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0); + if (OC_STACK_OK != ret) + { + OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error in OCDoResource %d", ret); + } + OIC_LOG(DEBUG, TAG, "OUT SendDeleteACLRequest"); + + return ret; +} + +/** + * Callback handler of unlink second device. + * + * @param[in] ctx ctx value passed to callback from calling function. + * @param[in] handle handle to an invocation + * @param[in] clientResponse Response from queries to remote servers. + * @return OC_STACK_DELETE_TRANSACTION to delete the transaction and + * OC_STACK_KEEP_TRANSACTION to keep it. + */ +static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle, + OCClientResponse *clientResponse) { (void) handle; OIC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB"); @@ -1445,6 +1534,34 @@ static void registerResultForRemoveDevice(RemoveData_t *removeData, OicUuid_t *p } } +static void registerResultForResetDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId, + OCStackResult stackresult, bool hasError) +{ + OIC_LOG_V(INFO, TAG, "Inside registerResultForResetDevice removeData->numOfResults is %zu\n", + removeData->numOfResults + 1); + if (pLinkedDevId) + { + memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id, + &pLinkedDevId->id, sizeof(pLinkedDevId->id)); + } + else + { + memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id, + 0, sizeof(pLinkedDevId->id) ); + } + removeData->removeRes[(removeData->numOfResults)].res = stackresult; + removeData->hasError = hasError; + ++(removeData->numOfResults); + + // If we get suffcient result from linked devices, we have to call user callback and do free + if (removeData->sizeOfResArray == removeData->numOfResults) + { + removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes, + removeData->hasError); + DeleteRemoveData_t(removeData); + } +} + /** * Callback handler of unlink first device. * @@ -1524,6 +1641,171 @@ static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle ha return OC_STACK_DELETE_TRANSACTION; } +/** + * Callback handler of reset device. + * + * @param[in] ctx ctx value passed to callback from calling function. + * @param[in] handle handle to an invocation + * @param[in] clientResponse Response from queries to remote servers. + * @return OC_STACK_DELETE_TRANSACTION to delete the transaction + * and OC_STACK_KEEP_TRANSACTION to keep it. + */ +static OCStackApplicationResult SRPSyncDeviceCredCB(void *delDevCtx, OCDoHandle handle, + OCClientResponse *clientResponse) +{ + //Update the delete credential into delete device context + //Save the deleted status in delDevCtx + (void)handle; + OIC_LOG_V(INFO, TAG, "Inside SRPSyncDeviceCredCB."); + VERIFY_NON_NULL(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION); + OCStackResult res = OC_STACK_ERROR; + + RemoveData_t* removeData = (RemoveData_t*)delDevCtx; + OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev); + OCProvisionResultCB resultCallback = removeData->resultCallback; + if (clientResponse) + { + OicUuid_t revDevUuid = {.id={0}}; + if(UUID_LENGTH == clientResponse->identity.id_length) + { + memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id)); + if (OC_STACK_RESOURCE_DELETED == clientResponse->result) + { + res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid); + if (OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one."); + registerResultForResetDevice(removeData, &revDevUuid, + OC_STACK_INCONSISTENT_DB, true); + + return OC_STACK_DELETE_TRANSACTION; + } + + registerResultForResetDevice(removeData, &revDevUuid, + OC_STACK_RESOURCE_DELETED, false); + } + else + { + registerResultForResetDevice(removeData, &revDevUuid, + clientResponse->result, false); + OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!"); + } + } + else + { + OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d", + clientResponse->devAddr.addr, clientResponse->devAddr.port); + + if (OC_STACK_RESOURCE_DELETED == clientResponse->result) + { + /** + * Since server's credential was deleted, + * register result as OC_STACK_INCONSISTENT_DB with NULL UUID. + */ + OIC_LOG_V(ERROR, TAG, "But server's credential was deleted."); + registerResultForResetDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true); + } + else + { + registerResultForResetDevice(removeData, NULL, clientResponse->result, true); + } + } + } + else + { + registerResultForResetDevice(removeData, NULL, OC_STACK_ERROR, true); + OIC_LOG(ERROR, TAG, "SRPSyncDevice received Null clientResponse"); + } + + SRPResetDevice(pTargetDev, resultCallback); + + return OC_STACK_DELETE_TRANSACTION; +} + +/** + * Callback handler of reset device sync-up + * + * @param[in] ctx ctx value passed to callback from calling function. + * @param[in] handle handle to an invocation + * @param[in] clientResponse Response from queries to remote servers. + * @return OC_STACK_DELETE_TRANSACTION to delete the transaction + * and OC_STACK_KEEP_TRANSACTION to keep it. + */ +static OCStackApplicationResult SRPSyncDeviceACLCB(void *ctx, OCDoHandle handle, + OCClientResponse *clientResponse) +{ + return OC_STACK_DELETE_TRANSACTION; +} + +/** + * Callback handler of device remote reset. + * + * @param[in] ctx ctx value passed to callback from calling function. + * @param[in] handle handle to an invocation + * @param[in] clientResponse Response from queries to remote servers. + * @return OC_STACK_DELETE_TRANSACTION to delete the transaction + * and OC_STACK_KEEP_TRANSACTION to keep it. + */ +static OCStackApplicationResult SRPResetDeviceCB(void *ctx, OCDoHandle handle, + OCClientResponse *clientResponse) +{ + OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB"); + if(OC_STACK_OK == clientResponse->result) + { + OIC_LOG(DEBUG, TAG, "Change Target Device Pstat Cm SUCCEEDED"); + } + + // Delete Cred and ACL related to the target device. + const OicSecCred_t *cred = NULL; + OCProvisionDev_t * pTargetDev = (OCProvisionDev_t *)ctx; + cred = GetCredResourceData(&pTargetDev->doxm->deviceID); + if (cred == NULL) + { + OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to get credential of target device."); + goto error; + } + + OCStackResult res = RemoveCredential(&cred->subject); + if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE) + { + OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove credential."); + goto error; + } + + res = RemoveACE(&cred->subject, NULL); + if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE) + { + OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove ACL."); + goto error; + } + if (OC_STACK_OK != PDMDeleteDevice(&pTargetDev->doxm->deviceID)) + { + OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to delete device from PDM"); + } + + //Close the DTLS session of the reset device. + CAEndpoint_t* endpoint = (CAEndpoint_t *)&clientResponse->devAddr; + CAResult_t caResult = CAcloseSslSession(endpoint); + if(CA_STATUS_OK != caResult) + { + OIC_LOG_V(WARNING, TAG, "OCResetDevice : Failed to close DTLS session : %d", caResult); + } + + /** + * If there is no linked device, PM does not send any request. + * So we should directly invoke the result callback to inform the result of OCResetDevice. + */ + if(OC_STACK_NO_RESOURCE == res) + { + res = OC_STACK_OK; + } + +error: + OICFree(pTargetDev); + return OC_STACK_DELETE_TRANSACTION; + +} + static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev, OCProvisionDev_t* pOwnedDevList, OCUuidList_t* pLinkedUuidList, @@ -1723,6 +2005,416 @@ error: return res; } +/* +* Function to device revocation +* This function will remove credential of target device from all devices in subnet. +* +* @param[in] ctx Application context would be returned in result callback +* @param[in] pOwnedDevList List of owned devices +* @param[in] pTargetDev Device information to be revoked. +* @param[in] resultCallback callback provided by API user, callback will be called when +* credential revocation is finished. +* @return OC_STACK_OK in case of success and other value otherwise. +* If OC_STACK_OK is returned, the caller of this API should wait for callback. +* OC_STACK_CONTINUE means operation is success but no request is need to be initiated. +*/ +OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* pOwnedDevList, + const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback) +{ + OIC_LOG(INFO, TAG, "IN SRPRemoveDeviceWithoutDiscovery"); + + if (!pOwnedDevList) + { + OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Owned Device List is empty"); + return OC_STACK_CONTINUE; + } + if (!pTargetDev) + { + OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL parameters"); + return OC_STACK_INVALID_PARAM; + } + if (!resultCallback) + { + OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL Callback"); + return OC_STACK_INVALID_CALLBACK; + } + + // Declare variables in here to handle error cases with goto statement. + OCProvisionDev_t* pLinkedDevList = NULL; + RemoveData_t* removeData = NULL; + + //1. Find all devices that has a credential of the revoked device + OCUuidList_t* pLinkedUuidList = NULL; + size_t numOfDevices = 0; + OCStackResult res = OC_STACK_ERROR; + res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices); + if (OC_STACK_OK != res) + { + OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to get linked devices information"); + return OC_STACK_CONTINUE; + } + // if there is no related device, we can skip further process. + if (0 == numOfDevices) + { + OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : No linked device found."); + return OC_STACK_CONTINUE; + } + + //2. Make a list of devices to send DELETE credential request + // by comparing owned devices from provisioning database with mutlicast discovery result. + size_t numOfLinkedDev = 0; + res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList, + &pLinkedDevList, &numOfLinkedDev); + if (OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : GetListofDevToReqDeleteCred() failed"); + goto error; + } + if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now. + { // So we don't have to send request message. + OIC_LOG(DEBUG, TAG, "SRPRemoveDeviceWithoutDiscovery : No alived & linked device found."); + return OC_STACK_CONTINUE; + } + + // 3. Prepare RemoveData Context data. + removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t)); + if (!removeData) + { + OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation"); + res = OC_STACK_NO_MEMORY; + goto error; + } + + removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev); + if (!removeData->revokeTargetDev) + { + OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : PMCloneOCProvisionDev Failed"); + res = OC_STACK_NO_MEMORY; + goto error; + } + + removeData->removeRes = + (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t)); + if (!removeData->removeRes) + { + OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation"); + res = OC_STACK_NO_MEMORY; + goto error; + } + + removeData->ctx = ctx; + removeData->linkedDevList = pLinkedDevList; + removeData->resultCallback = resultCallback; + removeData->numOfResults = 0; + removeData->sizeOfResArray = numOfLinkedDev; + removeData->hasError = false; + + // 5. Send DELETE credential request to linked devices. + OCProvisionDev_t *curDev = NULL, *tmpDev = NULL; + OCStackResult totalRes = OC_STACK_ERROR; /* variable for checking request is sent or not */ + LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev) + { + res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB, + removeData->revokeTargetDev, curDev); + if (OC_STACK_OK != res) + { + OIC_LOG_V(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Fail to send the DELETE credential request to\ + %s:%u", curDev->endpoint.addr, curDev->endpoint.port); + } + else + { + totalRes = OC_STACK_OK; // This means at least one request is successfully sent. + } + } + + PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention. + OIC_LOG(INFO, TAG, "OUT SRPRemoveDeviceWithoutDiscovery"); + + return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK. + +error: + PDMDestoryOicUuidLinkList(pLinkedUuidList); + PMDeleteDeviceList(pLinkedDevList); + if (removeData) + { + OICFree(removeData->revokeTargetDev); + OICFree(removeData->removeRes); + OICFree(removeData); + } + OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDeviceWithoutDiscovery"); + return res; +} + +/* + * Function to sync-up credential and ACL of the target device. + * This function will remove credential and ACL of target device from all devices in subnet. + * + * @param[in] ctx Application context would be returned in result callback + * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds) + * @param[in] pTargetDev Device information to be revoked. + * @param[in] resultCallback callback provided by API user, callback will be called when + * credential revocation is finished. + * when there is an error, this user callback is called immediately. + * @return OC_STACK_OK in case of success and other value otherwise. + * If OC_STACK_OK is returned, the caller of this API should wait for callback. + * OC_STACK_CONTINUE means operation is success but no request is need to be initiated. + */ +OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery, + const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback) +{ + OIC_LOG(INFO, TAG, "IN SRPSyncDevice"); + if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery) + { + OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL parameters"); + return OC_STACK_INVALID_PARAM; + } + if (!resultCallback) + { + OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL Callback"); + return OC_STACK_INVALID_CALLBACK; + } + + // Declare variables in here to handle error cases with goto statement. + OCProvisionDev_t* pOwnedDevList = NULL; + OCProvisionDev_t* pLinkedDevList = NULL; + RemoveData_t* removeData = NULL; + + //1. Find all devices that has a credential of the revoked device + OCUuidList_t* pLinkedUuidList = NULL; + size_t numOfDevices = 0; + OCStackResult res = OC_STACK_ERROR; + res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices); + if (OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to get linked devices information"); + return res; + } + // if there is no related device, we can skip further process. + if (0 == numOfDevices) + { + OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No linked device found."); + res = OC_STACK_CONTINUE; + goto error; + } + + //2. Find owned device from the network + res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList); + if (OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to PMDeviceDiscovery"); + goto error; + } + + //3. Make a list of devices to send DELETE credential request + // by comparing owned devices from provisioning database with mutlicast discovery result. + size_t numOfLinkedDev = 0; + res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList, + &pLinkedDevList, &numOfLinkedDev); + if (OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "SRPSyncDevice : GetListofDevToReqDeleteCred() failed"); + goto error; + } + if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now. + { // So we don't have to send request message. + OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No alived & linked device found."); + res = OC_STACK_CONTINUE; + goto error; + } + + // 4. Prepare RemoveData Context data. + removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t)); + if (!removeData) + { + OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to memory allocation"); + res = OC_STACK_NO_MEMORY; + goto error; + } + + removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev); + if (!removeData->revokeTargetDev) + { + OIC_LOG(ERROR, TAG, "SRPSyncDevice : PMCloneOCProvisionDev Failed"); + res = OC_STACK_NO_MEMORY; + goto error; + } + + removeData->removeRes = + (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t)); + if (!removeData->removeRes) + { + OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory"); + res = OC_STACK_NO_MEMORY; + goto error; + } + + removeData->ctx = ctx; + removeData->linkedDevList = pLinkedDevList; + removeData->resultCallback = resultCallback; + removeData->numOfResults = 0; + removeData->sizeOfResArray = numOfLinkedDev; + removeData->hasError = false; + + // 5. Send DELETE credential request to linked devices. + OCProvisionDev_t *curDev = NULL, *tmpDev = NULL; + OCStackResult totalRes = OC_STACK_ERROR; /* variable for checking request is sent or not */ + LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev) + { + res = SendDeleteACLRequest((void*)removeData, &SRPSyncDeviceACLCB, + removeData->revokeTargetDev, curDev); + if (OC_STACK_OK != res) + { + OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE ACL request to\ + %s:%u", curDev->endpoint.addr, curDev->endpoint.port); + goto error; + } + res = SendDeleteCredentialRequest((void*)removeData, &SRPSyncDeviceCredCB, + removeData->revokeTargetDev, curDev); + if (OC_STACK_OK != res) + { + OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE credential request to\ + %s:%u", curDev->endpoint.addr, curDev->endpoint.port); + totalRes = OC_STACK_ERROR; + } + else + { + totalRes = OC_STACK_OK; // This means at least one request is successfully sent. + } + } + + PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention. + PMDeleteDeviceList(pOwnedDevList); + OIC_LOG(INFO, TAG, "OUT SRPSyncDevice"); + + return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK. + +error: + PDMDestoryOicUuidLinkList(pLinkedUuidList); + PMDeleteDeviceList(pOwnedDevList); + PMDeleteDeviceList(pLinkedDevList); + if (removeData) + { + OICFree(removeData->revokeTargetDev); + OICFree(removeData->removeRes); + OICFree(removeData); + } + OIC_LOG(INFO, TAG, "OUT ERROR case SRPSyncDevice"); + return res; +} + +/* + * Function for remote reset + * This function will send pstat PUT message to the target device to initiate remote reset. + * + * @param[in] pTargetDev Device information to be revoked. + * @param[in] resultCallback callback provided by API user, callback will be called when + * credential revocation is finished. + * when there is an error, this user callback is called immediately. + * @return OC_STACK_OK in case of success and other value otherwise. + * If OC_STACK_OK is returned, the caller of this API should wait for callback. + * OC_STACK_CONTINUE means operation is success but no request is need to be initiated. + */ +OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev, + OCProvisionResultCB resultCallback) +{ + OIC_LOG(INFO, TAG, "IN SRPResetDevice"); + if (!pTargetDev) + { + OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters"); + return OC_STACK_INVALID_PARAM; + } + if (!resultCallback) + { + OIC_LOG(INFO, TAG, "SRPResetDevice : NULL Callback"); + return OC_STACK_INVALID_CALLBACK; + } + + OCStackResult res = OC_STACK_ERROR; + OicSecPstat_t * pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t)); + if (!pstat) + { + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); + return OC_STACK_NO_MEMORY; + } + + pstat->cm = RESET; + pstat->isOp = false; + memcpy(pstat->deviceID.id, pTargetDev->doxm->deviceID.id, sizeof(OicUuid_t)); + pstat->tm = TAKE_OWNER; + pstat->om = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently + pstat->smLen = 1; + pstat->sm = (OicSecDpom_t *) OICCalloc(pstat->smLen, sizeof(OicSecDpom_t)); + if (NULL == pstat->sm) + { + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); + OICFree(pstat); + return OC_STACK_NO_MEMORY; + } + pstat->sm[0] = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently + + OCSecurityPayload * secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload)); + if (!secPayload) + { + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); + res = OC_STACK_NO_MEMORY; + goto error; + } + secPayload->base.type = PAYLOAD_TYPE_SECURITY; + + if (OC_STACK_OK != PstatToCBORPayload(pstat, &(secPayload->securityData), + &(secPayload->payloadSize), true)) + { + OCPayloadDestroy((OCPayload *) secPayload); + OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload"); + res = OC_STACK_NO_MEMORY; + goto error; + } + OIC_LOG(DEBUG, TAG, "Created payload for pstat set"); + OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize); + + char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0}; + if (!PMGenerateQuery(true, + pTargetDev->endpoint.addr, + pTargetDev->securePort, + pTargetDev->connType, + query, sizeof(query), OIC_RSRC_PSTAT_URI)) + { + OIC_LOG(ERROR, TAG, "SRPResetDevice : Failed to generate query"); + OCPayloadDestroy((OCPayload *) secPayload); + res = OC_STACK_ERROR; + goto error; + } + OIC_LOG_V(DEBUG, TAG, "Query=%s", query); + + OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL }; + OCMethod method = OC_REST_POST; + OCDoHandle handle = NULL; + OCProvisionDev_t * targetDev = PMCloneOCProvisionDev(pTargetDev); + if (NULL == targetDev) + { + OIC_LOG(ERROR, TAG, "target dev is null"); + res = OC_STACK_ERROR; + goto error; + } + cbData.cb = &SRPResetDeviceCB; + cbData.context = (void *) targetDev; + cbData.cd = NULL; + OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server"); + res = OCDoResource(&handle, method, query, + &targetDev->endpoint, (OCPayload *)secPayload, + targetDev->connType, OC_LOW_QOS, &cbData, NULL, 0);\ + if (OC_STACK_OK != res) + { + OIC_LOG(ERROR, TAG, "OCStack resource error"); + } + +error: + OICFree(pstat->sm); + OICFree(pstat); + OIC_LOG(INFO, TAG, "OUT SRPResetDevice"); + return res; +} + /** * Internal Function to store results in result array during GetCredResourceCB. */