1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 #include "oic_malloc.h"
24 #include "resourcemanager.h"
25 #include "securevirtualresourcetypes.h"
26 #include "srmresourcestrings.h"
29 #include "aclresource.h"
30 #include "amaclresource.h"
31 #include "srmutility.h"
33 #include "secureresourcemanager.h"
34 #include "doxmresource.h"
35 #include "policyengine.h"
36 #include "oic_string.h"
37 #include "caremotehandler.h"
39 #define TAG "OIC_SRM_AMSMGR"
41 //Callback for AMS service multicast discovery request.
42 static OCStackApplicationResult AmsMgrDiscoveryCallback(void *ctx, OCDoHandle handle,
43 OCClientResponse * clientResponse);
45 //Callback for unicast secured port discovery request.
46 static OCStackApplicationResult SecurePortDiscoveryCallback(void *ctx, OCDoHandle handle,
47 OCClientResponse * clientResponse);
49 //Callback for unicast ACL request
50 static OCStackApplicationResult AmsMgrAclReqCallback(void *ctx, OCDoHandle handle,
51 OCClientResponse * clientResponse);
53 OCStackResult DiscoverAmsService(PEContext_t *context)
55 OIC_LOG(INFO, TAG, "IN DiscoverAmsService");
57 OCStackResult ret = OC_STACK_ERROR;
58 const char DOXM_DEVICEID_QUERY_FMT[] = "%s?%s=%s";
59 char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
60 OCCallbackData cbData = {.context=NULL};
62 VERIFY_NON_NULL(TAG, context, ERROR);
63 snprintf(uri, sizeof(uri), DOXM_DEVICEID_QUERY_FMT, OIC_RSRC_DOXM_URI,
64 OIC_JSON_DEVICE_ID_NAME,
65 context->amsMgrContext->amsDeviceId.id);
67 cbData.cb = &AmsMgrDiscoveryCallback;
68 cbData.context = (void*)context;
71 * If no good response was received for this discovery request,
72 * PE would be blocked forever waiting for AMS service to respond with the ACE.
73 * Need logic to reset the PE state and send ACCESS_DENIED response,
74 * when discovery response from AMS service is not received within certain time.
76 OIC_LOG_V(INFO, TAG,"AMS Manager Sending Multicast Discovery with URI = %s", uri);
77 ret = OCDoResource(NULL, OC_REST_DISCOVER, uri, NULL, NULL,
78 CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
81 OIC_LOG(INFO, TAG, "Leaving DiscoverAmsService");
85 static OCStackApplicationResult AmsMgrDiscoveryCallback(void *ctx, OCDoHandle handle,
86 OCClientResponse * clientResponse)
88 OIC_LOG_V(INFO, TAG, "%s Begin", __func__ );
92 !clientResponse->payload||
93 (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)||
94 (OC_STACK_OK != clientResponse->result))
96 OIC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
97 return OC_STACK_KEEP_TRANSACTION;
101 PEContext_t *context = (PEContext_t *) ctx;
102 if (context->state != AWAITING_AMS_RESPONSE)
104 OIC_LOG_V(ERROR, TAG, "%s Invalid PE State ", __func__);
105 return OC_STACK_DELETE_TRANSACTION;
108 OicSecDoxm_t *doxm = NULL;
110 OIC_LOG_V(INFO, TAG, "Doxm DeviceId Discovery response = %s\n",
111 ((OCSecurityPayload*)clientResponse->payload)->securityData);
112 uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
113 size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
115 //As doxm is NULL amsmgr can't test if response from trusted AMS service
116 //so keep the transaction.
117 if (OC_STACK_OK == CBORPayloadToDoxm(payload, size, &doxm))
119 OIC_LOG_V(ERROR, TAG, "%s : Unable to convert CBOR to Binary",__func__);
120 return OC_STACK_KEEP_TRANSACTION;
123 OicUuid_t deviceId = {.id={0}};
124 memcpy(&deviceId, &doxm->deviceID, sizeof(deviceId));
125 DeleteDoxmBinData(doxm);
127 /* TODO : By assuming that the first response received is the actual
128 * AMS service, a 'bad device' can cause DoS attack.
130 if (memcmp(&context->amsMgrContext->amsDeviceId, &deviceId,
131 sizeof(context->amsMgrContext->amsDeviceId)) == 0)
133 OIC_LOG(INFO, TAG, "AMS Manager Sending unicast discovery to get secured port info");
134 //Sending Unicast discovery to get secure port information
135 if (OC_STACK_OK == SendUnicastSecurePortDiscovery(context, &clientResponse->devAddr,
136 clientResponse->connType))
138 context->retVal = ACCESS_WAITING_FOR_AMS;
139 return OC_STACK_DELETE_TRANSACTION;
142 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
143 SRMSendResponse(context->retVal);
144 return OC_STACK_DELETE_TRANSACTION;
147 OCStackResult SendUnicastSecurePortDiscovery(PEContext_t *context,OCDevAddr *devAddr,
148 OCConnectivityType connType)
150 OIC_LOG(INFO, TAG, "IN SendUnicastSecurePortDiscovery");
152 const char RES_DOXM_QUERY_FMT[] = "%s?%s=%s";
153 OCCallbackData cbData = {.context=NULL};
154 char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
155 snprintf(uri, sizeof(uri), RES_DOXM_QUERY_FMT, OC_RSRVD_WELL_KNOWN_URI,
156 OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM);
158 cbData.cb = &SecurePortDiscoveryCallback;
159 cbData.context = context;
161 OIC_LOG_V(INFO, TAG, "AMS Manager Sending Unicast Discovery with URI = %s", uri);
163 return OCDoResource(NULL, OC_REST_DISCOVER, uri, devAddr, NULL,
164 connType, OC_LOW_QOS, &cbData, NULL, 0);
167 static OCStackApplicationResult SecurePortDiscoveryCallback(void *ctx, OCDoHandle handle,
168 OCClientResponse * clientResponse)
170 OIC_LOG(INFO, TAG, "In SecurePortDiscoveryCallback");
174 !clientResponse->payload||
175 (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)||
176 (OC_STACK_OK != clientResponse->result))
178 OIC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
179 SRMSendResponse(ACCESS_DENIED_AMS_SERVICE_ERROR);
180 return OC_STACK_DELETE_TRANSACTION;
183 PEContext_t *context = (PEContext_t *) ctx;
186 if (context->state != AWAITING_AMS_RESPONSE)
188 OIC_LOG_V(ERROR, TAG, "%s Invalid PE State ", __func__);
189 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
190 SRMSendResponse(context->retVal);
191 return OC_STACK_DELETE_TRANSACTION;
194 OCResourcePayload *resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
196 //Verifying if the ID of the sender is an AMS service that this device trusts.
198 memcmp(context->amsMgrContext->amsDeviceId.id,
199 ((OCDiscoveryPayload*)clientResponse->payload)->sid,
201 sizeof(context->amsMgrContext->amsDeviceId.id)) != 0)
203 OIC_LOG_V(ERROR, TAG, "%s Invalid AMS device", __func__);
204 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
205 SRMSendResponse(context->retVal);
206 return OC_STACK_DELETE_TRANSACTION;
209 if (resPayload && resPayload->secure)
211 if(OC_STACK_OK == SendAclReq(context, &clientResponse->devAddr, clientResponse->connType,
214 return OC_STACK_DELETE_TRANSACTION;
217 OIC_LOG(INFO, TAG, "Can not find secure port information");
219 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
220 SRMSendResponse(context->retVal);
221 return OC_STACK_DELETE_TRANSACTION;
224 OCStackResult SendAclReq(PEContext_t *context, OCDevAddr *devAddr, OCConnectivityType connType,
225 uint16_t securedPort)
227 OCStackResult ret = OC_STACK_ERROR;
228 const char GET_ACE_QUERY_FMT[] = "%s?%s=%s;%s=%s";
229 char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
230 OCCallbackData cbData = {.context=NULL};
231 OCDevAddr destAddr = {.adapter = OC_ADAPTER_IP};
234 VERIFY_NON_NULL(TAG, context, ERROR);
235 VERIFY_NON_NULL(TAG, devAddr, ERROR);
237 ret = ConvertUuidToStr(&context->subject, &subID);
238 if(OC_STACK_OK != ret)
240 OIC_LOG(ERROR, TAG, "SendAclReq : Failed to canonical UUID encoding");
241 return OC_STACK_ERROR;
244 snprintf(uri, sizeof(uri), GET_ACE_QUERY_FMT, OIC_RSRC_ACL_URI,
245 OIC_JSON_SUBJECTID_NAME, subID,
246 OIC_JSON_RESOURCES_NAME, context->resource);
249 cbData.cb = &AmsMgrAclReqCallback;
250 cbData.context = context;
254 destAddr.flags = (OCTransportFlags)(destAddr.flags | OC_FLAG_SECURE);
255 destAddr.port = securedPort;
257 OIC_LOG_V(INFO, TAG, "AMS Manager Sending Unicast ACL request with URI = %s", uri);
258 ret = OCDoResource(NULL, OC_REST_GET, uri, &destAddr, NULL,
259 connType, OC_LOW_QOS, &cbData, NULL, 0);
262 OIC_LOG_V(INFO, TAG, "%s returns %d ", __func__, ret);
266 static OCStackApplicationResult AmsMgrAclReqCallback(void *ctx, OCDoHandle handle,
267 OCClientResponse * clientResponse)
269 OIC_LOG_V(INFO, TAG, "%s Begin", __func__ );
272 PEContext_t *context = (PEContext_t *) ctx;
273 SRMAccessResponse_t rsps;
277 !clientResponse->payload||
278 (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type) ||
279 (clientResponse->result != OC_STACK_OK))
281 OIC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
282 SRMSendResponse(ACCESS_DENIED_AMS_SERVICE_ERROR);
283 return OC_STACK_DELETE_TRANSACTION;
286 if (context->state != AWAITING_AMS_RESPONSE)
288 OIC_LOG_V(ERROR, TAG, "%s Invalid State ", __func__);
289 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
290 SRMSendResponse(context->retVal);
291 return OC_STACK_DELETE_TRANSACTION;
294 // Verify before installing ACL if the ID of the sender of this ACL is an AMS
295 //service that this device trusts.
296 rsps = ACCESS_DENIED;
297 if((UUID_LENGTH == clientResponse->identity.id_length) &&
298 memcmp(context->amsMgrContext->amsDeviceId.id, clientResponse->identity.id,
299 sizeof(context->amsMgrContext->amsDeviceId.id)) == 0)
301 size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
303 AppendACL(((OCSecurityPayload*)clientResponse->payload)->securityData, size);
304 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
306 OIC_LOG_V(INFO, TAG, "%s : Calling checkPermission", __func__);
307 rsps = CheckPermission(context, &context->subject, context->resource, context->permission);
308 VERIFY_SUCCESS(TAG, (true == IsAccessGranted(rsps)), ERROR);
310 OIC_LOG_V(INFO, TAG, "%sAccess granted, Calling SRMCallCARequestHandler", __func__);
311 context->retVal = ACCESS_GRANTED;
312 SRMSendResponse(context->retVal);
313 return OC_STACK_DELETE_TRANSACTION;
317 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
318 SRMSendResponse(context->retVal);
319 return OC_STACK_DELETE_TRANSACTION;
322 OCStackResult UpdateAmsMgrContext(PEContext_t *context, const CAEndpoint_t *endpoint,
323 const CARequestInfo_t *requestInfo)
325 OCStackResult ret = OC_STACK_INVALID_PARAM;
326 VERIFY_NON_NULL(TAG, context->amsMgrContext, ERROR);
327 ret = OC_STACK_ERROR;
329 //The AmsMgr context endpoint and requestInfo will be free from ,
330 //AmsMgrAclReqCallback function
331 if (context->amsMgrContext->endpoint)
333 OICFree(context->amsMgrContext->endpoint);
334 context->amsMgrContext->endpoint = NULL;
336 context->amsMgrContext->endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof(CAEndpoint_t ));
337 VERIFY_NON_NULL(TAG, context->amsMgrContext->endpoint, ERROR);
338 *context->amsMgrContext->endpoint = *endpoint;
340 if (context->amsMgrContext->requestInfo)
342 FreeCARequestInfo(context->amsMgrContext->requestInfo);
343 context->amsMgrContext->requestInfo = NULL;
345 context->amsMgrContext->requestInfo = CACloneRequestInfo(requestInfo);
346 VERIFY_NON_NULL(TAG, context->amsMgrContext->requestInfo, ERROR);
352 void FreeCARequestInfo(CARequestInfo_t *requestInfo)
354 if (NULL == requestInfo)
356 OIC_LOG_V(DEBUG, TAG, "%s: Can't free memory. Received NULL requestInfo", __func__);
359 OICFree(requestInfo->info.token);
360 OICFree(requestInfo->info.options);
361 OICFree(requestInfo->info.payload);
362 OICFree(requestInfo->info.resourceUri);
363 OICFree(requestInfo);
367 //This method checks for Amacl resource. If Amacl is found then it fills up
368 //context->amsMgrContext->amsDeviceId with amsID of the Amacl else leaves it empty.
369 bool FoundAmaclForRequest(PEContext_t *context)
371 OIC_LOG_V(INFO, TAG, "%s:no ACL found. Searching for AMACL",__func__);
374 VERIFY_NON_NULL(TAG, context, ERROR);
375 memset(&context->amsMgrContext->amsDeviceId, 0, sizeof(context->amsMgrContext->amsDeviceId));
377 //Call amacl resource function to get the AMS service deviceID for the resource
378 if (OC_STACK_OK == AmaclGetAmsDeviceId(context->resource, &context->amsMgrContext->amsDeviceId))
380 OIC_LOG_V(INFO, TAG, "%s:AMACL found for the requested resource %s",
381 __func__, context->resource);
386 OIC_LOG_V(INFO, TAG, "%s:AMACL found for the requested resource %s",
387 __func__, context->resource);
395 void ProcessAMSRequest(PEContext_t *context)
397 OicUuid_t emptyUuid = {.id={0}};
398 OIC_LOG_V(INFO, TAG, "Entering %s", __func__);
401 if((ACCESS_GRANTED != context->retVal) && (false == context->amsProcessing))
403 context->amsProcessing = true;
405 //Checking if context AMS deviceId is empty
406 if(memcmp(&context->amsMgrContext->amsDeviceId, &emptyUuid, sizeof(OicUuid_t)) != 0 )
408 if(OC_STACK_OK == DiscoverAmsService(context))
410 context->retVal = ACCESS_WAITING_FOR_AMS;
411 OIC_LOG_V(INFO, TAG, "Leaving %s(WAITING_FOR_AMS)", __func__);
412 context->state = AWAITING_AMS_RESPONSE;
416 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
423 OIC_LOG_V(INFO, TAG, "Leaving %s(context is NULL)", __func__);