Add direct-pairing feature
[platform/upstream/iotivity.git] / resource / csdk / security / src / psinterface.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
21 #include "ocstack.h"
22 #include "logger.h"
23 #include "oic_malloc.h"
24 #include "cJSON.h"
25 #include "cainterface.h"
26 #include "secureresourcemanager.h"
27 #include "resourcemanager.h"
28 #include "srmresourcestrings.h"
29 #include "srmutility.h"
30 #include <stdlib.h>
31 #include <string.h>
32
33 #define TAG  "SRM-PSI"
34
35 //SVR database buffer block size
36 const size_t DB_FILE_SIZE_BLOCK = 1023;
37
38 /**
39  * Gets the Secure Virtual Database size.
40  *
41  * @param ps  pointer of OCPersistentStorage for the SVR name ("acl", "cred", "pstat" etc).
42  *
43  * @retval  total size of the SVR database.
44  */
45 size_t GetSVRDatabaseSize(OCPersistentStorage* ps)
46 {
47     size_t size = 0;
48     if (!ps)
49     {
50         return size;
51     }
52     size_t bytesRead  = 0;
53     char buffer[DB_FILE_SIZE_BLOCK];
54     FILE* fp = ps->open(SVR_DB_FILE_NAME, "r");
55     if (fp)
56     {
57         do
58         {
59             bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
60             size += bytesRead;
61         } while (bytesRead > 0);
62         ps->close(fp);
63     }
64     return size;
65 }
66
67 /**
68  * Reads the Secure Virtual Database from PS into dynamically allocated
69  * memory buffer.
70  *
71  * @note Caller of this method MUST use OICFree() method to release memory
72  *       referenced by return value.
73  *
74  * @retval  reference to memory buffer containing SVR database.
75  */
76 char * GetSVRDatabase()
77 {
78     char * jsonStr = NULL;
79     FILE * fp = NULL;
80     OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
81     int size = GetSVRDatabaseSize(ps);
82     if (0 == size)
83     {
84         OIC_LOG (ERROR, TAG, "FindSVRDatabaseSize failed");
85         return NULL;
86     }
87
88     if (ps && ps->open)
89     {
90         // Open default SRM database file. An app could change the path for its server.
91         fp = ps->open(SVR_DB_FILE_NAME, "r");
92         if (fp)
93         {
94             jsonStr = (char*)OICMalloc(size + 1);
95             VERIFY_NON_NULL(TAG, jsonStr, FATAL);
96             size_t bytesRead = ps->read(jsonStr, 1, size, fp);
97             jsonStr[bytesRead] = '\0';
98
99             OIC_LOG_V(DEBUG, TAG, "Read %zu bytes from SVR database file", bytesRead);
100             ps->close(fp);
101             fp = NULL;
102         }
103         else
104         {
105             OIC_LOG (ERROR, TAG, "Unable to open SVR database file!!");
106         }
107     }
108
109 exit:
110     if (ps && fp)
111     {
112         ps->close(fp);
113     }
114     return jsonStr;
115 }
116
117
118 /**
119  * This method is used by a entity handlers of SVR's to update
120  * SVR database.
121  *
122  * @param rsrcName string denoting the SVR name ("acl", "cred", "pstat" etc).
123  * @param jsonObj JSON object containing the SVR contents.
124  *
125  * @retval  OC_STACK_OK for Success, otherwise some error value
126  */
127 OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
128 {
129     OCStackResult ret = OC_STACK_ERROR;
130     cJSON *jsonSVRDb = NULL;
131     OCPersistentStorage* ps = NULL;
132
133     // Read SVR database from PS
134     char* jsonSVRDbStr = GetSVRDatabase();
135     VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
136
137     // Use cJSON_Parse to parse the existing SVR database
138     jsonSVRDb = cJSON_Parse(jsonSVRDbStr);
139     VERIFY_NON_NULL(TAG,jsonSVRDb, ERROR);
140
141     OICFree(jsonSVRDbStr);
142     jsonSVRDbStr = NULL;
143
144     //If Cred resource gets updated with empty list then delete the Cred
145     //object from database.
146     if(NULL == jsonObj && (0 == strcmp(rsrcName, OIC_JSON_CRED_NAME)))
147     {
148         cJSON_DeleteItemFromObject(jsonSVRDb, rsrcName);
149     }
150     else if (jsonObj->child )
151     {
152         // Create a duplicate of the JSON object which was passed.
153         cJSON* jsonDuplicateObj = cJSON_Duplicate(jsonObj, 1);
154         VERIFY_NON_NULL(TAG,jsonDuplicateObj, ERROR);
155
156         cJSON* jsonObj = cJSON_GetObjectItem(jsonSVRDb, rsrcName);
157
158         /*
159          ACL, PStat & Doxm resources at least have default entries in the database but
160          Cred resource may have no entries. The first cred resource entry (for provisioning tool)
161          is created when the device is owned by provisioning tool and it's ownerpsk is generated.*/
162         if((strcmp(rsrcName, OIC_JSON_CRED_NAME) == 0 ||
163                 strcmp(rsrcName, OIC_JSON_CRL_NAME) == 0 ||
164                 strcmp(rsrcName, OIC_JSON_PCONF_NAME) == 0 ||
165                 strcmp(rsrcName, OIC_JSON_DPAIRING_NAME) == 0) && (!jsonObj))
166         {
167             // Add the fist cred object in existing SVR database json
168             cJSON_AddItemToObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
169         }
170         else
171         {
172             VERIFY_NON_NULL(TAG,jsonObj, ERROR);
173
174             // Replace the modified json object in existing SVR database json
175             cJSON_ReplaceItemInObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
176         }
177     }
178
179     // Generate string representation of updated SVR database json object
180     jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);
181     VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
182
183     // Update the persistent storage with new SVR database
184     ps = SRMGetPersistentStorageHandler();
185     if (ps && ps->open)
186     {
187         FILE* fp = ps->open(SVR_DB_FILE_NAME, "w");
188         if (fp)
189         {
190             size_t bytesWritten = ps->write(jsonSVRDbStr, 1, strlen(jsonSVRDbStr), fp);
191             if (bytesWritten == strlen(jsonSVRDbStr))
192             {
193                 ret = OC_STACK_OK;
194             }
195             OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", bytesWritten);
196             ps->close(fp);
197             fp = NULL;
198         }
199         else
200         {
201             OIC_LOG (ERROR, TAG, "Unable to open SVR database file!! ");
202         }
203     }
204
205 exit:
206     OICFree(jsonSVRDbStr);
207     cJSON_Delete(jsonSVRDb);
208
209     return ret;
210 }