resource-container: Install unit tests
[iotivity.git] / resource / csdk / security / src / srmutility.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #define _POSIX_C_SOURCE 200112L
21 #include <string.h>
22
23 #include "srmutility.h"
24 #include "srmresourcestrings.h"
25 #include "experimental/logger.h"
26 #include "oic_malloc.h"
27 #include "experimental/ocrandom.h"
28 #include "experimental/doxmresource.h"
29
30 #define TAG  "OIC_SRM_UTILITY"
31
32 void ParseQueryIterInit(const unsigned char * query, OicParseQueryIter_t * parseIter)
33 {
34     OIC_LOG(INFO, TAG, "Initializing coap iterator");
35     if ((NULL == query) || (NULL == parseIter))
36     {
37         return;
38     }
39
40     parseIter->attrPos = NULL;
41     parseIter->attrLen = 0;
42     parseIter->valPos = NULL;
43     parseIter->valLen = 0;
44     coap_parse_iterator_init((unsigned char *)query, strlen((char *)query),
45                              (unsigned char *)OIC_SEC_REST_QUERY_SEPARATOR,
46                              (unsigned char *) "", 0, &parseIter->pi);
47 }
48
49 OicParseQueryIter_t * GetNextQuery(OicParseQueryIter_t * parseIter)
50 {
51     OIC_LOG(INFO, TAG, "Getting Next Query");
52     if (NULL == parseIter)
53     {
54         return NULL;
55     }
56
57     unsigned char * qrySeg = NULL;
58     char * delimPos;
59
60     // Get the next query. Querys are separated by OIC_SEC_REST_QUERY_SEPARATOR.
61     qrySeg = coap_parse_next(&parseIter->pi);
62
63     if (qrySeg)
64     {
65         delimPos = strchr((char *)qrySeg, OIC_SEC_REST_QUERY_DELIMETER);
66         if (delimPos)
67         {
68             parseIter->attrPos = parseIter->pi.pos;
69             parseIter->attrLen = (unsigned char *)delimPos - parseIter->pi.pos;
70             parseIter->valPos  = (unsigned char *)delimPos + 1;
71             parseIter->valLen  = &qrySeg[parseIter->pi.segment_length] - parseIter->valPos;
72             return parseIter;
73         }
74     }
75     return NULL;
76 }
77
78 /**
79  * Function to getting string of ownership transfer method
80  *
81  * @prarm oxmType ownership transfer method
82  *
83  * @return string value of ownership transfer method
84  */
85 const char* GetOxmString(OicSecOxm_t oxmType)
86 {
87     switch(oxmType)
88     {
89         case OIC_JUST_WORKS:
90             return OXM_JUST_WORKS;
91         case OIC_RANDOM_DEVICE_PIN:
92             return OXM_RANDOM_DEVICE_PIN;
93         case OIC_MANUFACTURER_CERTIFICATE:
94             return OXM_MANUFACTURER_CERTIFICATE;
95 #ifdef MULTIPLE_OWNER
96         case OIC_PRECONFIG_PIN:
97             return OXM_PRECONF_PIN;
98 #endif //MULTIPLE_OWNER
99         case OIC_MV_JUST_WORKS:
100             return OXM_MV_JUST_WORKS;
101         case OIC_CON_MFG_CERT:
102             return OXM_CON_MFG_CERT;
103         default:
104             return NULL;
105     }
106 }
107
108 OCStackResult ConvertUuidToStr(const OicUuid_t* uuid, char** strUuid)
109 {
110     if(NULL == uuid || NULL == strUuid || NULL != *strUuid)
111     {
112         OIC_LOG(ERROR, TAG, "ConvertUuidToStr : Invalid param");
113         return OC_STACK_INVALID_PARAM;
114     }
115
116     const size_t urnBufSize = (UUID_LENGTH * 2) + 4 + 1;
117     char* convertedUrn = (char*)OICCalloc(urnBufSize, sizeof(char));
118     VERIFY_NOT_NULL(TAG, convertedUrn, ERROR);
119     if(OCConvertUuidToString(uuid->id,convertedUrn))
120     {
121         *strUuid = convertedUrn;
122         return OC_STACK_OK;
123     }
124
125     return OC_STACK_INVALID_PARAM;
126
127 exit:
128     return OC_STACK_NO_MEMORY;
129 }
130
131 OCStackResult OC_CALL ConvertStrToUuid(const char* strUuid, OicUuid_t* uuid)
132 {
133     bool result = true;
134     size_t strUuidLen = strlen(strUuid);
135
136     if (0 == strUuidLen)
137     {
138         OIC_LOG(INFO, TAG, "Converting empty UUID string to 00000000-0000-0000-0000-000000000000");
139         memset(uuid->id, 0, sizeof(uuid->id));
140     }
141     else
142     {
143         result = OCConvertStringToUuid(strUuid, uuid->id);
144     }
145
146     if (!result)
147     {
148         OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter '%s'", __func__, strUuid);
149         return OC_STACK_INVALID_PARAM;
150     }
151
152     return OC_STACK_OK;
153 }
154
155 #ifndef NDEBUG
156 /**
157  * Log OicUuid_t structs.
158  */
159 void LogUuid(const OicUuid_t* uuid)
160 {
161     if(NULL == uuid)
162     {
163         OIC_LOG(ERROR, TAG, "ConvertUuidToStr : Invalid param");
164         return;
165     }
166
167     const size_t urnBufSize = (UUID_LENGTH * 2) + 4 + 1;
168     char* convertedUrn = (char*)OICCalloc(urnBufSize, sizeof(char));
169     VERIFY_NOT_NULL(TAG, convertedUrn, ERROR);
170     if(OCConvertUuidToString(uuid->id,convertedUrn))
171     {
172         OIC_LOG_V(DEBUG, TAG, "uuid: %s", convertedUrn);
173     }
174     OICFree(convertedUrn);
175 exit:
176     return;
177 }
178 #endif
179
180 /**
181  * Compares two OicUuid_t structs.
182  *
183  * @return true if the two OicUuid_t structs are equal, else false.
184  */
185 bool UuidCmp(const OicUuid_t *firstId, const OicUuid_t *secondId)
186 {
187     bool ret = false;
188     VERIFY_NOT_NULL(TAG, firstId, ERROR);
189     VERIFY_NOT_NULL(TAG, secondId, ERROR);
190
191     if (0 == memcmp(firstId, secondId, sizeof(OicUuid_t)))
192     {
193         ret = true;
194     }
195
196 exit:
197     OIC_LOG_V(DEBUG, TAG, "%s: returning %s.", __func__, ret?"true":"false");
198     return ret;
199 }
200
201 const OicUuid_t THE_NIL_UUID = {.id={0000000000000000}};
202
203 /**
204  * Compares OicUuid_t to Nil UUID {.id={0000000000000000}}
205  *
206  * @return true if the OicUuid_t is the Nil UUID.
207  */
208 bool IsNilUuid(const OicUuid_t *uuid)
209 {
210 #if !defined(NDEBUG)
211     char *strUuid = NULL;
212     ConvertUuidToStr(uuid, &strUuid);
213     if (strUuid)
214     {
215         OIC_LOG_V(DEBUG, TAG, "%s: uuid: %s.", __func__, strUuid);
216         OICFree(strUuid);
217     }
218 #endif
219     return UuidCmp(uuid, &THE_NIL_UUID);
220 }
221
222 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
223 OCStackResult OC_CALL SetDeviceIdSeed(const uint8_t* seed, size_t seedSize)
224 {
225     return SetDoxmDeviceIDSeed(seed, seedSize);
226 }
227 #endif
228
229 bool SRMIsSecurityResourceURI(const char* uri)
230 {
231     if (!uri)
232     {
233         return false;
234     }
235
236 #ifdef _MSC_VER
237     // The strings below are const but they are also marked as extern so they cause warnings.
238 #pragma warning(push)
239 #pragma warning(disable:4204)
240 #endif
241     const char *rsrcs[] = {
242         OIC_RSRC_SVC_URI,
243         OIC_RSRC_AMACL_URI,
244         OIC_RSRC_CRL_URI,
245         OIC_RSRC_CRED_URI,
246         OIC_RSRC_SP_URI,
247         OIC_RSRC_CSR_URI,
248         OIC_RSRC_ACL_URI,
249         OIC_RSRC_ACL2_URI,
250         OIC_RSRC_DOXM_URI,
251         OIC_RSRC_PSTAT_URI,
252         OIC_RSRC_VER_URI,
253         OIC_RSRC_ROLES_URI,
254         OC_RSRVD_PROV_CRL_URL
255     };
256
257 #ifdef _MSC_VER
258 #pragma warning(pop)
259 #endif
260
261     // Remove query from Uri for resource string comparison
262     size_t uriLen = strlen(uri);
263     char *query = strchr (uri, '?');
264     if (query)
265     {
266         uriLen = query - uri;
267     }
268
269     for (size_t i = 0; i < sizeof(rsrcs)/sizeof(rsrcs[0]); i++)
270     {
271         size_t svrLen = strlen(rsrcs[i]);
272
273         if ((uriLen == svrLen) &&
274             (strncmp(uri, rsrcs[i], svrLen) == 0))
275         {
276             OIC_LOG_V(INFO, TAG, "%s: resource %s is SVR.", __func__, uri);
277             return true;
278         }
279     }
280
281     return false;
282 }
283
284 /**
285  * return true IFF the uri is for a DCR as defined by Security Specification.
286  */
287 bool IsDeviceConfigurationResourceUri(const char *uri)
288 {
289     if (!uri)
290     {
291         return false;
292     }
293
294     if (SRMIsSecurityResourceURI(uri))
295     {
296         return true;
297     }
298
299 #ifdef _MSC_VER
300     // The strings below are const but they are also marked as extern so they cause warnings.
301 #pragma warning(push)
302 #pragma warning(disable:4204)
303 #endif
304     const char *rsrcs[] = {
305         OC_RSRVD_DEVICE_URI,
306         OC_RSRVD_PLATFORM_URI,
307         OC_RSRVD_WELL_KNOWN_URI
308         // TODO [IOT-3006]: add WES resources as needed to enable easy setup use cases
309         // TODO [IOT-3006]: add CNC resources as needed to enable CNC use cases
310     };
311
312 #ifdef _MSC_VER
313 #pragma warning(pop)
314 #endif
315
316     // Remove query from Uri for resource string comparison
317     size_t uriLen = strlen(uri);
318     char *query = strchr (uri, '?');
319     if (query)
320     {
321         uriLen = query - uri;
322     }
323
324     for (size_t i = 0; i < sizeof(rsrcs)/sizeof(rsrcs[0]); i++)
325     {
326         size_t svrLen = strlen(rsrcs[i]);
327
328         if ((uriLen == svrLen) &&
329             (strncmp(uri, rsrcs[i], svrLen) == 0))
330         {
331             OIC_LOG_V(INFO, TAG, "%s: resource %s is DCR.", __func__, uri);
332             return true;
333         }
334     }
335
336     OIC_LOG_V(INFO, TAG, "%s: resource %s is not DCR => resource is NCR.", __func__, uri);
337     return false;
338 }
339
340 /**
341  * Is the URI for a Non0Configuration Resource as defined
342  * by Security Specification.
343  *
344  * @return true IFF the uri is for a NCR
345  */
346 bool IsNonConfigurationResourceUri(const char *uri)
347 {
348     return !IsDeviceConfigurationResourceUri(uri);
349 }