Implement roleId property of an oic.sec.cred object.
Fix error path bugs in CRED<->CBOR code to fail properly if
certain serialization subroutines fail; error codes were
being ignored. Fix error path memory leaks.
Also fix the ACL/ACL2<->CBOR code to use the correct JSON
field names per the schema. Fix error path memory leaks.
Change-Id: Ie9aa8baba5903c482acb3adc6ef617a1ced7db31
Signed-off-by: Kevin Kane <kkane@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/18463
Reviewed-by: Alex Kelley <alexke@microsoft.com>
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dave Thaler <dthaler@microsoft.com>
Reviewed-by: Greg Zaverucha <gregz@microsoft.com>
OCStackResult DeInitRolesResource();
/**
+ * Register the PSK credential being used for authentication. This is used by the cred resource
+ * to inform the roles resource a symmetric PSK has a particular role associated with it.
+ *
+ * @param[in] cred PSK credential to register
+ *
+ * @return OC_STACK_OK if role credential is successfully registered; error otherwise.
+ */
+OCStackResult RegisterSymmetricCredentialRole(const OicSecCred_t *cred);
+
+/**
* Retrieve the roles asserted by a given endpoint with certificates.
*
* @param[in] endpoint Endpoint to retrieve roles for
*/
OicSecSvrType_t GetSvrTypeFromUri(const char* uri);
+extern const OicSecRole_t EMPTY_ROLE;
+
+/**
+ * Determine if a role is non-empty.
+ *
+ * @param[in] role Role to check
+ *
+ * @return true if role is non-empty, false if role is empty
+ */
+bool IsNonEmptyRole(const OicSecRole_t *role);
+
#ifdef __cplusplus
}
#endif
extern const char * OIC_JSON_OXM_SEL_NAME;
extern const char * OIC_JSON_DEVICE_ID_FORMAT_NAME;
extern const char * OIC_JSON_CREDID_NAME;
-extern const char * OIC_JSON_ROLEIDS_NAME;
+extern const char * OIC_JSON_ROLEID_NAME;
+extern const char * OIC_JSON_ROLE_NAME;
extern const char * OIC_JSON_AUTHORITY_NAME;
extern const char * OIC_JSON_CREDTYPE_NAME;
extern const char * OIC_JSON_PUBLICDATA_NAME;
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
uint16_t credId; // 0:R:S:Y:UINT16
OicUuid_t subject; // 1:R:S:Y:oic.uuid
- //Note: Need further clarification on roleID data type
- //NOTE: Need further clarification on roleId datatype.
- //size_t roleIdsLen; // the number of elts in RoleIds
- //OicSecRole_t *roleIds; // 2:R:M:N:oic.sec.role
+ // If roleId.id is all zeroes, this property is not set.
+ OicSecRole_t roleId; // 2:R:M:N:oic.sec.roletype
OicSecCredType_t credType; // 3:R:S:Y:oic.sec.credtype
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
OicSecKey_t publicData; // own cerificate chain
* @param[in] ptDeviceId Device ID of provisioning tool.
* @param[in] firstDeviceId DeviceID of the first device.
* @param[in] secondDeviceId DeviceID of the second device.
+ * @param[in] firstRole Role to grant firstDeviceId when communicating with secondDeviceId; NULL for none
+ * @param[in] secondRole Role to grant secondDeviceId when communicating with firstDeviceId; NULL for none
* @param[out] firstCred Generated credential for first device.
* @param[out] secondCred Generated credential for second device.
* @return OC_STACK_OK on success
const OicUuid_t *ptDeviceId,
const OicUuid_t *firstDeviceId,
const OicUuid_t *secondDeviceId,
+ const OicSecRole_t *firstRole,
+ const OicSecRole_t *secondRole,
OicSecCred_t **firstCred,
OicSecCred_t **secondCred);
* @param[in] ctx Application context to be returned in result callback.
* @param[in] type Type of credentials to be provisioned to the device.
* @param[in] keySize size of key
- * @param[in] pDev1 Pointer to PMOwnedDeviceInfo_t instance, respresenting resource to be provsioned.
- * @param[in] pDev2 Pointer to PMOwnedDeviceInfo_t instance, respresenting resource to be provsioned.
+ * @param[in] pDev1 Pointer to PMOwnedDeviceInfo_t instance, representing the resource to be provisioned.
+ * @param[in] pDev2 Pointer to PMOwnedDeviceInfo_t instance, representing the resource to be provisioned.
+ * Use NULL to indicate the local device.
* @param[in] pemCert When provisioning a certificate (type is SIGNED_ASYMMETRIC_KEY), this is the
* certificate, encoded as PEM.
+ * @param[in] role1 When provisioning a PSK (type is SYMMETRIC_PAIR_WISE_KEY), this is the role which
+ * the device indicated by pDev1 will also have when communicating with pDev2. Use NULL
+ * to associate no role with this credential.
+ * @param[in] role2 When provisioning a PSK (type is SYMMETRIC_PAIR_WISE_KEY), this is the role which
+ * the device indicated by pDev1 will also have when communicating with pDev2. Use NULL
+ * to associate no role with this credential.
* @param[in] resultCallback callback provided by API user, callback will be called when
* provisioning request recieves a response from first resource server.
* @return OC_STACK_OK in case of success and other value otherwise.
const OCProvisionDev_t *pDev1,
const OCProvisionDev_t *pDev2,
const char* pemCert,
+ const OicSecRole_t *role1,
+ const OicSecRole_t *role2,
OCProvisionResultCB resultCallback);
/**
* @param[in] ctx Application context returned in the result callback.
* @param[in] type Type of credentials to be provisioned to the device.
* @param[in] keySize size of key
- * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
- @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance, representing the resource to be provisioned.
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance, representing the resource to be provisioned.
* @param[in] resultCallback callback provided by API user, callback will be called when
* provisioning request recieves a response from first resource server.
* @return OC_STACK_OK in case of success and other value otherwise.
OCProvisionResultCB resultCallback);
/**
+ * API to provision symmetric pair-wise key credentials to devices that grant a role.
+ *
+ * @param[in] ctx Application context returned in the result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] keySize size of key
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance, representing the resource to be provisioned.
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance, representing the resource to be provisioned.
+ * Use NULL to indicate the local device.
+ * @param[in] role1 The role which the device indicated by pDev1 will have when communicating with pDev2.
+ * Use NULL to associate no role with this credential.
+ * @param[in] role2 The role which the device indicated by pDev2 will have when communicating with pDev1.
+ * Use NULL to associate no role with this credential.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request receives a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionSymmetricRoleCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1,
+ const OCProvisionDev_t *pDev2,
+ const OicSecRole_t *role1,
+ const OicSecRole_t *role2,
+ OCProvisionResultCB resultCallback);
+
+/**
* API to provision a certificate to a device.
*
* @param[in] ctx Application context returned in result callback.
return ret;
}
+static int provisionSymmetricRoleCred(int dev_num)
+{
+ OicSecRole_t role;
+ memset(&role, 0, sizeof(role));
+ OICStrcpy(role.id, sizeof(role.id), TEST_CERT_ROLE1);
+
+ // call |OCProvisionCredentials| API
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ OCStackResult rst =
+ OCProvisionSymmetricRoleCredentials((void*) g_ctx,
+ SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
+ NULL, NULL, &role,
+ provisionCredCB);
+ if (OC_STACK_OK != rst)
+ {
+ OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
+ return -1;
+ }
+ if (waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int testSymmetricRoleUse(int dev_num)
+{
+ const char* uri = "/a/led";
+ OicSecAcl_t* acl = NULL;
+
+ // Make sure we own at least one device to provision
+ if (!g_own_list || (g_own_cnt == 0))
+ {
+ OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first");
+ return -1; // Error, we should have registered unowned devices already
+ }
+
+ /* Create and provision a role-based ACL allowing ROLE1 to access '/a/led'. */
+ int ret = createLedAcl(&acl, TEST_CERT_ROLE1, NULL);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s failed to create led ACL", __func__);
+ return ret;
+ }
+
+ ret = provisionAcl(dev_num, acl);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s failed to provision led ACL", __func__);
+ goto exit;
+ }
+
+ /* Create and provision an ACL to allow anyone access to the roles resource. Since all actions
+ * on the roles resource first requires authentication by public key, this is effectively "any
+ * authenticated" access.
+ * @todo: This should be done by default and not be necessary here (IOT-1950).
+ */
+ OCDeleteACLList(acl);
+ acl = NULL;
+ ret = createRolesAcl(&acl);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s failed to create roles ACL", __func__);
+ goto exit;
+ }
+
+ ret = provisionAcl(dev_num, acl);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s failed to provision roles ACL", __func__);
+ goto exit;
+ }
+
+ /* Remove the owner credential so that we don't use it when asserting role certs. */
+ OCStackResult res = OCRemoveCredential(&g_uuidDev1);
+ if (res != OC_STACK_RESOURCE_DELETED)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s failed to remove owner credential for subject UUID: ", __func__);
+ OIC_LOG_BUFFER(DEBUG, TAG, g_uuidDev1.id, UUID_LENGTH);
+ ret = -1;
+ goto exit;
+ }
+
+ /* The server has an owner PSK associated with our GUID. Change our GUID to something else,
+ * which will both be used to generate the role credential and for the later connection.
+ */
+ const OCUUIdentity newIdentity = { .id = { 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46 } };
+ if (OC_STACK_OK != OCSetDeviceId(&newIdentity))
+ {
+ OIC_LOG_V(ERROR, TAG, "%s failed to set device ID", __func__);
+ ret = -1;
+ goto exit;
+ }
+
+ /* Create a new symmetric credential with the role. */
+ ret = provisionSymmetricRoleCred(dev_num);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s failed to provision symmetric role pair-wise keys", __func__);
+ goto exit;
+ }
+
+ /* Close all secure sessions */
+ if (closeAllSessions() != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s Failed to close sessions", __func__);
+ ret = -1;
+ goto exit;
+ }
+
+ /* Try a get request, expect success */
+ ret = doGetRequest(uri, dev_num);
+ if (ret != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s Get request to %s failed, but should have succeeded", __func__, uri);
+ goto exit;
+ }
+
+exit:
+
+ OCDeleteACLList(acl);
+
+ return ret;
+}
+
/* Get a specific device from the provided device list. The devices in the list
* are numbered starting from 1.
*/
return ret;
}
+int TestSymmetricRoleUse()
+{
+ int ret = -1;
+
+ OIC_LOG_V(ERROR, TAG, "Running %s", __func__);
+
+ if (initDiscoverRegisterAllDevices())
+ {
+ OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__);
+ goto exit;
+ }
+
+ /* There should be one owned device with number 1. */
+ if (testSymmetricRoleUse(1))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to use symmetric key role");
+ goto exit;
+ }
+
+exit:
+
+ shutdownProvisionClient();
+
+ return ret;
+}
+
// main function for provisioning client using C-level provisioning API
int main(int argc, char** argv)
{
return TestRoleProvisioning();
case 5:
return TestRoleAssertionAndUse();
+ case 6:
+ return TestSymmetricRoleUse();
default:
printf("%s: Invalid test number\n", argv[0]);
return 1;
### main ###
# Number of unit tests in autoprovisioningclient
-NUM_TESTS = 5
+NUM_TESTS = 6
usage = '''
Run end-to-end certificate tests between autoprovisioningclient and sampleserver_justworks
OCStackResult PMGeneratePairWiseCredentials(OicSecCredType_t type, size_t keySize,
const OicUuid_t *ptDeviceId, const OicUuid_t *firstDeviceId,
- const OicUuid_t *secondDeviceId, OicSecCred_t **firstCred, OicSecCred_t **secondCred)
+ const OicUuid_t *secondDeviceId,
+ const OicSecRole_t *firstRole, const OicSecRole_t *secondRole,
+ OicSecCred_t **firstCred, OicSecCred_t **secondCred)
{
if (NULL == ptDeviceId || NULL == firstDeviceId || NULL == firstCred || NULL != *firstCred || \
NULL == secondDeviceId || NULL == secondCred || NULL != *secondCred)
tempSecondCred = GenerateCredential(firstDeviceId, type, NULL, &privKey, ptDeviceId, NULL);
VERIFY_NOT_NULL(TAG, tempSecondCred, ERROR);
+ // firstRole and secondRole are the roles granted to the client when authenticating with this credential;
+ // therefore, the role to be granted has to be stored on the corresponding server. This is why secondRole
+ // is assigned to tempFirstCred and vice versa.
+ if (NULL != secondRole)
+ {
+ tempFirstCred->roleId = *secondRole;
+ }
+ if (NULL != firstRole)
+ {
+ tempSecondCred->roleId = *firstRole;
+ }
+
*firstCred = tempFirstCred;
*secondCred = tempSecondCred;
res = OC_STACK_OK;
OCProvisionResultCB resultCallback)
{
return SRPProvisionCredentials(ctx, type, keySize,
- pDev1, pDev2, NULL, resultCallback);
+ pDev1, pDev2, NULL, NULL, NULL, resultCallback);
+}
+/**
+ * API to provision symmetric pair-wise key credentials to devices that grant a role.
+ *
+ * @param[in] ctx Application context returned in the result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] keySize size of key
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance, representing the resource to be provisioned.
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance, representing the resource to be provisioned.
+ * Use NULL to indicate the local device.
+ * @param[in] role1 The role which the device indicated by pDev1 will have when communicating with pDev2.
+ * Use NULL to associate no role with this credential.
+ * @param[in] role2 The role which the device indicated by pDev2 will have when communicating with pDev1.
+ * Use NULL to associate no role with this credential.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request receives a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionSymmetricRoleCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1,
+ const OCProvisionDev_t *pDev2,
+ const OicSecRole_t *role1,
+ const OicSecRole_t *role2,
+ OCProvisionResultCB resultCallback)
+{
+ return SRPProvisionCredentials(ctx, type, keySize, pDev1, pDev2, NULL, role1, role2, resultCallback);
}
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
OCProvisionResultCB resultCallback)
{
return SRPProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0,
- pDev, NULL, pemCert, resultCallback);
+ pDev, NULL, pemCert, NULL, NULL, resultCallback);
}
#endif
link->currentCountResults = 0;
link->resArr = (OCProvisionResult_t*) OICMalloc(sizeof(OCProvisionResult_t)*noOfResults);
res = SRPProvisionCredentials(link, type, keySize,
- pDev1, pDev2, NULL, &ProvisionCredsCB);
+ pDev1, pDev2, NULL, NULL, NULL, &ProvisionCredsCB);
if (res != OC_STACK_OK)
{
OICFree(link->resArr);
/**
* Function prototype
*/
-static OCStackResult provisionCredentials(const OicSecCred_t *cred,
+static OCStackResult provisionCredentials(OicSecCred_t *cred,
const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
OCClientResponseHandler responseHandler);
+typedef enum {
+ DEVICE_1_FINISHED,
+ DEVICE_2_FINISHED,
+ DEVICE_LOCAL_FINISHED
+} CredProvisioningResultCause_t;
+
/**
* Internal function to update result in result array.
*/
static void registerResultForCredProvisioning(CredentialData_t *credData,
- OCStackResult stackresult, int cause)
+ OCStackResult stackresult, CredProvisioningResultCause_t cause)
{
-
+ OCStackResult res = OC_STACK_ERROR;
OIC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",credData->numOfResults);
- if(1 == cause)
+ switch (cause)
{
+ case DEVICE_1_FINISHED:
memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
credData->deviceInfo1->doxm->deviceID.id,UUID_LENGTH);
- }
- else
- {
+ break;
+ case DEVICE_2_FINISHED:
memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
credData->deviceInfo2->doxm->deviceID.id,UUID_LENGTH);
+ break;
+ case DEVICE_LOCAL_FINISHED:
+ res = GetDoxmDeviceID(&credData->resArr[(credData->numOfResults)].deviceId);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG_V(WARNING, TAG, "%s: Could not retrieve own device ID to populate result for cred provisioning: %d", __func__, res);
+ memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
+ }
+ break;
+ default:
+ assert(!"Unknown value for cause");
+ OIC_LOG_V(ERROR, TAG, "%s: unknown value of cause: %d", __func__, cause);
+ memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
+ break;
}
credData->resArr[(credData->numOfResults)].res = stackresult;
++(credData->numOfResults);
{
if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
{
- registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, 2);
+ registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
OCStackResult res = PDMLinkDevices(&credData->deviceInfo1->doxm->deviceID,
&credData->deviceInfo2->doxm->deviceID);
if (OC_STACK_OK != res)
}
OIC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
- registerResultForCredProvisioning(credData, OC_STACK_ERROR, 2);
+ registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
credData->resArr,
true);
if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
{
// send credentials to second device
- registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED,1);
+ registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
provisionCredentialCB2);
- DeleteCredList(credInfo);
+ // If deviceInfo is NULL, this device is the second device. Don't delete the cred
+ // because provisionCredentials added it to the local cred store and it now owns
+ // the memory.
+ if ((NULL != deviceInfo) || (OC_STACK_OK != res))
+ {
+ DeleteCredList(credInfo);
+ }
if (OC_STACK_OK != res)
{
registerResultForCredProvisioning(credData, res,2);
}
else
{
- registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
+ registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
credData->resArr,
true);
else
{
OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
- registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
+ registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
credData->resArr,
true);
* @param[in] responseHandler callbak called by OC stack when request API receives response.
* @return OC_STACK_OK in case of success and other value otherwise.
*/
-static OCStackResult provisionCredentials(const OicSecCred_t *cred,
+static OCStackResult provisionCredentials(OicSecCred_t *cred,
const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
OCClientResponseHandler responseHandler)
{
- OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
- if (!secPayload)
- {
- OIC_LOG(ERROR, TAG, "Failed to allocate memory");
- return OC_STACK_NO_MEMORY;
- }
- secPayload->base.type = PAYLOAD_TYPE_SECURITY;
- int secureFlag = 0;
- OCStackResult res = CredToCBORPayload(cred, &secPayload->securityData,
- &secPayload->payloadSize, secureFlag);
- if((OC_STACK_OK != res) && (NULL == secPayload->securityData))
- {
- OCPayloadDestroy((OCPayload *)secPayload);
- OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
- return OC_STACK_NO_MEMORY;
- }
+ OCStackResult res = OC_STACK_OK;
- 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,
- deviceInfo->endpoint.addr,
- deviceInfo->securePort,
- deviceInfo->connType,
- query, sizeof(query), OIC_RSRC_CRED_URI))
+ if (NULL != deviceInfo)
{
- OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
- OCPayloadDestroy((OCPayload *)secPayload);
- return OC_STACK_ERROR;
- }
- OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if (!secPayload)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ int secureFlag = 0;
+ res = CredToCBORPayload(cred, &secPayload->securityData, &secPayload->payloadSize, secureFlag);
+ if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
+ {
+ OCPayloadDestroy((OCPayload *)secPayload);
+ OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
+ return OC_STACK_NO_MEMORY;
+ }
- OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
- cbData.cb = responseHandler;
- cbData.context = (void *) credData;
- cbData.cd = NULL;
+ 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,
+ deviceInfo->endpoint.addr,
+ deviceInfo->securePort,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_CRED_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);
- OCDoHandle handle = NULL;
- OCMethod method = OC_REST_POST;
- OCStackResult ret = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
+ OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
+ cbData.cb = responseHandler;
+ cbData.context = (void *)credData;
+ cbData.cd = NULL;
+
+ OCDoHandle handle = NULL;
+ OCMethod method = OC_REST_POST;
+ res = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
- OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d",ret);
- if (ret != OC_STACK_OK)
+ OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
+ if (res != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ return res;
+ }
+ return OC_STACK_OK;
+ }
+ else
{
- OIC_LOG(ERROR, TAG, "OCStack resource error");
- return ret;
+ /* Provision this credential to the local cred store. On success, the cred resource takes
+ * ownership of the memory. On failure, provisionCredentialCB1 will delete the cred object.
+ */
+ res = AddCredential(cred);
+ /* Call the result callback directly. */
+ registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
+ (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
+ return res;
}
- return OC_STACK_OK;
}
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
const OCProvisionDev_t *pDev1,
const OCProvisionDev_t *pDev2,
const char* pemCert,
+ const OicSecRole_t *role1,
+ const OicSecRole_t *role2,
OCProvisionResultCB resultCallback)
{
VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR, OC_STACK_INVALID_PARAM);
- if (SYMMETRIC_PAIR_WISE_KEY == type)
- {
- VERIFY_NOT_NULL_RETURN(TAG, pDev2, ERROR, OC_STACK_INVALID_PARAM);
- }
if (!resultCallback)
{
OIC_LOG(INFO, TAG, "SRPProvisionCredentials: NULL Callback");
return OC_STACK_INVALID_CALLBACK;
}
- if (SYMMETRIC_PAIR_WISE_KEY == type &&
- 0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t)))
+ if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
+ (NULL != pDev2) &&
+ (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
{
OIC_LOG(INFO, TAG, "SRPProvisionCredentials : Same device ID");
return OC_STACK_INVALID_PARAM;
OIC_LOG(INFO, TAG, "In SRPProvisionCredentials");
- if (SYMMETRIC_PAIR_WISE_KEY == type)
+ if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
{
bool linkExisits = true;
OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
OicSecCred_t *firstCred = NULL;
OicSecCred_t *secondCred = NULL;
OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
- &firstDevice->doxm->deviceID, &secondDevice->doxm->deviceID,
+ &firstDevice->doxm->deviceID, (NULL != secondDevice) ? &secondDevice->doxm->deviceID : &provTooldeviceID,
+ role1, role2,
&firstCred, &secondCred);
VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
OIC_LOG(INFO, TAG, "Credentials generated successfully");
OicSecCred_t *cred2 = NULL;
size_t keySize = OWNER_PSK_LENGTH_128;
EXPECT_EQ(OC_STACK_INVALID_PARAM, PMGeneratePairWiseCredentials(NO_SECURITY_MODE,
- keySize, NULL, firstDevID, SecondDevID, &cred1, &cred2));
+ keySize, NULL, firstDevID, SecondDevID, NULL, NULL, &cred1, &cred2));
OICFree(firstDevID);
OICFree(SecondDevID);
}
OicSecCred_t *cred2 = NULL;
size_t keySize = OWNER_PSK_LENGTH_128;
EXPECT_EQ(OC_STACK_INVALID_PARAM, PMGeneratePairWiseCredentials(NO_SECURITY_MODE,
- keySize, provisioningDevID, NULL, SecondDevID, &cred1, &cred2));
+ keySize, provisioningDevID, NULL, SecondDevID, NULL, NULL, &cred1, &cred2));
OICFree(SecondDevID);
OICFree(provisioningDevID);
}
OicSecCred_t *cred2 = NULL;
size_t keySize = OWNER_PSK_LENGTH_128;
EXPECT_EQ(OC_STACK_INVALID_PARAM, PMGeneratePairWiseCredentials(NO_SECURITY_MODE, keySize,
- provisioningDevID, firstDevID, NULL, &cred1, &cred2));
+ provisioningDevID, firstDevID, NULL, NULL, NULL, &cred1, &cred2));
OICFree(firstDevID);
OICFree(provisioningDevID);
}
}
size_t keySize = OWNER_PSK_LENGTH_128;
EXPECT_EQ(OC_STACK_INVALID_PARAM, PMGeneratePairWiseCredentials(NO_SECURITY_MODE, keySize,
- provisioningDevID, firstDevID, SecondDevID, NULL, NULL));
+ provisioningDevID, firstDevID, SecondDevID, NULL, NULL, NULL, NULL));
OICFree(firstDevID);
OICFree(SecondDevID);
OICFree(provisioningDevID);
}
-
{
EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
OWNER_PSK_LENGTH_128, NULL,
- &pDev2, NULL, &provisioningCB));
+ &pDev2, NULL, NULL, NULL, &provisioningCB));
}
TEST(SRPProvisionCredentialsTest, SamelDeviceId)
{
EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
OWNER_PSK_LENGTH_128, &pDev1,
- &pDev1, NULL, &provisioningCB));
+ &pDev1, NULL, NULL, NULL, &provisioningCB));
}
TEST(SRPProvisionCredentialsTest, NullCallback)
{
EXPECT_EQ(OC_STACK_INVALID_CALLBACK, SRPProvisionCredentials(NULL, credType,
OWNER_PSK_LENGTH_128,
- &pDev1, &pDev2, NULL, NULL));
+ &pDev1, &pDev2, NULL, NULL, NULL, NULL));
}
TEST(SRPProvisionCredentialsTest, InvalidKeySize)
{
EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
- 0, &pDev1, &pDev2, NULL,
+ 0, &pDev1, &pDev2, NULL, NULL, NULL,
&provisioningCB));
}
EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPUnlinkDevices(NULL, NULL, &pDev2, provisioningCB));
}
-TEST(SRPUnlinkDevicesTest, NullDevice2)
-{
- EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPUnlinkDevices(NULL, &pDev1, NULL, provisioningCB));
-}
-
TEST(SRPUnlinkDevicesTest, SamelDeviceId)
{
EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPUnlinkDevices(NULL, &pDev1, &pDev1, provisioningCB));
#include "srmresourcestrings.h"
#include "aclresource.h"
#include "doxmresource.h"
+#include "rolesresource.h"
#include "resourcemanager.h"
#include "srmutility.h"
#include "psinterface.h"
#include "ocpayloadcbor.h"
+#include "secureresourcemanager.h"
#include "security_internals.h"
static const uint8_t ACL_ACLIST_MAP_SIZE = 1;
static const uint8_t ACL_ACES_MAP_SIZE = 3;
static const uint8_t ACL_RESOURCE_MAP_SIZE = 3;
-static const uint8_t ACE_ROLE_MAP_SIZE = 2;
+static const uint8_t ACE_ROLE_MAP_SIZE = 1;
// CborSize is the default cbor payload size being used.
{
assert(OIC_SEC_ACL_V2 <= aclVersion);
CborEncoder roleMap;
- cborEncoderResult = cbor_encoder_create_map(&oicSecAclMap, &roleMap, ACE_ROLE_MAP_SIZE);
+
+ bool includeAuthority = (0 != memcmp(&ace->subjectRole.authority, &EMPTY_ROLE.authority, sizeof(EMPTY_ROLE.authority)));
+
+ cborEncoderResult = cbor_encoder_create_map(&oicSecAclMap, &roleMap, ACE_ROLE_MAP_SIZE + includeAuthority?1:0);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed creating role map");
- cborEncoderResult = cbor_encode_text_string(&roleMap, OIC_JSON_ROLEIDS_NAME, strlen(OIC_JSON_ROLEIDS_NAME));
+ cborEncoderResult = cbor_encode_text_string(&roleMap, OIC_JSON_ROLE_NAME, strlen(OIC_JSON_ROLE_NAME));
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding roleid tag");
cborEncoderResult = cbor_encode_text_string(&roleMap, ace->subjectRole.id, strlen(ace->subjectRole.id));
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding roleid value");
- cborEncoderResult = cbor_encode_text_string(&roleMap, OIC_JSON_AUTHORITY_NAME, strlen(OIC_JSON_AUTHORITY_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding authority tag");
+ if (includeAuthority)
+ {
+ cborEncoderResult = cbor_encode_text_string(&roleMap, OIC_JSON_AUTHORITY_NAME, strlen(OIC_JSON_AUTHORITY_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding authority tag");
- cborEncoderResult = cbor_encode_text_string(&roleMap, ace->subjectRole.authority, strlen(ace->subjectRole.authority));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding authority value");
+ cborEncoderResult = cbor_encode_text_string(&roleMap, ace->subjectRole.authority, strlen(ace->subjectRole.authority));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding authority value");
+ }
cborEncoderResult = cbor_encoder_close_container(&oicSecAclMap, &roleMap);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing role map");
if (NULL != roleTagName)
{
- if (strcmp(roleTagName, OIC_JSON_ROLEIDS_NAME) == 0)
+ if (strcmp(roleTagName, OIC_JSON_ROLE_NAME) == 0)
{
char *roleId = NULL;
cborFindResult = cbor_value_dup_text_string(&roleMap, &roleId, &unusedLen, NULL);
if (strlen(roleId) >= sizeof(ace->subjectRole.id))
{
cborFindResult = CborUnknownError;
+ free(roleId);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Role ID is too long");
}
OICStrcpy(ace->subjectRole.id, sizeof(ace->subjectRole.id), roleId);
if (strlen(authorityName) >= sizeof(ace->subjectRole.authority))
{
cborFindResult = CborUnknownError;
+ free(authorityName);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Authority name is too long");
}
OICStrcpy(ace->subjectRole.authority, sizeof(ace->subjectRole.authority), authorityName);
#include "pinoxmcommon.h"
#include "certhelpers.h"
#include "cacommon.h"
+#include "secureresourcemanager.h"
#ifdef __unix__
#include <sys/types.h>
/** CRED size - Number of mandatory items. */
static const uint8_t CRED_ROOT_MAP_SIZE = 4;
static const uint8_t CRED_MAP_SIZE = 3;
+static const uint8_t ROLEID_MAP_SIZE = 1;
static OicSecCred_t *gCred = NULL;
OicUuid_t emptyUuid = {.id={0}};
VERIFY_SUCCESS(TAG, (0 == memcmp(cred->subject.id, emptyUuid.id, sizeof(emptyUuid))), ERROR);
+ VERIFY_SUCCESS(TAG, !IsNonEmptyRole(&cred->roleId), ERROR);
VERIFY_SUCCESS(TAG, (0 == cred->credId), ERROR);
VERIFY_SUCCESS(TAG, (0 == cred->credType), ERROR);
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
cborEncoderResult = cbor_encoder_create_map(rootMap, &map, mapSize);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Map");
- VERIFY_CBOR_SUCCESS(TAG, SerializeEncodingToCborInternal(&map, value),
- "Failed adding OicSecKey_t structure");
+ cborEncoderResult = SerializeEncodingToCborInternal(&map, value);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding OicSecKey_t structure");
cborEncoderResult = cbor_encoder_close_container(rootMap, &map);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Map.");
in.encoding = value->encoding;
in.len = value->len;
- VERIFY_CBOR_SUCCESS(TAG, SerializeEncodingToCborInternal(&map, &in),
- "Failed adding OicSecKey_t structure");
+ cborEncoderResult = SerializeEncodingToCborInternal(&map, &in);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding OicSecKey_t structure");
cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_REVOCATION_STATUS_NAME,
strlen(OIC_JSON_REVOCATION_STATUS_NAME));
}
if (name)
{
- VERIFY_CBOR_SUCCESS(TAG, DeserializeEncodingFromCborInternal(&map, name, value),
- "Failed to read OicSecKey_t value");
+ cborFindResult = DeserializeEncodingFromCborInternal(&map, name, value);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read OicSecKey_t value");
}
if (cbor_value_is_valid(&map))
{
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding revstat Value.")
}
OicSecKey_t out;
- VERIFY_CBOR_SUCCESS(TAG, DeserializeEncodingFromCborInternal(&map, name, &out),
- "Failed to read OicSecKey_t value");
+ cborFindResult = DeserializeEncodingFromCborInternal(&map, name, &out);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read OicSecKey_t value");
value->data = out.data;
value->encoding = out.encoding;
{
OIC_LOG_V(DEBUG, TAG, "Subject UUID: %s", uuidString);
}
+ if (IsNonEmptyRole(&temp->roleId))
+ {
+ OIC_LOG_V(DEBUG, TAG, "Role ID: %s", temp->roleId.id);
+ OIC_LOG_V(DEBUG, TAG, "Role authority: %s", temp->roleId.authority);
+ }
OIC_LOG_V(DEBUG, TAG, "Cred Type: %d", temp->credType);
OIC_LOG_V(DEBUG, TAG, "privateData length: %d, encoding: %d", temp->privateData.len, temp->privateData.encoding);
#endif
}
-
OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
size_t *cborSize, int secureFlag)
{
CborEncoder encoder;
CborEncoder credArray;
CborEncoder credRootMap;
+ CborEncoder roleIdMap;
if (0 == cborLen)
{
{
mapSize++;
}
+ if (IsNonEmptyRole(&cred->roleId))
+ {
+ mapSize++;
+ }
#endif /* __WITH_DTLS__ || __WITH_TLS__*/
if (!secureFlag && cred->privateData.data)
{
OICFree(subject);
}
+ //Role ID -- optional
+ if (IsNonEmptyRole(&cred->roleId))
+ {
+ cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_ROLEID_NAME,
+ strlen(OIC_JSON_ROLEID_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding role ID map tag");
+
+ bool includeAuthority = (0 != memcmp(&cred->roleId.authority, &EMPTY_ROLE.authority, sizeof(EMPTY_ROLE.authority)));
+
+ cborEncoderResult = cbor_encoder_create_map(&credMap, &roleIdMap, ROLEID_MAP_SIZE + includeAuthority ? 1 : 0);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding role ID map");
+
+ cborEncoderResult = cbor_encode_text_string(&roleIdMap, OIC_JSON_ROLE_NAME, strlen(OIC_JSON_ROLE_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding role tag");
+
+ cborEncoderResult = cbor_encode_text_string(&roleIdMap, cred->roleId.id, strlen(cred->roleId.id));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding role value");
+
+ if (includeAuthority)
+ {
+ cborEncoderResult = cbor_encode_text_string(&roleIdMap, OIC_JSON_AUTHORITY_NAME, strlen(OIC_JSON_AUTHORITY_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding authority tag");
+
+ cborEncoderResult = cbor_encode_text_string(&roleIdMap, cred->roleId.authority, strlen(cred->roleId.authority));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding authority value");
+ }
+
+ cborEncoderResult = cbor_encoder_close_container(&credMap, &roleIdMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing role ID map");
+ }
+
//CredType -- Mandatory
cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
strlen(OIC_JSON_CREDTYPE_NAME));
return OC_STACK_INVALID_PARAM;
}
+ char* tagName = NULL;
+ char* roleIdTagName = NULL;
+ char* name = NULL;
OCStackResult ret = OC_STACK_ERROR;
CborValue credCbor = { .parser = NULL };
CborParser parser = { .end = NULL };
while (cbor_value_is_valid(&CredRootMap))
{
- char* tagName = NULL;
size_t len = 0;
CborType type = cbor_value_get_type(&CredRootMap);
if (type == CborTextStringType && cbor_value_is_text_string(&CredRootMap))
while(cbor_value_is_valid(&credMap) && cbor_value_is_text_string(&credMap))
{
- char* name = NULL;
CborType cmType = cbor_value_get_type(&credMap);
if (cmType == CborTextStringType)
{
//It is required to use free() instead of OICFree
free(subjectid);
}
+ // roleid
+ if (strcmp(name, OIC_JSON_ROLEID_NAME) == 0)
+ {
+ /* Role subject */
+ size_t unusedLen = 0;
+ CborValue roleIdMap;
+ memset(&roleIdMap, 0, sizeof(roleIdMap));
+
+ cborFindResult = cbor_value_enter_container(&credMap, &roleIdMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed entering role ID map");
+
+ while (cbor_value_is_valid(&roleIdMap) && cbor_value_is_text_string(&roleIdMap))
+ {
+ cborFindResult = cbor_value_dup_text_string(&roleIdMap, &roleIdTagName, &unusedLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting role ID map tag name");
+ cborFindResult = cbor_value_advance(&roleIdMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing role ID map");
+
+ if (NULL != roleIdTagName)
+ {
+ if (strcmp(roleIdTagName, OIC_JSON_ROLE_NAME) == 0)
+ {
+ char *roleId = NULL;
+ cborFindResult = cbor_value_dup_text_string(&roleIdMap, &roleId, &unusedLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting role id value");
+ if (strlen(roleId) >= sizeof(cred->roleId.id))
+ {
+ cborFindResult = CborUnknownError;
+ free(roleId);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Role ID is too long");
+ }
+ OICStrcpy(cred->roleId.id, sizeof(cred->roleId.id), roleId);
+ free(roleId);
+ }
+ else if (strcmp(roleIdTagName, OIC_JSON_AUTHORITY_NAME) == 0)
+ {
+ char *authorityName = NULL;
+ cborFindResult = cbor_value_dup_text_string(&roleIdMap, &authorityName, &unusedLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting role authority value");
+ if (strlen(authorityName) >= sizeof(cred->roleId.authority))
+ {
+ cborFindResult = CborUnknownError;
+ free(authorityName);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Authority name is too long");
+ }
+ OICStrcpy(cred->roleId.authority, sizeof(cred->roleId.authority), authorityName);
+ free(authorityName);
+ }
+ else
+ {
+ OIC_LOG_V(WARNING, TAG, "Unknown tag name in role ID map: %s", roleIdTagName);
+ }
+
+ free(roleIdTagName);
+ roleIdTagName = NULL;
+ }
+
+ if (cbor_value_is_valid(&roleIdMap))
+ {
+ cborFindResult = cbor_value_advance(&roleIdMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing role map");
+ }
+ }
+
+ /* Make sure at least the id is present. */
+ if ('\0' == cred->roleId.id[0])
+ {
+ cborFindResult = CborUnknownError;
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "ID for role was not present in role map");
+ }
+ }
// credtype
if (strcmp(name, OIC_JSON_CREDTYPE_NAME) == 0)
{
//Because cbor using malloc directly
//It is required to use free() instead of OICFree
free(name);
+ name = NULL;
}
}
cred->next = NULL;
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
ret = ConvertStrToUuid(stRowner, &headCred->rownerID);
- VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
//Because cbor using malloc directly
//It is required to use free() instead of OICFree
free(stRowner);
+ VERIFY_SUCCESS(TAG, (ret == OC_STACK_OK), ERROR);
}
else if (NULL != gCred)
{
//Because cbor using malloc directly
//It is required to use free() instead of OICFree
free(tagName);
+ tagName = NULL;
}
if (cbor_value_is_valid(&CredRootMap))
{
ret = OC_STACK_ERROR;
}
+ free(tagName);
+ free(roleIdTagName);
+ free(name);
+
return ret;
}
VERIFY_SUCCESS(TAG, (l->credType == r->credType), INFO);
VERIFY_SUCCESS(TAG, (0 == memcmp(l->subject.id, r->subject.id, sizeof(l->subject.id))), INFO);
+ VERIFY_SUCCESS(TAG, (0 == memcmp(&l->roleId, &r->roleId, sizeof(l->roleId))), INFO);
switch(l->credType)
{
OICFree(outKey);
}
+ if (OC_STACK_OK != RegisterSymmetricCredentialRole(cred))
+ {
+ OIC_LOG(WARNING, TAG, "Couldn't RegisterRoleForSubject");
+ }
+
return ret;
}
}
#include "ca_adapter_net_ssl.h"
#include "ocstackinternal.h"
#include "rolesresource.h"
+#include "secureresourcemanager.h"
#define TAG "OIC_SRM_ROLES"
struct RolesEntry *next;
} RolesEntry_t;
-static OCResourceHandle gRolesHandle = NULL;
-static RolesEntry_t *gRoles = NULL;
-static uint32_t gIdCounter = 1;
+typedef struct SymmetricRoleEntry {
+ OicUuid_t subject; /**< Subject of the symmetric credential */
+ OicSecRole_t role; /**< Role of the symmetric credential */
-/**
+ struct SymmetricRoleEntry *next;
+} SymmetricRoleEntry_t;
+
+static OCResourceHandle gRolesHandle = NULL;
+static RolesEntry_t *gRoles = NULL;
+static SymmetricRoleEntry_t *gSymmetricRoles = NULL;
+static uint32_t gIdCounter = 1;
+
+/**
* Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
* The value of payload size is increased until reaching max cbor size.
*/
if ((NULL == sep.publicKey) || (0 == sep.publicKeyLength))
{
OIC_LOG_V(ERROR, TAG, "%s: Peer did not have a public key", __func__);
- return OC_STACK_ERROR;
+ return OC_STACK_INVALID_PARAM;
}
*publicKey = OICCalloc(1, sep.publicKeyLength);
}
}
+static void FreeSymmetricRoleEntry(SymmetricRoleEntry_t *symRoleEntry)
+{
+ OICFree(symRoleEntry);
+}
+
+static void FreeSymmetricRolesList(SymmetricRoleEntry_t *head)
+{
+ if (NULL != head)
+ {
+ SymmetricRoleEntry_t *entryTmp1 = NULL;
+ SymmetricRoleEntry_t *entryTmp2 = NULL;
+
+ LL_FOREACH_SAFE(head, entryTmp1, entryTmp2)
+ {
+ LL_DELETE(head, entryTmp1);
+ FreeSymmetricRoleEntry(entryTmp1);
+ }
+ }
+}
+
+OCStackResult RegisterSymmetricCredentialRole(const OicSecCred_t *cred)
+{
+ VERIFY_NON_NULL_RET(cred, TAG, "Parameter cred is NULL", OC_STACK_INVALID_PARAM);
+ VERIFY_SUCCESS_RETURN(TAG, (SYMMETRIC_PAIR_WISE_KEY == cred->credType), ERROR, OC_STACK_INVALID_PARAM);
+
+ SymmetricRoleEntry_t *curr = NULL;
+
+ LL_FOREACH(gSymmetricRoles, curr)
+ {
+ if (0 == memcmp(&cred->subject, &curr->subject, sizeof(curr->subject)))
+ {
+ if (!IsNonEmptyRole(&cred->roleId))
+ {
+ LL_DELETE(gSymmetricRoles, curr);
+ }
+ else
+ {
+ curr->role = cred->roleId;
+ }
+
+ return OC_STACK_OK;
+ }
+ }
+
+ /* No entry found; add a new one if we're setting a role. */
+ if (IsNonEmptyRole(&cred->roleId))
+ {
+ curr = (SymmetricRoleEntry_t *)OICCalloc(1, sizeof(SymmetricRoleEntry_t));
+ if (NULL == curr)
+ {
+ OIC_LOG(ERROR, TAG, "No memory allocating new symmetric role entry");
+ return OC_STACK_NO_MEMORY;
+ }
+ LL_APPEND(gSymmetricRoles, curr);
+ curr->subject = cred->subject;
+ curr->role = cred->roleId;
+ }
+
+ return OC_STACK_OK;
+}
+
static OCStackResult DuplicateRoleCertChain(const RoleCertChain_t *roleCert, RoleCertChain_t **duplicate)
{
OIC_LOG(DEBUG, TAG, "DuplicateRoleCertChain IN");
gRolesHandle = NULL;
FreeRolesList(gRoles);
+ FreeSymmetricRolesList(gSymmetricRoles);
gRoles = NULL;
{
/*
* OC_STACK_INVALID_PARAM means the endpoint didn't authenticate with a certificate.
- * Succeed and return no roles.
+ * Look for a symmetric key-based role and return that if present.
*/
+ CASecureEndpoint_t sep;
+ CAResult_t caRes = GetCASecureEndpointData(endpoint, &sep);
+ if (CA_STATUS_OK != caRes)
+ {
+ *roles = NULL;
+ *roleCount = 0;
+ return OC_STACK_OK;
+ }
+
+ SymmetricRoleEntry_t *curr = NULL;
+ LL_FOREACH(gSymmetricRoles, curr)
+ {
+ if ((UUID_LENGTH == sep.identity.id_length) &&
+ (0 == memcmp(curr->subject.id, sep.identity.id, sizeof(curr->subject.id))))
+ {
+ *roles = (OicSecRole_t *)OICCalloc(1, sizeof(OicSecRole_t));
+ if (NULL == *roles)
+ {
+ OIC_LOG(ERROR, TAG, "No memory allocating roles for symmetric credential");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ (*roles)[0] = curr->role;
+ *roleCount = 1;
+ return OC_STACK_OK;
+ }
+ }
+
+ /* No symmetric role found. Return empty list. */
*roles = NULL;
*roleCount = 0;
return OC_STACK_OK;
return NOT_A_SVR_RESOURCE;
}
+
+/**
+ * An unset role, used in comparisons.
+ */
+const OicSecRole_t EMPTY_ROLE = { .id = { 0 }, .authority = { 0 } };
+
+bool IsNonEmptyRole(const OicSecRole_t *role)
+{
+ return (0 != memcmp(&role->id, &EMPTY_ROLE.id, sizeof(role->id)));
+}
const char * OIC_JSON_SM_NAME = "sm";
const char * OIC_JSON_CREDID_NAME = "credid";
const char * OIC_JSON_SUBJECTID_NAME = "subjectuuid";
-const char * OIC_JSON_ROLEIDS_NAME = "roleid";
+const char * OIC_JSON_ROLEID_NAME = "roleid";
+const char * OIC_JSON_ROLE_NAME = "role";
const char * OIC_JSON_AUTHORITY_NAME = "authority";
const char * OIC_JSON_CREDTYPE_NAME = "credtype";
const char * OIC_JSON_PUBLICDATA_NAME = "publicdata";
OCProvisionCredentials
OCProvisionDirectPairing
OCProvisionPairwiseDevices
+OCProvisionSymmetricRoleCredentials
OCProvisionTrustCertChain
OCReadTrustCertChain
OCRegisterTrustCertChainNotifier