#include "oic_malloc.h"
#include "logger.h"
#include "cacommon.h"
-#include "ocpayload.h"
#include "cainterface.h"
#include "provisioningmanager.h"
#include "credentialgenerator.h"
#include "pstatresource.h"
#include "srmresourcestrings.h"
#include "credresource.h"
+#include "oic_string.h"
+#include "secureresourcemanager.h"
+
typedef enum
{
#define COAPS_QUERY "coaps://%s:%d%s"
#define CA_SECURE_PORT 5684
-void (*handler)(const CAEndpoint_t *, const CAResponseInfo_t *);
+bool (*handler)(const CAEndpoint_t *, const CAResponseInfo_t *);
/**
* CA token to keep track of response.
const char *resourceUri,
char *payload, int payloadLen)
{
+ if (payload && '\0' != (*(payload + payloadLen)))
+ {
+ OC_LOG(ERROR, TAG, "Payload not properly terminated.");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
{
OC_LOG(ERROR, TAG, "Error while generating token");
return CA_MEMORY_ALLOC_FAILED;
}
+
CAEndpoint_t *endpoint = NULL;
if (CA_STATUS_OK != CACreateEndpoint((CATransportFlags_t)secure,
devAddr->adapter, devAddr->addr,
CADestroyEndpoint(endpoint);
return CA_STATUS_FAILED;
}
- CAMessageType_t msgType = CA_MSG_CONFIRM;
- if (payload && '\0' != (*(payload + payloadLen)))
- {
- OC_LOG(ERROR, TAG, "Payload not properly terminated.");
- CADestroyEndpoint(endpoint);
- return CA_STATUS_INVALID_PARAM;
- }
- OCSecurityPayload secPayload;
+
+ OCSecurityPayload secPayload = {};
secPayload.securityData = payload;
secPayload.base.type = PAYLOAD_TYPE_SECURITY;
- CARequestInfo_t requestInfo = { 0 };
+
+ CARequestInfo_t requestInfo = {};
requestInfo.method = method;
requestInfo.isMulticast = false;
OCConvertPayload((OCPayload*)(&secPayload), &requestInfo.info.payload,
&requestInfo.info.payloadSize);
- requestInfo.info.type = msgType;
+
+ requestInfo.info.type = CA_MSG_CONFIRM;
requestInfo.info.token = gToken;
requestInfo.info.tokenLength = CA_MAX_TOKEN_LEN;
- requestInfo.info.resourceUri = resourceUri;
+ requestInfo.info.resourceUri = (CAURI_t)resourceUri;
- requestInfo.isMulticast = false;
CAResult_t caResult = CA_STATUS_OK;
caResult = CASendRequest(endpoint, &requestInfo);
if (CA_STATUS_OK != caResult)
/**
* addDevice to list.
*
- * @param[in] ip IP of target device.
- * @param[in] port port of remote server.
- * @param[in] adapter adapter type of endpoint.
- * @param[in] doxm pointer to doxm instance.
+ * @param[in] endpoint Endpoint information
+ * @param[in] doxm pointer to doxm instance.
* @return SP_RESULT_SUCCESS for success and errorcode otherwise.
*/
-static SPResult addDevice(const char *ip, int port, OCTransportAdapter adapter, OicSecDoxm_t *doxm)
+static SPResult addDevice(const CAEndpoint_t *endpoint, OicSecDoxm_t* doxm)
{
- if (NULL == ip || 0 >= port)
+ if (NULL == endpoint)
{
return SP_RESULT_INVALID_PARAM;
}
return SP_RESULT_MEM_ALLOCATION_FAIL;
}
- SPStringCopy(ptr->endpoint.addr, ip, MAX_ADDR_STR_SIZE);
- ptr->endpoint.port = port;
- ptr->endpoint.adapter = adapter;
-
+ memcpy(&(ptr->endpoint), endpoint, sizeof(CAEndpoint_t));
ptr->doxm = doxm;
ptr->next = NULL;
return SP_RESULT_SUCCESS;
}
-OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, size_t payloadSize);
/**
* Response handler for discovery.
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void ProvisionDiscoveryHandler(const CAEndpoint_t *object,
+static bool ProvisionDiscoveryHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_DISCOVERY_STARTED) && gToken)
{
OC_LOG(DEBUG, TAG, "Successfully converted doxm json to bin.");
- SPResult res = addDevice(object->addr, object->port, object->adapter, ptrDoxm);
+ SPResult res = addDevice(object, ptrDoxm);
if (SP_RESULT_SUCCESS != res)
{
OC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
gStateManager = gStateManager | SP_DISCOVERY_ERROR;
DeleteDoxmBinData(ptrDoxm);
- return;
+ return true;
}
OC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
gStateManager |= SP_DISCOVERY_DONE;
}
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void OwnerShipTransferModeHandler(const CAEndpoint_t *object,
+static bool OwnerShipTransferModeHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_UP_OWN_TR_METH_STARTED) && gToken)
gStateManager |= SP_UP_OWN_TR_METH_ERROR;
OC_LOG(ERROR, TAG, "Error in OwnerShipTransferModeHandler.");
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void ListMethodsHandler(const CAEndpoint_t *object,
+static bool ListMethodsHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_LIST_METHODS_STARTED) && gToken)
{
OC_LOG(ERROR, TAG, "response payload is null.");
gStateManager |= SP_LIST_METHODS_ERROR;
- return;
+ return true;
}
OCPayload* payload;
{
OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
gStateManager |= SP_LIST_METHODS_ERROR;
- return;
+ return true;
}
DeletePstatBinData(gPstat);
OC_LOG(INFO, TAG, "Exiting ListMethodsHandler.");
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void OperationModeUpdateHandler(const CAEndpoint_t *object,
+static bool OperationModeUpdateHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_UPDATE_OP_MODE_STARTED) && gToken)
gStateManager |= SP_UPDATE_OP_MODE_ERROR;
OC_LOG(ERROR, TAG, "Error in OperationModeUpdateHandler.");
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void OwnerShipUpdateHandler(const CAEndpoint_t *object,
+static bool OwnerShipUpdateHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_UPDATE_OWNER_STARTED) && gToken)
gStateManager |= SP_UPDATE_OWNER_ERROR;
OC_LOG(ERROR, TAG, "Error in OwnerShipUpdateHandler.");
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void ACLProvisioningHandler(const CAEndpoint_t *object,
+static bool ACLProvisioningHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_PROV_ACL_STARTED) && gToken)
OC_LOG(ERROR, TAG, "Error in ACLProvisioningHandler.");
gStateManager |= SP_PROV_ACL_ERROR;
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void FinalizeProvisioningHandler(const CAEndpoint_t *object,
+static bool FinalizeProvisioningHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_UP_HASH_STARTED) && gToken)
gStateManager |= SP_UP_HASH_ERROR;
OC_LOG(ERROR, TAG, "Error in FinalizeProvisioningHandler.");
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] requestInfo Datastructure containing request information.
+ * @return true is CA token matches request token, false otherwise.
*/
-static void CredProvisioningHandler(const CAEndpoint_t *object,
+static bool CredProvisioningHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
if ((gStateManager & SP_PROV_CRED_STARTED) && gToken)
gStateManager |= SP_PROV_CRED_ERROR;
OC_LOG(ERROR, TAG, "Error in CredProvisioningHandler.");
}
+ return true;
}
}
+ return false;
}
/**
*
* @param[in] object Remote endpoint object
* @param[in] responseInfo Datastructure containing response information.
+ * @return true if received response is for provisioning API false otherwise.
*/
-static void SPResponseHandler(const CAEndpoint_t *object,
+static bool SPResponseHandler(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo)
{
+ bool isProvResponse = false;
if ((NULL != responseInfo) && (NULL != responseInfo->info.token))
{
- handler(object, responseInfo);
+ isProvResponse = handler(object, responseInfo);
}
-}
-
-/**
- * Error Handler
- *
- * @param[in] object Remote endpoint object
- * @param[in] errorInfo Datastructure containing error information.
- */
-static void SPErrorHandler(const CAEndpoint_t *object,
- const CAErrorInfo_t *errorInfo)
-{
- OC_LOG(INFO, TAG, "Error Handler.");
-}
-
-/**
- * Request Handler
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- */
-static void SPRequestHandler(const CAEndpoint_t *object, const CARequestInfo_t *requestInfo)
-{
- OC_LOG(INFO, TAG, "Request Handler.");
+ return isProvResponse;
}
/**
* @param[in] deviceInfo Provisioning context
* @return SP_SUCCESS on success
*/
-static SPResult initiateDtlsHandshake(SPTargetDeviceInfo_t *deviceInfo)
+static SPResult initiateDtlsHandshake(const CAEndpoint_t *endpoint)
{
- CAResult_t caresult = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
-
- if (CA_STATUS_OK != caresult)
- {
- OC_LOG(ERROR, TAG, "Unable to select cipher suite");
- return SP_RESULT_INTERNAL_ERROR;
- }
- OC_LOG(INFO, TAG, "Anonymous cipher suite selected. ");
- caresult = CAEnableAnonECDHCipherSuite(true);
+ CAResult_t caresult = CAEnableAnonECDHCipherSuite(true);
if (CA_STATUS_OK != caresult)
{
OC_LOG_V(ERROR, TAG, "Unable to enable anon cipher suite");
}
OC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
- //TODO: It is a temporary fix. Revisit it.
- deviceInfo->endpoint.port = CA_SECURE_PORT;
- caresult = CAInitiateHandshake((CAEndpoint_t *)&deviceInfo->endpoint);
+ caresult = CAInitiateHandshake(endpoint);
if (CA_STATUS_OK != caresult)
{
OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
CAResult_t result = sendCARequest(CA_PUT,
&selectedDeviceInfo->endpoint,
- OC_SECURE,
+ OC_FLAG_SECURE,
OIC_RSRC_DOXM_URI,
payloadBuffer, payloadLen);
if (CA_STATUS_OK != result)
{
SPResult result = SP_RESULT_INTERNAL_ERROR;
- CAEndpoint_t endpoint = {0};
- strncpy(endpoint.addr, selectedDeviceInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA);
- endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
+ CAEndpoint_t endpoint = {};
+ OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
endpoint.port = CA_SECURE_PORT;
OicUuid_t provTooldeviceID = {};
}
if (*selectedOperationMode == SINGLE_SERVICE_CLIENT_DRIVEN)
{
- res = initiateDtlsHandshake(selectedDeviceInfo);
- if (SP_RESULT_SUCCESS != res)
+ CAEndpoint_t endpoint = {0};
+ OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
+ endpoint.port = CA_SECURE_PORT;
+
+ res = initiateDtlsHandshake(&endpoint);
+ if (SP_RESULT_SUCCESS == res)
{
- OC_LOG(ERROR, TAG, "Error while DTLS handshake.");
- return SP_RESULT_INTERNAL_ERROR;
- }
+ selectedDeviceInfo->endpoint.port = CA_SECURE_PORT;
+ res = sendOwnershipInfo(timeout, selectedDeviceInfo);
+ if (SP_RESULT_SUCCESS != res)
+ {
+ OC_LOG(ERROR, TAG, "Error while updating ownership information.");
+ }
+ res = saveOwnerPSK(selectedDeviceInfo);
- res = sendOwnershipInfo(timeout, selectedDeviceInfo);
- if (SP_RESULT_SUCCESS != res)
+ //Close temporal DTLS session
+ if(CA_STATUS_OK != CACloseDtlsSession(&endpoint))
+ {
+ OC_LOG(WARNING, TAG, "doOwnerShipTransfer() : failed to close the dtls session");
+ }
+ }
+ else
{
- OC_LOG(ERROR, TAG, "Error while updating ownership information.");
- return SP_RESULT_INTERNAL_ERROR;
+ OC_LOG(ERROR, TAG, "Error during initiating DTLS handshake.");
}
- saveOwnerPSK(selectedDeviceInfo);
+ //Disable Anonymous ECDH cipher suite before leaving this method
+ if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
+ {
+ OC_LOG(WARNING, TAG, "doOwnerShipTransfer() : failed to disable Anon ECDH cipher suite");
+ }
}
- return SP_RESULT_SUCCESS;
+ return (res != SP_RESULT_SUCCESS) ? SP_RESULT_INTERNAL_ERROR : SP_RESULT_SUCCESS;
}
CAResult_t result = sendCARequest(CA_POST,
&deviceInfo->endpoint,
- OC_SECURE,
+ OC_FLAG_SECURE,
OIC_RSRC_CRED_URI,
credJson, payloadLen);
OICFree(credJson);
return SP_RESULT_TIMEOUT;
}
CADestroyToken(gToken);
+ gStateManager = 0;
return res;
}
OC_LOG(ERROR, TAG, "List is not null can cause memory leak");
return SP_RESULT_INVALID_PARAM;
}
-
- CARegisterHandler(SPRequestHandler, SPResponseHandler, SPErrorHandler);
+ SRMRegisterProvisioningResponseHandler(SPResponseHandler);
SPResult smResponse = SP_RESULT_SUCCESS;
smResponse = findResource(timeout);
if (SP_RESULT_SUCCESS != smResponse)
CAResult_t result = sendCARequest(CA_POST,
&selectedDeviceInfo->endpoint,
- OC_SECURE,
+ OC_FLAG_SECURE,
OIC_RSRC_ACL_URI,
aclString, payloadLen);
OICFree(aclString);
CAResult_t result = sendCARequest(CA_PUT,
&selectedDeviceInfo->endpoint,
- OC_SECURE,
+ OC_FLAG_SECURE,
OIC_RSRC_PSTAT_URI,
payloadBuffer, payloadLen);
OICFree(payloadBuffer);
return SP_RESULT_TIMEOUT;
}
- CAEndpoint_t endpoint = {0};
- strncpy(endpoint.addr, selectedDeviceInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA);
- endpoint.addr[DEV_ADDR_SIZE_MAX - 1] = '\0';
+ CAEndpoint_t endpoint = {};
+ OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
endpoint.port = CA_SECURE_PORT;
result = CACloseDtlsSession(&endpoint);
if (CA_STATUS_OK != result)
{
- OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+ OC_LOG(WARNING, TAG, "Failed to close the DTLS session.");
}
CADestroyToken(gToken);