Newer
Older
#include <iostream>
#include <fstream>
#include "certificates_loader.hh"
namespace fs = std::experimental::filesystem;
#include "converter.hh"
#include "loggers.hh"
certificates_loader * certificates_loader::instance = nullptr;
certificates_loader::certificates_loader(): _certificateExt{".crt"}, _privateKeyExt{".pkey"}, _publicKeysExt{".vkey"}, _hashedidDigestExt{".hashedid"}, _issuerDigestExt{".issuer"}, _full_path(), _is_cache_initialized{false}, _directory_filter{".svn", "._.DS_Store", ".DS_Store"} {
loggers::get_instance().log(">>> certificates_loader::certificates_loader");
} // End of ctor
int certificates_loader::build_path(const std::string& p_root_directory) {
loggers::get_instance().log(">>> certificates_loader::build_path: '%s'", p_root_directory.c_str());
// Build full path
if (!p_root_directory.empty()) {
_full_path = p_root_directory;
if (!std::experimental::filesystem::is_directory(_full_path)) {
_full_path = "./";
}
std::experimental::filesystem::canonical(_full_path);
loggers::get_instance().log("certificates_loader::build_path: full path: %s", _full_path.string().c_str());
if (!std::experimental::filesystem::exists(_full_path)) {
loggers::get_instance().warning("certificates_loader::build_path: Invalid path");
_full_path.clear();
return -1;
}
return 0;
} // End of method build_path
int certificates_loader::load_certificates(std::map<std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<std::vector<unsigned char>, std::string>& p_hashed_id8s) {
loggers::get_instance().log(">>> certificates_loader::load_certificates");
// Sanity check
if (_is_cache_initialized) {
return 0;
}
std::set<std::experimental::filesystem::path> files;
loggers::get_instance().warning("certificates_loader::load_certificates: Failed to build the list of certificate files");
return -1;
}
// Build the certificates cache
if (build_certificates_cache(files, p_certificates, p_hashed_id8s) == -1) {
loggers::get_instance().warning("certificates_loader::load_certificates: Failed to build the certificate cache");
return -1;
}
_is_cache_initialized = true;
return 0;
} // End of method load_certificates
int certificates_loader::retrieve_certificates_list(std::set<std::experimental::filesystem::path>& p_files) {
loggers::get_instance().log(">>> certificates_loader::retrieve_certificates_list");
// Walk through directories
std::set<std::experimental::filesystem::path> folders;
for (const std::experimental::filesystem::directory_entry it : std::experimental::filesystem::recursive_directory_iterator(_full_path.string())) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing directory '%s'", it.path().string().c_str());
if (std::experimental::filesystem::is_directory(it)) {
std::set<std::string>::const_iterator i = _directory_filter.find(it.path().filename());
if (i != _directory_filter.cend()) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Exclude directory '%s'", it.path().string().c_str());
continue;
}
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Add directory '%s'", it.path().string().c_str());
folders.insert(it.path());
}
} // End of 'for' statement
if (folders.size() == 0) {
loggers::get_instance().warning("certificates_loader::retrieve_certificates_list: No folder after filtering");
return -1;
}
// Process files
p_files.clear();
std::set<std::string> extensions_filter{ _certificateExt, _privateKeyExt, _publicKeysExt };
for (std::set<std::experimental::filesystem::path>::const_reverse_iterator f = folders.crbegin(); f != folders.crend(); ++f) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing directory '%s'", f->string().c_str());
for(const std::experimental::filesystem::directory_entry it : std::experimental::filesystem::recursive_directory_iterator(*f)) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing file '%s'", it.path().filename().string().c_str());
if (std::experimental::filesystem::is_regular_file(it)) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Check extension '%s'", it.path().extension().string().c_str());
std::set<std::string>::const_iterator i = extensions_filter.find(it.path().extension().string());
if (i != extensions_filter.cend()) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Add file '%s'", it.path().filename().string().c_str());
p_files.insert(it);
}
}
} // End of 'for' statement
} // End of 'for' statement
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: # of files to cache:", p_files.size());
if (p_files.size() == 0) {
loggers::get_instance().warning("certificates_loader::retrieve_certificates_list: No certificate found");
return -1;
}
return 0;
} // End of method retrieve_certificates_list
int certificates_loader::build_certificates_cache(std::set<std::experimental::filesystem::path>& p_files, std::map<std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<std::vector<unsigned char>, std::string>& p_hashed_id8s) {
loggers::get_instance().log(">>> certificates_loader::build_certificates_cache");
std::set<std::experimental::filesystem::path>::const_iterator it = p_files.cbegin();
do {
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching '%s'", it->string().c_str());
std::experimental::filesystem::path p = *it;
std::string key = p.filename();
// Load certificate file
it = p_files.find(p.replace_extension(_certificateExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Certificate file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching certificate '%s'", it->string().c_str());
std::ifstream is(it->string(), ios::in | ios::binary);
std::vector<unsigned char> certificate(std::experimental::filesystem::file_size(*it), 0x00);
is.read(reinterpret_cast<char *>(certificate.data()), certificate.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load private key file
it = p_files.find(p.replace_extension(_privateKeyExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Private keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching private keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
int size = std::experimental::filesystem::file_size(*it);
if ((size != 32) && (size != 48)) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Private keys file not found for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> private_key(size, 0x00);
is.read(reinterpret_cast<char *>(private_key.data()), private_key.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load public key file
it = p_files.find(p.replace_extension(_publicKeysExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching public keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
if ((size != 64) && (size != 96)) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public keys file not found for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> public_key_x(size / 2, 0x00);
is.read(reinterpret_cast<char *>(public_key_x.data()), public_key_x.size());
std::vector<unsigned char> public_key_y(size / 2, 0x00);
is.read(reinterpret_cast<char *>(public_key_y.data()), public_key_y.size());
is.close();
// Remove items from the list
p_files.erase(it);
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// Load issuer
it = p_files.find(p.replace_extension(_issuerDigestExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Issuer keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching issuer keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
if (size != 8) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Issuer keys file not found for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> issuer(size, 0x00);
is.read(reinterpret_cast<char *>(issuer.data()), issuer.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load hashed_id
it = p_files.find(p.replace_extension(_hashedidDigestExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Hashed_Id keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching hashed_id keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
if (size != 8) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Hashed_Id keys file not found for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> hashed_id(size, 0x00);
is.read(reinterpret_cast<char *>(hashed_id.data()), hashed_id.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Create new record
p_certificates.insert(std::pair<const std::string, std::unique_ptr<security_db_record> >(key, std::unique_ptr<security_db_record>(
new security_db_record(
key,
certificate, // Certificate
issuer, // Hashed ID fo the issuer, empty for CA
private_key, // Private key
public_key_x, // Public key X
public_key_y // Public key Y
))
));
std::map<std::string, std::unique_ptr<security_db_record> >::const_iterator i = p_certificates.find(key);
if (i == p_certificates.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Failed to insert new record '%s'", key.c_str());
return -1;
}
p_hashed_id8s.insert(std::pair<std::vector<unsigned char>, std::string>(i->second.get()->hashed_id(), i->first));
// Reset pointer
it = p_files.cbegin();
} while (it != p_files.cend());
return 0;
} // End of method build_certificates_cache
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
int certificates_loader::save_certificate(const security_db_record& p_certificate) {
loggers::get_instance().log(">>> certificates_loader::save_certificate");
// Certificate file
std::experimental::filesystem::path p(_full_path);
p /= p_certificate.certificate_id();
p += _certificateExt;//, _privateKeyExt{".pkey"}, _publicKeysExt{".vkey"}
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Certificate file: '%s'", p.string().c_str());
std::ofstream os(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.certificate().data()), p_certificate.certificate().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Private key
p = _full_path;
p /= p_certificate.certificate_id();
p += _privateKeyExt; // _publicKeysExt{".vkey"}
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Private key file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.private_key().data()), p_certificate.private_key().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Public keys
p = _full_path;
p /= p_certificate.certificate_id();
p += _publicKeysExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Public key file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.public_key_x().data()), p_certificate.public_key_x().size());
os.write(reinterpret_cast<const char *>(p_certificate.public_key_y().data()), p_certificate.public_key_y().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Issuer
p = _full_path;
p /= p_certificate.certificate_id();
p += _issuerDigestExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Issuer digest file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.hashed_id_issuer().data()), p_certificate.hashed_id_issuer().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Hashedid8
p = _full_path;
p /= p_certificate.certificate_id();
p += _hashedidDigestExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Hashedid8 digest file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.hashed_id().data()), p_certificate.hashed_id().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
return 0;
} // End of method save_certificate