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

 

Introduction

Documentation

Support

Miscellaneous