/** * 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(__ANDROID32__) #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(__ANDROID32__)) // 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; }