certificate_db.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "base/HardFun.h"
12 
13 #include <cerrno>
14 #include <fstream>
15 #include <memory>
16 #include <stdexcept>
17 #if HAVE_SYS_STAT_H
18 #include <sys/stat.h>
19 #endif
20 #if HAVE_FCNTL_H
21 #include <fcntl.h>
22 #endif
23 #if HAVE_SYS_FILE_H
24 #include <sys/file.h>
25 #endif
26 
27 #define HERE "(security_file_certgen) " << __FILE__ << ':' << __LINE__ << ": "
28 
29 Ssl::Lock::Lock(std::string const &aFilename) :
30  filename(aFilename),
31 #if _SQUID_WINDOWS_
32  hFile(INVALID_HANDLE_VALUE)
33 #else
34  fd(-1)
35 #endif
36 {
37 }
38 
39 bool Ssl::Lock::locked() const
40 {
41 #if _SQUID_WINDOWS_
42  return hFile != INVALID_HANDLE_VALUE;
43 #else
44  return fd != -1;
45 #endif
46 }
47 
49 {
50 
51 #if _SQUID_WINDOWS_
52  hFile = CreateFile(TEXT(filename.c_str()), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
53  if (hFile == INVALID_HANDLE_VALUE)
54 #else
55  fd = open(filename.c_str(), O_RDWR);
56  if (fd == -1)
57 #endif
58  throw std::runtime_error("Failed to open file " + filename);
59 
60 #if _SQUID_WINDOWS_
61  if (!LockFile(hFile, 0, 0, 1, 0))
62 #elif _SQUID_SOLARIS_
63  if (lockf(fd, F_LOCK, 0) != 0)
64 #else
65  if (flock(fd, LOCK_EX) != 0)
66 #endif
67  throw std::runtime_error("Failed to get a lock of " + filename);
68 }
69 
71 {
72 #if _SQUID_WINDOWS_
73  if (hFile != INVALID_HANDLE_VALUE) {
74  UnlockFile(hFile, 0, 0, 1, 0);
75  CloseHandle(hFile);
76  hFile = INVALID_HANDLE_VALUE;
77  }
78 #else
79  if (fd != -1) {
80 #if _SQUID_SOLARIS_
81  lockf(fd, F_ULOCK, 0);
82 #else
83  flock(fd, LOCK_UN);
84 #endif
85  close(fd);
86  fd = -1;
87  }
88 #endif
89  else
90  throw std::runtime_error("Lock is already unlocked for " + filename);
91 }
92 
94 {
95  if (locked())
96  unlock();
97 }
98 
99 Ssl::Locker::Locker(Lock &aLock, const char *aFileName, int aLineNo):
100  weLocked(false), lock(aLock), fileName(aFileName), lineNo(aLineNo)
101 {
102  if (!lock.locked()) {
103  lock.lock();
104  weLocked = true;
105  }
106 }
107 
109 {
110  if (weLocked)
111  lock.unlock();
112 }
113 
115  : width(cnlNumber)
116 {
117  row = (char **)OPENSSL_malloc(sizeof(char *) * (width + 1));
118  for (size_t i = 0; i < width + 1; ++i)
119  row[i] = NULL;
120 }
121 
122 Ssl::CertificateDb::Row::Row(char **aRow, size_t aWidth): width(aWidth)
123 {
124  row = aRow;
125 }
126 
128 {
129  if (!row)
130  return;
131 
132  void *max;
133  if ((max = (void *)row[width]) != NULL) {
134  // It is an openSSL allocated row. The TXT_DB_read function stores the
135  // index and row items one one memory segment. The row[width] points
136  // to the end of buffer. We have to check for items in the array which
137  // are not stored in this segment. These items should released.
138  for (size_t i = 0; i < width + 1; ++i) {
139  if (((row[i] < (char *)row) || (row[i] > max)) && (row[i] != NULL))
140  OPENSSL_free(row[i]);
141  }
142  } else {
143  for (size_t i = 0; i < width + 1; ++i) {
144  if (row[i])
145  OPENSSL_free(row[i]);
146  }
147  }
148  OPENSSL_free(row);
149 }
150 
152 {
153  row = NULL;
154 }
155 
156 void Ssl::CertificateDb::Row::setValue(size_t cell, char const * value)
157 {
158  assert(cell < width);
159  if (row[cell]) {
160  free(row[cell]);
161  }
162  if (value) {
163  row[cell] = static_cast<char *>(OPENSSL_malloc(sizeof(char) * (strlen(value) + 1)));
164  memcpy(row[cell], value, sizeof(char) * (strlen(value) + 1));
165  } else
166  row[cell] = NULL;
167 }
168 
170 {
171  return row;
172 }
173 
174 void Ssl::CertificateDb::sq_TXT_DB_delete(TXT_DB *db, const char **row)
175 {
176  if (!db)
177  return;
178 
179 #if SQUID_SSLTXTDB_PSTRINGDATA
180  for (int i = 0; i < sk_OPENSSL_PSTRING_num(db->data); ++i) {
181 #if SQUID_STACKOF_PSTRINGDATA_HACK
182  const char ** current_row = ((const char **)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, db->data), i));
183 #else
184  const char ** current_row = ((const char **)sk_OPENSSL_PSTRING_value(db->data, i));
185 #endif
186 #else
187  for (int i = 0; i < sk_num(db->data); ++i) {
188  const char ** current_row = ((const char **)sk_value(db->data, i));
189 #endif
190  if (current_row == row) {
191  sq_TXT_DB_delete_row(db, i);
192  return;
193  }
194  }
195 }
196 
197 #define countof(arr) (sizeof(arr)/sizeof(*arr))
198 void Ssl::CertificateDb::sq_TXT_DB_delete_row(TXT_DB *db, int idx) {
199  char **rrow;
200 #if SQUID_SSLTXTDB_PSTRINGDATA
201  rrow = (char **)sk_OPENSSL_PSTRING_delete(db->data, idx);
202 #else
203  rrow = (char **)sk_delete(db->data, idx);
204 #endif
205 
206  if (!rrow)
207  return;
208 
209  Row row(rrow, cnlNumber); // row wrapper used to free the rrow
210 
211  const Columns db_indexes[]= {cnlSerial, cnlKey};
212  for (unsigned int i = 0; i < countof(db_indexes); ++i) {
213  void *data = NULL;
214 #if SQUID_SSLTXTDB_PSTRINGDATA
215  if (LHASH_OF(OPENSSL_STRING) *fieldIndex = db->index[db_indexes[i]])
216  data = lh_OPENSSL_STRING_delete(fieldIndex, rrow);
217 #else
218  if (LHASH *fieldIndex = db->index[db_indexes[i]])
219  data = lh_delete(fieldIndex, rrow);
220 #endif
221  if (data)
222  assert(data == rrow);
223  }
224 }
225 
226 unsigned long Ssl::CertificateDb::index_serial_hash(const char **a) {
227  const char *n = a[Ssl::CertificateDb::cnlSerial];
228  while (*n == '0')
229  ++n;
230  return lh_strhash(n);
231 }
232 
233 int Ssl::CertificateDb::index_serial_cmp(const char **a, const char **b) {
234  const char *aa, *bb;
235  for (aa = a[Ssl::CertificateDb::cnlSerial]; *aa == '0'; ++aa);
236  for (bb = b[Ssl::CertificateDb::cnlSerial]; *bb == '0'; ++bb);
237  return strcmp(aa, bb);
238 }
239 
240 unsigned long Ssl::CertificateDb::index_name_hash(const char **a) {
241  return(lh_strhash(a[Ssl::CertificateDb::cnlKey]));
242 }
243 
244 int Ssl::CertificateDb::index_name_cmp(const char **a, const char **b) {
245  return(strcmp(a[Ssl::CertificateDb::cnlKey], b[CertificateDb::cnlKey]));
246 }
247 
248 const std::string Ssl::CertificateDb::db_file("index.txt");
249 const std::string Ssl::CertificateDb::cert_dir("certs");
250 const std::string Ssl::CertificateDb::size_file("size");
251 
252 Ssl::CertificateDb::CertificateDb(std::string const & aDb_path, size_t aMax_db_size, size_t aFs_block_size)
253  : db_path(aDb_path),
254  db_full(aDb_path + "/" + db_file),
255  cert_full(aDb_path + "/" + cert_dir),
256  size_full(aDb_path + "/" + size_file),
257  max_db_size(aMax_db_size),
258  fs_block_size((aFs_block_size ? aFs_block_size : 2048)),
259  dbLock(db_full),
261  if (db_path.empty() && !max_db_size)
262  enabled_disk_store = false;
263  else if ((db_path.empty() && max_db_size) || (!db_path.empty() && !max_db_size))
264  throw std::runtime_error("security_file_certgen is missing the required parameter. There should be -s and -M parameters together.");
265 }
266 
267 bool
268 Ssl::CertificateDb::find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey)
269 {
270  const Locker locker(dbLock, Here);
271  load();
272  return pure_find(key, expectedOrig, cert, pkey);
273 }
274 
275 bool Ssl::CertificateDb::purgeCert(std::string const & key) {
276  const Locker locker(dbLock, Here);
277  load();
278  if (!db)
279  return false;
280 
281  if (!deleteByKey(key))
282  return false;
283 
284  save();
285  return true;
286 }
287 
288 bool
289 Ssl::CertificateDb::addCertAndPrivateKey(std::string const &useKey, const Security::CertPointer &cert, const Security::PrivateKeyPointer &pkey, const Security::CertPointer &orig)
290 {
291  const Locker locker(dbLock, Here);
292  load();
293  if (!db || !cert || !pkey)
294  return false;
295 
296  if(useKey.empty())
297  return false;
298 
299  // Functor to wrap xfree() for std::unique_ptr
300  typedef HardFun<void, const void*, &xfree> CharDeleter;
301 
302  Row row;
303  ASN1_INTEGER * ai = X509_get_serialNumber(cert.get());
304  std::string serial_string;
305  Ssl::BIGNUM_Pointer serial(ASN1_INTEGER_to_BN(ai, NULL));
306  {
307  std::unique_ptr<char, CharDeleter> hex_bn(BN_bn2hex(serial.get()));
308  serial_string = std::string(hex_bn.get());
309  }
310  row.setValue(cnlSerial, serial_string.c_str());
311  char ** rrow = TXT_DB_get_by_index(db.get(), cnlSerial, row.getRow());
312  // We are creating certificates with unique serial numbers. If the serial
313  // number is found in the database, the same certificate is already stored.
314  if (rrow != NULL) {
315  // TODO: check if the stored row is valid.
316  return true;
317  }
318 
319  // Remove any entry with given key
320  deleteByKey(useKey);
321 
322  // check db size while trying to minimize calls to size()
323  size_t dbSize = size();
324  if ((dbSize == 0 && hasRows()) ||
325  (dbSize > 0 && !hasRows()) ||
326  (dbSize > 10 * max_db_size)) {
327  // Invalid database size, rebuild
328  dbSize = rebuildSize();
329  }
330  while (dbSize > max_db_size && deleteInvalidCertificate()) {
331  dbSize = size(); // get the current database size
332  // and try to find another invalid certificate if needed
333  }
334  // there are no more invalid ones, but there must be valid certificates
335  while (dbSize > max_db_size) {
336  if (!deleteOldestCertificate()) {
337  rebuildSize(); // No certificates in database.Update the size file.
338  save(); // Some entries may have been removed. Update the index file.
339  return false; // errors prevented us from freeing enough space
340  }
341  dbSize = size(); // get the current database size
342  }
343 
344  ASN1_UTCTIME * tm = X509_get_notAfter(cert.get());
345  row.setValue(cnlExp_date, std::string(reinterpret_cast<char *>(tm->data), tm->length).c_str());
346  std::unique_ptr<char, CharDeleter> subject(X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0));
347  row.setValue(cnlName, subject.get());
348  row.setValue(cnlKey, useKey.c_str());
349 
350  if (!TXT_DB_insert(db.get(), row.getRow())) {
351  // failed to add index (???) but we may have already modified
352  // the database so save before exit
353  save();
354  return false;
355  }
356  rrow = row.getRow();
357  row.reset();
358 
359  std::string filename(cert_full + "/" + serial_string + ".pem");
360  if (!WriteEntry(filename.c_str(), cert, pkey, orig)) {
361  //remove row from txt_db and save
362  sq_TXT_DB_delete(db.get(), (const char **)rrow);
363  save();
364  return false;
365  }
366  addSize(filename);
367 
368  save();
369  return true;
370 }
371 
372 void
373 Ssl::CertificateDb::Create(std::string const & db_path) {
374  if (db_path == "")
375  throw std::runtime_error("Path to db is empty");
376  std::string db_full(db_path + "/" + db_file);
377  std::string cert_full(db_path + "/" + cert_dir);
378  std::string size_full(db_path + "/" + size_file);
379 
380  if (mkdir(db_path.c_str(), 0777))
381  throw std::runtime_error("Cannot create " + db_path);
382 
383  if (mkdir(cert_full.c_str(), 0777))
384  throw std::runtime_error("Cannot create " + cert_full);
385 
386  std::ofstream size(size_full.c_str());
387  if (size)
388  size << 0;
389  else
390  throw std::runtime_error("Cannot open " + size_full + " to open");
391  std::ofstream db(db_full.c_str());
392  if (!db)
393  throw std::runtime_error("Cannot open " + db_full + " to open");
394 }
395 
396 void
397 Ssl::CertificateDb::Check(std::string const & db_path, size_t max_db_size, size_t fs_block_size) {
398  CertificateDb db(db_path, max_db_size, fs_block_size);
399  db.load();
400 
401  // Call readSize to force rebuild size file in the case it is corrupted
402  (void)db.readSize();
403 }
404 
406 {
407  size_t dbSize = 0;
408 #if SQUID_SSLTXTDB_PSTRINGDATA
409  for (int i = 0; i < sk_OPENSSL_PSTRING_num(db.get()->data); ++i) {
410 #if SQUID_STACKOF_PSTRINGDATA_HACK
411  const char ** current_row = ((const char **)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, db.get()->data), i));
412 #else
413  const char ** current_row = ((const char **)sk_OPENSSL_PSTRING_value(db.get()->data, i));
414 #endif
415 #else
416  for (int i = 0; i < sk_num(db.get()->data); ++i) {
417  const char ** current_row = ((const char **)sk_value(db.get()->data, i));
418 #endif
419  const std::string filename(cert_full + "/" + current_row[cnlSerial] + ".pem");
420  const size_t fSize = getFileSize(filename);
421  dbSize += fSize;
422  }
423  writeSize(dbSize);
424  return dbSize;
425 }
426 
427 bool
428 Ssl::CertificateDb::pure_find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey)
429 {
430  if (!db)
431  return false;
432 
433  Row row;
434  row.setValue(cnlKey, key.c_str());
435 
436  char **rrow = TXT_DB_get_by_index(db.get(), cnlKey, row.getRow());
437  if (rrow == NULL)
438  return false;
439 
440  if (!sslDateIsInTheFuture(rrow[cnlExp_date]))
441  return false;
442 
443  Security::CertPointer storedOrig;
444  // read cert and pkey from file.
445  std::string filename(cert_full + "/" + rrow[cnlSerial] + ".pem");
446  if (!ReadEntry(filename.c_str(), cert, pkey, storedOrig))
447  return false;
448 
449  if (!storedOrig && !expectedOrig)
450  return true;
451  else
452  return Ssl::CertificatesCmp(expectedOrig, storedOrig);
453 }
454 
456  return readSize();
457 }
458 
459 void Ssl::CertificateDb::addSize(std::string const & filename) {
460  // readSize will rebuild 'size' file if missing or it is corrupted
461  size_t dbSize = readSize();
462  dbSize += getFileSize(filename);
463  writeSize(dbSize);
464 }
465 
466 void Ssl::CertificateDb::subSize(std::string const & filename) {
467  // readSize will rebuild 'size' file if missing or it is corrupted
468  size_t dbSize = readSize();
469  const size_t fileSize = getFileSize(filename);
470  dbSize = dbSize > fileSize ? dbSize - fileSize : 0;
471  writeSize(dbSize);
472 }
473 
475  std::ifstream ifstr(size_full.c_str());
476  size_t db_size = 0;
477  if (!ifstr || !(ifstr >> db_size))
478  return rebuildSize();
479  return db_size;
480 }
481 
482 void Ssl::CertificateDb::writeSize(size_t db_size) {
483  std::ofstream ofstr(size_full.c_str());
484  if (!ofstr)
485  throw std::runtime_error("cannot write \"" + size_full + "\" file");
486  ofstr << db_size;
487 }
488 
489 size_t Ssl::CertificateDb::getFileSize(std::string const & filename) {
490  std::ifstream file(filename.c_str(), std::ios::binary);
491  if (!file)
492  return 0;
493  file.seekg(0, std::ios_base::end);
494  const std::streampos file_size = file.tellg();
495  if (file_size < 0)
496  return 0;
497  return ((static_cast<size_t>(file_size) + fs_block_size - 1) / fs_block_size) * fs_block_size;
498 }
499 
501  // Load db from file.
502  Ssl::BIO_Pointer in(BIO_new(BIO_s_file()));
503  if (!in || BIO_read_filename(in.get(), db_full.c_str()) <= 0)
504  throw std::runtime_error("Uninitialized SSL certificate database directory: " + db_path + ". To initialize, run \"security_file_certgen -c -s " + db_path + "\".");
505 
506  bool corrupt = false;
507  Ssl::TXT_DB_Pointer temp_db(TXT_DB_read(in.get(), cnlNumber));
508  if (!temp_db)
509  corrupt = true;
510 
511  // Create indexes in db.
512  if (!corrupt && !TXT_DB_create_index(temp_db.get(), cnlSerial, NULL, LHASH_HASH_FN(index_serial_hash), LHASH_COMP_FN(index_serial_cmp)))
513  corrupt = true;
514 
515  if (!corrupt && !TXT_DB_create_index(temp_db.get(), cnlKey, NULL, LHASH_HASH_FN(index_name_hash), LHASH_COMP_FN(index_name_cmp)))
516  corrupt = true;
517 
518  if (corrupt)
519  throw std::runtime_error("The SSL certificate database " + db_path + " is corrupted. Please rebuild");
520 
521  db.reset(temp_db.release());
522 }
523 
525  if (!db)
526  throw std::runtime_error("The certificates database is not loaded");;
527 
528  // To save the db to file, create a new BIO with BIO file methods.
529  Ssl::BIO_Pointer out(BIO_new(BIO_s_file()));
530  if (!out || !BIO_write_filename(out.get(), const_cast<char *>(db_full.c_str())))
531  throw std::runtime_error("Failed to initialize " + db_full + " file for writing");;
532 
533  if (TXT_DB_write(out.get(), db.get()) < 0)
534  throw std::runtime_error("Failed to write " + db_full + " file");
535 }
536 
537 // Normally defined in defines.h file
538 void Ssl::CertificateDb::deleteRow(const char **row, int rowIndex) {
539  const std::string filename(cert_full + "/" + row[cnlSerial] + ".pem");
540  sq_TXT_DB_delete_row(db.get(), rowIndex);
541 
542  subSize(filename);
543  int ret = remove(filename.c_str());
544  if (ret < 0 && errno != ENOENT)
545  throw std::runtime_error("Failed to remove certficate file " + filename + " from db");
546 }
547 
549  if (!db)
550  return false;
551 
552  bool removed_one = false;
553 #if SQUID_SSLTXTDB_PSTRINGDATA
554  for (int i = 0; i < sk_OPENSSL_PSTRING_num(db.get()->data); ++i) {
555 #if SQUID_STACKOF_PSTRINGDATA_HACK
556  const char ** current_row = ((const char **)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, db.get()->data), i));
557 #else
558  const char ** current_row = ((const char **)sk_OPENSSL_PSTRING_value(db.get()->data, i));
559 #endif
560 #else
561  for (int i = 0; i < sk_num(db.get()->data); ++i) {
562  const char ** current_row = ((const char **)sk_value(db.get()->data, i));
563 #endif
564 
565  if (!sslDateIsInTheFuture(current_row[cnlExp_date])) {
566  deleteRow(current_row, i);
567  removed_one = true;
568  break;
569  }
570  }
571 
572  if (!removed_one)
573  return false;
574  return true;
575 }
576 
578 {
579  if (!hasRows())
580  return false;
581 
582 #if SQUID_SSLTXTDB_PSTRINGDATA
583 #if SQUID_STACKOF_PSTRINGDATA_HACK
584  const char **row = ((const char **)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, db.get()->data), 0));
585 #else
586  const char **row = (const char **)sk_OPENSSL_PSTRING_value(db.get()->data, 0);
587 #endif
588 #else
589  const char **row = (const char **)sk_value(db.get()->data, 0);
590 #endif
591 
592  deleteRow(row, 0);
593 
594  return true;
595 }
596 
597 bool
598 Ssl::CertificateDb::deleteByKey(std::string const & key) {
599  if (!db)
600  return false;
601 
602 #if SQUID_SSLTXTDB_PSTRINGDATA
603  for (int i = 0; i < sk_OPENSSL_PSTRING_num(db.get()->data); ++i) {
604 #if SQUID_STACKOF_PSTRINGDATA_HACK
605  const char ** current_row = ((const char **)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, db.get()->data), i));
606 #else
607  const char ** current_row = ((const char **)sk_OPENSSL_PSTRING_value(db.get()->data, i));
608 #endif
609 #else
610  for (int i = 0; i < sk_num(db.get()->data); ++i) {
611  const char ** current_row = ((const char **)sk_value(db.get()->data, i));
612 #endif
613  if (key == current_row[cnlKey]) {
614  deleteRow(current_row, i);
615  return true;
616  }
617  }
618  return false;
619 }
620 
622 {
623  if (!db)
624  return false;
625 
626 #if SQUID_SSLTXTDB_PSTRINGDATA
627  if (sk_OPENSSL_PSTRING_num(db.get()->data) == 0)
628 #else
629  if (sk_num(db.get()->data) == 0)
630 #endif
631  return false;
632  return true;
633 }
634 
636  return enabled_disk_store;
637 }
638 
639 bool
640 Ssl::CertificateDb::WriteEntry(const std::string &filename, const Security::CertPointer &cert, const Security::PrivateKeyPointer &pkey, const Security::CertPointer &orig)
641 {
642  Ssl::BIO_Pointer bio;
643  if (!Ssl::OpenCertsFileForWriting(bio, filename.c_str()))
644  return false;
645  if (!Ssl::WriteX509Certificate(bio, cert))
646  return false;
647  if (!Ssl::WritePrivateKey(bio, pkey))
648  return false;
649  if (orig && !Ssl::WriteX509Certificate(bio, orig))
650  return false;
651  return true;
652 }
653 
654 bool
655 Ssl::CertificateDb::ReadEntry(std::string filename, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, Security::CertPointer &orig)
656 {
657  Ssl::BIO_Pointer bio;
658  if (!Ssl::OpenCertsFileForReading(bio, filename.c_str()))
659  return false;
660  if (!Ssl::ReadX509Certificate(bio, cert))
661  return false;
662  if (!Ssl::ReadPrivateKey(bio, pkey, NULL))
663  return false;
664  // The orig certificate is not mandatory
665  (void)Ssl::ReadX509Certificate(bio, orig);
666  return true;
667 }
668 
bool deleteInvalidCertificate()
Delete invalid certificate.
static bool WriteEntry(const std::string &filename, const Security::CertPointer &cert, const Security::PrivateKeyPointer &pkey, const Security::CertPointer &orig)
stores the db entry into a file
void addSize(std::string const &filename)
Increase db size by the given file size and update size_file.
~Lock()
releases the lock if it is locked
bool sslDateIsInTheFuture(char const *date)
Definition: gadgets.cc:770
static int index_name_cmp(const char **a, const char **b)
Callback compare function for names. Used to create TXT_DB index of names..
#define assert(EX)
Definition: assert.h:17
Lock & lock
the lock we are operating on
an exception-safe way to obtain and release a lock
size_t readSize()
Read size from file size_file.
static void Create(std::string const &db_path)
Create and initialize a database under the db_path.
bool OpenCertsFileForReading(BIO_Pointer &bio, const char *filename)
Definition: gadgets.cc:696
Lock(std::string const &filename)
creates an unlocked lock
static unsigned long index_serial_hash(const char **a)
Callback hash function for serials. Used to create TXT_DB index of serials.
bool deleteOldestCertificate()
Delete oldest certificate.
#define countof(arr)
bool WritePrivateKey(BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey)
Definition: gadgets.cc:761
DB * db
int i
Definition: membanger.c:49
bool ReadX509Certificate(BIO_Pointer &bio, Security::CertPointer &cert)
Definition: gadgets.cc:707
bool IsEnabledDiskStore() const
Check enabled of dist store.
const size_t max_db_size
Max size of db.
static const char **static const char **static const std::string db_file
Base name of the database index file.
bool pure_find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey)
Only find certificate in current db and return it.
void unlock()
unlocks locked lock or throws
static void sq_TXT_DB_delete(TXT_DB *db, const char **row)
Removes the first matching row from TXT_DB. Ignores failures.
std::unique_ptr< BIGNUM, HardFun< void, BIGNUM *,&BN_free > > BIGNUM_Pointer
Definition: gadgets.h:48
static int index_serial_cmp(const char **a, const char **b)
Callback compare function for serials. Used to create TXT_DB index of serials.
~Locker()
unlocks the lock if it was locked by us
bool OpenCertsFileForWriting(BIO_Pointer &bio, const char *filename)
Definition: gadgets.cc:740
A const & max(A const &lhs, A const &rhs)
bool locked() const
whether our lock is locked
void const char HLPCB void * data
Definition: stub_helper.cc:16
bool deleteByKey(std::string const &key)
Delete using key.
size_t getFileSize(std::string const &filename)
get file size on disk.
#define true
Definition: GnuRegex.c:234
const std::string size_full
Full path of the file to store the db size.
static void sq_TXT_DB_delete_row(TXT_DB *db, int idx)
Remove the row on position idx from TXT_DB. Ignores failures.
static void Check(std::string const &db_path, size_t max_db_size, size_t fs_block_size)
Check the database stored under the db_path.
const std::string cert_full
Full path of the directory to store the certs.
Row()
Create row wrapper.
bool enabled_disk_store
The storage on the disk is enabled.
bool ReadPrivateKey(BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
Definition: gadgets.cc:718
void writeSize(size_t db_size)
Write size to file size_file.
bool find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey)
finds matching generated certificate and its private key
maintains an exclusive blocking file-based lock
std::unique_ptr< BIO, HardFun< void, BIO *,&BIO_vfree > > BIO_Pointer
Definition: gadgets.h:50
bool WriteX509Certificate(BIO_Pointer &bio, const Security::CertPointer &cert)
Definition: gadgets.cc:751
bool purgeCert(std::string const &key)
Delete a certificate from database.
size_t width
Number of cells in the row.
const std::string db_path
The database directory.
bool hasRows() const
Whether the TXT_DB has stored items.
Locker(Lock &lock, const char *aFileName, int lineNo)
locks the lock if the lock was unlocked
void lock()
locks the lock, may block
char ** getRow()
Raw row.
bool weLocked
whether we locked the lock
Lock dbLock
protects the database file
void reset()
Abandon row and don't free memory.
char * db_path
static unsigned long index_name_hash(const char **a)
Callback hash function for names. Used to create TXT_DB index of names..
~Row()
Delete all row.
A wrapper for OpenSSL database row of TXT_DB database.
#define Here
convenience macro to pass source code location to Locker and others
int a
Definition: membanger.c:50
std::unique_ptr< TXT_DB, HardFun< void, TXT_DB *,&TXT_DB_free > > TXT_DB_Pointer
Definition: gadgets.h:56
static const std::string cert_dir
Base name of the directory to store the certs.
static const std::string size_file
const size_t fs_block_size
File system block size.
void save()
Save db to disk.
CertificateDb(std::string const &db_path, size_t aMax_db_size, size_t aFs_block_size)
Columns
Names of db columns.
bool CertificatesCmp(const Security::CertPointer &cert1, const Security::CertPointer &cert2)
Definition: gadgets.cc:924
void deleteRow(const char **row, int rowIndex)
Delete a row from TXT_DB.
#define NULL
Definition: types.h:166
void subSize(std::string const &filename)
Decrease db size by the given file size and update size_file.
int size
Definition: ModDevPoll.cc:77
void load()
Load db from disk.
bool addCertAndPrivateKey(std::string const &useKey, const Security::CertPointer &cert, const Security::PrivateKeyPointer &pkey, const Security::CertPointer &orig)
Save certificate to disk.
#define false
Definition: GnuRegex.c:233
static bool ReadEntry(std::string filename, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, Security::CertPointer &orig)
loads a db entry from the file
const std::string db_full
Full path of the database index file.
void setValue(size_t number, char const *value)
Set cell's value in row.
#define free(a)
Definition: hash.c:31

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors