1/**
2 * Copyright(c) 2011 Trusted Logic.   All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *  * Neither the name Trusted Logic nor the names of its
15 *    contributors may be used to endorse or promote products derived
16 *    from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <ctype.h>
35#include <errno.h>
36#include <sys/types.h>
37#include <fcntl.h>
38
39#if defined(_WIN32_WCE)
40#include "os_wm.h"
41#else
42#include <sys/stat.h>
43#endif
44
45#include "smc_properties.h"
46#include "smc_properties_parser.h"
47#include "s_type.h"
48#include "s_error.h"
49
50#if defined(__SYMBIAN32__)
51#include "smc_properties_symbian.h"
52#endif
53
54
55#define SECURE_CONFIG_FILE_HDR     66
56#define SECURE_CONFIG_FILE_VERSION 01
57
58
59#define SYSTEM_SECTION_NAME               "Global"
60
61typedef enum {
62   MANDATORY_FILE_SYSTEM_FILE_NAME,
63   MANDATORY_KEYSTORE_SYSTEM_FILE_NAME,
64   MANDATORY_KEYSTORE_USER_FILE_NAME,
65   MANDATORY_SUPER_PARTITION_FILE_NAME,
66
67   NB_MANDATORY_PROPS,
68} MANDATORY_PROPS;
69
70
71typedef enum
72{
73   STATE_NONE,
74   STATE_DECIMAL,
75   STATE_HEXA,
76   STATE_BINARY
77} INTEGER_FORMAT;
78
79#if defined (LINUX) || defined(ANDROID)
80#define SEPARATOR_CHAR '/'
81
82#elif defined (WIN32) || defined (__SYMBIAN32__) || defined (_WIN32_WCE)
83#define SEPARATOR_CHAR '\\'
84
85#else
86#error SEPARATOR_CHAR not implemented...
87#endif
88
89#if defined(__SYMBIAN32__)
90#define printf RDebugPrintf
91#endif
92
93
94/** the sturct that keep the data stored in the config file */
95static CONF_FILE gConfFile;
96
97
98
99/**
100 * check the validity of a given path (is a directory, has the READ/WRITE access rights)
101 * @param pPath the path we want to check
102 * @return true if the path is OK, else false
103 */
104static bool checkFilePath(char *pPath)
105{
106   struct stat buf;
107   uint32_t  result;
108   char *pDir = pPath;
109
110   // cobra & buffalo version : complete path (directory and filename) is given in the config file.
111   // so we extract from this path the parent directory
112   {
113      uint32_t nSlashIndex = 0;
114      uint32_t i = 0;
115      while(pPath[i] != '\0')
116      {
117         if (pPath[i] == SEPARATOR_CHAR)
118            nSlashIndex = i;
119         i++;
120      }
121      pDir = malloc(sizeof(char) * nSlashIndex);
122      if (pDir == NULL)
123      {
124         printf("Out of memory.");
125         return false;
126      }
127      strncpy(pDir, pPath, nSlashIndex);
128      pDir[nSlashIndex] = '\0';
129   }
130
131   /* check if file exists */
132   result = stat(pDir, &buf);
133   if(result != 0 )
134   {
135#if defined(__SYMBIAN32__)
136      if (SymbianCheckFSDirectory(pDir) == -1)
137      {
138         printf("Cannot create directory : %s\n.", pDir);
139         return false;
140      }
141#else
142      printf("Unknown path : %s\n.", pDir);
143      return false;
144#endif
145   }
146   else
147   {
148      /* check it's a directory */
149      if ((buf.st_mode & S_IFDIR) != S_IFDIR)
150      {
151         printf("Path %s doesn't point on a directory.\n", pDir);
152         return false;
153      }
154#if (!defined(__SYMBIAN32__)) && (!defined(_WIN32_WCE)) && (!defined(ANDROID))
155      // TODO : under Symbian, Android and WM, check access right of a directory failed? I don't know why...
156       /* check read access */
157       if ((buf.st_mode & S_IREAD) != S_IREAD)
158       {
159          printf("Path %s doesn't have the READ access rights.\n", pDir);
160          return false;
161       }
162       /* check write */
163       if ((buf.st_mode & S_IWRITE) != S_IWRITE)
164       {
165          printf("Path %s doesn't have the WRITE access rights.\n", pDir);
166          return false;
167       }
168#endif
169   }
170
171   return true;
172}
173
174/**
175 * check properties (value, range...)
176 * @param sConfFile struct where are stored the properties we will check
177 * @return true if the check succeed, else false
178 */
179static bool smcPropertiesCheck(CONF_FILE sConfFile)
180{
181   NODE* pNext = NULL;
182   char *pPropVal = NULL;
183   bool bCheckResult = true;
184   bool pMandatoryProps[NB_MANDATORY_PROPS];
185   uint32_t i = 0;
186
187   // reset properties table
188   for (i=0; i<NB_MANDATORY_PROPS; i++)
189      pMandatoryProps[i] = false;
190
191   // check properties type and set MandatoryProps field to true (check later)
192   pNext = sConfFile.sSystemSectionPropertyList.pFirst;
193   while(pNext != NULL)
194   {
195      pPropVal = ((PROPERTY*)pNext)->pValue;
196
197      //printf("Checking %s = %s.\n", pNext->pName, pPropVal);
198      if(strcmp(pNext->pName, FILE_SYSTEM_FILE_NAME) == 0)
199      {
200         /* File System */
201         bCheckResult = checkFilePath(pPropVal);
202         pMandatoryProps[MANDATORY_FILE_SYSTEM_FILE_NAME] = true;
203      }
204      else if(strcmp(pNext->pName, KEYSTORE_SYSTEM_FILE_NAME) == 0)
205      {
206         bCheckResult = checkFilePath(pPropVal);
207         pMandatoryProps[MANDATORY_KEYSTORE_SYSTEM_FILE_NAME] = true;
208      }
209      else if(strcmp(pNext->pName, KEYSTORE_USER_FILE_NAME) == 0)
210      {
211         bCheckResult = checkFilePath(pPropVal);
212         pMandatoryProps[MANDATORY_KEYSTORE_USER_FILE_NAME] = true;
213      }
214      else if(strcmp(pNext->pName, SUPER_PARTITION_FILE_NAME) == 0)
215      {
216         bCheckResult = checkFilePath(pPropVal);
217         pMandatoryProps[MANDATORY_SUPER_PARTITION_FILE_NAME] = true;
218      }
219      else
220      {
221         bCheckResult = true;
222      }
223
224      if (! bCheckResult)
225      {
226         printf("Property %s = %s. Bad value!!!\n", pNext->pName, pPropVal);
227         return false;
228      }
229      pNext=pNext->pNext;
230   }
231
232   /* check all mandatory properties had been found */
233   for (i=0; i<NB_MANDATORY_PROPS; i++)
234   {
235      if (!pMandatoryProps[i])
236      {
237         char *pMissingProp = NULL;
238         switch(i){
239            case MANDATORY_FILE_SYSTEM_FILE_NAME :
240               pMissingProp = FILE_SYSTEM_FILE_NAME;
241               break;
242            case MANDATORY_KEYSTORE_SYSTEM_FILE_NAME :
243               pMissingProp = KEYSTORE_SYSTEM_FILE_NAME;
244               break;
245            case MANDATORY_KEYSTORE_USER_FILE_NAME :
246               pMissingProp = KEYSTORE_USER_FILE_NAME;
247               break;
248            case MANDATORY_SUPER_PARTITION_FILE_NAME :
249               pMissingProp = SUPER_PARTITION_FILE_NAME;
250               break;
251         }
252         printf("Mandatory property %s is missing.\n", pMissingProp);
253         bCheckResult = false;
254      }
255   }
256
257   return bCheckResult;
258}
259
260
261
262/**
263 * parse the config file
264 * @param configFile the path of the configuration file
265 * @return 0 if succeed, else 1
266 */
267int smcPropertiesParse(const char *configFile)
268{
269   S_RESULT nResult = S_SUCCESS;
270
271   // first : parse the config file
272   memset(&gConfFile, 0x00, sizeof(CONF_FILE));
273   nResult=SMCPropParseConfigFile((char *)configFile, &gConfFile);
274   if (nResult!=S_SUCCESS)
275   {
276      printf("Parsing error in file %s : %x.\n", configFile, nResult);
277      return 1;
278   }
279
280   // check properties
281   if (!smcPropertiesCheck(gConfFile))
282   {
283      printf("Properties check failed.\n");
284      return 1;
285   }
286
287   return 0;
288}
289
290
291
292/**
293 * get the value of a property
294 * @param pProp we are asking the value of this property
295 * @return the value if found, else NULL
296 */
297char *smcGetPropertyAsString(char *pProp)
298{
299   return SMCPropGetSystemProperty(&gConfFile, pProp);
300}
301
302
303/**
304 * get the value of a property
305 * @param pProp we are asking the value of this property
306 * @param pVal the value of the property
307 * @return 0 if found, else 1 (and pVal set to 0)
308 */
309int smcGetPropertyAsInt(char *pProp, int *pVal)
310{
311   char *pStr = SMCPropGetSystemProperty(&gConfFile, pProp);
312   if (pStr == NULL)
313   {
314      *pVal = 0;
315      return 1;
316   }
317   if (libString2GetStringAsInt(pStr, (uint32_t*)pVal) == S_SUCCESS)
318   {
319      return 0;
320   }
321   *pVal = 0;
322   return 1;
323}
324