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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "oic_malloc.h"
23 #include "resourcemanager.h"
24 #include "securevirtualresourcetypes.h"
25 #include "srmresourcestrings.h"
28 #include "aclresource.h"
29 #include "amaclresource.h"
30 #include "srmutility.h"
32 #include "secureresourcemanager.h"
33 #include "doxmresource.h"
34 #include "policyengine.h"
35 #include "oic_string.h"
36 #include "caremotehandler.h"
39 #define TAG "SRM-AMSMGR"
42 //Callback for AMS service multicast discovery request.
43 static OCStackApplicationResult AmsMgrDiscoveryCallback(void *ctx, OCDoHandle handle,
44 OCClientResponse * clientResponse);
46 //Callback for unicast secured port discovery request.
47 static OCStackApplicationResult SecurePortDiscoveryCallback(void *ctx, OCDoHandle handle,
48 OCClientResponse * clientResponse);
50 //Callback for unicast ACL request
51 static OCStackApplicationResult AmsMgrAclReqCallback(void *ctx, OCDoHandle handle,
52 OCClientResponse * clientResponse);
55 OCStackResult DiscoverAmsService(PEContext_t *context)
57 OC_LOG(INFO, TAG, "IN DiscoverAmsService");
59 OCStackResult ret = OC_STACK_ERROR;
60 const char DOXM_DEVICEID_QUERY_FMT[] = "%s?%s=%s";
61 char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {};
62 OCCallbackData cbData = {.context=NULL};
63 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
67 VERIFY_NON_NULL(TAG, context, ERROR);
68 b64Ret = b64Encode(context->amsMgrContext->amsDeviceId.id,
69 sizeof(context->amsMgrContext->amsDeviceId.id), base64Buff, sizeof(base64Buff), &outLen);
70 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
71 snprintf(uri, sizeof(uri), DOXM_DEVICEID_QUERY_FMT, OIC_RSRC_DOXM_URI,
72 OIC_JSON_DEVICE_ID_NAME, base64Buff);
74 cbData.cb = &AmsMgrDiscoveryCallback;
75 cbData.context = (void*)context;
78 * If no good response was received for this discovery request,
79 * PE would be blocked forever waiting for AMS service to respond with the ACE.
80 * Need logic to reset the PE state and send ACCESS_DENIED response,
81 * when discovery response from AMS service is not received within certain time.
83 OC_LOG_V(INFO, TAG,"AMS Manager Sending Multicast Discovery with URI = %s", uri);
84 ret = OCDoResource(NULL, OC_REST_DISCOVER, uri, NULL, NULL,
85 CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
88 OC_LOG(INFO, TAG, "Leaving DiscoverAmsService");
93 static OCStackApplicationResult AmsMgrDiscoveryCallback(void *ctx, OCDoHandle handle,
94 OCClientResponse * clientResponse)
96 OC_LOG_V(INFO, TAG, "%s Begin", __func__ );
100 !clientResponse->payload||
101 (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)||
102 (OC_STACK_OK != clientResponse->result))
104 OC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
105 return OC_STACK_KEEP_TRANSACTION;
109 PEContext_t *context = (PEContext_t *) ctx;
110 if (context->state != AWAITING_AMS_RESPONSE)
112 OC_LOG_V(ERROR, TAG, "%s Invalid PE State ", __func__);
113 return OC_STACK_DELETE_TRANSACTION;
116 OicSecDoxm_t *doxm = NULL;
117 OC_LOG_V(INFO, TAG, "Doxm DeviceId Discovery response = %s\n",
118 ((OCSecurityPayload*)clientResponse->payload)->securityData);
119 doxm = JSONToDoxmBin(((OCSecurityPayload*)clientResponse->payload)->securityData);
121 //As doxm is NULL amsmgr can't test if response from trusted AMS service
122 //so keep the transaction.
125 OC_LOG_V(ERROR, TAG, "%s : Unable to convert JSON to Binary",__func__);
126 return OC_STACK_KEEP_TRANSACTION;
129 OicUuid_t deviceId = {.id={}};
130 memcpy(&deviceId, &doxm->deviceID, sizeof(deviceId));
133 /* TODO : By assuming that the first response received is the actual
134 * AMS service, a 'bad device' can cause DoS attack.
136 if (memcmp(&context->amsMgrContext->amsDeviceId, &deviceId,
137 sizeof(context->amsMgrContext->amsDeviceId)) == 0)
139 OC_LOG(INFO, TAG, "AMS Manager Sending unicast discovery to get secured port info");
140 //Sending Unicast discovery to get secure port information
141 if(OC_STACK_OK == SendUnicastSecurePortDiscovery(context, &clientResponse->devAddr,
142 clientResponse->connType))
144 context->retVal = ACCESS_WAITING_FOR_AMS;
145 return OC_STACK_DELETE_TRANSACTION;
148 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
149 SRMSendResponse(context->retVal);
150 return OC_STACK_DELETE_TRANSACTION;
154 OCStackResult SendUnicastSecurePortDiscovery(PEContext_t *context,OCDevAddr *devAddr,
155 OCConnectivityType connType)
157 OC_LOG(INFO, TAG, "IN SendUnicastSecurePortDiscovery");
159 const char RES_DOXM_QUERY_FMT[] = "%s?%s=%s";
160 OCCallbackData cbData = {.context=NULL};
161 char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {};
162 snprintf(uri, sizeof(uri), RES_DOXM_QUERY_FMT, OC_RSRVD_WELL_KNOWN_URI,
163 OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM);
165 cbData.cb = &SecurePortDiscoveryCallback;
166 cbData.context = context;
168 OC_LOG_V(INFO, TAG, "AMS Manager Sending Unicast Discovery with URI = %s", uri);
170 return OCDoResource(NULL, OC_REST_DISCOVER, uri, devAddr, NULL,
171 connType, OC_LOW_QOS, &cbData, NULL, 0);
174 static OCStackApplicationResult SecurePortDiscoveryCallback(void *ctx, OCDoHandle handle,
175 OCClientResponse * clientResponse)
177 OC_LOG(INFO, TAG, "In SecurePortDiscoveryCallback");
181 !clientResponse->payload||
182 (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)||
183 (OC_STACK_OK != clientResponse->result))
185 OC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
186 SRMSendResponse(ACCESS_DENIED_AMS_SERVICE_ERROR);
187 return OC_STACK_DELETE_TRANSACTION;
190 PEContext_t *context = (PEContext_t *) ctx;
193 if (context->state != AWAITING_AMS_RESPONSE)
195 OC_LOG_V(ERROR, TAG, "%s Invalid PE State ", __func__);
196 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
197 SRMSendResponse(context->retVal);
198 return OC_STACK_DELETE_TRANSACTION;
201 OCResourcePayload* resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
203 //Verifying if the ID of the sender is an AMS service that this device trusts.
205 memcmp(context->amsMgrContext->amsDeviceId.id, resPayload->sid,
206 sizeof(context->amsMgrContext->amsDeviceId.id)) != 0)
208 OC_LOG_V(ERROR, TAG, "%s Invalid AMS device", __func__);
209 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
210 SRMSendResponse(context->retVal);
211 return OC_STACK_DELETE_TRANSACTION;
214 if (resPayload && resPayload->secure)
216 if(OC_STACK_OK == SendAclReq(context, &clientResponse->devAddr, clientResponse->connType,
219 return OC_STACK_DELETE_TRANSACTION;
222 OC_LOG(INFO, TAG, "Can not find secure port information");
224 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
225 SRMSendResponse(context->retVal);
226 return OC_STACK_DELETE_TRANSACTION;
230 OCStackResult SendAclReq(PEContext_t *context, OCDevAddr *devAddr, OCConnectivityType connType,
231 uint16_t securedPort)
233 OCStackResult ret = OC_STACK_ERROR;
234 const char GET_ACE_QUERY_FMT[] = "%s?%s=%s;%s=%s";
235 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
237 char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {};
238 OCCallbackData cbData = {.context=NULL};
239 OCDevAddr destAddr = {.adapter = OC_ADAPTER_IP};
242 VERIFY_NON_NULL(TAG, context, ERROR);
243 VERIFY_NON_NULL(TAG, devAddr, ERROR);
245 b64Ret = b64Encode(context->subject.id, sizeof(context->subject.id),
246 base64Buff, sizeof(base64Buff), &outLen);
247 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
249 snprintf(uri, sizeof(uri), GET_ACE_QUERY_FMT, OIC_RSRC_ACL_URI,
250 OIC_JSON_SUBJECT_NAME, base64Buff,
251 OIC_JSON_RESOURCES_NAME, context->resource);
253 cbData.cb = &AmsMgrAclReqCallback;
254 cbData.context = context;
258 destAddr.flags = (OCTransportFlags)(destAddr.flags | OC_FLAG_SECURE);
259 destAddr.port = securedPort;
261 OC_LOG_V(INFO, TAG, "AMS Manager Sending Unicast ACL request with URI = %s", uri);
262 ret = OCDoResource(NULL, OC_REST_GET, uri, &destAddr, NULL,
263 connType, OC_LOW_QOS, &cbData, NULL, 0);
266 OC_LOG_V(INFO, TAG, "%s returns %d ", __func__, ret);
271 static OCStackApplicationResult AmsMgrAclReqCallback(void *ctx, OCDoHandle handle,
272 OCClientResponse * clientResponse)
274 OC_LOG_V(INFO, TAG, "%s Begin", __func__ );
277 PEContext_t *context = (PEContext_t *) ctx;
278 SRMAccessResponse_t rsps;
282 !clientResponse->payload||
283 (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type) ||
284 (clientResponse->result != OC_STACK_OK))
286 OC_LOG_V(ERROR, TAG, "%s Invalid Response ", __func__);
287 SRMSendResponse(ACCESS_DENIED_AMS_SERVICE_ERROR);
288 return OC_STACK_DELETE_TRANSACTION;
291 if (context->state != AWAITING_AMS_RESPONSE)
293 OC_LOG_V(ERROR, TAG, "%s Invalid State ", __func__);
294 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
295 SRMSendResponse(context->retVal);
296 return OC_STACK_DELETE_TRANSACTION;
299 // Verify before installing ACL if the ID of the sender of this ACL is an AMS
300 //service that this device trusts.
301 rsps = ACCESS_DENIED;
302 if((UUID_LENGTH == clientResponse->identity.id_length) &&
303 memcmp(context->amsMgrContext->amsDeviceId.id, clientResponse->identity.id,
304 sizeof(context->amsMgrContext->amsDeviceId.id)) == 0)
307 InstallNewACL(((OCSecurityPayload*)clientResponse->payload)->securityData);
308 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
310 OC_LOG_V(INFO, TAG, "%s : Calling checkPermission", __func__);
311 rsps = CheckPermission(context, &context->subject, context->resource, context->permission);
312 VERIFY_SUCCESS(TAG, (true == IsAccessGranted(rsps)), ERROR);
314 OC_LOG_V(INFO, TAG, "%sAccess granted, Calling SRMCallCARequestHandler", __func__);
315 context->retVal = ACCESS_GRANTED;
316 SRMSendResponse(context->retVal);
317 return OC_STACK_DELETE_TRANSACTION;
321 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
322 SRMSendResponse(context->retVal);
323 return OC_STACK_DELETE_TRANSACTION;
327 OCStackResult UpdateAmsMgrContext(PEContext_t *context, const CAEndpoint_t *endpoint,
328 const CARequestInfo_t *requestInfo)
330 OCStackResult ret = OC_STACK_ERROR;
332 //The AmsMgr context endpoint and requestInfo will be free from ,
333 //AmsMgrAclReqCallback function
334 if(context->amsMgrContext->endpoint)
336 OICFree(context->amsMgrContext->endpoint);
337 context->amsMgrContext->endpoint = NULL;
339 context->amsMgrContext->endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof(CAEndpoint_t ));
340 VERIFY_NON_NULL(TAG, context->amsMgrContext->endpoint, ERROR);
341 *context->amsMgrContext->endpoint = *endpoint;
343 if(context->amsMgrContext->requestInfo)
345 FreeCARequestInfo(context->amsMgrContext->requestInfo);
346 context->amsMgrContext->requestInfo = NULL;
348 context->amsMgrContext->requestInfo = CACloneRequestInfo(requestInfo);
349 VERIFY_NON_NULL(TAG, context->amsMgrContext->requestInfo, ERROR);
355 void FreeCARequestInfo(CARequestInfo_t *requestInfo)
357 if(NULL == requestInfo)
359 OC_LOG_V(ERROR, TAG, "%s: Can't free memory. Received NULL requestInfo", __func__);
362 OICFree(requestInfo->info.token);
363 OICFree(requestInfo->info.options);
364 OICFree(requestInfo->info.payload);
365 OICFree(requestInfo->info.resourceUri);
366 OICFree(requestInfo);
370 //This method checks for Amacl resource. If Amacl is found then it fills up
371 //context->amsMgrContext->amsDeviceId with amsID of the Amacl else leaves it empty.
372 bool FoundAmaclForRequest(PEContext_t *context)
374 OC_LOG_V(INFO, TAG, "%s:no ACL found. Searching for AMACL",__func__);
377 VERIFY_NON_NULL(TAG, context, ERROR);
378 memset(&context->amsMgrContext->amsDeviceId, 0, sizeof(context->amsMgrContext->amsDeviceId));
380 //Call amacl resource function to get the AMS service deviceID for the resource
381 if(OC_STACK_OK == AmaclGetAmsDeviceId(context->resource, &context->amsMgrContext->amsDeviceId))
383 OC_LOG_V(INFO, TAG, "%s:AMACL found for the requested resource %s",
384 __func__, context->resource);
389 OC_LOG_V(INFO, TAG, "%s:AMACL found for the requested resource %s",
390 __func__, context->resource);
399 void ProcessAMSRequest(PEContext_t *context)
401 OicUuid_t emptyUuid = {.id={}};
402 OC_LOG_V(INFO, TAG, "Entering %s", __func__);
405 if((false == context->matchingAclFound) && (false == context->amsProcessing))
407 context->amsProcessing = true;
409 //Checking if context AMS deviceId is empty
410 if(memcmp(&context->amsMgrContext->amsDeviceId, &emptyUuid, sizeof(OicUuid_t)) != 0 )
412 if(OC_STACK_OK == DiscoverAmsService(context))
414 context->retVal = ACCESS_WAITING_FOR_AMS;
415 context->state = AWAITING_AMS_RESPONSE;
419 context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
426 OC_LOG_V(INFO, TAG, "Leaving %s(context is NULL)", __func__);
429 if(ACCESS_WAITING_FOR_AMS == context->retVal )
431 OC_LOG_V(INFO, TAG, "Leaving %s(WAITING_FOR_AMS)", __func__);