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