/**
* Copyright(c) 2011 Trusted Logic. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Trusted Logic nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#if defined(_WIN32_WCE)
#include "os_wm.h"
#else
#include <sys/stat.h>
#endif
#include "smc_properties.h"
#include "smc_properties_parser.h"
#include "s_type.h"
#include "s_error.h"
#if defined(__SYMBIAN32__)
#include "smc_properties_symbian.h"
#endif
#define SECURE_CONFIG_FILE_HDR 66
#define SECURE_CONFIG_FILE_VERSION 01
#define SYSTEM_SECTION_NAME "Global"
typedef enum {
MANDATORY_FILE_SYSTEM_FILE_NAME,
MANDATORY_KEYSTORE_SYSTEM_FILE_NAME,
MANDATORY_KEYSTORE_USER_FILE_NAME,
MANDATORY_SUPER_PARTITION_FILE_NAME,
NB_MANDATORY_PROPS,
} MANDATORY_PROPS;
typedef enum
{
STATE_NONE,
STATE_DECIMAL,
STATE_HEXA,
STATE_BINARY
} INTEGER_FORMAT;
#if defined (LINUX) || defined(ANDROID)
#define SEPARATOR_CHAR '/'
#elif defined (WIN32) || defined (__SYMBIAN32__) || defined (_WIN32_WCE)
#define SEPARATOR_CHAR '\\'
#else
#error SEPARATOR_CHAR not implemented...
#endif
#if defined(__SYMBIAN32__)
#define printf RDebugPrintf
#endif
/** the sturct that keep the data stored in the config file */
static CONF_FILE gConfFile;
/**
* check the validity of a given path (is a directory, has the READ/WRITE access rights)
* @param pPath the path we want to check
* @return true if the path is OK, else false
*/
static bool checkFilePath(char *pPath)
{
struct stat buf;
uint32_t result;
char *pDir = pPath;
// cobra & buffalo version : complete path (directory and filename) is given in the config file.
// so we extract from this path the parent directory
{
uint32_t nSlashIndex = 0;
uint32_t i = 0;
while(pPath[i] != '\0')
{
if (pPath[i] == SEPARATOR_CHAR)
nSlashIndex = i;
i++;
}
pDir = malloc(sizeof(char) * nSlashIndex);
if (pDir == NULL)
{
printf("Out of memory.");
return false;
}
strncpy(pDir, pPath, nSlashIndex);
pDir[nSlashIndex] = '\0';
}
/* check if file exists */
result = stat(pDir, &buf);
if(result != 0 )
{
#if defined(__SYMBIAN32__)
if (SymbianCheckFSDirectory(pDir) == -1)
{
printf("Cannot create directory : %s\n.", pDir);
return false;
}
#else
printf("Unknown path : %s\n.", pDir);
return false;
#endif
}
else
{
/* check it's a directory */
if ((buf.st_mode & S_IFDIR) != S_IFDIR)
{
printf("Path %s doesn't point on a directory.\n", pDir);
return false;
}
#if (!defined(__SYMBIAN32__)) && (!defined(_WIN32_WCE)) && (!defined(ANDROID))
// TODO : under Symbian, Android and WM, check access right of a directory failed? I don't know why...
/* check read access */
if ((buf.st_mode & S_IREAD) != S_IREAD)
{
printf("Path %s doesn't have the READ access rights.\n", pDir);
return false;
}
/* check write */
if ((buf.st_mode & S_IWRITE) != S_IWRITE)
{
printf("Path %s doesn't have the WRITE access rights.\n", pDir);
return false;
}
#endif
}
return true;
}
/**
* check properties (value, range...)
* @param sConfFile struct where are stored the properties we will check
* @return true if the check succeed, else false
*/
static bool smcPropertiesCheck(CONF_FILE sConfFile)
{
NODE* pNext = NULL;
char *pPropVal = NULL;
bool bCheckResult = true;
bool pMandatoryProps[NB_MANDATORY_PROPS];
uint32_t i = 0;
// reset properties table
for (i=0; i<NB_MANDATORY_PROPS; i++)
pMandatoryProps[i] = false;
// check properties type and set MandatoryProps field to true (check later)
pNext = sConfFile.sSystemSectionPropertyList.pFirst;
while(pNext != NULL)
{
pPropVal = ((PROPERTY*)pNext)->pValue;
//printf("Checking %s = %s.\n", pNext->pName, pPropVal);
if(strcmp(pNext->pName, FILE_SYSTEM_FILE_NAME) == 0)
{
/* File System */
bCheckResult = checkFilePath(pPropVal);
pMandatoryProps[MANDATORY_FILE_SYSTEM_FILE_NAME] = true;
}
else if(strcmp(pNext->pName, KEYSTORE_SYSTEM_FILE_NAME) == 0)
{
bCheckResult = checkFilePath(pPropVal);
pMandatoryProps[MANDATORY_KEYSTORE_SYSTEM_FILE_NAME] = true;
}
else if(strcmp(pNext->pName, KEYSTORE_USER_FILE_NAME) == 0)
{
bCheckResult = checkFilePath(pPropVal);
pMandatoryProps[MANDATORY_KEYSTORE_USER_FILE_NAME] = true;
}
else if(strcmp(pNext->pName, SUPER_PARTITION_FILE_NAME) == 0)
{
bCheckResult = checkFilePath(pPropVal);
pMandatoryProps[MANDATORY_SUPER_PARTITION_FILE_NAME] = true;
}
else
{
bCheckResult = true;
}
if (! bCheckResult)
{
printf("Property %s = %s. Bad value!!!\n", pNext->pName, pPropVal);
return false;
}
pNext=pNext->pNext;
}
/* check all mandatory properties had been found */
for (i=0; i<NB_MANDATORY_PROPS; i++)
{
if (!pMandatoryProps[i])
{
char *pMissingProp = NULL;
switch(i){
case MANDATORY_FILE_SYSTEM_FILE_NAME :
pMissingProp = FILE_SYSTEM_FILE_NAME;
break;
case MANDATORY_KEYSTORE_SYSTEM_FILE_NAME :
pMissingProp = KEYSTORE_SYSTEM_FILE_NAME;
break;
case MANDATORY_KEYSTORE_USER_FILE_NAME :
pMissingProp = KEYSTORE_USER_FILE_NAME;
break;
case MANDATORY_SUPER_PARTITION_FILE_NAME :
pMissingProp = SUPER_PARTITION_FILE_NAME;
break;
}
printf("Mandatory property %s is missing.\n", pMissingProp);
bCheckResult = false;
}
}
return bCheckResult;
}
/**
* parse the config file
* @param configFile the path of the configuration file
* @return 0 if succeed, else 1
*/
int smcPropertiesParse(const char *configFile)
{
S_RESULT nResult = S_SUCCESS;
// first : parse the config file
memset(&gConfFile, 0x00, sizeof(CONF_FILE));
nResult=SMCPropParseConfigFile((char *)configFile, &gConfFile);
if (nResult!=S_SUCCESS)
{
printf("Parsing error in file %s : %x.\n", configFile, nResult);
return 1;
}
// check properties
if (!smcPropertiesCheck(gConfFile))
{
printf("Properties check failed.\n");
return 1;
}
return 0;
}
/**
* get the value of a property
* @param pProp we are asking the value of this property
* @return the value if found, else NULL
*/
char *smcGetPropertyAsString(char *pProp)
{
return SMCPropGetSystemProperty(&gConfFile, pProp);
}
/**
* get the value of a property
* @param pProp we are asking the value of this property
* @param pVal the value of the property
* @return 0 if found, else 1 (and pVal set to 0)
*/
int smcGetPropertyAsInt(char *pProp, int *pVal)
{
char *pStr = SMCPropGetSystemProperty(&gConfFile, pProp);
if (pStr == NULL)
{
*pVal = 0;
return 1;
}
if (libString2GetStringAsInt(pStr, (uint32_t*)pVal) == S_SUCCESS)
{
return 0;
}
*pVal = 0;
return 1;
}