summaryrefslogtreecommitdiffstats
path: root/security/tf_daemon/smc_properties_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tf_daemon/smc_properties_parser.c')
-rw-r--r--security/tf_daemon/smc_properties_parser.c556
1 files changed, 556 insertions, 0 deletions
diff --git a/security/tf_daemon/smc_properties_parser.c b/security/tf_daemon/smc_properties_parser.c
new file mode 100644
index 0000000..1f97224
--- /dev/null
+++ b/security/tf_daemon/smc_properties_parser.c
@@ -0,0 +1,556 @@
+/**
+ * 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 <assert.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#if defined(_WIN32_WCE)
+#include "os_wm.h"
+#else
+#include <errno.h>
+#endif
+
+#include "smc_properties_parser.h"
+#include "lib_manifest2.h"
+#include "s_error.h"
+
+/* ---------------------------------------------------------------------------------
+ Defines
+ ---------------------------------------------------------------------------------*/
+
+#define STRUE "true"
+#define SFALSE "false"
+
+#if defined(_WIN32_WCE)
+#define GET_LAST_ERR GetLastError()
+#else
+#define GET_LAST_ERR errno
+#endif
+
+#if defined (LINUX) || defined (__SYMBIAN32__) || defined (__ANDROID32__)
+#define STRICMP strcasecmp
+#elif defined(_WIN32_WCE)
+#define STRICMP _stricmp
+#else
+#define STRICMP stricmp
+#endif
+
+
+/* ---------------------------------------------------------------------------------
+ Logs and Traces.
+ ---------------------------------------------------------------------------------*/
+#ifdef __SYMBIAN32__
+#include "os_symbian.h"
+#elif NDEBUG
+/* Compile-out the traces */
+#define TRACE_ERROR(...)
+#define TRACE_WARNING(...)
+#define TRACE_INFO(...)
+#else
+#include <stdarg.h>
+static void TRACE_ERROR(const char* format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "TRACE: ERROR: ");
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+static void TRACE_WARNING(const char* format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "TRACE: WARNING: ");
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+static void TRACE_INFO(const char* format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "TRACE: ");
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+#endif /* NDEBUG */
+
+/* ---------------------------------------------------------------------------------
+ private functions.
+ ---------------------------------------------------------------------------------*/
+
+static NODE* static_listFindNodeElement(NODE* pList,char* pName,bool bIsCaseSensitive)
+{
+ int32_t nCmp;
+
+ assert(pName!=NULL);
+
+ while (pList!=NULL)
+ {
+ if (bIsCaseSensitive)
+ {
+ nCmp=strcmp(pName,pList->pName);
+ }
+ else
+ {
+ nCmp=STRICMP(pName,pList->pName);
+ }
+ if (nCmp>0)
+ {
+ pList=pList->pRight;
+ }
+ else if (nCmp<0)
+ {
+ pList=pList->pLeft;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return pList;
+}
+
+
+static S_RESULT static_listSortedAddNode(NODE* pList,NODE* pNode)
+{
+ int32_t nCmp;
+
+ do {
+ nCmp=strcmp(pNode->pName,pList->pName);
+ if (nCmp>0)
+ {
+ if (pList->pRight!=NULL)
+ {
+ pList=pList->pRight;
+ }
+ else
+ {
+ pList->pRight=pNode;
+ /* update linked list */
+ pNode->pPrevious=pList;
+ pNode->pNext=pList->pNext;
+ if (pList->pNext!=NULL)
+ {
+ pList->pNext->pPrevious=pNode;
+ }
+ pList->pNext=pNode;
+ return S_SUCCESS;
+ }
+ }
+ else if (nCmp<0)
+ {
+ if (pList->pLeft!=NULL)
+ {
+ pList=pList->pLeft;
+ }
+ else
+ {
+ pList->pLeft=pNode;
+ /* update linked list */
+ pNode->pNext=pList;
+ pNode->pPrevious=pList->pPrevious;
+ if (pList->pPrevious!=NULL)
+ {
+ pList->pPrevious->pNext=pNode;
+ }
+ pList->pPrevious=pNode;
+ return S_SUCCESS;
+ }
+ }
+ } while (nCmp!=0);
+
+ TRACE_ERROR("%s already exist !\n",pNode->pName);
+ return S_ERROR_ITEM_EXISTS;
+}
+
+
+static S_RESULT SMCPropListSortedAdd(LIST* pList,NODE* pNode)
+{
+ S_RESULT nResult;
+
+ assert(pList!=NULL && pNode!=NULL);
+
+ if (pNode->pName==NULL)
+ {
+ TRACE_ERROR("Trying to insert a NULL node name !\n");
+ return S_ERROR_BAD_PARAMETERS;
+ }
+
+ if (pList->pRoot==NULL)
+ {
+ pList->pRoot=pNode;
+ pList->pFirst=pNode;
+ return S_SUCCESS;
+ }
+ else
+ {
+ nResult=static_listSortedAddNode(pList->pRoot,pNode);
+ /* update the first node of the linked list */
+ if (nResult==S_SUCCESS && pNode->pPrevious==NULL)
+ {
+ pList->pFirst=pNode;
+ }
+ }
+ return nResult;
+}
+
+
+static NODE* SMCPropListFindElement(LIST* pList,char* pName,bool bIsCaseSensitive)
+{
+ if (pList->pRoot!=NULL)
+ {
+ return static_listFindNodeElement(pList->pRoot,pName,bIsCaseSensitive);
+ }
+ return NULL;
+}
+
+
+static S_RESULT SMCPropYacc(uint8_t* pBuffer, uint32_t nBufferLength,
+ CONF_FILE* pConfFile)
+{
+ S_RESULT nError=S_SUCCESS;
+ LIST *pPublicPropertyList=NULL;
+ LIST *pPrivatePropertyList=NULL;
+ PROPERTY* pProperty=NULL;
+ SERVICE_SECTION* pServSection;
+ SERVICE_SECTION* pPreviousService=NULL;
+
+ uint8_t* pName;
+ uint32_t nNameLength;
+ uint8_t* pValue;
+ uint32_t nValueLength;
+ char* pNameZ = NULL;
+ char* pValueZ = NULL;
+ LIB_MANIFEST2_CONTEXT sParserContext;
+ char serviceManifestName[1024];
+
+ sParserContext.pManifestName = "Configuration File";
+ sParserContext.pManifestContent = pBuffer;
+ sParserContext.nManifestLength = nBufferLength;
+ sParserContext.nType = LIB_MANIFEST2_TYPE_SOURCE_WITH_SECTIONS;
+
+ libManifest2InitContext(&sParserContext);
+
+ while (true)
+ {
+ nError = libManifest2GetNextItem(
+ &sParserContext,
+ &pName,
+ &nNameLength,
+ &pValue,
+ &nValueLength);
+ if (nError == S_ERROR_ITEM_NOT_FOUND)
+ {
+ /* End of parsing */
+ nError = S_SUCCESS;
+ break;
+ }
+ else if (nError != S_SUCCESS)
+ {
+ /* Error */
+ goto error;
+ }
+
+ /* Duplicate name and value in as zero-terminated strings */
+ /* Unclean: those strings are not going to be deallocated
+ This is not a problem because this code is run in a tool
+ */
+ pNameZ = malloc(nNameLength+1);
+ if (pNameZ == NULL)
+ {
+ nError = S_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+ memcpy(pNameZ, pName, nNameLength);
+ pNameZ[nNameLength] = 0;
+
+ if (pValue == NULL)
+ {
+ /* It's a section */
+ if (STRICMP(pNameZ, SYSTEM_SECTION_NAME) == 0)
+ {
+ free(pNameZ);
+ pPublicPropertyList=&pConfFile->sSystemSectionPropertyList;
+ }
+ else
+ {
+ pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
+ &pConfFile->sDriverSectionList,
+ pNameZ,
+ false);
+ if (pServSection==NULL)
+ {
+ pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
+ &pConfFile->sPreinstalledSectionList,
+ pNameZ,
+ false);
+ }
+ if (pServSection==NULL)
+ {
+ pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
+ &pConfFile->sSectionList,
+ pNameZ,
+ false);
+ if (pServSection==NULL)
+ {
+ nError=S_ERROR_ITEM_NOT_FOUND;
+ goto error;
+ }
+ }
+ free(pNameZ);
+
+ pServSection->inSCF=true;
+ if (pPreviousService!=NULL)
+ {
+ pPreviousService->pNextInSCF=pServSection;
+ }
+ else
+ {
+ pConfFile->pFirstSectionInSCF=pServSection;
+ }
+ pPreviousService=pServSection;
+
+ pPublicPropertyList=&pServSection->sPublicPropertyList;
+ pPrivatePropertyList=&pServSection->sPrivatePropertyList;
+ }
+ }
+ else
+ {
+ /* It's a property definition */
+ pValueZ = malloc(nValueLength+1);
+ if (pValueZ == NULL)
+ {
+ nError = S_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+ memcpy(pValueZ, pValue, nValueLength);
+ pValueZ[nValueLength] = 0;
+
+ pProperty=(PROPERTY*)malloc(sizeof(PROPERTY));
+ if (pProperty==NULL)
+ {
+ nError=S_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+ memset(pProperty, 0x00, sizeof(PROPERTY));
+ pProperty->sNode.pName=pNameZ;
+
+ pProperty->pValue=pValueZ;
+
+ if (pPrivatePropertyList==NULL)
+ {
+ nError=SMCPropListSortedAdd(pPublicPropertyList,(NODE*)pProperty);
+ if (nError!=S_SUCCESS)
+ {
+ goto error;
+ }
+ }
+ else
+ {
+ if ((nValueLength > strlen(CONFIG_PROPERTY_NAME)) &&
+ (memcmp(pProperty->sNode.pName, CONFIG_PROPERTY_NAME, strlen(CONFIG_PROPERTY_NAME)) == 0))
+ {
+ nError=SMCPropListSortedAdd(pPrivatePropertyList,(NODE*)pProperty);
+ }
+ else
+ {
+ nError=SMCPropListSortedAdd(pPublicPropertyList,(NODE*)pProperty);
+ }
+ if (nError!=S_SUCCESS)
+ {
+ goto error;
+ }
+ }
+ }
+ }
+
+error:
+ if (nError!=S_SUCCESS)
+ {
+ switch (nError)
+ {
+ case S_ERROR_BAD_FORMAT:
+ /* Error message already output */
+ break;
+ case S_ERROR_WRONG_SIGNATURE:
+ TRACE_ERROR("Configuration file: wrong service UUID: %s\n", pValueZ);
+ break;
+ case S_ERROR_OUT_OF_MEMORY:
+ TRACE_ERROR("Out of memory\n");
+ break;
+ case S_ERROR_ITEM_NOT_FOUND:
+ TRACE_ERROR("Configuration file: service \"%s\" not found\n", pNameZ);
+ break;
+ }
+ }
+ return nError;
+}
+
+
+S_RESULT static_readFile(const char* pFilename, void** ppFile, uint32_t* pnFileLength)
+{
+ S_RESULT nResult = S_SUCCESS;
+ long nFilesize;
+ FILE* pFile = NULL;
+ void *pBuff = NULL;
+
+ // open file and get its size...
+ if ((pFile = fopen(pFilename, "rb")) == NULL)
+ {
+ TRACE_ERROR("static_readFile: fopen(%s) failed [%d]", pFilename, GET_LAST_ERR);
+ nResult = S_ERROR_ITEM_NOT_FOUND;
+ return nResult;
+ }
+ if (fseek(pFile, 0, SEEK_END) != 0)
+ {
+ TRACE_ERROR("static_readFile: fseek(%s) failed [%d]", pFilename, GET_LAST_ERR);
+ nResult = S_ERROR_UNDERLYING_OS;
+ goto error;
+ }
+ nFilesize = ftell(pFile);
+ if (nFilesize < 0)
+ {
+ TRACE_ERROR("static_readFile: ftell(%s) failed [%d]", pFilename, GET_LAST_ERR);
+ nResult = S_ERROR_UNDERLYING_OS;
+ goto error;
+ }
+ rewind(pFile);
+
+ // allocate the buffer
+ pBuff = malloc(nFilesize + 1);
+ if (pBuff == NULL)
+ {
+ TRACE_ERROR("static_readFile: out of memory");
+ nResult = S_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ // read the file
+ if (fread(pBuff, sizeof(uint8_t), (size_t)nFilesize, pFile) != (size_t)nFilesize)
+ {
+ TRACE_ERROR("static_readFile: fread failed [%d]", GET_LAST_ERR);
+ nResult = S_ERROR_UNDERLYING_OS;
+ goto error;
+ }
+ ((char*)pBuff)[nFilesize] = 0;
+
+ *ppFile = pBuff;
+ *pnFileLength = nFilesize;
+ return S_SUCCESS;
+
+error:
+ if (pBuff != NULL)
+ free(pBuff);
+ fclose(pFile);
+
+ *ppFile = NULL;
+ *pnFileLength = 0;
+ return nResult;
+}
+
+
+
+
+
+/* ---------------------------------------------------------------------------------
+ API functions.
+ ---------------------------------------------------------------------------------*/
+
+char* SMCPropGetSystemProperty(CONF_FILE* pConfFile, char* pPropertyName)
+{
+ PROPERTY* pProperty;
+
+ pProperty=(PROPERTY*)SMCPropListFindElement(
+ &pConfFile->sSystemSectionPropertyList,
+ pPropertyName,
+ true);
+ if (pProperty!=NULL)
+ {
+ return pProperty->pValue;
+ }
+ return NULL;
+}
+
+uint32_t SMCPropGetSystemPropertyAsInt(CONF_FILE* pConfFile, char* pPropertyName)
+{
+ uint32_t nValue;
+ char* pValue=SMCPropGetSystemProperty(pConfFile,pPropertyName);
+
+ if (libString2GetStringAsInt(pValue, &nValue) == S_SUCCESS)
+ {
+ return nValue;
+ }
+ return 0;
+}
+
+
+S_RESULT SMCPropParseConfigFile(char* pConfigFilename,CONF_FILE* pConfFile)
+{
+ S_RESULT nError=S_SUCCESS;
+ void* pFile;
+ uint32_t nFileLength;
+ bool bReuseManifest;
+
+ assert(pConfFile!=NULL);
+
+ TRACE_INFO("Processing configuration file '%s'", pConfigFilename);
+
+ if(pConfigFilename != NULL)
+ {
+ nError=static_readFile(pConfigFilename,&pFile,&nFileLength);
+ if (nError!=S_SUCCESS)
+ {
+ goto error;
+ }
+ bReuseManifest = true;
+ }
+ else
+ {
+ assert(0);
+ }
+
+ nError=SMCPropYacc(pFile,nFileLength,pConfFile);
+
+ if(pConfigFilename != NULL)
+ {
+ free(pFile);
+ }
+
+error:
+ return nError;
+}