1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/securityanddataprivacytools/securitytools/certapp/certapp.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1054 @@
1.4 +/*
1.5 +* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +static const char * const sVersion = "certapp version 1.1.++";
1.23 +#include <e32base.h>
1.24 +#include <f32file.h>
1.25 +#include <s32file.h>
1.26 +#include <map>
1.27 +#include <sys/stat.h>
1.28 +#include "encdec.h"
1.29 +#include "certclients.h"
1.30 +#include "filecertstore.h"
1.31 +#include "swicertstore.h"
1.32 +#include "logger.h"
1.33 +#include "stringconv.h"
1.34 +#include <errno.h>
1.35 +#include "appuidmap.h"
1.36 +#include "openssl_license.h"
1.37 +#include "utils.h"
1.38 +
1.39 +#ifdef __TOOLS2_LINUX__
1.40 +#include <unistd.h>
1.41 +#include <stdio.h>
1.42 +#else
1.43 +#include <io.h>
1.44 +#endif // __TOOLS2_LINUX__
1.45 +
1.46 +#ifdef __TOOLS2_LINUX__
1.47 +#define DIR_SEPARATOR "/"
1.48 +#else
1.49 +#define DIR_SEPARATOR "\\"
1.50 +#endif
1.51 +
1.52 +enum CertStoreFileType
1.53 +{
1.54 + EBinCertClients,
1.55 + EHumanCertClients,
1.56 + EBinFileCertStore,
1.57 + EHumanFileCertStore,
1.58 + EBinSwiCertStore,
1.59 + EHumanSwiCertStore
1.60 +};
1.61 +
1.62 +struct AppMapEntry
1.63 + {
1.64 + TUint32 iUid;
1.65 + TUint32 iInputFileIndex;
1.66 + };
1.67 +typedef std::map<std::string, AppMapEntry> AppMap;
1.68 +
1.69 +typedef std::map<std::string, TUint32> FCSLabelMap; // maps cert label to inputFileIndex
1.70 +
1.71 +typedef std::vector<std::string> StringVector;
1.72 +typedef std::vector<CertStoreFileType> CertStoreFileTypeVector;
1.73 +
1.74 +void ProcessCommandLine(int aArgc, char **aArgv,
1.75 + StringVector &aInputFiles,
1.76 + StringVector &aInputDirs,
1.77 + CertStoreFileTypeVector &aInputFileTypes,
1.78 + StringVector &aOutputFiles,
1.79 + StringVector &aOutputDirs,
1.80 + CertStoreFileTypeVector &aOutputFileTypes,
1.81 + bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates);
1.82 +
1.83 +void ProcessCertClientFiles(const std::string &aBaseDir,
1.84 + const StringVector &aInputFiles,
1.85 + const StringVector &aInputDirs,
1.86 + const CertStoreFileTypeVector &aInputFileTypes,
1.87 + bool &aAllowDuplicates,
1.88 + EncDecContainer &aCertAppInfoContainer);
1.89 +
1.90 +void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
1.91 + const EncDecContainer &aFileCertStoreContainer,
1.92 + const EncDecContainer &aSwiCertStoreContainer,
1.93 + const std::string &aBaseDir,
1.94 + const StringVector &aOutputFiles,
1.95 + const StringVector &aOutputDirs,
1.96 + const CertStoreFileTypeVector &aOutputFileTypes,
1.97 + bool aVerbose, bool aPemOut);
1.98 +
1.99 +bool ValidateLabel(FCSLabelMap &aLabelMap,
1.100 + const StringVector &aInputFiles,
1.101 + CertStoreFileType aFileType,
1.102 + TUint32 aFileIndex,
1.103 + const TCertLabel &aCertLabel);
1.104 +
1.105 +
1.106 +struct SubjectToSubjectKeyIdEntry
1.107 + {
1.108 + bool iDuplicate;
1.109 + std::string iLabel;
1.110 + TKeyIdentifier iSubjectKeyIdentifier;
1.111 + };
1.112 +typedef std::map<std::string, SubjectToSubjectKeyIdEntry> SubjectToSubjectKeyIdMap;
1.113 +void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
1.114 + SubjectToSubjectKeyIdMap &aSubjectMap);
1.115 +
1.116 +void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap,
1.117 + EUseCertificateExtension aUseExtension,
1.118 + EncDecContainer &aCertStoreContainer);
1.119 +
1.120 +static const std::string OPT_PROGRESS("--progress=");
1.121 +static const std::string OPT_ERRORS("--errors=");
1.122 +static const std::string OPT_VERBOSE("--verbose");
1.123 +static const std::string OPT_ALLOWDUPLICATES("--allowduplicates");
1.124 +static const std::string OPT_CHDIR("--chdir=");
1.125 +static const std::string OPT_HCERTCLIENTS_L("--hcertclients=");
1.126 +static const std::string OPT_HCERTCLIENTS_S("--hcc=");
1.127 +static const std::string OPT_BCERTCLIENTS_L("--bcertclients=");
1.128 +static const std::string OPT_BCERTCLIENTS_S("--bcc=");
1.129 +static const std::string OPT_HFILECERTSTORE_L("--hfilecertstore=");
1.130 +static const std::string OPT_HFILECERTSTORE_S("--hca=");
1.131 +static const std::string OPT_BFILECERTSTORE_L("--bfilecertstore=");
1.132 +static const std::string OPT_BFILECERTSTORE_S("--bca=");
1.133 +static const std::string OPT_HSWICERTSTORE_L("--hswicertstore=");
1.134 +static const std::string OPT_HSWICERTSTORE_S("--hswi=");
1.135 +static const std::string OPT_BSWICERTSTORE_L("--bswicertstore=");
1.136 +static const std::string OPT_BSWICERTSTORE_S("--bswi=");
1.137 +
1.138 +
1.139 +
1.140 +void usage()
1.141 +{
1.142 + prog << "certapp: general_options file_options --out file_options" << Log::Endl();
1.143 + prog << Log::Endl();
1.144 + prog << "Basic usage is to give one or more input files of any supported type, followed by --out and a list of output files using the same syntax" << Log::Endl();
1.145 + prog << "Typically at least one input file of type certclients should be given (via --bcertclients or --hcertclients) because this is required to encode/decode the application usage fields in the swicertstore and filecertstore files." << Log::Endl();
1.146 + prog << Log::Endl();
1.147 + prog << "general_options contains one or more of the following options:-" << Log::Endl();
1.148 + prog << "\t--help|-h\tDisplay this usage message" << Log::Endl();
1.149 + prog << "\t" << OPT_PROGRESS << "filename\tSave progress output to specified file" << Log::Endl();
1.150 + prog << "\t" << OPT_ERRORS << "filename\tSave error output to specified file" << Log::Endl();
1.151 + prog << "\t" << OPT_VERBOSE << "Include additional debug comments in output files" << Log::Endl();
1.152 + prog << "\t--license Display license information" << Log::Endl();
1.153 + prog << "\t--pemout Output certificates in PEM format (nb. format is auto-detected when reading)" << Log::Endl();
1.154 + prog << "\t" << OPT_ALLOWDUPLICATES << "\tWhen reading human readable config files, permit adding duplicate certificate labels in stores and UIDs in certclients (testing ONLY)" << Log::Endl();
1.155 + prog << "An errors/progress filename of - will write to the standard output." << Log::Endl();
1.156 + prog << "If the errors/progress filenames are identical, the output will be merged." << Log::Endl();
1.157 + prog << Log::Endl();
1.158 + prog << "Both instances of file_options contains one or more of the following options:-" << Log::Endl();
1.159 + prog << "\t" << OPT_HCERTCLIENTS_L << "|" << OPT_HCERTCLIENTS_S << "filename\t\tHuman readable certclients file" << Log::Endl();
1.160 + prog << "\t" << OPT_BCERTCLIENTS_L << "|" << OPT_BCERTCLIENTS_S << "filename\t\tBinary certclients file" << Log::Endl();
1.161 + prog << Log::Endl();
1.162 + prog << "\t" << OPT_HFILECERTSTORE_L << "|" << OPT_HFILECERTSTORE_S << "filename\tHuman readable filecertstore" << Log::Endl();
1.163 + prog << "\t" << OPT_BFILECERTSTORE_L << "|" << OPT_BFILECERTSTORE_S << "filename\tBinary filecertstore" << Log::Endl();
1.164 + prog << Log::Endl();
1.165 + prog << "\t" << OPT_HSWICERTSTORE_L << "|" << OPT_HSWICERTSTORE_S << "filename\tHuman readable swicertstore" << Log::Endl();
1.166 + prog << "\t" << OPT_BSWICERTSTORE_L << "|" << OPT_BSWICERTSTORE_S << "filename\tBinary swicertstore" << Log::Endl();
1.167 + prog << Log::Endl();
1.168 + prog << "\t" << "--out Change to specifying output files" << Log::Endl();
1.169 + prog << "\t" << "--in Change to specifying input files" << Log::Endl();
1.170 + prog << "\t" << "--chdir=relativeDir Change to the specified dir. Can be specified multiple times. Missing dir will be created if only last element is missing." << Log::Endl();
1.171 + prog << Log::Endl();
1.172 +
1.173 + prog << "Examples" << Log::Endl();
1.174 + prog << "Read/dump a swicertstore" << Log::Endl();
1.175 + prog << "\tcertapp --bcertclients=certclients.dat --bswicertstore=swicertstore.dat --out --hswicertstore=swicertstore.txt" << Log::Endl();
1.176 + prog << "Read/dump a filecertstore" << Log::Endl();
1.177 + prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --out --hfilecertstore=cacerts.txt" << Log::Endl();
1.178 + prog << "Augment a filecertstore" << Log::Endl();
1.179 + prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --hfilecertstore=cacerts_extras.txt --out --bfilecertstore=cacerts_new.dat" << Log::Endl();
1.180 + prog << Log::Endl();
1.181 + prog << "Device file locations" << Log::Endl();
1.182 + prog << "ROM swicertstore - z:\\resource\\swicertstore.dat" << Log::Endl();
1.183 + prog << "Writable swicertstore - !:\\resource\\swicertstore\\dat\\* where ! is the system drive" << Log::Endl();
1.184 + prog << "Initial filecertstore and certclients z:\\private\\101f72a6\\cacerts.dat and certclients.dat. Copied to sys drive on first use." << Log::Endl();
1.185 + prog << "Filecertstore !:\\private\\101f72a6\\cacerts.dat and certclients.dat. where ! is the system drive." << Log::Endl();
1.186 +}
1.187 +
1.188 +void ChangeDir(const std::string &aBaseDir, const std::string &aRelativeDir)
1.189 +{
1.190 + std::string dir(aBaseDir);
1.191 + if(aRelativeDir != ".")
1.192 + {
1.193 + // Build dir to create and change into
1.194 + dir.append(DIR_SEPARATOR);
1.195 + dir.append(aRelativeDir);
1.196 + }
1.197 +
1.198 + prog << Log::Indent() << "Setting dir to " << dir << Log::Endl();
1.199 +#ifdef __LINUX__
1.200 + (void) mkdir(dir.c_str(),0755); // May already exist so no need to check return code
1.201 +#else
1.202 + (void) mkdir(dir.c_str()); // May already exist so no need to check return code
1.203 +#endif
1.204 + if(chdir(dir.c_str()) < 0)
1.205 + {
1.206 + dbg << Log::Indent() << "failed to change dir to " << dir << Log::Endl();
1.207 + FatalError();
1.208 + }
1.209 + return;
1.210 +}
1.211 +
1.212 +int main(int argc, char **argv)
1.213 +{
1.214 + dbg.SetStream(&std::cout);
1.215 + prog.SetStream(&std::cout);
1.216 +
1.217 + try{
1.218 + if(argc==1)
1.219 + {
1.220 + prog << sVersion << " Use -h for help." << Log::Endl();
1.221 + }
1.222 +
1.223 + StringVector inputFiles;
1.224 + StringVector inputDirs;
1.225 + CertStoreFileTypeVector inputFileTypes;
1.226 +
1.227 + StringVector outputFiles;
1.228 + StringVector outputDirs;
1.229 + CertStoreFileTypeVector outputFileTypes;
1.230 +
1.231 +
1.232 + bool verbose = false;
1.233 + bool pemOut = false;
1.234 + bool allowDuplicates = false;
1.235 +
1.236 + // Process all the command line options and file arguments
1.237 + ProcessCommandLine(argc, argv,
1.238 + inputFiles, inputDirs, inputFileTypes,
1.239 + outputFiles, outputDirs, outputFileTypes,
1.240 + verbose, pemOut, allowDuplicates);
1.241 +
1.242 +
1.243 + // Save current directory
1.244 + std::string baseDir;
1.245 + {
1.246 + char tmp[FILENAME_MAX];
1.247 + if(getcwd(tmp, FILENAME_MAX) == 0)
1.248 + {
1.249 + dbg << Log::Indent() << "Failed to read current dir" << Log::Endl();
1.250 + FatalError();
1.251 + }
1.252 + baseDir = tmp;
1.253 + }
1.254 +
1.255 +
1.256 + //
1.257 + // Process input files starting with certclient files and working from right to left
1.258 + //
1.259 + EncDecContainer certAppInfoContainer("ClientInfo", CertificateAppInfo::Factory);
1.260 + ProcessCertClientFiles(baseDir, inputFiles, inputDirs, inputFileTypes,
1.261 + allowDuplicates,
1.262 + certAppInfoContainer);
1.263 +
1.264 +
1.265 + // Generate config data for application uid EncDecEnum object in AppUidListEntry
1.266 + AppUidMap::GenerateEnumEntries();
1.267 +
1.268 + //
1.269 + // Process remaining input files working from right to left
1.270 + //
1.271 + EncDecContainer fileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
1.272 + FCSLabelMap fcsLabels;
1.273 + EncDecContainer swiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
1.274 + FCSLabelMap swiLabels;
1.275 + for(int fileIndex = inputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
1.276 + {
1.277 + CertStoreFileType fileType = inputFileTypes[fileIndex];
1.278 + if((fileType == EBinFileCertStore) || (fileType == EHumanFileCertStore))
1.279 + {
1.280 + // Change to correct directory
1.281 + ChangeDir(baseDir, inputDirs[fileIndex]);
1.282 +
1.283 + EncDecContainer tmpFileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
1.284 + if(fileType == EBinFileCertStore)
1.285 + {
1.286 + prog << "Reading binary filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
1.287 + AutoIndent ai(prog);
1.288 + readContainer(inputFiles[fileIndex], false, tmpFileCertStoreContainer);
1.289 + }
1.290 + if(fileType == EHumanFileCertStore)
1.291 + {
1.292 + prog << "Reading human filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
1.293 + AutoIndent ai(prog);
1.294 + readContainer(inputFiles[fileIndex], true, tmpFileCertStoreContainer);
1.295 + }
1.296 +
1.297 + // Now merge the new file into the running store.
1.298 + prog << Log::Indent() << "Merging filecertstore data" << Log::Endl();
1.299 + AutoIndent ai(prog);
1.300 + for(TUint32 entryIndex = 0; entryIndex < tmpFileCertStoreContainer.size(); ++entryIndex)
1.301 + {
1.302 + const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(tmpFileCertStoreContainer[entryIndex]);
1.303 + std::string nname = stringFromUtf16(entry.Label());
1.304 +
1.305 + if(!ValidateLabel(fcsLabels, inputFiles, fileType, fileIndex, entry.Label()))
1.306 + {
1.307 + // Duplicate detected
1.308 + if(!allowDuplicates || (fileType == EBinFileCertStore))
1.309 + {
1.310 + continue; // Skip adding duplicate
1.311 + }
1.312 + // Only allow duplicates if debugging and reading
1.313 + // human readable config file.
1.314 + dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
1.315 + }
1.316 +
1.317 + // Add entry
1.318 + CertStoreEntry *newEntry = new CertStoreEntry;
1.319 + *newEntry = entry;
1.320 + fileCertStoreContainer.push_back(newEntry);
1.321 + }
1.322 + continue;
1.323 + }
1.324 +
1.325 +
1.326 + if((fileType == EBinSwiCertStore) || (fileType == EHumanSwiCertStore))
1.327 + {
1.328 + // Change to correct directory
1.329 + ChangeDir(baseDir, inputDirs[fileIndex]);
1.330 +
1.331 + EncDecContainer tmpSwiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
1.332 + if(fileType == EBinSwiCertStore)
1.333 + {
1.334 + prog << "Reading binary swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
1.335 + AutoIndent ai(prog);
1.336 + readContainer(inputFiles[fileIndex], false, tmpSwiCertStoreContainer);
1.337 + }
1.338 + if(fileType == EHumanSwiCertStore)
1.339 + {
1.340 + prog << "Reading human swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
1.341 + AutoIndent ai(prog);
1.342 + readContainer(inputFiles[fileIndex], true, tmpSwiCertStoreContainer);
1.343 + }
1.344 +
1.345 + // Now merge the new file into the running store.
1.346 + prog << Log::Indent() << "Merging swicerstore data" << Log::Endl();
1.347 + AutoIndent ai(prog);
1.348 + for(TUint32 entryIndex = 0; entryIndex < tmpSwiCertStoreContainer.size(); ++entryIndex)
1.349 + {
1.350 + const SwiCertStoreEntry &entry = static_cast<const SwiCertStoreEntry &>(tmpSwiCertStoreContainer[entryIndex]);
1.351 + std::string nname = stringFromUtf16(entry.Label());
1.352 +
1.353 + if(!ValidateLabel(swiLabels, inputFiles, fileType, fileIndex, entry.Label()))
1.354 + {
1.355 + // Duplicate detected
1.356 + if(!allowDuplicates || (fileType == EBinSwiCertStore))
1.357 + {
1.358 + continue; // Skip adding duplicate
1.359 + }
1.360 + // Only allow duplicates if debugging and reading
1.361 + // human readable config file.
1.362 + dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
1.363 + }
1.364 +
1.365 + // Add entry
1.366 + SwiCertStoreEntry *newEntry = new SwiCertStoreEntry;
1.367 + *newEntry = entry;
1.368 + swiCertStoreContainer.push_back(newEntry);
1.369 + }
1.370 + continue;
1.371 + }
1.372 + }
1.373 +
1.374 + // Fix Certificate IDs in fileCertStoreContainer
1.375 + for(TUint32 entryIndex=0; entryIndex < fileCertStoreContainer.size(); ++entryIndex)
1.376 + {
1.377 + CertStoreEntry &entry = static_cast<CertStoreEntry &>(fileCertStoreContainer[entryIndex]);
1.378 + entry.Info().SetOutputCertificateId(entryIndex);
1.379 + }
1.380 +
1.381 + // Fix Certificate IDs in swicertstore container.
1.382 + for(TUint32 entryIndex=0; entryIndex < swiCertStoreContainer.size(); ++entryIndex)
1.383 + {
1.384 + SwiCertStoreEntry &entry = static_cast<SwiCertStoreEntry &>(swiCertStoreContainer[entryIndex]);
1.385 + entry.Info().SetOutputCertificateId(entryIndex);
1.386 + }
1.387 +
1.388 + //
1.389 + // Fix auto IssuerKeyId values
1.390 + //
1.391 + SubjectToSubjectKeyIdMap subjectMap;
1.392 + //
1.393 + // Fix IssuerKeyId values in swiCertStoreContainer
1.394 + //
1.395 + // We do not use the AuthorityKeyId extension and only consider
1.396 + // certificates in swi certstores.
1.397 + //
1.398 + // First map all the SWI certificate subject names to SubjectKeyId values
1.399 + BuildSubjectToSubjectKeyIdMap(swiCertStoreContainer, subjectMap);
1.400 + // Now update IssuerKeyId fields which are set to auto.
1.401 + // The AuthorityKeyId extension value will be ignored.
1.402 + // The SubjectKeyId of a matching certificate (if there is a
1.403 + // single match on issuer name) in the swi cert store will be
1.404 + // used.
1.405 + SetIssuerKeyId(subjectMap, KIgnoreCertificateExtension, swiCertStoreContainer);
1.406 +
1.407 +
1.408 + //
1.409 + // Fix IssuerKeyId values in fileCertStoreContainer
1.410 + //
1.411 + // Add all filecertstore certificates to the
1.412 + // subjectName/SubjectKeyId map
1.413 + BuildSubjectToSubjectKeyIdMap(fileCertStoreContainer, subjectMap);
1.414 + // Now update IssuerKeyId fields which are set to auto. If an the
1.415 + // AuthorityKeyId extension is present and <160bits use it,
1.416 + // otherwise use the SubjectKeyId of the matching certificate (if
1.417 + // there is a single match on issuer name).
1.418 + SetIssuerKeyId(subjectMap, KUseCertificateExtension, fileCertStoreContainer);
1.419 +
1.420 + //
1.421 + // Now generate output files
1.422 + //
1.423 + GenerateOutputFiles(certAppInfoContainer, fileCertStoreContainer, swiCertStoreContainer,
1.424 + baseDir, outputFiles, outputDirs, outputFileTypes, verbose, pemOut);
1.425 +
1.426 +
1.427 + }
1.428 + catch(...)
1.429 + {
1.430 + dbg << Log::Indent() << "C++ expection!" << Log::Endl();
1.431 + FatalError();
1.432 + }
1.433 +
1.434 + prog << Log::Indent() << "Normal exit" << Log::Endl();
1.435 + prog.Stream().flush();
1.436 + dbg.Stream().flush();
1.437 + return 0; // All ok
1.438 +}
1.439 +
1.440 +/**
1.441 + ProcessCommandLine
1.442 +*/
1.443 +void ProcessCommandLine(int aArgc, char **aArgv,
1.444 + StringVector &aInputFiles, StringVector &aInputDirs, CertStoreFileTypeVector &aInputFileTypes,
1.445 + StringVector &aOutputFiles, StringVector &aOutputDirs, CertStoreFileTypeVector &aOutputFileTypes,
1.446 + bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates)
1.447 +{
1.448 + std::string progressFile("-");
1.449 + static std::fstream sProgressStream;
1.450 +
1.451 + std::string dbgFile("-");
1.452 + static std::fstream sDbgStream;
1.453 +
1.454 + StringVector *files = &aInputFiles;
1.455 + StringVector *dirs = &aInputDirs;
1.456 + CertStoreFileTypeVector *fileTypes = &aInputFileTypes;
1.457 +
1.458 + int argIndex=1;
1.459 + // Process overall arguments (-h --progress --errors)
1.460 + for(; argIndex < aArgc; ++argIndex)
1.461 + {
1.462 + std::string arg(aArgv[argIndex]);
1.463 +
1.464 + if(arg == "--license")
1.465 + {
1.466 + prog << sVersion << Log::Endl();
1.467 + prog << "Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies)." << Log::Endl();
1.468 + prog << "All rights reserved." << Log::Endl();
1.469 + prog << "This component and the accompanying materials are made available" << Log::Endl();
1.470 + prog << "under the terms of the License \"Eclipse Public License v1.0\"" << Log::Endl();
1.471 + prog << "which accompanies this distribution, and is available" << Log::Endl();
1.472 + prog << "at the URL \"http://www.eclipse.org/legal/epl-v10.html\"." << Log::Endl();
1.473 + prog << "Initial Contributors:" << Log::Endl();
1.474 + prog << "Nokia Corporation - initial contribution." << Log::Endl() << Log::Endl();
1.475 +
1.476 + prog << "Linked against openssl. Credits and license for openssl follow:-" << Log::Endl();
1.477 + prog << openssl_license << Log::Endl();
1.478 +
1.479 + continue;
1.480 + }
1.481 +
1.482 + if(arg == OPT_VERBOSE)
1.483 + {
1.484 + prog << "Enabling additional output file comments" << Log::Endl();
1.485 + aVerbose = true;
1.486 +
1.487 + continue;
1.488 + }
1.489 +
1.490 + if(arg == "--pemout")
1.491 + {
1.492 + prog << "Setting output certificate format to PEM" << Log::Endl();
1.493 + aPemOut = true;
1.494 +
1.495 + continue;
1.496 + }
1.497 +
1.498 + if(arg == OPT_ALLOWDUPLICATES)
1.499 + {
1.500 + prog << "Allowing addition of duplicate labels in stores and UIDs in certclients when reading human readable input (testing ONLY)" << Log::Endl();
1.501 + aAllowDuplicates = true;
1.502 +
1.503 + continue;
1.504 + }
1.505 +
1.506 + if((arg.find(OPT_PROGRESS) == 0) ||
1.507 + (arg.find(OPT_ERRORS) == 0))
1.508 + {
1.509 + // The following logic is required so that if both streams
1.510 + // are set to the same destination we share a streams
1.511 + // object and hence avoid buffering issues.
1.512 + std::string *thisFile;
1.513 + std::fstream *thisStream;
1.514 + Log *thisLog;
1.515 + std::string *otherFile;
1.516 + std::fstream *otherStream;
1.517 + Log *otherLog;
1.518 +
1.519 + if(arg.find(OPT_PROGRESS) == 0)
1.520 + {
1.521 + thisFile = &progressFile;
1.522 + thisStream = &sProgressStream;
1.523 + thisLog = &prog;
1.524 + otherFile = &dbgFile;
1.525 + otherStream = &sDbgStream;
1.526 + otherLog = &dbg;
1.527 +
1.528 + *thisFile = arg.substr(OPT_PROGRESS.size(), arg.npos);
1.529 + }
1.530 + else
1.531 + {
1.532 + thisFile = &dbgFile;
1.533 + thisStream = &sDbgStream;
1.534 + thisLog = &dbg;
1.535 + otherFile = &progressFile;
1.536 + otherStream = &sProgressStream;
1.537 + otherLog = &prog;
1.538 +
1.539 + *thisFile = arg.substr(OPT_ERRORS.size(), arg.npos);
1.540 + }
1.541 +
1.542 + if(*thisFile == *otherFile)
1.543 + {
1.544 + // Reuse existing stream. This avoids two streams opening the same file...
1.545 + thisLog->SetStream(&otherLog->Stream());
1.546 + continue;
1.547 + }
1.548 +
1.549 + // Need to open a new stream
1.550 + if(thisStream->is_open()) thisStream->close();
1.551 + if(*thisFile == "-")
1.552 + {
1.553 + thisLog->SetStream(&std::cout);
1.554 + continue;
1.555 + }
1.556 +
1.557 + OpenUtf8FStreamForWrite(*thisStream, thisFile->c_str());
1.558 + if(thisStream->fail())
1.559 + {
1.560 + if(thisLog == &dbg)
1.561 + {
1.562 + dbg.SetStream(&std::cout);
1.563 + }
1.564 + dbg << Log::Indent() << "Failed to open log file specified by " << aArgv[argIndex-1] << " '" << *thisFile << "'" << Log::Endl();
1.565 + return;
1.566 + }
1.567 + thisLog->SetStream(thisStream);
1.568 + continue;
1.569 + }
1.570 +
1.571 + if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
1.572 + {
1.573 + usage();
1.574 + continue;
1.575 + }
1.576 +
1.577 + // Not a general option, probably an input file...
1.578 + break;
1.579 + }
1.580 +
1.581 + // Process main arguments
1.582 + for(; argIndex < aArgc; ++argIndex)
1.583 + {
1.584 + std::string arg(aArgv[argIndex]);
1.585 +
1.586 + bool gotFile = false;
1.587 + if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
1.588 + {
1.589 + usage();
1.590 + continue;
1.591 + }
1.592 +
1.593 + if(arg.find(OPT_CHDIR) == 0)
1.594 + {
1.595 + dirs->push_back(arg.substr(OPT_CHDIR.size(), arg.npos));
1.596 + // Move to next option
1.597 + ++argIndex;
1.598 + if(argIndex >= aArgc) break;
1.599 + arg = aArgv[argIndex];
1.600 + }
1.601 + else
1.602 + {
1.603 + dirs->push_back(".");
1.604 + }
1.605 +
1.606 + std::string fileArg;
1.607 + if(arg.find(OPT_BCERTCLIENTS_L) == 0)
1.608 + {
1.609 + fileTypes->push_back(EBinCertClients);
1.610 + fileArg = arg.substr(OPT_BCERTCLIENTS_L.size(), arg.npos);
1.611 + gotFile = true;
1.612 + }
1.613 + if(arg.find(OPT_BCERTCLIENTS_S) == 0)
1.614 + {
1.615 + fileTypes->push_back(EBinCertClients);
1.616 + fileArg = arg.substr(OPT_BCERTCLIENTS_S.size(), arg.npos);
1.617 + gotFile = true;
1.618 + }
1.619 + if(arg.find(OPT_HCERTCLIENTS_L) == 0)
1.620 + {
1.621 + fileTypes->push_back(EHumanCertClients);
1.622 + fileArg = arg.substr(OPT_HCERTCLIENTS_L.size(), arg.npos);
1.623 + gotFile = true;
1.624 + }
1.625 + if(arg.find(OPT_HCERTCLIENTS_S) == 0)
1.626 + {
1.627 + fileTypes->push_back(EHumanCertClients);
1.628 + fileArg = arg.substr(OPT_HCERTCLIENTS_S.size(), arg.npos);
1.629 + gotFile = true;
1.630 + }
1.631 + if(arg.find(OPT_BFILECERTSTORE_L) == 0)
1.632 + {
1.633 + fileTypes->push_back(EBinFileCertStore);
1.634 + fileArg = arg.substr(OPT_BFILECERTSTORE_L.size(), arg.npos);
1.635 + gotFile = true;
1.636 + }
1.637 + if(arg.find(OPT_BFILECERTSTORE_S) == 0)
1.638 + {
1.639 + fileTypes->push_back(EBinFileCertStore);
1.640 + fileArg = arg.substr(OPT_BFILECERTSTORE_S.size(), arg.npos);
1.641 + gotFile = true;
1.642 + }
1.643 + if(arg.find(OPT_HFILECERTSTORE_L) == 0)
1.644 + {
1.645 + fileTypes->push_back(EHumanFileCertStore);
1.646 + fileArg = arg.substr(OPT_HFILECERTSTORE_L.size(), arg.npos);
1.647 + gotFile = true;
1.648 + }
1.649 + if(arg.find(OPT_HFILECERTSTORE_S) == 0)
1.650 + {
1.651 + fileTypes->push_back(EHumanFileCertStore);
1.652 + fileArg = arg.substr(OPT_HFILECERTSTORE_S.size(), arg.npos);
1.653 + gotFile = true;
1.654 + }
1.655 + if(arg.find(OPT_BSWICERTSTORE_L) == 0)
1.656 + {
1.657 + fileTypes->push_back(EBinSwiCertStore);
1.658 + fileArg = arg.substr(OPT_BSWICERTSTORE_L.size(), arg.npos);
1.659 + gotFile = true;
1.660 + }
1.661 + if(arg.find(OPT_BSWICERTSTORE_S) == 0)
1.662 + {
1.663 + fileTypes->push_back(EBinSwiCertStore);
1.664 + fileArg = arg.substr(OPT_BSWICERTSTORE_S.size(), arg.npos);
1.665 + gotFile = true;
1.666 + }
1.667 + if(arg.find(OPT_HSWICERTSTORE_L) == 0)
1.668 + {
1.669 + fileTypes->push_back(EHumanSwiCertStore);
1.670 + fileArg = arg.substr(OPT_HSWICERTSTORE_L.size(), arg.npos);
1.671 + gotFile = true;
1.672 + }
1.673 + if(arg.find(OPT_HSWICERTSTORE_S) == 0)
1.674 + {
1.675 + fileTypes->push_back(EHumanSwiCertStore);
1.676 + fileArg = arg.substr(OPT_HSWICERTSTORE_S.size(), arg.npos);
1.677 + gotFile = true;
1.678 + }
1.679 +
1.680 + if(arg.find("--out") == 0)
1.681 + {
1.682 + files = &aOutputFiles;
1.683 + dirs = &aOutputDirs;
1.684 + fileTypes = &aOutputFileTypes;
1.685 + continue;
1.686 + }
1.687 +
1.688 + if(arg.find("--in") == 0)
1.689 + {
1.690 + files = &aInputFiles;
1.691 + dirs = &aInputDirs;
1.692 + fileTypes = &aInputFileTypes;
1.693 + continue;
1.694 + }
1.695 +
1.696 + if(gotFile)
1.697 + {
1.698 + files->push_back(fileArg);
1.699 + continue;
1.700 + }
1.701 +
1.702 + usage();
1.703 + dbg << Log::Indent() << "Unknown option " << (const char *) aArgv[argIndex] << Log::Endl();
1.704 + FatalError();
1.705 + }
1.706 + return;
1.707 +}
1.708 +
1.709 +void ProcessCertClientFiles(const std::string &aBaseDir,
1.710 + const StringVector &aInputFiles,
1.711 + const StringVector &aInputDirs,
1.712 + const CertStoreFileTypeVector &aInputFileTypes,
1.713 + bool &aAllowDuplicates,
1.714 + EncDecContainer &aCertAppInfoContainer)
1.715 +{
1.716 + AppMap appMap;
1.717 + for(int fileIndex = aInputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
1.718 + {
1.719 + CertStoreFileType fileType = aInputFileTypes[fileIndex];
1.720 + if((fileType != EBinCertClients) && (fileType != EHumanCertClients))
1.721 + {
1.722 + continue;
1.723 + }
1.724 +
1.725 + // Change to correct directory
1.726 + ChangeDir(aBaseDir, aInputDirs[fileIndex]);
1.727 +
1.728 + EncDecContainer tmpCertInfoContainer("ClientInfo", CertificateAppInfo::Factory);
1.729 +
1.730 + if(fileType == EBinCertClients)
1.731 + {
1.732 + prog << Log::Indent() << "Reading binary certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
1.733 + AutoIndent ai(prog);
1.734 + readContainer(aInputFiles[fileIndex], false, tmpCertInfoContainer);
1.735 + }
1.736 + else
1.737 + {
1.738 + prog << Log::Indent() << "Reading human certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
1.739 + AutoIndent ai(prog);
1.740 + readContainer(aInputFiles[fileIndex], true, tmpCertInfoContainer);
1.741 + }
1.742 +
1.743 + // Now merge the new file into the running store.
1.744 + prog << Log::Indent() << "Merging certclients data" << Log::Endl();
1.745 + AutoIndent ai(prog);
1.746 + AutoIndent ai2(dbg);
1.747 + for(TUint32 entryIndex = 0; entryIndex < tmpCertInfoContainer.size(); ++entryIndex)
1.748 + {
1.749 + const CertificateAppInfo &info = static_cast<const CertificateAppInfo &>(tmpCertInfoContainer[entryIndex]);
1.750 + std::string nname = stringFromUtf16(info.Name());
1.751 + //prog << Log::Indent() << "checking " << nname << Log::Endl();
1.752 +
1.753 +
1.754 + TInt32 lastIndex;
1.755 + std::string firstDef;
1.756 + if(!AppUidMap::InsertUidDefinition(info.Id().iUid, nname, fileIndex,
1.757 + lastIndex, firstDef))
1.758 + {
1.759 + // Duplicate entry for UID
1.760 + if(nname == firstDef)
1.761 + {
1.762 + // But both entries have the same value
1.763 + prog << Log::Indent() << "Duplicate, but identical, entries for UID 0x" << info.Id().iUid << " '" << nname << "'." << Log::Endl();
1.764 + AutoIndent ai(prog);
1.765 + prog << Log::Indent() << "From files '" << aInputFiles[lastIndex] << "' and '" << aInputFiles[fileIndex] << "'." << Log::Endl();
1.766 + }
1.767 + else
1.768 + {
1.769 + // Entries have different values
1.770 + dbg << Log::Indent() << "DUPLICATE entry for UID 0x" << info.Id().iUid << Log::Endl();
1.771 + AutoIndent ai(dbg);
1.772 + dbg << Log::Indent() << "Ignoring '" << nname << "' from '" << aInputFiles[fileIndex] << "'." << Log::Endl();
1.773 + dbg << Log::Indent() << "Keeping '" << firstDef << "' from '" << aInputFiles[lastIndex] << "'." << Log::Endl();
1.774 + if(lastIndex == fileIndex)
1.775 + {
1.776 + if(fileType == EBinCertClients)
1.777 + {
1.778 + dbg << Log::Indent() << "Both entries are in the same binary same file!" << Log::Endl();
1.779 + continue; // Skip adding duplicate
1.780 + }
1.781 + dbg << Log::Indent() << "Clash is within a single text configuration file!" << Log::Endl();
1.782 + if(!aAllowDuplicates)
1.783 + {
1.784 + FatalError();
1.785 + }
1.786 + }
1.787 + }
1.788 +
1.789 + // Only add duplicates when debugging and the add is
1.790 + // from a human readable config file.
1.791 + if(!aAllowDuplicates || (fileType != EHumanCertClients))
1.792 + {
1.793 + continue; // Skip adding duplicate
1.794 + }
1.795 + dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
1.796 + }
1.797 +
1.798 + // Add entry
1.799 + CertificateAppInfo *newInfo = new CertificateAppInfo;
1.800 + *newInfo = info;
1.801 + aCertAppInfoContainer.push_back(newInfo);
1.802 + }
1.803 + }
1.804 +}
1.805 +
1.806 +
1.807 +
1.808 +/**
1.809 + Write output files to disk
1.810 + */
1.811 +void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
1.812 + const EncDecContainer &aFileCertStoreContainer,
1.813 + const EncDecContainer &aSwiCertStoreContainer,
1.814 + const std::string &aBaseDir,
1.815 + const StringVector &aOutputFiles,
1.816 + const StringVector &aOutputDirs,
1.817 + const CertStoreFileTypeVector &aOutputFileTypes,
1.818 + bool aVerbose, bool aPemOut)
1.819 +{
1.820 + for(int fileIndex = aOutputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
1.821 + {
1.822 + // Change to correct directory
1.823 + ChangeDir(aBaseDir, aOutputDirs[fileIndex]);
1.824 +
1.825 + CertStoreFileType fileType = aOutputFileTypes[fileIndex];
1.826 + //
1.827 + // Set the container and write mode to use
1.828 + //
1.829 + const EncDecContainer *container = 0;
1.830 + bool humanReadable = false;
1.831 + if(fileType == EBinCertClients)
1.832 + {
1.833 + container = &aCertAppInfoContainer;
1.834 + humanReadable = false;
1.835 + }
1.836 + if(fileType == EHumanCertClients)
1.837 + {
1.838 + container = &aCertAppInfoContainer;
1.839 + humanReadable = true;
1.840 + }
1.841 + if(fileType == EBinFileCertStore)
1.842 + {
1.843 + container = &aFileCertStoreContainer;
1.844 + humanReadable = false;
1.845 + }
1.846 + if(fileType == EHumanFileCertStore)
1.847 + {
1.848 + container = &aFileCertStoreContainer;
1.849 + humanReadable = true;
1.850 + }
1.851 + if(fileType == EBinSwiCertStore)
1.852 + {
1.853 + container = &aSwiCertStoreContainer;
1.854 + humanReadable = false;
1.855 + }
1.856 + if(fileType == EHumanSwiCertStore)
1.857 + {
1.858 + container = &aSwiCertStoreContainer;
1.859 + humanReadable = true;
1.860 + }
1.861 +
1.862 + if(container == 0)
1.863 + {
1.864 + // failed to decode the output file type!
1.865 + FatalError();
1.866 + }
1.867 + //
1.868 + // Write the container out
1.869 + //
1.870 + writeContainer(aOutputFiles[fileIndex].c_str(), humanReadable, aPemOut, aVerbose, *container);
1.871 + }
1.872 + return;
1.873 +}
1.874 +
1.875 +
1.876 +
1.877 +/**
1.878 + ValidateLabel
1.879 +
1.880 + This function maintains a map of certificate labels to input file
1.881 + (ie file index) and definition.
1.882 +
1.883 + If the label is NOT already defined in the map, then the function
1.884 + returns true, which instructs the caller to include the
1.885 + label/certificate in the generated store.
1.886 +
1.887 + If the label is already defined in the map, then the function
1.888 + returns false, which instructs the caller to NOT include the
1.889 + label/certificate in the generated store.
1.890 +
1.891 + The files on the command line are processed right to left, so if
1.892 + multiple definitions (for the same label) are seen, only the first
1.893 + will be included in the generated store.
1.894 +
1.895 + The information saved in the map is used to generate helpful
1.896 + warning/error messages as follows:-
1.897 +
1.898 + 1) The saved definition is the first definition encountered, and is
1.899 + therefore the one which has been included in the store.
1.900 +
1.901 + 2) The saved file index is the index of the LAST file processed
1.902 + containing a definition for this label. This may be different to
1.903 + the one containing the first definition.
1.904 +
1.905 + Consider the following sequence:-
1.906 +
1.907 + First processed file - Definition for label Fred
1.908 + Second processed file - Another two definitions for label Fred
1.909 +
1.910 + When processing the third definition (in the second file), the
1.911 + saved file index will be that of the second file. The code uses
1.912 + this to check if there are multiple definitions within a SINGLE
1.913 + input file, for the same label.
1.914 +
1.915 + If the multiple definitions are within a single human readable
1.916 + file, then this is considered a fatal error, otherwise only a
1.917 + warning is generated.
1.918 +
1.919 + Duplicate definitions in different files, generate a warning.
1.920 + */
1.921 +bool ValidateLabel(FCSLabelMap &aLabelMap,
1.922 + const StringVector &aInputFiles,
1.923 + CertStoreFileType aFileType,
1.924 + TUint32 aFileIndex,
1.925 + const TCertLabel &aCertLabel)
1.926 +{
1.927 + std::string nname = stringFromUtf16(aCertLabel);
1.928 + FCSLabelMap::value_type e(nname, aFileIndex);
1.929 + std::pair<FCSLabelMap::iterator,bool> result = aLabelMap.insert(e);
1.930 + if(result.second == true)
1.931 + {
1.932 + // Not a duplicate
1.933 + return true;
1.934 + }
1.935 +
1.936 + // Duplicate label entry
1.937 + dbg << Log::Indent() << "DUPLICATE label detected in '" << aInputFiles[aFileIndex] << "'." << Log::Endl();
1.938 + AutoIndent ai(dbg);
1.939 + dbg << Log::Indent() << "Duplicate entry for '" << e.first << "' ignored. Keeping entry from '" << aInputFiles[(*result.first).second] << "'" <<Log::Endl();
1.940 + if((result.first)->second == TUint32(aFileIndex))
1.941 + {
1.942 + dbg << Log::Indent() << "Both entries are in the same file." << Log::Endl();
1.943 + if((aFileType == EHumanFileCertStore) || (aFileType == EHumanSwiCertStore))
1.944 + {
1.945 + dbg << Log::Indent() << "FATAL error - Clash is within a single text configuration file - aborting!" << Log::Endl();
1.946 + FatalError();
1.947 + }
1.948 + return false; // Insert failed, keep earlier def
1.949 + }
1.950 + else
1.951 + {
1.952 + // Update file index for last definition. This is used to
1.953 + // detect if the last two defs were within a single file.
1.954 + (result.first)->second = TUint32(aFileIndex);
1.955 + return false; // Insert failed, keep earlier def
1.956 + }
1.957 + return false;
1.958 +}
1.959 +
1.960 +void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
1.961 + SubjectToSubjectKeyIdMap &aSubjectMap)
1.962 +{
1.963 + // Collect subjectName/SubjectKeyId for all certs
1.964 + for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
1.965 + {
1.966 + const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(aCertStoreContainer[entryIndex]);
1.967 + if(entry.Info().CertificateFormat() != EX509Certificate)
1.968 + {
1.969 + continue;
1.970 + }
1.971 +
1.972 + std::pair<SubjectToSubjectKeyIdMap::key_type, SubjectToSubjectKeyIdMap::mapped_type> e;
1.973 + e.first = entry.CertSubject();
1.974 + e.second.iDuplicate = false;
1.975 + e.second.iLabel = stringFromUtf16(entry.Label());
1.976 + e.second.iSubjectKeyIdentifier = entry.Info().SubjectKeyId().iHash;
1.977 + std::pair<SubjectToSubjectKeyIdMap::iterator, bool> result = aSubjectMap.insert(e);
1.978 + if(result.second == false)
1.979 + {
1.980 + dbg << Log::Indent() << "WARNING: Certificate '" << e.second.iLabel << "' has a subject name of '" << e.first << "' which clashes with certificate '" << (*result.first).second.iLabel <<"'" << Log::Endl();
1.981 + (*result.first).second.iDuplicate = true;
1.982 + }
1.983 + }
1.984 +
1.985 +}
1.986 +
1.987 +
1.988 +void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap,
1.989 + EUseCertificateExtension aUseExtension,
1.990 + EncDecContainer &aCertStoreContainer)
1.991 +{
1.992 + // Now loop across certs setting the issuer key id.
1.993 + for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
1.994 + {
1.995 + CertStoreEntry &entry = static_cast<CertStoreEntry &>(aCertStoreContainer[entryIndex]);
1.996 + if(entry.Info().CertificateFormat() != EX509Certificate)
1.997 + {
1.998 + continue;
1.999 + }
1.1000 + if(!entry.Info().IssuerKeyId().iAutoKey)
1.1001 + {
1.1002 + continue;
1.1003 + }
1.1004 +
1.1005 + std::string certLabel = stringFromUtf16(entry.Label());
1.1006 +
1.1007 + prog << Log::Indent() << "Attempting to auto set IssuerIeyId for '" << certLabel << "'" << Log::Endl();
1.1008 +
1.1009 + AutoIndent ai(prog);
1.1010 +
1.1011 + // Lookup issuer key id in certificate extension and if found use that.
1.1012 + //
1.1013 + // X509IssuerKeyId will always set the issuerName.
1.1014 + // If aIgnoreExtension is false, then it will attempt to read
1.1015 + // the AuthorityKeyId extension. If found (and <160bits), it
1.1016 + // will write the ID to issuerId and return true.
1.1017 + // Otherwise it will return false.
1.1018 + // Certificate read errors are fatal.
1.1019 + std::string issuerName;
1.1020 + TKeyIdentifier issuerId;
1.1021 + if(X509IssuerKeyId(aUseExtension,
1.1022 + entry.CertData(), entry.Info().CertSize(),
1.1023 + issuerName, issuerId))
1.1024 + {
1.1025 + // There is an authority key id extension so use its value
1.1026 + prog << Log::Indent() << "Using value from certificate '" << certLabel << "' extension" << Log::Endl();
1.1027 + entry.Info().IssuerKeyId().iHash = issuerId;
1.1028 + }
1.1029 + else
1.1030 + {
1.1031 + // No extension so lookup issuerName in the map
1.1032 + prog << Log::Indent() << "Looking up issuer '" << issuerName << "' in map" << Log::Endl();
1.1033 + SubjectToSubjectKeyIdMap::const_iterator it = aSubjectMap.find(issuerName);
1.1034 + if(it == aSubjectMap.end())
1.1035 + {
1.1036 + prog << Log::Indent() << "Not found - Using empty IssuerKeyId " << Log::Endl();
1.1037 + }
1.1038 + else
1.1039 + {
1.1040 + if((*it).second.iDuplicate)
1.1041 + {
1.1042 + prog << Log::Indent() << "Found - but multiple certs with matching subject name - Using empty IssuerKeyId" << Log::Endl();
1.1043 + }
1.1044 + else
1.1045 + {
1.1046 + prog << Log::Indent() << "Found - Using Subject Key of matching cert" << Log::Endl();
1.1047 + entry.Info().IssuerKeyId().iHash = (*it).second.iSubjectKeyIdentifier;
1.1048 + }
1.1049 + }
1.1050 + }
1.1051 + }
1.1052 +
1.1053 +}
1.1054 +
1.1055 +
1.1056 +
1.1057 +// End of file