securityanddataprivacytools/securitytools/certapp/certapp.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     1 /*
       
     2 * Copyright (c) 2008-2009 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 the License "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: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 static const char * const sVersion = "certapp version 1.1.++";
       
    20 #include <e32base.h>
       
    21 #include <f32file.h>
       
    22 #include <s32file.h>
       
    23 #include <map>
       
    24 #include <sys/stat.h>
       
    25 #include "encdec.h"
       
    26 #include "certclients.h"
       
    27 #include "filecertstore.h"
       
    28 #include "swicertstore.h"
       
    29 #include "logger.h"
       
    30 #include "stringconv.h"
       
    31 #include <errno.h>
       
    32 #include "appuidmap.h"
       
    33 #include "openssl_license.h"
       
    34 #include "utils.h"
       
    35 
       
    36 #ifdef __TOOLS2_LINUX__
       
    37 #include <unistd.h>
       
    38 #include <stdio.h>
       
    39 #else
       
    40 #include <io.h>
       
    41 #endif // __TOOLS2_LINUX__
       
    42 
       
    43 #ifdef __TOOLS2_LINUX__
       
    44 #define DIR_SEPARATOR "/"
       
    45 #else
       
    46 #define DIR_SEPARATOR "\\"
       
    47 #endif
       
    48 
       
    49 enum CertStoreFileType
       
    50 {
       
    51 	EBinCertClients,
       
    52 	EHumanCertClients,
       
    53 	EBinFileCertStore,
       
    54 	EHumanFileCertStore,
       
    55 	EBinSwiCertStore,
       
    56 	EHumanSwiCertStore
       
    57 };
       
    58 
       
    59 struct AppMapEntry
       
    60 	{
       
    61 	TUint32 iUid;
       
    62 	TUint32 iInputFileIndex;
       
    63 	};
       
    64 typedef std::map<std::string, AppMapEntry> AppMap;
       
    65 
       
    66 typedef std::map<std::string, TUint32> FCSLabelMap; // maps cert label to inputFileIndex
       
    67 
       
    68 typedef std::vector<std::string> StringVector;
       
    69 typedef std::vector<CertStoreFileType> CertStoreFileTypeVector;
       
    70 
       
    71 void ProcessCommandLine(int aArgc, char **aArgv, 
       
    72 						StringVector &aInputFiles, 
       
    73 						StringVector &aInputDirs,
       
    74 						CertStoreFileTypeVector &aInputFileTypes,
       
    75 						StringVector &aOutputFiles,
       
    76 						StringVector &aOutputDirs,
       
    77 						CertStoreFileTypeVector &aOutputFileTypes,
       
    78 						bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates);
       
    79 
       
    80 void ProcessCertClientFiles(const std::string &aBaseDir,
       
    81 							const StringVector &aInputFiles,
       
    82 							const StringVector &aInputDirs,
       
    83 							const CertStoreFileTypeVector &aInputFileTypes,
       
    84 							bool &aAllowDuplicates,
       
    85 							EncDecContainer &aCertAppInfoContainer);
       
    86 
       
    87 void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
       
    88 						 const EncDecContainer &aFileCertStoreContainer,
       
    89 						 const EncDecContainer &aSwiCertStoreContainer,
       
    90 						 const std::string &aBaseDir,
       
    91 						 const StringVector &aOutputFiles, 
       
    92 						 const StringVector &aOutputDirs,
       
    93 						 const CertStoreFileTypeVector &aOutputFileTypes,
       
    94 						 bool aVerbose, bool aPemOut);
       
    95 
       
    96 bool ValidateLabel(FCSLabelMap &aLabelMap, 
       
    97 				   const StringVector &aInputFiles, 
       
    98 				   CertStoreFileType aFileType,
       
    99 				   TUint32 aFileIndex, 
       
   100 				   const TCertLabel &aCertLabel);
       
   101 
       
   102 
       
   103 struct SubjectToSubjectKeyIdEntry
       
   104 	{
       
   105 	bool iDuplicate;
       
   106 	std::string iLabel;
       
   107 	TKeyIdentifier iSubjectKeyIdentifier;
       
   108 	};
       
   109 typedef std::map<std::string, SubjectToSubjectKeyIdEntry> SubjectToSubjectKeyIdMap;
       
   110 void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
       
   111 								   SubjectToSubjectKeyIdMap &aSubjectMap);
       
   112 
       
   113 void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap, 
       
   114 					EUseCertificateExtension aUseExtension,
       
   115 					EncDecContainer &aCertStoreContainer);
       
   116 
       
   117 static const std::string OPT_PROGRESS("--progress=");
       
   118 static const std::string OPT_ERRORS("--errors=");
       
   119 static const std::string OPT_VERBOSE("--verbose");
       
   120 static const std::string OPT_ALLOWDUPLICATES("--allowduplicates");
       
   121 static const std::string OPT_CHDIR("--chdir=");
       
   122 static const std::string OPT_HCERTCLIENTS_L("--hcertclients=");
       
   123 static const std::string OPT_HCERTCLIENTS_S("--hcc=");
       
   124 static const std::string OPT_BCERTCLIENTS_L("--bcertclients=");
       
   125 static const std::string OPT_BCERTCLIENTS_S("--bcc=");
       
   126 static const std::string OPT_HFILECERTSTORE_L("--hfilecertstore=");
       
   127 static const std::string OPT_HFILECERTSTORE_S("--hca=");
       
   128 static const std::string OPT_BFILECERTSTORE_L("--bfilecertstore=");
       
   129 static const std::string OPT_BFILECERTSTORE_S("--bca=");
       
   130 static const std::string OPT_HSWICERTSTORE_L("--hswicertstore=");
       
   131 static const std::string OPT_HSWICERTSTORE_S("--hswi=");
       
   132 static const std::string OPT_BSWICERTSTORE_L("--bswicertstore=");
       
   133 static const std::string OPT_BSWICERTSTORE_S("--bswi=");
       
   134 
       
   135 
       
   136 
       
   137 void usage()
       
   138 {
       
   139 	prog << "certapp: general_options file_options --out file_options" << Log::Endl();
       
   140 	prog << Log::Endl();
       
   141 	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();
       
   142 	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();
       
   143 	prog << Log::Endl();
       
   144 	prog << "general_options contains one or more of the following options:-" << Log::Endl();
       
   145 	prog << "\t--help|-h\tDisplay this usage message" << Log::Endl();
       
   146 	prog << "\t" << OPT_PROGRESS << "filename\tSave progress output to specified file" << Log::Endl();
       
   147 	prog << "\t" << OPT_ERRORS << "filename\tSave error output to specified file" << Log::Endl();
       
   148 	prog << "\t" << OPT_VERBOSE << "Include additional debug comments in output files" << Log::Endl();
       
   149 	prog << "\t--license Display license information" << Log::Endl();
       
   150 	prog << "\t--pemout Output certificates in PEM format (nb. format is auto-detected when reading)" << Log::Endl();
       
   151 	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();
       
   152 	prog << "An errors/progress filename of - will write to the standard output." << Log::Endl();
       
   153 	prog << "If the errors/progress filenames are identical, the output will be merged." << Log::Endl();
       
   154 	prog << Log::Endl();
       
   155 	prog << "Both instances of file_options contains one or more of the following options:-" << Log::Endl();
       
   156 	prog << "\t" << OPT_HCERTCLIENTS_L << "|" << OPT_HCERTCLIENTS_S << "filename\t\tHuman readable certclients file" << Log::Endl();
       
   157 	prog << "\t" << OPT_BCERTCLIENTS_L << "|" << OPT_BCERTCLIENTS_S << "filename\t\tBinary certclients file" << Log::Endl();
       
   158 	prog << Log::Endl();
       
   159 	prog << "\t" << OPT_HFILECERTSTORE_L << "|" << OPT_HFILECERTSTORE_S << "filename\tHuman readable filecertstore" << Log::Endl();
       
   160 	prog << "\t" << OPT_BFILECERTSTORE_L << "|" << OPT_BFILECERTSTORE_S << "filename\tBinary filecertstore" << Log::Endl();
       
   161 	prog << Log::Endl();
       
   162 	prog << "\t" << OPT_HSWICERTSTORE_L << "|" << OPT_HSWICERTSTORE_S << "filename\tHuman readable swicertstore" << Log::Endl();
       
   163 	prog << "\t" << OPT_BSWICERTSTORE_L << "|" << OPT_BSWICERTSTORE_S << "filename\tBinary swicertstore" << Log::Endl();
       
   164 	prog << Log::Endl();
       
   165 	prog << "\t" << "--out Change to specifying output files" << Log::Endl();
       
   166 	prog << "\t" << "--in Change to specifying input files" << Log::Endl();
       
   167 	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();	
       
   168 	prog << Log::Endl();
       
   169 	
       
   170 	prog << "Examples" << Log::Endl();
       
   171 	prog << "Read/dump a swicertstore" << Log::Endl();
       
   172 	prog << "\tcertapp --bcertclients=certclients.dat --bswicertstore=swicertstore.dat --out --hswicertstore=swicertstore.txt" << Log::Endl();
       
   173 	prog << "Read/dump a filecertstore" << Log::Endl();
       
   174 	prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --out --hfilecertstore=cacerts.txt" << Log::Endl();
       
   175 	prog << "Augment a filecertstore" << Log::Endl();
       
   176 	prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --hfilecertstore=cacerts_extras.txt --out --bfilecertstore=cacerts_new.dat" << Log::Endl();
       
   177 	prog << Log::Endl();
       
   178 	prog << "Device file locations" << Log::Endl();
       
   179 	prog << "ROM swicertstore - z:\\resource\\swicertstore.dat" << Log::Endl();
       
   180 	prog << "Writable swicertstore - !:\\resource\\swicertstore\\dat\\* where ! is the system drive" << Log::Endl();
       
   181 	prog << "Initial filecertstore and certclients z:\\private\\101f72a6\\cacerts.dat and certclients.dat. Copied to sys drive on first use." << Log::Endl();
       
   182 	prog << "Filecertstore !:\\private\\101f72a6\\cacerts.dat and certclients.dat. where ! is the system drive." << Log::Endl();
       
   183 }
       
   184 
       
   185 void ChangeDir(const std::string &aBaseDir, const std::string &aRelativeDir)
       
   186 {
       
   187 	std::string dir(aBaseDir);
       
   188 	if(aRelativeDir != ".")
       
   189 		{
       
   190 		// Build dir to create and change into
       
   191 		dir.append(DIR_SEPARATOR);
       
   192 		dir.append(aRelativeDir);
       
   193 		}
       
   194 		
       
   195 	prog << Log::Indent() << "Setting dir to " << dir << Log::Endl();
       
   196 #ifdef __LINUX__
       
   197 	(void) mkdir(dir.c_str(),0755); // May already exist so no need to check return code
       
   198 #else
       
   199 	(void) mkdir(dir.c_str()); // May already exist so no need to check return code
       
   200 #endif
       
   201 	if(chdir(dir.c_str()) < 0)
       
   202 		{
       
   203 		dbg << Log::Indent() << "failed to change dir to " << dir << Log::Endl();
       
   204 		FatalError();
       
   205 		}
       
   206 	return;
       
   207 }
       
   208 
       
   209 int main(int argc, char **argv)
       
   210 {
       
   211 	dbg.SetStream(&std::cout);
       
   212 	prog.SetStream(&std::cout);
       
   213 
       
   214 	try{
       
   215 	if(argc==1)
       
   216 		{
       
   217 		prog << sVersion << " Use -h for help." << Log::Endl();
       
   218 		}
       
   219 
       
   220 	StringVector inputFiles;
       
   221 	StringVector inputDirs;
       
   222 	CertStoreFileTypeVector inputFileTypes;
       
   223 
       
   224 	StringVector outputFiles;
       
   225 	StringVector outputDirs;
       
   226 	CertStoreFileTypeVector outputFileTypes;
       
   227 
       
   228 
       
   229 	bool verbose = false;
       
   230 	bool pemOut = false;
       
   231 	bool allowDuplicates = false;
       
   232 
       
   233 	// Process all the command line options and file arguments
       
   234 	ProcessCommandLine(argc, argv, 
       
   235 					   inputFiles, inputDirs, inputFileTypes,
       
   236 					   outputFiles, outputDirs, outputFileTypes,
       
   237 					   verbose, pemOut, allowDuplicates);
       
   238 
       
   239 
       
   240 	// Save current directory
       
   241 	std::string baseDir;
       
   242 	{
       
   243 	char tmp[FILENAME_MAX];
       
   244 	if(getcwd(tmp, FILENAME_MAX) == 0)
       
   245 		{
       
   246 		dbg << Log::Indent() << "Failed to read current dir" << Log::Endl();
       
   247 		FatalError();
       
   248 		}
       
   249 	baseDir = tmp;
       
   250 	}
       
   251 	
       
   252 
       
   253 	//
       
   254 	// Process input files starting with certclient files and working from right to left
       
   255 	//
       
   256 	EncDecContainer certAppInfoContainer("ClientInfo", CertificateAppInfo::Factory);
       
   257 	ProcessCertClientFiles(baseDir, inputFiles, inputDirs, inputFileTypes, 
       
   258 						   allowDuplicates,
       
   259 						   certAppInfoContainer);
       
   260 	
       
   261 	
       
   262 	// Generate config data for application uid EncDecEnum object in AppUidListEntry
       
   263 	AppUidMap::GenerateEnumEntries();
       
   264 
       
   265 	//
       
   266 	// Process remaining input files working from right to left
       
   267 	//
       
   268 	EncDecContainer fileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
       
   269 	FCSLabelMap fcsLabels;
       
   270 	EncDecContainer swiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
       
   271 	FCSLabelMap swiLabels;
       
   272 	for(int fileIndex = inputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
       
   273 		{
       
   274 		CertStoreFileType fileType = inputFileTypes[fileIndex];
       
   275 		if((fileType == EBinFileCertStore) || (fileType == EHumanFileCertStore))
       
   276 			{
       
   277 			// Change to correct directory
       
   278 			ChangeDir(baseDir, inputDirs[fileIndex]);
       
   279 
       
   280 			EncDecContainer tmpFileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
       
   281 			if(fileType == EBinFileCertStore)
       
   282 				{
       
   283 				prog << "Reading binary filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
       
   284 				AutoIndent ai(prog);
       
   285 				readContainer(inputFiles[fileIndex], false, tmpFileCertStoreContainer);
       
   286 				}
       
   287 			if(fileType == EHumanFileCertStore)
       
   288 				{
       
   289 				prog << "Reading human filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
       
   290 				AutoIndent ai(prog);
       
   291 				readContainer(inputFiles[fileIndex], true, tmpFileCertStoreContainer);
       
   292 				}
       
   293 			
       
   294 			// Now merge the new file into the running store.
       
   295 			prog << Log::Indent() << "Merging filecertstore data" << Log::Endl();
       
   296 			AutoIndent ai(prog);
       
   297 			for(TUint32 entryIndex = 0; entryIndex < tmpFileCertStoreContainer.size(); ++entryIndex)
       
   298 				{
       
   299 				const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(tmpFileCertStoreContainer[entryIndex]);
       
   300 				std::string nname = stringFromUtf16(entry.Label());
       
   301 
       
   302 				if(!ValidateLabel(fcsLabels, inputFiles, fileType, fileIndex, entry.Label()))
       
   303 					{
       
   304 					// Duplicate detected
       
   305 					if(!allowDuplicates || (fileType == EBinFileCertStore))
       
   306 						{
       
   307 						continue; // Skip adding duplicate
       
   308 						}
       
   309 					// Only allow duplicates if debugging and reading
       
   310 					// human readable config file.
       
   311 					dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
       
   312 					}
       
   313 				
       
   314 				// Add entry
       
   315 				CertStoreEntry *newEntry = new CertStoreEntry;
       
   316 				*newEntry = entry;
       
   317 				fileCertStoreContainer.push_back(newEntry);
       
   318 				}
       
   319 			continue;
       
   320 			}
       
   321 		
       
   322 
       
   323 		if((fileType == EBinSwiCertStore) || (fileType == EHumanSwiCertStore))
       
   324 			{
       
   325 			// Change to correct directory
       
   326 			ChangeDir(baseDir, inputDirs[fileIndex]);
       
   327 
       
   328 			EncDecContainer tmpSwiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
       
   329 			if(fileType == EBinSwiCertStore)
       
   330 				{
       
   331 				prog << "Reading binary swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
       
   332 				AutoIndent ai(prog);
       
   333 				readContainer(inputFiles[fileIndex], false, tmpSwiCertStoreContainer);
       
   334 				}
       
   335 			if(fileType == EHumanSwiCertStore)
       
   336 				{
       
   337 				prog << "Reading human swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
       
   338 				AutoIndent ai(prog);
       
   339 				readContainer(inputFiles[fileIndex], true, tmpSwiCertStoreContainer);
       
   340 				}
       
   341 
       
   342 			// Now merge the new file into the running store.
       
   343 			prog << Log::Indent() << "Merging swicerstore data" << Log::Endl();
       
   344 			AutoIndent ai(prog);
       
   345 			for(TUint32 entryIndex = 0; entryIndex < tmpSwiCertStoreContainer.size(); ++entryIndex)
       
   346 				{
       
   347 				const SwiCertStoreEntry &entry = static_cast<const SwiCertStoreEntry &>(tmpSwiCertStoreContainer[entryIndex]);
       
   348 				std::string nname = stringFromUtf16(entry.Label());
       
   349 		
       
   350 				if(!ValidateLabel(swiLabels, inputFiles, fileType, fileIndex, entry.Label()))
       
   351 					{
       
   352 					// Duplicate detected
       
   353 					if(!allowDuplicates || (fileType == EBinSwiCertStore))
       
   354 						{
       
   355 						continue; // Skip adding duplicate
       
   356 						}
       
   357 					// Only allow duplicates if debugging and reading
       
   358 					// human readable config file.
       
   359 					dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
       
   360 					}
       
   361 				
       
   362 				// Add entry
       
   363 				SwiCertStoreEntry *newEntry = new SwiCertStoreEntry;
       
   364 				*newEntry = entry;
       
   365 				swiCertStoreContainer.push_back(newEntry);
       
   366 				}
       
   367 			continue;
       
   368 			}
       
   369 		}
       
   370 
       
   371 	// Fix Certificate IDs in fileCertStoreContainer
       
   372 	for(TUint32 entryIndex=0; entryIndex < fileCertStoreContainer.size(); ++entryIndex)
       
   373 		{
       
   374 		CertStoreEntry &entry = static_cast<CertStoreEntry &>(fileCertStoreContainer[entryIndex]);
       
   375 		entry.Info().SetOutputCertificateId(entryIndex);
       
   376 		}
       
   377 	
       
   378 	// Fix Certificate IDs in swicertstore container.
       
   379 	for(TUint32 entryIndex=0; entryIndex < swiCertStoreContainer.size(); ++entryIndex)
       
   380 		{
       
   381 		SwiCertStoreEntry &entry = static_cast<SwiCertStoreEntry &>(swiCertStoreContainer[entryIndex]);
       
   382 		entry.Info().SetOutputCertificateId(entryIndex);
       
   383 		}
       
   384 
       
   385 	//
       
   386 	// Fix auto IssuerKeyId values
       
   387 	//
       
   388 	SubjectToSubjectKeyIdMap subjectMap;
       
   389 	//
       
   390 	// Fix IssuerKeyId values in swiCertStoreContainer
       
   391 	//
       
   392 	// We do not use the AuthorityKeyId extension and only consider
       
   393 	// certificates in swi certstores.
       
   394 	//
       
   395 	// First map all the SWI certificate subject names to SubjectKeyId values
       
   396 	BuildSubjectToSubjectKeyIdMap(swiCertStoreContainer, subjectMap);
       
   397 	// Now update IssuerKeyId fields which are set to auto.
       
   398 	// The AuthorityKeyId extension value will be ignored.
       
   399 	// The SubjectKeyId of a matching certificate (if there is a
       
   400 	// single match on issuer name) in the swi cert store will be
       
   401 	// used.
       
   402 	SetIssuerKeyId(subjectMap, KIgnoreCertificateExtension, swiCertStoreContainer);
       
   403 
       
   404 
       
   405 	//
       
   406 	// Fix IssuerKeyId values in fileCertStoreContainer
       
   407 	//
       
   408 	// Add all filecertstore certificates to the
       
   409 	// subjectName/SubjectKeyId map
       
   410 	BuildSubjectToSubjectKeyIdMap(fileCertStoreContainer, subjectMap);
       
   411 	// Now update IssuerKeyId fields which are set to auto.  If an the
       
   412 	// AuthorityKeyId extension is present and <160bits use it,
       
   413 	// otherwise use the SubjectKeyId of the matching certificate (if
       
   414 	// there is a single match on issuer name).
       
   415 	SetIssuerKeyId(subjectMap, KUseCertificateExtension, fileCertStoreContainer);
       
   416 
       
   417 	//
       
   418 	// Now generate output files
       
   419 	//
       
   420 	GenerateOutputFiles(certAppInfoContainer, fileCertStoreContainer, swiCertStoreContainer,
       
   421 						baseDir, outputFiles, outputDirs, outputFileTypes, verbose, pemOut);
       
   422 	
       
   423 
       
   424 	}
       
   425 	catch(...)
       
   426 		{
       
   427 		dbg << Log::Indent() << "C++ expection!" << Log::Endl();
       
   428 		FatalError();
       
   429 		}
       
   430 	
       
   431 	prog << Log::Indent() << "Normal exit" << Log::Endl();
       
   432 	prog.Stream().flush();
       
   433 	dbg.Stream().flush();
       
   434 	return 0; // All ok
       
   435 }
       
   436 
       
   437 /**
       
   438    ProcessCommandLine
       
   439 */
       
   440 void ProcessCommandLine(int aArgc, char **aArgv, 
       
   441 						StringVector &aInputFiles, StringVector &aInputDirs, CertStoreFileTypeVector &aInputFileTypes,
       
   442 						StringVector &aOutputFiles, StringVector &aOutputDirs, CertStoreFileTypeVector &aOutputFileTypes,
       
   443 						bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates)
       
   444 {
       
   445 	std::string progressFile("-");
       
   446 	static std::fstream sProgressStream;
       
   447 
       
   448 	std::string dbgFile("-");
       
   449 	static std::fstream sDbgStream;
       
   450 
       
   451 	StringVector *files = &aInputFiles;
       
   452 	StringVector *dirs = &aInputDirs;
       
   453 	CertStoreFileTypeVector *fileTypes = &aInputFileTypes;
       
   454 
       
   455 	int argIndex=1;
       
   456 	// Process overall arguments (-h --progress --errors)
       
   457 	for(; argIndex < aArgc; ++argIndex)
       
   458 		{
       
   459 		std::string arg(aArgv[argIndex]);
       
   460 
       
   461 		if(arg == "--license")
       
   462 			{
       
   463 			prog << sVersion << Log::Endl();
       
   464 			prog << "Copyright (c) 2008 Symbian Software Ltd. All rights reserved." << Log::Endl();
       
   465 			prog << "Linked against openssl. Credits and license for openssl follow:-" << Log::Endl();
       
   466 			prog << openssl_license << Log::Endl();
       
   467 			
       
   468 			continue;
       
   469 			}
       
   470 
       
   471 		if(arg == OPT_VERBOSE)
       
   472 			{
       
   473 			prog << "Enabling additional output file comments" << Log::Endl();
       
   474 			aVerbose = true;
       
   475 			
       
   476 			continue;
       
   477 			}
       
   478 
       
   479 		if(arg == "--pemout")
       
   480 			{
       
   481 			prog << "Setting output certificate format to PEM" << Log::Endl();
       
   482 			aPemOut = true;
       
   483 			
       
   484 			continue;
       
   485 			}
       
   486 
       
   487 		if(arg == OPT_ALLOWDUPLICATES)
       
   488 			{
       
   489 			prog << "Allowing addition of duplicate labels in stores and UIDs in certclients when reading human readable input (testing ONLY)" << Log::Endl();
       
   490 			aAllowDuplicates = true;
       
   491 			
       
   492 			continue;
       
   493 			}
       
   494 
       
   495 		if((arg.find(OPT_PROGRESS) == 0) ||
       
   496 		   (arg.find(OPT_ERRORS) == 0))
       
   497 			{
       
   498 			// The following logic is required so that if both streams
       
   499 			// are set to the same destination we share a streams
       
   500 			// object and hence avoid buffering issues.
       
   501 			std::string *thisFile;
       
   502 			std::fstream *thisStream;
       
   503 			Log *thisLog;
       
   504 			std::string *otherFile;
       
   505 			std::fstream *otherStream;
       
   506 			Log *otherLog;
       
   507 
       
   508 			if(arg.find(OPT_PROGRESS) == 0)
       
   509 				{
       
   510 				thisFile = &progressFile;
       
   511 				thisStream = &sProgressStream;
       
   512 				thisLog = &prog;
       
   513 				otherFile = &dbgFile;
       
   514 				otherStream = &sDbgStream;
       
   515 				otherLog = &dbg;
       
   516 
       
   517 				*thisFile = arg.substr(OPT_PROGRESS.size(), arg.npos);
       
   518 				}
       
   519 			else
       
   520 				{
       
   521 				thisFile = &dbgFile;
       
   522 				thisStream = &sDbgStream;
       
   523 				thisLog = &dbg;
       
   524 				otherFile = &progressFile;
       
   525 				otherStream = &sProgressStream;
       
   526 				otherLog = &prog;
       
   527 
       
   528 				*thisFile = arg.substr(OPT_ERRORS.size(), arg.npos);
       
   529 				}
       
   530 
       
   531 			if(*thisFile == *otherFile)
       
   532 				{
       
   533 				// Reuse existing stream. This avoids two streams opening the same file...
       
   534 				thisLog->SetStream(&otherLog->Stream());
       
   535 				continue;
       
   536 				}
       
   537 
       
   538 			// Need to open a new stream
       
   539 			if(thisStream->is_open()) thisStream->close();
       
   540 			if(*thisFile == "-")
       
   541 				{
       
   542 				thisLog->SetStream(&std::cout);
       
   543 				continue;
       
   544 				}
       
   545 			
       
   546 			OpenUtf8FStreamForWrite(*thisStream, thisFile->c_str());
       
   547 			if(thisStream->fail())
       
   548 				{
       
   549 				if(thisLog == &dbg)
       
   550 					{
       
   551 					dbg.SetStream(&std::cout);
       
   552 					}
       
   553 				dbg << Log::Indent() << "Failed to open log file specified by " << aArgv[argIndex-1] << " '" << *thisFile << "'" << Log::Endl();
       
   554 				return;
       
   555 				}
       
   556 			thisLog->SetStream(thisStream);
       
   557 			continue;
       
   558 			}
       
   559 
       
   560 		if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
       
   561 			{
       
   562 			usage();
       
   563 			continue;
       
   564 			}
       
   565 
       
   566 		// Not a general option, probably an input file...
       
   567 		break;
       
   568 		}
       
   569 	
       
   570 	// Process main arguments
       
   571 	for(; argIndex < aArgc; ++argIndex)
       
   572 		{
       
   573 		std::string arg(aArgv[argIndex]);
       
   574 
       
   575 		bool gotFile = false;
       
   576 		if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
       
   577 			{
       
   578 			usage();
       
   579 			continue;
       
   580 			}
       
   581 		
       
   582 		if(arg.find(OPT_CHDIR) == 0)
       
   583 			{
       
   584 			dirs->push_back(arg.substr(OPT_CHDIR.size(), arg.npos));
       
   585 			// Move to next option
       
   586 			++argIndex;
       
   587 			if(argIndex >= aArgc) break;
       
   588 			arg = aArgv[argIndex];
       
   589 			}
       
   590 		else
       
   591 			{
       
   592 			dirs->push_back(".");
       
   593 			}
       
   594 
       
   595 		std::string fileArg;
       
   596 		if(arg.find(OPT_BCERTCLIENTS_L) == 0)
       
   597 			{
       
   598 			fileTypes->push_back(EBinCertClients);
       
   599 			fileArg = arg.substr(OPT_BCERTCLIENTS_L.size(), arg.npos);
       
   600 			gotFile = true;
       
   601 			}
       
   602 		if(arg.find(OPT_BCERTCLIENTS_S) == 0)
       
   603 			{
       
   604 			fileTypes->push_back(EBinCertClients);
       
   605 			fileArg = arg.substr(OPT_BCERTCLIENTS_S.size(), arg.npos);
       
   606 			gotFile = true;
       
   607 			}
       
   608 		if(arg.find(OPT_HCERTCLIENTS_L) == 0)
       
   609 			{
       
   610 			fileTypes->push_back(EHumanCertClients);
       
   611 			fileArg = arg.substr(OPT_HCERTCLIENTS_L.size(), arg.npos);
       
   612 			gotFile = true;
       
   613 			}
       
   614 		if(arg.find(OPT_HCERTCLIENTS_S) == 0)
       
   615 			{
       
   616 			fileTypes->push_back(EHumanCertClients);
       
   617 			fileArg = arg.substr(OPT_HCERTCLIENTS_S.size(), arg.npos);
       
   618 			gotFile = true;
       
   619 			}
       
   620 		if(arg.find(OPT_BFILECERTSTORE_L) == 0)
       
   621 			{
       
   622 			fileTypes->push_back(EBinFileCertStore);
       
   623 			fileArg = arg.substr(OPT_BFILECERTSTORE_L.size(), arg.npos);
       
   624 			gotFile = true;
       
   625 			}
       
   626 		if(arg.find(OPT_BFILECERTSTORE_S) == 0)
       
   627 			{
       
   628 			fileTypes->push_back(EBinFileCertStore);
       
   629 			fileArg = arg.substr(OPT_BFILECERTSTORE_S.size(), arg.npos);
       
   630 			gotFile = true;
       
   631 			}
       
   632 		if(arg.find(OPT_HFILECERTSTORE_L) == 0)
       
   633 			{
       
   634 			fileTypes->push_back(EHumanFileCertStore);
       
   635 			fileArg = arg.substr(OPT_HFILECERTSTORE_L.size(), arg.npos);
       
   636 			gotFile = true;
       
   637 			}
       
   638 		if(arg.find(OPT_HFILECERTSTORE_S) == 0)
       
   639 			{
       
   640 			fileTypes->push_back(EHumanFileCertStore);
       
   641 			fileArg = arg.substr(OPT_HFILECERTSTORE_S.size(), arg.npos);
       
   642 			gotFile = true;
       
   643 			}
       
   644 		if(arg.find(OPT_BSWICERTSTORE_L) == 0)
       
   645 			{
       
   646 			fileTypes->push_back(EBinSwiCertStore);
       
   647 			fileArg = arg.substr(OPT_BSWICERTSTORE_L.size(), arg.npos);
       
   648 			gotFile = true;
       
   649 			}
       
   650 		if(arg.find(OPT_BSWICERTSTORE_S) == 0)
       
   651 			{
       
   652 			fileTypes->push_back(EBinSwiCertStore);
       
   653 			fileArg = arg.substr(OPT_BSWICERTSTORE_S.size(), arg.npos);
       
   654 			gotFile = true;
       
   655 			}
       
   656 		if(arg.find(OPT_HSWICERTSTORE_L) == 0)
       
   657 			{
       
   658 			fileTypes->push_back(EHumanSwiCertStore);
       
   659 			fileArg = arg.substr(OPT_HSWICERTSTORE_L.size(), arg.npos);
       
   660 			gotFile = true;
       
   661 			}
       
   662 		if(arg.find(OPT_HSWICERTSTORE_S) == 0)
       
   663 			{
       
   664 			fileTypes->push_back(EHumanSwiCertStore);
       
   665 			fileArg = arg.substr(OPT_HSWICERTSTORE_S.size(), arg.npos);
       
   666 			gotFile = true;
       
   667 			}
       
   668 
       
   669 		if(arg.find("--out") == 0)
       
   670 			{
       
   671 			files = &aOutputFiles;
       
   672 			dirs = &aOutputDirs;
       
   673 			fileTypes = &aOutputFileTypes;
       
   674 			continue;
       
   675 			}
       
   676 
       
   677 		if(arg.find("--in") == 0)
       
   678 			{
       
   679 			files = &aInputFiles;
       
   680 			dirs = &aInputDirs;
       
   681 			fileTypes = &aInputFileTypes;
       
   682 			continue;
       
   683 			}
       
   684 
       
   685 		if(gotFile)
       
   686 			{
       
   687 			files->push_back(fileArg);
       
   688 			continue;
       
   689 			}
       
   690 		
       
   691 		usage();
       
   692 		dbg << Log::Indent() << "Unknown option " << (const char *) aArgv[argIndex] << Log::Endl();
       
   693 		FatalError();
       
   694 		}
       
   695 	return;
       
   696 }
       
   697 
       
   698 void ProcessCertClientFiles(const std::string &aBaseDir,
       
   699 							const StringVector &aInputFiles,
       
   700 							const StringVector &aInputDirs,
       
   701 							const CertStoreFileTypeVector &aInputFileTypes,
       
   702 							bool &aAllowDuplicates,
       
   703 							EncDecContainer &aCertAppInfoContainer)
       
   704 {
       
   705 	AppMap appMap;
       
   706 	for(int fileIndex = aInputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
       
   707 		{
       
   708 		CertStoreFileType fileType = aInputFileTypes[fileIndex];
       
   709 		if((fileType != EBinCertClients) && (fileType != EHumanCertClients))
       
   710 			{
       
   711 			continue;
       
   712 			}
       
   713 		
       
   714 		// Change to correct directory
       
   715 		ChangeDir(aBaseDir, aInputDirs[fileIndex]);
       
   716 
       
   717 		EncDecContainer tmpCertInfoContainer("ClientInfo", CertificateAppInfo::Factory);
       
   718 
       
   719 		if(fileType == EBinCertClients)
       
   720 			{
       
   721 			prog << Log::Indent() << "Reading binary certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
       
   722 			AutoIndent ai(prog);
       
   723 			readContainer(aInputFiles[fileIndex], false, tmpCertInfoContainer);
       
   724 			}
       
   725 		else
       
   726 			{
       
   727 			prog << Log::Indent() << "Reading human certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
       
   728 			AutoIndent ai(prog);
       
   729 			readContainer(aInputFiles[fileIndex], true, tmpCertInfoContainer);
       
   730 			}
       
   731 
       
   732 		// Now merge the new file into the running store.
       
   733 		prog << Log::Indent() << "Merging certclients data" << Log::Endl();
       
   734 		AutoIndent ai(prog);
       
   735 		AutoIndent ai2(dbg);
       
   736 		for(TUint32 entryIndex = 0; entryIndex < tmpCertInfoContainer.size(); ++entryIndex)
       
   737 			{
       
   738 			const CertificateAppInfo &info = static_cast<const CertificateAppInfo &>(tmpCertInfoContainer[entryIndex]);
       
   739 			std::string nname = stringFromUtf16(info.Name());
       
   740 			//prog << Log::Indent() << "checking " << nname << Log::Endl();
       
   741 
       
   742 
       
   743 			TInt32 lastIndex;
       
   744 			std::string firstDef;
       
   745 			if(!AppUidMap::InsertUidDefinition(info.Id().iUid, nname, fileIndex,
       
   746 											   lastIndex, firstDef))
       
   747 				{
       
   748 				// Duplicate entry for UID
       
   749 				if(nname == firstDef)
       
   750 					{
       
   751 					// But both entries have the same value
       
   752 					prog << Log::Indent() << "Duplicate, but identical, entries for UID 0x" << info.Id().iUid << " '" << nname << "'." << Log::Endl();
       
   753 					AutoIndent ai(prog);
       
   754 					prog << Log::Indent() << "From files '" << aInputFiles[lastIndex] << "' and '" << aInputFiles[fileIndex] << "'." << Log::Endl();
       
   755 					}
       
   756 				else
       
   757 					{
       
   758 					// Entries have different values
       
   759 					dbg << Log::Indent() << "DUPLICATE entry for UID 0x" << info.Id().iUid << Log::Endl();
       
   760 					AutoIndent ai(dbg);
       
   761 					dbg << Log::Indent() << "Ignoring '" << nname << "' from '"  << aInputFiles[fileIndex] << "'." << Log::Endl();
       
   762 					dbg << Log::Indent() << "Keeping '" << firstDef << "' from '" << aInputFiles[lastIndex] << "'." << Log::Endl();
       
   763 					if(lastIndex == fileIndex)
       
   764 						{
       
   765 						if(fileType == EBinCertClients)
       
   766 							{
       
   767 							dbg << Log::Indent() << "Both entries are in the same binary same file!" << Log::Endl();
       
   768 							continue; // Skip adding duplicate
       
   769 							}
       
   770 						dbg << Log::Indent() << "Clash is within a single text configuration file!" << Log::Endl();
       
   771 						if(!aAllowDuplicates)
       
   772 							{
       
   773 							FatalError();
       
   774 							}
       
   775 						}
       
   776 					}
       
   777 
       
   778 				// Only add duplicates when debugging and the add is
       
   779 				// from a human readable config file.
       
   780 				if(!aAllowDuplicates || (fileType != EHumanCertClients))
       
   781 					{
       
   782 					continue; // Skip adding duplicate
       
   783 					}
       
   784 				dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
       
   785 				}
       
   786 
       
   787 			// Add entry
       
   788 			CertificateAppInfo *newInfo = new CertificateAppInfo;
       
   789 			*newInfo = info;
       
   790 			aCertAppInfoContainer.push_back(newInfo);
       
   791 			}
       
   792 		}
       
   793 }
       
   794 
       
   795 
       
   796 
       
   797 /**
       
   798    Write output files to disk
       
   799  */
       
   800 void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
       
   801 						 const EncDecContainer &aFileCertStoreContainer,
       
   802 						 const EncDecContainer &aSwiCertStoreContainer,
       
   803 						 const std::string &aBaseDir,
       
   804 						 const StringVector &aOutputFiles, 
       
   805 						 const StringVector &aOutputDirs,
       
   806 						 const CertStoreFileTypeVector &aOutputFileTypes,
       
   807 						 bool aVerbose, bool aPemOut)
       
   808 {
       
   809 	for(int fileIndex = aOutputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
       
   810 		{
       
   811 		// Change to correct directory
       
   812 		ChangeDir(aBaseDir, aOutputDirs[fileIndex]);
       
   813 		
       
   814 		CertStoreFileType fileType = aOutputFileTypes[fileIndex];
       
   815 		//
       
   816 		// Set the container and write mode to use
       
   817 		//
       
   818 		const EncDecContainer *container = 0;
       
   819 		bool humanReadable = false;
       
   820 		if(fileType == EBinCertClients)
       
   821 			{
       
   822 			container = &aCertAppInfoContainer;
       
   823 			humanReadable = false;
       
   824 			}
       
   825 		if(fileType == EHumanCertClients)
       
   826 			{
       
   827 			container = &aCertAppInfoContainer;
       
   828 			humanReadable = true;
       
   829 			}
       
   830 		if(fileType == EBinFileCertStore)
       
   831 			{
       
   832 			container = &aFileCertStoreContainer;
       
   833 			humanReadable = false;
       
   834 			}
       
   835 		if(fileType == EHumanFileCertStore)
       
   836 			{
       
   837 			container = &aFileCertStoreContainer;
       
   838 			humanReadable = true;
       
   839 			}
       
   840 		if(fileType == EBinSwiCertStore)
       
   841 			{
       
   842 			container = &aSwiCertStoreContainer;
       
   843 			humanReadable = false;
       
   844 			}
       
   845 		if(fileType == EHumanSwiCertStore)
       
   846 			{
       
   847 			container = &aSwiCertStoreContainer;
       
   848 			humanReadable = true;
       
   849 			}
       
   850 		
       
   851 		if(container == 0)
       
   852 			{
       
   853 			// failed to decode the output file type!
       
   854 			FatalError();
       
   855 			}
       
   856 		//
       
   857 		// Write the container out
       
   858 		//
       
   859 		writeContainer(aOutputFiles[fileIndex].c_str(), humanReadable, aPemOut, aVerbose, *container);
       
   860 		}
       
   861 	return;
       
   862 }
       
   863 
       
   864 
       
   865 
       
   866 /**
       
   867    ValidateLabel
       
   868 
       
   869    This function maintains a map of certificate labels to input file
       
   870    (ie file index) and definition.
       
   871    
       
   872    If the label is NOT already defined in the map, then the function
       
   873    returns true, which instructs the caller to include the
       
   874    label/certificate in the generated store.
       
   875 
       
   876    If the label is already defined in the map, then the function
       
   877    returns false, which instructs the caller to NOT include the
       
   878    label/certificate in the generated store.
       
   879 
       
   880    The files on the command line are processed right to left, so if
       
   881    multiple definitions (for the same label) are seen, only the first
       
   882    will be included in the generated store.
       
   883 
       
   884    The information saved in the map is used to generate helpful
       
   885    warning/error messages as follows:-
       
   886 
       
   887    1) The saved definition is the first definition encountered, and is
       
   888    therefore the one which has been included in the store.
       
   889 
       
   890    2) The saved file index is the index of the LAST file processed
       
   891    containing a definition for this label. This may be different to
       
   892    the one containing the first definition.
       
   893 
       
   894    Consider the following sequence:-
       
   895 
       
   896    First processed file - Definition for label Fred
       
   897    Second processed file - Another two definitions for label Fred
       
   898 
       
   899    When processing the third definition (in the second file), the
       
   900    saved file index will be that of the second file. The code uses
       
   901    this to check if there are multiple definitions within a SINGLE
       
   902    input file, for the same label.
       
   903 
       
   904    If the multiple definitions are within a single human readable
       
   905    file, then this is considered a fatal error, otherwise only a
       
   906    warning is generated.
       
   907 
       
   908    Duplicate definitions in different files, generate a warning.
       
   909  */
       
   910 bool ValidateLabel(FCSLabelMap &aLabelMap, 
       
   911 				   const StringVector &aInputFiles, 
       
   912 				   CertStoreFileType aFileType,
       
   913 				   TUint32 aFileIndex, 
       
   914 				   const TCertLabel &aCertLabel)
       
   915 {
       
   916 	std::string nname = stringFromUtf16(aCertLabel);
       
   917 	FCSLabelMap::value_type e(nname, aFileIndex);
       
   918 	std::pair<FCSLabelMap::iterator,bool> result = aLabelMap.insert(e);
       
   919 	if(result.second == true)
       
   920 		{
       
   921 		// Not a duplicate
       
   922 		return true;
       
   923 		}
       
   924 	
       
   925 	// Duplicate label entry
       
   926 	dbg << Log::Indent() << "DUPLICATE label detected in '" << aInputFiles[aFileIndex] << "'." << Log::Endl();
       
   927 	AutoIndent ai(dbg);
       
   928 	dbg << Log::Indent() << "Duplicate entry for '" << e.first << "' ignored. Keeping entry from '" << aInputFiles[(*result.first).second] << "'" <<Log::Endl();
       
   929 	if((result.first)->second == TUint32(aFileIndex))
       
   930 		{
       
   931 		dbg << Log::Indent() << "Both entries are in the same file." << Log::Endl();
       
   932 		if((aFileType == EHumanFileCertStore) || (aFileType == EHumanSwiCertStore))
       
   933 			{
       
   934 			dbg << Log::Indent() << "FATAL error - Clash is within a single text configuration file - aborting!" << Log::Endl();
       
   935 			FatalError();
       
   936 			}
       
   937 		return false; // Insert failed, keep earlier def
       
   938 		}
       
   939 	else
       
   940 		{
       
   941 		// Update file index for last definition. This is used to
       
   942 		// detect if the last two defs were within a single file.
       
   943 		(result.first)->second = TUint32(aFileIndex);
       
   944 		return false; // Insert failed, keep earlier def
       
   945 		}
       
   946 	return false;
       
   947 }
       
   948 
       
   949 void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
       
   950 								   SubjectToSubjectKeyIdMap &aSubjectMap)
       
   951 {
       
   952 	// Collect subjectName/SubjectKeyId for all certs
       
   953 	for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
       
   954 		{
       
   955 		const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(aCertStoreContainer[entryIndex]);
       
   956 		if(entry.Info().CertificateFormat() !=  EX509Certificate)
       
   957 			{
       
   958 			continue;
       
   959 			}
       
   960 
       
   961 		std::pair<SubjectToSubjectKeyIdMap::key_type, SubjectToSubjectKeyIdMap::mapped_type> e;
       
   962 		e.first = entry.CertSubject();
       
   963 		e.second.iDuplicate = false;
       
   964 		e.second.iLabel = stringFromUtf16(entry.Label());
       
   965 		e.second.iSubjectKeyIdentifier =  entry.Info().SubjectKeyId().iHash;
       
   966 		std::pair<SubjectToSubjectKeyIdMap::iterator, bool> result = aSubjectMap.insert(e);
       
   967 		if(result.second == false)
       
   968 			{
       
   969 			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();
       
   970 			(*result.first).second.iDuplicate = true;
       
   971 			}
       
   972 		}
       
   973 	
       
   974 }
       
   975 
       
   976 
       
   977 void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap,
       
   978 					EUseCertificateExtension aUseExtension,
       
   979 					EncDecContainer &aCertStoreContainer)
       
   980 {
       
   981 	// Now loop across certs setting the issuer key id.
       
   982 	for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
       
   983 		{
       
   984 		CertStoreEntry &entry = static_cast<CertStoreEntry &>(aCertStoreContainer[entryIndex]);
       
   985 		if(entry.Info().CertificateFormat() !=  EX509Certificate)
       
   986 			{
       
   987 			continue;
       
   988 			}
       
   989 		if(!entry.Info().IssuerKeyId().iAutoKey)
       
   990 			{
       
   991 			continue;
       
   992 			}
       
   993 
       
   994 		std::string certLabel = stringFromUtf16(entry.Label());
       
   995 		
       
   996 		prog << Log::Indent() << "Attempting to auto set IssuerIeyId for '" << certLabel << "'" << Log::Endl();
       
   997 
       
   998 		AutoIndent ai(prog);
       
   999 
       
  1000 		// Lookup issuer key id in certificate extension and if found use that.
       
  1001 		// 
       
  1002 		// X509IssuerKeyId will always set the issuerName.
       
  1003 		// If aIgnoreExtension is false, then it will attempt to read
       
  1004 		// the AuthorityKeyId extension. If found (and <160bits), it
       
  1005 		// will write the ID to issuerId and return true.
       
  1006 		// Otherwise it will return false.
       
  1007 		// Certificate read errors are fatal.
       
  1008 		std::string issuerName;
       
  1009 		TKeyIdentifier issuerId;
       
  1010 		if(X509IssuerKeyId(aUseExtension,
       
  1011 						   entry.CertData(), entry.Info().CertSize(),
       
  1012 						   issuerName, issuerId))
       
  1013 			{
       
  1014 			// There is an authority key id extension so use its value
       
  1015 			prog << Log::Indent() << "Using value from certificate '" << certLabel << "' extension" << Log::Endl();
       
  1016 			entry.Info().IssuerKeyId().iHash = issuerId;
       
  1017 			}
       
  1018 		else
       
  1019 			{
       
  1020 			// No extension so lookup issuerName in the map
       
  1021 			prog << Log::Indent() << "Looking up issuer '" << issuerName << "' in map" << Log::Endl();
       
  1022 			SubjectToSubjectKeyIdMap::const_iterator it = aSubjectMap.find(issuerName);
       
  1023 			if(it == aSubjectMap.end())
       
  1024 				{
       
  1025 				prog << Log::Indent() << "Not found - Using empty IssuerKeyId " << Log::Endl();
       
  1026 				}
       
  1027 			else
       
  1028 				{
       
  1029 				if((*it).second.iDuplicate)
       
  1030 					{
       
  1031 					prog << Log::Indent() << "Found - but multiple certs with matching subject name - Using empty IssuerKeyId" << Log::Endl();
       
  1032 					}
       
  1033 				else
       
  1034 					{
       
  1035 					prog << Log::Indent() << "Found - Using Subject Key of matching cert" << Log::Endl();
       
  1036 					entry.Info().IssuerKeyId().iHash = (*it).second.iSubjectKeyIdentifier;
       
  1037 					}
       
  1038 				}
       
  1039 			}
       
  1040 		}
       
  1041 
       
  1042 }
       
  1043 
       
  1044 
       
  1045 
       
  1046 // End of file