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