javamanager/javacaptain/extensionplugins/javacertstore/src/javacertstore.cpp
branchRCL_3
changeset 19 04becd199f91
child 25 9ac0a0a7da70
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  JavaCertStore
       
    15 *
       
    16 */
       
    17 
       
    18 #include "commsendpoint.h"
       
    19 #include "comms.h"
       
    20 #include "commsmessage.h"
       
    21 #include "logger.h"
       
    22 #include "javaoslayer.h"
       
    23 #include "coreinterface.h"
       
    24 #include "javacertstore.h"
       
    25 #include "securitycommsmessagedefs.h"
       
    26 #include "javacommonutils.h"
       
    27 #include <sys/stat.h>
       
    28 #include <sys/types.h>
       
    29 #include <errno.h>
       
    30 #include <dirent.h>
       
    31 #include <stdlib.h>
       
    32 #include <string.h>
       
    33 #include <algorithm>
       
    34 #include "trustedcertificate.h"
       
    35 #include "javasmartcardcertificatesreader.h"
       
    36 #include "metadatafilehandler.h"
       
    37 
       
    38 #ifdef __SYMBIAN32__
       
    39 java::captain::ExtensionPluginInterface* getExtensionPlugin()
       
    40 {
       
    41 #else
       
    42 extern "C" java::captain::ExtensionPluginInterface* getExtensionPlugin()
       
    43 {
       
    44 #endif
       
    45     return new java::captain::JavaCertStore();
       
    46 }
       
    47 
       
    48 using namespace std;
       
    49 using namespace java::security;
       
    50 using namespace java::util;
       
    51 using namespace java::comms;
       
    52 
       
    53 namespace java
       
    54 {
       
    55 namespace captain
       
    56 {
       
    57 
       
    58 
       
    59 JavaCertStore::JavaCertStore() : iCore(0)
       
    60 {
       
    61     JELOG2(EJavaCaptain);
       
    62 }
       
    63 
       
    64 JavaCertStore::~JavaCertStore()
       
    65 {
       
    66     JELOG2(EJavaCaptain);
       
    67 }
       
    68 
       
    69 void JavaCertStore::startPlugin(CoreInterface* core)
       
    70 {
       
    71     JELOG2(EJavaCaptain);
       
    72     iCore = core;
       
    73     iCore->getComms()->registerListener(java::comms::PLUGIN_ID_JAVA_CERT_STORE_EXTENSION_C, this);
       
    74     loadCertsMetadata();
       
    75 }
       
    76 
       
    77 void JavaCertStore::stopPlugin()
       
    78 {
       
    79     JELOG2(EJavaCaptain);
       
    80     iCore->getComms()->unregisterListener(java::comms::PLUGIN_ID_JAVA_CERT_STORE_EXTENSION_C, this);
       
    81     iCore = 0;
       
    82     unloadCertsMetadata();
       
    83 }
       
    84 
       
    85 java::comms::CommsListener* JavaCertStore::getCommsListener()
       
    86 {
       
    87     JELOG2(EJavaCaptain);
       
    88     return this;
       
    89 }
       
    90 
       
    91 void JavaCertStore::processMessage(java::comms::CommsMessage& aMessage)
       
    92 {
       
    93     JELOG2(EJavaCaptain);
       
    94 
       
    95     switch (aMessage.getMessageId())
       
    96     {
       
    97     case JAVA_CERT_STORE_MSG_ID_REQUEST:
       
    98     {
       
    99         int operation = 0;
       
   100         aMessage >> operation;
       
   101         switch (operation)
       
   102         {
       
   103         case JAVA_CERT_STORE_OPERATION_QUERY_CERTS:
       
   104             queryCerts(aMessage);
       
   105             break;
       
   106         case JAVA_CERT_STORE_OPERATION_REFRESH_CERTS:
       
   107             /*if (!aMessage.hasPermission(MANAGE_CERTIFICATES)) {
       
   108               break;
       
   109             }*/
       
   110             unloadCertsMetadata();
       
   111             loadCertsMetadata();
       
   112             break;
       
   113         case JAVA_CERT_STORE_OPERATION_DELETE_CERT:
       
   114         case JAVA_CERT_STORE_OPERATION_DISABLE_CERT:
       
   115         case JAVA_CERT_STORE_OPERATION_ENABLE_CERT:
       
   116             // check that the client is trusted
       
   117             if (!aMessage.hasPermission(MANAGE_CERTIFICATES))
       
   118             {
       
   119                 break;
       
   120             }
       
   121             std::string id;
       
   122             aMessage >> id;
       
   123             int state;
       
   124             switch (operation)
       
   125             {
       
   126             case JAVA_CERT_STORE_OPERATION_DELETE_CERT:
       
   127                 state = STATE_DELETED;
       
   128                 break;
       
   129             case JAVA_CERT_STORE_OPERATION_DISABLE_CERT:
       
   130                 state = STATE_DISABLED;
       
   131                 break;
       
   132             case JAVA_CERT_STORE_OPERATION_ENABLE_CERT:
       
   133                 state = STATE_ENABLED;
       
   134                 break;
       
   135             }
       
   136             manageCert(id, state);
       
   137             break;
       
   138         }
       
   139     }
       
   140     break;
       
   141     }
       
   142 }
       
   143 
       
   144 void JavaCertStore::queryCerts(java::comms::CommsMessage& aMessage)
       
   145 {
       
   146     JELOG2(EJavaCaptain);
       
   147     int id = 0;
       
   148     std::string hash;
       
   149     int state = 0;
       
   150     aMessage >> id;
       
   151     int query = 0;
       
   152     // process the filter
       
   153     while (id != 0)
       
   154     {
       
   155         switch (id)
       
   156         {
       
   157         case JAVA_CERT_STORE_FILTER_ID_HASH:
       
   158             aMessage >> hash;
       
   159             break;
       
   160         case JAVA_CERT_STORE_FILTER_ID_STATE:
       
   161             int tmp;
       
   162             aMessage >> tmp;
       
   163             state = state | tmp;
       
   164             break;
       
   165         case JAVA_CERT_STORE_QUERY_ID_PROTECTION_DOMAIN:
       
   166             query = JAVA_CERT_STORE_QUERY_ID_PROTECTION_DOMAIN;
       
   167             break;
       
   168         case JAVA_CERT_STORE_QUERY_ID_FULL_DETAILS:
       
   169             query = JAVA_CERT_STORE_QUERY_ID_FULL_DETAILS;
       
   170             break;
       
   171         case JAVA_CERT_STORE_QUERY_ID_CERT_CONTENT:
       
   172             query = JAVA_CERT_STORE_QUERY_ID_CERT_CONTENT;
       
   173             break;
       
   174         case JAVA_CERT_STORE_QUERY_ID_CERT_CONTENT_PEM:
       
   175             query = JAVA_CERT_STORE_QUERY_ID_CERT_CONTENT_PEM;
       
   176             break;
       
   177         case JAVA_CERT_STORE_QUERY_ID_STATE:
       
   178             query = JAVA_CERT_STORE_QUERY_ID_STATE;
       
   179             break;
       
   180         }
       
   181         aMessage >> id;
       
   182     }
       
   183     java::comms::CommsMessage replyMsg;
       
   184     replyMsg.setReceiver(aMessage.getSender());
       
   185     replyMsg.setMessageRef(aMessage.getMessageRef());
       
   186     bool queryEnabled = (state & JAVA_CERT_STORE_STATE_ENABLED);
       
   187     bool queryDisabled = (state & JAVA_CERT_STORE_STATE_DISABLED);
       
   188     bool queryDeleted = (state & JAVA_CERT_STORE_STATE_DELETED);
       
   189     bool queryState = (query == JAVA_CERT_STORE_QUERY_ID_STATE);
       
   190     bool queryResponseSet = false;
       
   191     transform(hash.begin(), hash.end(), hash.begin(), (int(*)(int)) tolower);
       
   192     for (int i=0; i<no_certs; i++)
       
   193     {
       
   194         if ((state == 0 ||
       
   195                 (queryEnabled && iCertsMetadata[i]->state == STATE_ENABLED)
       
   196                 || (queryDisabled && iCertsMetadata[i]->state == STATE_DISABLED)
       
   197                 || (queryDeleted && iCertsMetadata[i]->state == STATE_DELETED))
       
   198                 && (hash.compare("") == 0
       
   199                     || iCertsMetadata[i]->hash.compare(hash) == 0))
       
   200         {
       
   201             // what we return back depends on what was queried
       
   202             switch (query)
       
   203             {
       
   204             case JAVA_CERT_STORE_QUERY_ID_PROTECTION_DOMAIN:
       
   205                 replyMsg << iCertsMetadata[i]->prot_domain_name;
       
   206                 replyMsg << iCertsMetadata[i]->prot_domain_category;
       
   207                 break;
       
   208             case JAVA_CERT_STORE_QUERY_ID_FULL_DETAILS:
       
   209                 // return content, ID (which is the actual hash)
       
   210                 // and the encoded info about the state
       
   211                 if (replyWithContent(replyMsg, *iCertsMetadata[i]))
       
   212                 {
       
   213                     // add also the ID and the state
       
   214                     replyMsg << iCertsMetadata[i]->hash;
       
   215                     replyMsg << encodeState(iCertsMetadata[i]->disposable,
       
   216                                             iCertsMetadata[i]->disablable,
       
   217                                             iCertsMetadata[i]->state);
       
   218                 }
       
   219                 break;
       
   220             case JAVA_CERT_STORE_QUERY_ID_CERT_CONTENT:
       
   221                 // return the length and the content of the certificate
       
   222                 replyWithContent(replyMsg, *iCertsMetadata[i]);
       
   223                 break;
       
   224             case JAVA_CERT_STORE_QUERY_ID_CERT_CONTENT_PEM:
       
   225                 // return the length and the content of the certificate in PEM format
       
   226                 replyWithContent(replyMsg, *iCertsMetadata[i], PEM_FORMAT);
       
   227                 break;
       
   228             case JAVA_CERT_STORE_QUERY_ID_STATE:
       
   229                 if (iCertsMetadata[i]->state == STATE_ENABLED)
       
   230                 {
       
   231                     replyMsg << JAVA_CERT_STORE_STATE_ENABLED;
       
   232                 }
       
   233                 else if (iCertsMetadata[i]->state == STATE_DISABLED)
       
   234                 {
       
   235                     replyMsg << JAVA_CERT_STORE_STATE_DISABLED;
       
   236                 }
       
   237                 else if (iCertsMetadata[i]->state == STATE_DELETED)
       
   238                 {
       
   239                     replyMsg << JAVA_CERT_STORE_STATE_DELETED;
       
   240                 }
       
   241                 else
       
   242                 {
       
   243                     replyMsg << JAVA_CERT_STORE_STATE_UNKNOWN;
       
   244                 }
       
   245                 break;
       
   246             default:
       
   247                 // if nothing specifically was queried,
       
   248                 // return the full_path
       
   249                 replyMsg << iCertsMetadata[i]->full_path;
       
   250             }
       
   251             queryResponseSet = true;
       
   252         }
       
   253     }
       
   254     if (queryState && !queryResponseSet)
       
   255     {
       
   256         replyMsg << JAVA_CERT_STORE_STATE_NOT_PRESENT;
       
   257     }
       
   258     int r = iCore->getComms()->send(replyMsg);
       
   259     if (r != 0)
       
   260     {
       
   261         ELOG1(EJavaCaptain,
       
   262               "[JavaCertStore] - error replying to JavaCaptain %s",
       
   263               java::util::JavaCommonUtils::intToString(r).c_str());
       
   264     }
       
   265 }
       
   266 
       
   267 void JavaCertStore::loadCertsMetadata()
       
   268 {
       
   269     // loads the metadata of the certificates stored on device
       
   270     iPrimaryCertsPath = "Z";
       
   271     java::util::JavaOsLayer::getJavaCaptainRoot(iPrimaryCertsPath, true);
       
   272     iPrimaryCertsPath.append(KJavaCertsDir);
       
   273     iPrimaryCertsPath.append(1, KFileSeparator);
       
   274     iSecondaryCertsPath = "C";
       
   275     java::util::JavaOsLayer::getJavaCaptainRoot(iSecondaryCertsPath, true);
       
   276     iSecondaryCertsPath.append(KJavaCertsDir);
       
   277     iSecondaryCertsPath.append(1, KFileSeparator);
       
   278     iCertsMetadataPath = "C";
       
   279     java::util::JavaOsLayer::getJavaCaptainRoot(iCertsMetadataPath, true);
       
   280     iCertsMetadataPath.append(KJavaCertsStateDir);
       
   281     iCertsMetadataPath.append(1, KFileSeparator);
       
   282     no_certs = 0;
       
   283     loadCertsMetadata(iPrimaryCertsPath);
       
   284     loadCertsMetadata(iSecondaryCertsPath);
       
   285 
       
   286     // loads the metadata of the smart card certificates
       
   287     vector<TrustedCertificate> trustedCerts;
       
   288     JavaSmartCardCertificatesReader::retrieveTrustedCertificates(trustedCerts);
       
   289     for (int i=0; i<trustedCerts.size(); i++)
       
   290     {
       
   291         CERT_METADATA * metadata = new CERT_METADATA();
       
   292         metadata->disposable = false;
       
   293         metadata->disablable = false;
       
   294         metadata->state = STATE_ENABLED;
       
   295         metadata->changes = false;
       
   296         metadata->hash = trustedCerts[i].getId();
       
   297         transform(metadata->hash.begin(), metadata->hash.end(), metadata->hash.begin(), (int(*)(int)) tolower);
       
   298         metadata->full_path = "Smart Card";
       
   299         metadata->len = trustedCerts[i].getData().size();
       
   300         metadata->data = trustedCerts[i].getData();
       
   301         assignProtectionDomain(trustedCerts[i].getTrustedUsage(), metadata);
       
   302         addCertMetadataToCache(metadata, true /* overwrite */);
       
   303     }
       
   304     trustedCerts.clear();
       
   305 }
       
   306 
       
   307 void JavaCertStore::unloadCertsMetadata()
       
   308 {
       
   309     for (int i=0; i<no_certs; i++)
       
   310     {
       
   311         // free the memory
       
   312         CERT_METADATA * metadata = iCertsMetadata[i];
       
   313         writeMetadataIntoFile(metadata);
       
   314         delete metadata;
       
   315     }
       
   316     // clear the cache
       
   317     iCertsMetadata.clear();
       
   318     no_certs = 0;
       
   319 }
       
   320 
       
   321 void JavaCertStore::writeMetadataIntoFile(CERT_METADATA * metadata)
       
   322 {
       
   323     if (!metadata->changes)
       
   324     {
       
   325         // no changes
       
   326         return;
       
   327     }
       
   328 
       
   329     if (JavaCertStoreMetadataFileHandler::writeState(
       
   330                 metadata->file_name, metadata->state))
       
   331     {
       
   332         // reset the changes flag
       
   333         metadata->changes = false;
       
   334     }
       
   335 }
       
   336 
       
   337 bool JavaCertStore::readMetadataFromFiles(const std::string& cert_file_name, CERT_METADATA * metadata)
       
   338 {
       
   339     // there are two types of metadata:
       
   340     // 1) read-only metadata (this metadata resides into file with the same name than
       
   341     //    certificate file, but with KMetadataSuffix as extension)
       
   342     // 2) read-write metadata (this metadata resides into file with the same name than
       
   343     //    certificate file, but with KStateSuffix as extension)
       
   344     bool readingSucceeded = false;
       
   345     size_t ext = cert_file_name.rfind('.');
       
   346     if (ext != string::npos)
       
   347     {
       
   348         std::string file_name_without_extension = string(cert_file_name, 0, ext);
       
   349         // read-only metadata
       
   350         std::string read_only_metadata_file_name = iPrimaryCertsPath
       
   351                 + file_name_without_extension
       
   352                 + KMetadataSuffix;
       
   353         std::string read_write_metadata_file_name = iCertsMetadataPath
       
   354                 + file_name_without_extension
       
   355                 + KStateSuffix;
       
   356         // read the read-only metadata file */
       
   357         FILE * read_only_metadata_file = fopen(read_only_metadata_file_name.c_str(),"r");
       
   358         if (read_only_metadata_file == NULL)
       
   359         {
       
   360             read_only_metadata_file_name = iSecondaryCertsPath
       
   361                                            + file_name_without_extension
       
   362                                            + KMetadataSuffix;
       
   363             read_only_metadata_file = fopen(read_only_metadata_file_name.c_str(),"r");
       
   364         }
       
   365         if (read_only_metadata_file != NULL)
       
   366         {
       
   367             // save the name of the metadata_file for later use
       
   368             metadata->file_name = read_write_metadata_file_name;
       
   369 
       
   370             // identifier for the metadata value being read
       
   371             const int READ_DOMAIN_NAME = 2;
       
   372             const int READ_DOMAIN_CATEGORY = 3;
       
   373             const int READ_HASH = 4;
       
   374             const int READ_REMOVABLE = 5;
       
   375             const int READ_DISABLABLE = 6;
       
   376 
       
   377             // domain_name_info
       
   378             int domain_name_index = 0;
       
   379             char domain_name[50];
       
   380 
       
   381             // domain_category info
       
   382             int domain_category_index = 0;
       
   383             char domain_category[50];
       
   384 
       
   385             // hash info
       
   386             int hash_index = 0;
       
   387             char hash[50];
       
   388 
       
   389             // removable&disablable
       
   390             bool removable = false;
       
   391             bool disablable = false;
       
   392 
       
   393             // start&end separators for the metadata's keys
       
   394             bool key_ss = true;
       
   395             bool key_es = false;
       
   396             int retval;
       
   397 
       
   398             // identifier for the operation being performed
       
   399             int op = 0;
       
   400             while ((int)(retval = getc(read_only_metadata_file))!= EOF)
       
   401             {
       
   402                 if (key_ss)
       
   403                 {
       
   404                     // start of reading something new
       
   405                     switch ((char)retval)
       
   406                     {
       
   407                     case 'n':
       
   408                         op = READ_DOMAIN_NAME;
       
   409                         key_ss = false;
       
   410                         break;
       
   411                     case 'c':
       
   412                         op = READ_DOMAIN_CATEGORY;
       
   413                         key_ss = false;
       
   414                         break;
       
   415                     case 'h':
       
   416                         op = READ_HASH;
       
   417                         key_ss = false;
       
   418                         break;
       
   419                     case 'r':
       
   420                         op = READ_REMOVABLE;
       
   421                         key_ss = false;
       
   422                         break;
       
   423                     case 'd':
       
   424                         op = READ_DISABLABLE;
       
   425                         key_ss = false;
       
   426                         break;
       
   427                     }
       
   428                 }
       
   429                 else
       
   430                 {
       
   431                     if ((char)retval == '=')
       
   432                     {
       
   433                         // end separator
       
   434                         key_es = true;
       
   435                     }
       
   436                     else if (retval == 10 || retval == 13 /* CR or LF */)
       
   437                     {
       
   438                         key_ss = true;
       
   439                         key_es = false;
       
   440                     }
       
   441                     else if (key_es)
       
   442                     {
       
   443                         switch (op)
       
   444                         {
       
   445                         case READ_DOMAIN_NAME:
       
   446                             domain_name[domain_name_index] = (char)retval;
       
   447                             domain_name_index++;
       
   448                             domain_name[domain_name_index] = '\0';
       
   449                             break;
       
   450                         case READ_DOMAIN_CATEGORY:
       
   451                             domain_category[domain_category_index] = (char)retval;
       
   452                             domain_category_index++;
       
   453                             domain_category[domain_category_index] = '\0';
       
   454                             break;
       
   455                         case READ_HASH:
       
   456                             hash[hash_index] = (char)retval;
       
   457                             hash_index++;
       
   458                             hash[hash_index] = '\0';
       
   459                             break;
       
   460                         case READ_REMOVABLE:
       
   461                             if ((char)retval == '1')
       
   462                             {
       
   463                                 removable = true;
       
   464                             }
       
   465                             break;
       
   466                         case READ_DISABLABLE:
       
   467                             if ((char)retval == '1')
       
   468                             {
       
   469                                 disablable = true;
       
   470                             }
       
   471                             break;
       
   472                         }
       
   473                     }
       
   474                 }
       
   475             }
       
   476             if (domain_name_index > 0
       
   477                     && domain_category_index > 0
       
   478                     && hash_index > 0)
       
   479             {
       
   480                 metadata->prot_domain_name = string(domain_name, domain_name_index);
       
   481                 metadata->prot_domain_category = string(domain_category, domain_category_index);
       
   482                 metadata->hash = string(hash, hash_index);
       
   483                 transform(metadata->hash.begin(), metadata->hash.end(), metadata->hash.begin(), (int(*)(int)) tolower);
       
   484                 metadata->disposable = removable;
       
   485                 metadata->disablable = disablable;
       
   486                 fclose(read_only_metadata_file);
       
   487                 // read the read-write metadata file
       
   488                 int state = JavaCertStoreMetadataFileHandler::readState(
       
   489                                 read_write_metadata_file_name);
       
   490                 if (state == STATE_UNDEFINED)
       
   491                 {
       
   492                     // create the file and initialize it with
       
   493                     metadata->state = STATE_ENABLED;
       
   494                     // create the directory (if it doesn't exist)
       
   495                     if (mkDirAll(KJavaCertsStateDir))
       
   496                     {
       
   497                         // force the writing
       
   498                         metadata->changes = true;
       
   499                         writeMetadataIntoFile(metadata);
       
   500                     }
       
   501                 }
       
   502                 else
       
   503                 {
       
   504                     switch (state)
       
   505                     {
       
   506                     case STATE_ENABLED:
       
   507                     case STATE_DISABLED:
       
   508                     case STATE_DELETED:
       
   509                         // it's ok
       
   510                         break;
       
   511                     default:
       
   512                         // any other state will be translated
       
   513                         // into enabled
       
   514                         state = STATE_ENABLED;
       
   515                     }
       
   516                     metadata->state = state;
       
   517                 }
       
   518                 // the data has just been read, so no changes
       
   519                 metadata->changes = false;
       
   520                 readingSucceeded = true;
       
   521             }
       
   522         }
       
   523     }
       
   524     return readingSucceeded;
       
   525 }
       
   526 
       
   527 // The state of a certificate is encoded on 3 bits:
       
   528 // XXX, the most significant bit represents a boolean indicating if the certificate can be deleted,
       
   529 // the second one represents a boolean indicating if the certificate can be disabled and the third
       
   530 // one represents a boolean indicating if the certificate is disabled or not can_be_disabled and
       
   531 // the third one is_disabled
       
   532 int JavaCertStore::encodeState(bool disposable, bool disablable, int state)
       
   533 {
       
   534     const int DISPOSABLE_STATE_MASK = 4;
       
   535     const int DISABLABLE_STATE_MASK = 2;
       
   536     const int IS_DISABLED_MASK = 1;
       
   537 
       
   538     int encoded_state = 0;
       
   539 
       
   540     if (disposable == true)
       
   541     {
       
   542         encoded_state = encoded_state | DISPOSABLE_STATE_MASK;
       
   543     }
       
   544     if (disablable == true)
       
   545     {
       
   546         encoded_state = encoded_state | DISABLABLE_STATE_MASK;
       
   547     }
       
   548     if (state == STATE_DISABLED)
       
   549     {
       
   550         encoded_state = encoded_state | IS_DISABLED_MASK;
       
   551     }
       
   552     return encoded_state;
       
   553 }
       
   554 
       
   555 void JavaCertStore::manageCert(const std::string& cert_id, int state)
       
   556 {
       
   557     // go through the certidicates and find the right one
       
   558     for (int i=0; i<no_certs; i++)
       
   559     {
       
   560         if (cert_id.compare(iCertsMetadata[i]->hash) == 0)
       
   561         {
       
   562             switch (state)
       
   563             {
       
   564             case STATE_DELETED:
       
   565                 // check if it can be deleted, before deleting it
       
   566                 if (iCertsMetadata[i]->disposable)
       
   567                 {
       
   568                     // mark down if there are any changes
       
   569                     iCertsMetadata[i]->changes =
       
   570                         (iCertsMetadata[i]->state != STATE_DELETED);
       
   571                     // do the actual state change
       
   572                     iCertsMetadata[i]->state = STATE_DELETED;
       
   573                 }
       
   574                 break;
       
   575             case STATE_DISABLED:
       
   576                 // check if it can be disabled before disabling it
       
   577                 if (iCertsMetadata[i]->disablable)
       
   578                 {
       
   579                     // mark down if there are any changes
       
   580                     iCertsMetadata[i]->changes =
       
   581                         (iCertsMetadata[i]->state != STATE_DISABLED);
       
   582                     // do the actual state change
       
   583                     iCertsMetadata[i]->state = STATE_DISABLED;
       
   584                 }
       
   585                 break;
       
   586             case STATE_ENABLED:
       
   587                 // mark down if there are any changes
       
   588                 iCertsMetadata[i]->changes =
       
   589                     (iCertsMetadata[i]->state != STATE_ENABLED);
       
   590                 // do the actual state change
       
   591                 iCertsMetadata[i]->state = STATE_ENABLED;
       
   592                 break;
       
   593             }
       
   594             // Do we need to do this write so often, or can we rely on
       
   595             // doing it only when this plugin is unloaded? this depends on
       
   596             // how reliable the stopPlugin() method is
       
   597             // -> to be checked with JavaCaptain
       
   598             writeMetadataIntoFile(iCertsMetadata[i]);
       
   599             break;
       
   600         }
       
   601     }
       
   602 }
       
   603 
       
   604 std::string JavaCertStore::readCert(const std::string& certFileName, long * length)
       
   605 {
       
   606     char* data = NULL;
       
   607     FILE    *certFile;
       
   608     long    len = 0;
       
   609     certFile = fopen(certFileName.c_str(), "rb");
       
   610     if (certFile != NULL)
       
   611     {
       
   612         fseek(certFile, 0L, SEEK_END);
       
   613         len = ftell(certFile);
       
   614         if (len < 0)
       
   615         {
       
   616             fclose(certFile);
       
   617             return "";
       
   618         }
       
   619         fseek(certFile, 0L, SEEK_SET);
       
   620         data = (char*)calloc(len, sizeof(char));
       
   621         if (data != NULL)
       
   622         {
       
   623             fread(data, sizeof(char), len, certFile);
       
   624         }
       
   625         fclose(certFile);
       
   626     }
       
   627     *length = len;
       
   628     if (data != NULL)
       
   629     {
       
   630         return string(data, len);
       
   631     }
       
   632     else
       
   633     {
       
   634         return "";
       
   635     }
       
   636 }
       
   637 
       
   638 long JavaCertStore::replyWithContent(java::comms::CommsMessage& aReplyMsg, const CERT_METADATA& metadata, int format)
       
   639 {
       
   640     long len = metadata.len;
       
   641     if (len != 0)
       
   642     {
       
   643         if (format == DER_FORMAT)
       
   644         {
       
   645             long long lLen = len;
       
   646             aReplyMsg << lLen;
       
   647             aReplyMsg << metadata.data;
       
   648         }
       
   649         else
       
   650         {
       
   651             std::string encCert = JavaCommonUtils::base64encode(metadata.data);
       
   652             long long lLen = encCert.size();
       
   653             aReplyMsg << lLen;
       
   654             aReplyMsg << encCert;
       
   655         }
       
   656     }
       
   657     else
       
   658     {
       
   659         // signal that cert content not available
       
   660         aReplyMsg << 0;
       
   661     }
       
   662     return len;
       
   663 }
       
   664 
       
   665 void JavaCertStore::assignProtectionDomain(vector<string> aTrustedUsage, CERT_METADATA * metadata)
       
   666 {
       
   667     // by default assign it to trustedthird party
       
   668     metadata->prot_domain_name = string(KIdentifiedThirdPartyDomainName);
       
   669     metadata->prot_domain_category = string(KIdentifiedThirdPartyDomainCategory);
       
   670     // overwrite the identified third party with an operator if present
       
   671     for (int i=0; i<aTrustedUsage.size(); i++)
       
   672     {
       
   673         if (strcmp(aTrustedUsage[i].c_str(), KOperatorTrustedUsage) == 0
       
   674                 || strcmp(aTrustedUsage[i].c_str(), KSupplementaryOperatorTrustedUsage1) == 0
       
   675                 || strcmp(aTrustedUsage[i].c_str(), KSupplementaryOperatorTrustedUsage2) == 0
       
   676                 || strcmp(aTrustedUsage[i].c_str(), KSupplementaryOperatorTrustedUsage3) == 0)
       
   677         {
       
   678             metadata->prot_domain_name = string(KOperatorDomainName);
       
   679             metadata->prot_domain_category = string(KOperatorDomainCategory);
       
   680             return;
       
   681         }
       
   682     }
       
   683 }
       
   684 
       
   685 void JavaCertStore::loadCertsMetadata(std::string aCertsLocation)
       
   686 {
       
   687     const char * certs_dir = aCertsLocation.c_str();
       
   688     DIR * dirp = opendir(certs_dir);
       
   689     if (dirp != NULL)
       
   690     {
       
   691         struct dirent * dirent;
       
   692         while ((dirent = readdir(dirp)) != NULL)
       
   693         {
       
   694             char * tmp = dirent->d_name;
       
   695             bool cert_file = (strlen(dirent->d_name) > strlen(KCertSuffix1)
       
   696                               && strcmp(tmp + (strlen(dirent->d_name) - strlen(KCertSuffix1)),KCertSuffix1) == 0)
       
   697                              || (strlen(dirent->d_name) > strlen(KCertSuffix2)
       
   698                                  && strcmp(tmp + (strlen(dirent->d_name) - strlen(KCertSuffix2)),KCertSuffix2) == 0);
       
   699             if (strcmp(dirent->d_name,".")
       
   700                     && strcmp(dirent->d_name,"..")
       
   701                     && cert_file)
       
   702             {
       
   703                 CERT_METADATA * metadata = new CERT_METADATA();
       
   704                 if (readMetadataFromFiles(dirent->d_name, metadata))
       
   705                 {
       
   706                     int len = aCertsLocation.size() + strlen(dirent->d_name) + 1;
       
   707                     metadata->full_path = aCertsLocation + string(dirent->d_name);
       
   708                     metadata->data = readCert(metadata->full_path,
       
   709                                               &(metadata->len));
       
   710                     // if the cert already exists, overwrite it: since the primary location is Z and
       
   711                     // the secondary is C, this is a way to update certificates
       
   712                     addCertMetadataToCache(metadata, true /* overwrite*/);
       
   713                 }
       
   714                 else
       
   715                 {
       
   716                     delete metadata;
       
   717                     metadata = NULL;
       
   718                 }
       
   719             }
       
   720         }
       
   721         closedir(dirp);
       
   722     }
       
   723 }
       
   724 
       
   725 void JavaCertStore::addCertMetadataToCache(CERT_METADATA* metadata, bool overwrite)
       
   726 {
       
   727     vector<CERT_METADATA *>::iterator startIterator;
       
   728     startIterator = iCertsMetadata.begin();
       
   729     bool found = false;
       
   730     for (int i=0; i<no_certs; i++)
       
   731     {
       
   732         if (iCertsMetadata[i]->hash.compare(metadata->hash) == 0)
       
   733         {
       
   734             if (overwrite)
       
   735             {
       
   736                 delete iCertsMetadata[i];
       
   737                 iCertsMetadata.erase(startIterator + i);
       
   738                 iCertsMetadata.push_back(metadata);
       
   739             }
       
   740             else
       
   741             {
       
   742                 // just append it
       
   743                 iCertsMetadata.push_back(metadata);
       
   744                 no_certs++;
       
   745             }
       
   746             found = true;
       
   747             break;
       
   748         }
       
   749     }
       
   750     if (!found)
       
   751     {
       
   752         // simply add it
       
   753         iCertsMetadata.push_back(metadata);
       
   754         no_certs++;
       
   755     }
       
   756 }
       
   757 
       
   758 bool JavaCertStore::mkDirAll(const char* aDirPath)
       
   759 {
       
   760     // split the path into single directories
       
   761     // (separated by file separator) and create
       
   762     // each of the directories
       
   763     std::string dirPath = string(aDirPath);
       
   764     std::string currentDirPath = "";
       
   765     int startPos = 0;
       
   766     int endPos = dirPath.find(KFileSeparator);
       
   767     while (endPos > startPos)
       
   768     {
       
   769         currentDirPath += dirPath.substr(startPos, endPos - startPos) + KFileSeparator;
       
   770         int mkdir_result = mkdir(currentDirPath.c_str(), 0666);
       
   771         if (mkdir_result != 0 && errno != EEXIST)
       
   772         {
       
   773             return false;
       
   774         }
       
   775         startPos = endPos + 1;
       
   776         endPos = dirPath.find(KFileSeparator, startPos);
       
   777     }
       
   778     // the last round
       
   779     currentDirPath += dirPath.substr(startPos, dirPath.size() - startPos);
       
   780     int mkdir_result = mkdir(currentDirPath.c_str(), 0666);
       
   781     if (mkdir_result != 0 && errno != EEXIST)
       
   782     {
       
   783         return false;
       
   784     }
       
   785     return true;
       
   786 }
       
   787 
       
   788 } // namespace captain
       
   789 } // namespace java
       
   790