Home | History | Annotate | Download | only in tf_daemon
      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 <assert.h>
     33 #include <stdio.h>
     34 #include <ctype.h>
     35 #include <string.h>
     36 
     37 #if defined(_WIN32_WCE)
     38 #include "os_wm.h"
     39 #else
     40 #include <errno.h>
     41 #endif
     42 
     43 #include "smc_properties_parser.h"
     44 #include "lib_manifest2.h"
     45 #include "lib_uuid.h"
     46 #include "s_error.h"
     47 
     48 /* ---------------------------------------------------------------------------------
     49    Defines
     50    ---------------------------------------------------------------------------------*/
     51 
     52 #define STRUE                             "true"
     53 #define SFALSE                            "false"
     54 
     55 #if defined(_WIN32_WCE)
     56 #define GET_LAST_ERR GetLastError()
     57 #else
     58 #define GET_LAST_ERR  errno
     59 #endif
     60 
     61 #if defined (LINUX) || defined (__SYMBIAN32__) || defined (ANDROID)
     62 #define STRICMP strcasecmp
     63 #elif defined(_WIN32_WCE)
     64 #define STRICMP _stricmp
     65 #else
     66 #define STRICMP stricmp
     67 #endif
     68 
     69 
     70 /* ---------------------------------------------------------------------------------
     71    Logs and Traces.
     72    ---------------------------------------------------------------------------------*/
     73 #ifdef __SYMBIAN32__
     74 #include "os_symbian.h"
     75 #elif NDEBUG
     76 /* Compile-out the traces */
     77 #define TRACE_ERROR(...)
     78 #define TRACE_WARNING(...)
     79 #define TRACE_INFO(...)
     80 #else
     81 #include <stdarg.h>
     82 static void TRACE_ERROR(const char* format, ...)
     83 {
     84    va_list ap;
     85    va_start(ap, format);
     86    fprintf(stderr, "TRACE: ERROR: ");
     87    vfprintf(stderr, format, ap);
     88    fprintf(stderr, "\n");
     89    va_end(ap);
     90 }
     91 
     92 static void TRACE_WARNING(const char* format, ...)
     93 {
     94    va_list ap;
     95    va_start(ap, format);
     96    fprintf(stderr, "TRACE: WARNING: ");
     97    vfprintf(stderr, format, ap);
     98    fprintf(stderr, "\n");
     99    va_end(ap);
    100 }
    101 
    102 static void TRACE_INFO(const char* format, ...)
    103 {
    104    va_list ap;
    105    va_start(ap, format);
    106    fprintf(stderr, "TRACE: ");
    107    vfprintf(stderr, format, ap);
    108    fprintf(stderr, "\n");
    109    va_end(ap);
    110 }
    111 #endif /* NDEBUG */
    112 
    113 /* ---------------------------------------------------------------------------------
    114    private functions.
    115    ---------------------------------------------------------------------------------*/
    116 
    117 static NODE* static_listFindNodeElement(NODE* pList,char* pName,bool bIsCaseSensitive)
    118 {
    119    int32_t nCmp;
    120 
    121    assert(pName!=NULL);
    122 
    123    while (pList!=NULL)
    124    {
    125       if (bIsCaseSensitive)
    126       {
    127          nCmp=strcmp(pName,pList->pName);
    128       }
    129       else
    130       {
    131          nCmp=STRICMP(pName,pList->pName);
    132       }
    133       if (nCmp>0)
    134       {
    135          pList=pList->pRight;
    136       }
    137       else if (nCmp<0)
    138       {
    139          pList=pList->pLeft;
    140       }
    141       else
    142       {
    143          break;
    144       }
    145    }
    146    return pList;
    147 }
    148 
    149 
    150 static S_RESULT static_listSortedAddNode(NODE* pList,NODE* pNode)
    151 {
    152    int32_t nCmp;
    153 
    154    do {
    155       nCmp=strcmp(pNode->pName,pList->pName);
    156       if (nCmp>0)
    157       {
    158          if (pList->pRight!=NULL)
    159          {
    160             pList=pList->pRight;
    161          }
    162          else
    163          {
    164             pList->pRight=pNode;
    165             /* update linked list */
    166             pNode->pPrevious=pList;
    167             pNode->pNext=pList->pNext;
    168             if (pList->pNext!=NULL)
    169             {
    170                pList->pNext->pPrevious=pNode;
    171             }
    172             pList->pNext=pNode;
    173             return S_SUCCESS;
    174          }
    175       }
    176       else if (nCmp<0)
    177       {
    178          if (pList->pLeft!=NULL)
    179          {
    180             pList=pList->pLeft;
    181          }
    182          else
    183          {
    184             pList->pLeft=pNode;
    185             /* update linked list */
    186             pNode->pNext=pList;
    187             pNode->pPrevious=pList->pPrevious;
    188             if (pList->pPrevious!=NULL)
    189             {
    190                pList->pPrevious->pNext=pNode;
    191             }
    192             pList->pPrevious=pNode;
    193             return S_SUCCESS;
    194          }
    195       }
    196    } while (nCmp!=0);
    197 
    198    TRACE_ERROR("%s already exist !\n",pNode->pName);
    199    return S_ERROR_ITEM_EXISTS;
    200 }
    201 
    202 
    203 static S_RESULT SMCPropListSortedAdd(LIST* pList,NODE* pNode)
    204 {
    205    S_RESULT nResult;
    206 
    207    assert(pList!=NULL && pNode!=NULL);
    208 
    209    if (pNode->pName==NULL)
    210    {
    211 	   TRACE_ERROR("Trying to insert a NULL node name !\n");
    212       return S_ERROR_BAD_PARAMETERS;
    213    }
    214 
    215    if (pList->pRoot==NULL)
    216    {
    217       pList->pRoot=pNode;
    218       pList->pFirst=pNode;
    219       return S_SUCCESS;
    220    }
    221    else
    222    {
    223       nResult=static_listSortedAddNode(pList->pRoot,pNode);
    224       /* update the first node of the linked list */
    225       if (nResult==S_SUCCESS && pNode->pPrevious==NULL)
    226       {
    227          pList->pFirst=pNode;
    228       }
    229    }
    230    return nResult;
    231 }
    232 
    233 
    234 static NODE* SMCPropListFindElement(LIST* pList,char* pName,bool bIsCaseSensitive)
    235 {
    236    if (pList->pRoot!=NULL)
    237    {
    238       return static_listFindNodeElement(pList->pRoot,pName,bIsCaseSensitive);
    239    }
    240    return NULL;
    241 }
    242 
    243 
    244 static S_RESULT SMCPropYacc(uint8_t* pBuffer, uint32_t nBufferLength,
    245                      CONF_FILE* pConfFile, SERVICE_SECTION* pService)
    246 {
    247    S_RESULT nError=S_SUCCESS;
    248    LIST *pPublicPropertyList=NULL;
    249    LIST *pPrivatePropertyList=NULL;
    250    PROPERTY* pProperty=NULL;
    251    SERVICE_SECTION* pServSection;
    252    SERVICE_SECTION* pPreviousService=NULL;
    253 
    254    uint8_t* pName;
    255    uint32_t nNameLength;
    256    uint8_t* pValue;
    257    uint32_t nValueLength;
    258    char* pNameZ = NULL;
    259    char* pValueZ = NULL;
    260    LIB_MANIFEST2_CONTEXT sParserContext;
    261    char serviceManifestName[1024];
    262 
    263    sParserContext.pManifestName = "Configuration File";
    264    sParserContext.pManifestContent = pBuffer;
    265    sParserContext.nManifestLength = nBufferLength;
    266    sParserContext.nType = LIB_MANIFEST2_TYPE_SOURCE_WITH_SECTIONS;
    267 
    268    if (pService!=NULL)
    269    {
    270       pPublicPropertyList=&pService->sPublicPropertyList;
    271       pPrivatePropertyList=&pService->sPrivatePropertyList;
    272       /* read inside a service compiled manifest */
    273       sParserContext.nType = LIB_MANIFEST2_TYPE_COMPILED;
    274       sprintf(serviceManifestName, "%s(manifest)", pService->sNode.pName);
    275       sParserContext.pManifestName = serviceManifestName;
    276    }
    277    libManifest2InitContext(&sParserContext);
    278 
    279    while (true)
    280    {
    281       nError = libManifest2GetNextItem(
    282          &sParserContext,
    283          &pName,
    284          &nNameLength,
    285          &pValue,
    286          &nValueLength);
    287       if (nError == S_ERROR_ITEM_NOT_FOUND)
    288       {
    289          /* End of parsing */
    290          nError = S_SUCCESS;
    291          break;
    292       }
    293       else if (nError != S_SUCCESS)
    294       {
    295          /* Error */
    296          goto error;
    297       }
    298 
    299       /* Duplicate name and value in as zero-terminated strings */
    300       /* Unclean: those strings are not going to be deallocated
    301          This is not a problem because this code is run in a tool
    302       */
    303       pNameZ = malloc(nNameLength+1);
    304       if (pNameZ == NULL)
    305       {
    306          nError = S_ERROR_OUT_OF_MEMORY;
    307          goto error;
    308       }
    309       memcpy(pNameZ, pName, nNameLength);
    310       pNameZ[nNameLength] = 0;
    311 
    312       if (pValue == NULL)
    313       {
    314          /* It's a section */
    315          if (STRICMP(pNameZ, SYSTEM_SECTION_NAME) == 0)
    316          {
    317             free(pNameZ);
    318             pPublicPropertyList=&pConfFile->sSystemSectionPropertyList;
    319          }
    320          else
    321          {
    322             pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
    323                &pConfFile->sDriverSectionList,
    324                pNameZ,
    325                false);
    326             if (pServSection==NULL)
    327             {
    328                pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
    329                      &pConfFile->sPreinstalledSectionList,
    330                      pNameZ,
    331                      false);
    332             }
    333             if (pServSection==NULL)
    334             {
    335                pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
    336                   &pConfFile->sSectionList,
    337                   pNameZ,
    338                   false);
    339                if (pServSection==NULL)
    340                {
    341                   nError=S_ERROR_ITEM_NOT_FOUND;
    342                   goto error;
    343                }
    344             }
    345             free(pNameZ);
    346 
    347             pServSection->inSCF=true;
    348             if (pPreviousService!=NULL)
    349             {
    350                pPreviousService->pNextInSCF=pServSection;
    351             }
    352             else
    353             {
    354                pConfFile->pFirstSectionInSCF=pServSection;
    355             }
    356             pPreviousService=pServSection;
    357 
    358             pPublicPropertyList=&pServSection->sPublicPropertyList;
    359             pPrivatePropertyList=&pServSection->sPrivatePropertyList;
    360          }
    361       }
    362       else
    363       {
    364          /* It's a property definition */
    365          pValueZ = malloc(nValueLength+1);
    366          if (pValueZ == NULL)
    367          {
    368             nError = S_ERROR_OUT_OF_MEMORY;
    369             goto error;
    370          }
    371          memcpy(pValueZ, pValue, nValueLength);
    372          pValueZ[nValueLength] = 0;
    373 
    374          pProperty=(PROPERTY*)malloc(sizeof(PROPERTY));
    375          if (pProperty==NULL)
    376          {
    377             nError=S_ERROR_OUT_OF_MEMORY;
    378             goto error;
    379          }
    380          memset(pProperty, 0x00, sizeof(PROPERTY));
    381          pProperty->sNode.pName=pNameZ;
    382 
    383          pProperty->pValue=pValueZ;
    384 
    385          if (pPrivatePropertyList==NULL)
    386          {
    387             nError=SMCPropListSortedAdd(pPublicPropertyList,(NODE*)pProperty);
    388             if (nError!=S_SUCCESS)
    389             {
    390                goto error;
    391             }
    392          }
    393          else
    394          {
    395             if (strcmp(pProperty->sNode.pName,CONFIG_SERVICE_ID_PROPERTY_NAME) == 0)
    396             {
    397                if (pService!=NULL)
    398                {
    399                   pService->sNode.pName=malloc(nValueLength+1);
    400                   if (pService->sNode.pName==NULL)
    401                   {
    402                      nError=S_ERROR_OUT_OF_MEMORY;
    403                      goto error;
    404                   }
    405 #if defined (LINUX) || defined (__SYMBIAN32__) || defined(ANDROID)
    406                   {
    407                      // put each char of the value in uppercase
    408                      char* p=pProperty->pValue;
    409                      while(*p)
    410                      {
    411                         *p=toupper(*p);
    412                         p++;
    413                      }
    414                   }
    415 #else
    416                   _strupr(pProperty->pValue);
    417 #endif
    418                   memcpy(pService->sNode.pName,pProperty->pValue,nValueLength+1);
    419 
    420                   if (!libUUIDFromString((const uint8_t*)pProperty->pValue,&pService->sUUID))
    421                   {
    422                      nError=S_ERROR_WRONG_SIGNATURE;
    423                      goto error;
    424                   }
    425                   {
    426                      S_UUID sNullUUID;
    427                      memset(&sNullUUID,0,sizeof(S_UUID));
    428                      if (!memcmp(&pService->sUUID,&sNullUUID,sizeof(S_UUID)))
    429                      {
    430                         nError=S_ERROR_WRONG_SIGNATURE;
    431                         goto error;
    432                      }
    433                   }
    434                }
    435             }
    436             if ((nValueLength > strlen(CONFIG_PROPERTY_NAME)) &&
    437                 (memcmp(pProperty->sNode.pName, CONFIG_PROPERTY_NAME, strlen(CONFIG_PROPERTY_NAME)) == 0))
    438             {
    439                nError=SMCPropListSortedAdd(pPrivatePropertyList,(NODE*)pProperty);
    440             }
    441             else
    442             {
    443                nError=SMCPropListSortedAdd(pPublicPropertyList,(NODE*)pProperty);
    444             }
    445             if (nError!=S_SUCCESS)
    446             {
    447                goto error;
    448             }
    449          }
    450       }
    451    }
    452 
    453 error:
    454    if (nError!=S_SUCCESS)
    455    {
    456       switch (nError)
    457       {
    458       case S_ERROR_BAD_FORMAT:
    459          /* Error message already output */
    460          break;
    461       case S_ERROR_WRONG_SIGNATURE:
    462          TRACE_ERROR("Configuration file: wrong service UUID: %s\n", pValueZ);
    463          break;
    464       case S_ERROR_OUT_OF_MEMORY:
    465          TRACE_ERROR("Out of memory\n");
    466          break;
    467       case S_ERROR_ITEM_NOT_FOUND:
    468          TRACE_ERROR("Configuration file: service \"%s\" not found\n", pNameZ);
    469          break;
    470       }
    471    }
    472    return nError;
    473 }
    474 
    475 
    476 S_RESULT static_readFile(const char* pFilename, void** ppFile, uint32_t* pnFileLength)
    477 {
    478    S_RESULT nResult = S_SUCCESS;
    479    long nFilesize;
    480    FILE* pFile = NULL;
    481    void *pBuff = NULL;
    482 
    483    // open file and get its size...
    484    if ((pFile = fopen(pFilename, "rb")) == NULL)
    485    {
    486       TRACE_ERROR("static_readFile: fopen(%s) failed [%d]", pFilename, GET_LAST_ERR);
    487 	   nResult = S_ERROR_ITEM_NOT_FOUND;
    488 	   return nResult;
    489    }
    490    if (fseek(pFile, 0, SEEK_END) != 0)
    491    {
    492       TRACE_ERROR("static_readFile: fseek(%s) failed [%d]", pFilename, GET_LAST_ERR);
    493 	   nResult = S_ERROR_UNDERLYING_OS;
    494 	   goto error;
    495    }
    496    nFilesize = ftell(pFile);
    497    if (nFilesize < 0)
    498    {
    499       TRACE_ERROR("static_readFile: ftell(%s) failed [%d]", pFilename, GET_LAST_ERR);
    500 	   nResult = S_ERROR_UNDERLYING_OS;
    501 	   goto error;
    502    }
    503    rewind(pFile);
    504 
    505    // allocate the buffer
    506    pBuff = malloc(nFilesize + 1);
    507    if (pBuff == NULL)
    508    {
    509       TRACE_ERROR("static_readFile: out of memory");
    510       nResult = S_ERROR_OUT_OF_MEMORY;
    511       goto error;
    512    }
    513 
    514    // read the file
    515    if (fread(pBuff, sizeof(uint8_t), (size_t)nFilesize, pFile) != (size_t)nFilesize)
    516    {
    517       TRACE_ERROR("static_readFile: fread failed [%d]", GET_LAST_ERR);
    518       nResult = S_ERROR_UNDERLYING_OS;
    519       goto error;
    520    }
    521    ((char*)pBuff)[nFilesize] = 0;
    522 
    523    *ppFile = pBuff;
    524    *pnFileLength = nFilesize;
    525    return S_SUCCESS;
    526 
    527 error:
    528    if (pBuff != NULL)
    529       free(pBuff);
    530    fclose(pFile);
    531 
    532    *ppFile = NULL;
    533    *pnFileLength = 0;
    534    return nResult;
    535 }
    536 
    537 
    538 
    539 
    540 
    541 /* ---------------------------------------------------------------------------------
    542    API functions.
    543    ---------------------------------------------------------------------------------*/
    544 
    545 char* SMCPropGetSystemProperty(CONF_FILE* pConfFile, char* pPropertyName)
    546 {
    547    PROPERTY* pProperty;
    548 
    549    pProperty=(PROPERTY*)SMCPropListFindElement(
    550       &pConfFile->sSystemSectionPropertyList,
    551       pPropertyName,
    552       true);
    553    if (pProperty!=NULL)
    554    {
    555       return pProperty->pValue;
    556    }
    557    return NULL;
    558 }
    559 
    560 uint32_t SMCPropGetSystemPropertyAsInt(CONF_FILE* pConfFile, char* pPropertyName)
    561 {
    562    uint32_t nValue;
    563    char* pValue=SMCPropGetSystemProperty(pConfFile,pPropertyName);
    564 
    565    if (libString2GetStringAsInt(pValue, &nValue) == S_SUCCESS)
    566    {
    567       return nValue;
    568    }
    569    return 0;
    570 }
    571 
    572 
    573 S_RESULT SMCPropParseConfigFile(char* pConfigFilename,CONF_FILE* pConfFile)
    574 {
    575    S_RESULT nError=S_SUCCESS;
    576    void* pFile;
    577    uint32_t nFileLength;
    578    bool bReuseManifest;
    579 
    580    assert(pConfFile!=NULL);
    581 
    582    TRACE_INFO("Processing configuration file '%s'", pConfigFilename);
    583 
    584    if(pConfigFilename != NULL)
    585    {
    586       nError=static_readFile(pConfigFilename,&pFile,&nFileLength);
    587       if (nError!=S_SUCCESS)
    588       {
    589          goto error;
    590       }
    591       bReuseManifest = true;
    592    }
    593    else
    594    {
    595       assert(0);
    596    }
    597 
    598    nError=SMCPropYacc(pFile,nFileLength,pConfFile,NULL);
    599 
    600    if(pConfigFilename != NULL)
    601    {
    602       free(pFile);
    603    }
    604 
    605 error:
    606    return nError;
    607 }
    608