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
|