certificate_db.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2022 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, 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 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] = NULL;
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]) != NULL) {
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] != NULL))
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 = NULL;
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] = NULL;
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 = NULL;
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, NULL));
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 != NULL) {
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 == NULL)
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, NULL, 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, NULL, 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, NULL))
653  return false;
654 
655  orig = Ssl::ReadOptionalCertificate(bio);
656 
657  return true;
658 }
659 
#define false
Definition: GnuRegex.c:233
#define Here()
source code location of the caller
Definition: Here.h:15
int size
Definition: ModDevPoll.cc:75
#define assert(EX)
Definition: assert.h:19
#define countof(arr)
T * get() const
Returns raw and possibly nullptr pointer.
a source code location that is cheap to create, copy, and store
Definition: Here.h:30
A wrapper for OpenSSL database row of TXT_DB database.
void setValue(size_t number, char const *value)
Set cell's value in row.
size_t width
Number of cells in the row.
Row()
Create row wrapper.
void reset()
Abandon row and don't free memory.
char ** getRow()
Raw row.
bool deleteByKey(std::string const &key)
Delete using key.
const size_t fs_block_size
File system block size.
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
static int index_serial_cmp(const char **a, const char **b)
Callback compare function for serials. Used to create TXT_DB index of serials.
static void Create(std::string const &db_path)
Create and initialize a database under the db_path.
void deleteRow(const char **row, int rowIndex)
Delete a row from TXT_DB.
const std::string size_full
Full path of the file to store the db size.
TXT_DB_Pointer db
Database with certificates info.
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 writeSize(size_t db_size)
Write size to file size_file.
static unsigned long index_serial_hash(const char **a)
Callback hash function for serials. Used to create TXT_DB index of serials.
bool purgeCert(std::string const &key)
Delete a certificate from database.
static const std::string cert_dir
Base name of the directory to store the certs.
const std::string cert_full
Full path of the directory to store the certs.
void subSize(std::string const &filename)
Decrease db size by the given file size and update size_file.
bool deleteOldestCertificate()
Delete oldest certificate.
static unsigned long index_name_hash(const char **a)
Callback hash function for names. Used to create TXT_DB index of names..
void addSize(std::string const &filename)
Increase db size by the given file size and update size_file.
static bool ReadEntry(std::string filename, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, Security::CertPointer &orig)
loads a db entry from the file
size_t readSize()
Read size from file size_file.
bool hasRows() const
Whether the TXT_DB has stored items.
static int index_name_cmp(const char **a, const char **b)
Callback compare function for names. Used to create TXT_DB index of names..
const size_t max_db_size
Max size of db.
void save()
Save db to disk.
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.
Columns
Names of db columns.
CertificateDb(std::string const &db_path, size_t aMax_db_size, size_t aFs_block_size)
bool addCertAndPrivateKey(std::string const &useKey, const Security::CertPointer &cert, const Security::PrivateKeyPointer &pkey, const Security::CertPointer &orig)
Save certificate to disk.
static const std::string 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
const std::string db_full
Full path of the database index file.
static const char **static const char **static const std::string db_file
Base name of the database index file.
const std::string db_path
The database directory.
bool deleteInvalidCertificate()
Delete invalid certificate.
static void sq_TXT_DB_delete(TXT_DB *db, const char **row)
Removes the first matching row from TXT_DB. Ignores failures.
Lock dbLock
protects the database file
static void sq_TXT_DB_delete_row(TXT_DB *db, int idx)
Remove the row on position idx from TXT_DB. Ignores failures.
size_t getFileSize(std::string const &filename)
get file size on disk.
void load()
Load db from disk.
maintains an exclusive blocking file-based lock
Lock(std::string const &filename)
creates an unlocked lock
~Lock()
releases the lock if it is locked
bool locked() const
whether our lock is locked
void lock()
locks the lock, may block
void unlock()
unlocks locked lock or throws
an exception-safe way to obtain and release a lock
~Locker()
unlocks the lock if it was locked by us
Locker(Lock &, const SourceLocation &)
locks the lock if the lock was unlocked
Lock & lock
the lock we are operating on
bool weLocked
whether we locked the lock
an std::runtime_error with thrower location info
Definition: TextException.h:21
A const & max(A const &lhs, A const &rhs)
char * db_path
TDB_CONTEXT * db
bool CertificatesCmp(const Security::CertPointer &cert1, const Security::CertPointer &cert2)
Definition: gadgets.cc:988
bool ReadPrivateKey(BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
Definition: gadgets.cc:776
bool OpenCertsFileForWriting(BIO_Pointer &bio, const char *filename)
Definition: gadgets.cc:798
bool WritePrivateKey(BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey)
Definition: gadgets.cc:819
bool sslDateIsInTheFuture(char const *date)
Definition: gadgets.cc:834
bool OpenCertsFileForReading(BIO_Pointer &bio, const char *filename)
Definition: gadgets.cc:730
bool WriteX509Certificate(BIO_Pointer &bio, const Security::CertPointer &cert)
Definition: gadgets.cc:809
std::unique_ptr< BIO, HardFun< void, BIO *, &BIO_vfree > > BIO_Pointer
Definition: gadgets.h:51
std::unique_ptr< BIGNUM, HardFun< void, BIGNUM *, &BN_free > > BIGNUM_Pointer
Definition: gadgets.h:49
std::unique_ptr< TXT_DB, HardFun< void, TXT_DB *, &TXT_DB_free > > TXT_DB_Pointer
Definition: gadgets.h:57
Security::CertPointer ReadOptionalCertificate(const BIO_Pointer &)
Definition: gadgets.cc:741
UniqueCString OneLineSummary(X509_NAME &)
a RAII wrapper for the memory-allocating flavor of X509_NAME_oneline()
Definition: gadgets.cc:829
Security::CertPointer ReadCertificate(const BIO_Pointer &)
Definition: gadgets.cc:766
std::unique_ptr< char, HardFun< void, char *, &OPENSSL_free_for_c_strings > > UniqueCString
Definition: gadgets.h:78
#define OPENSSL_LH_strhash
Definition: openssl.h:129
#define OPENSSL_LH_delete
Definition: openssl.h:128
#define X509_getm_notAfter
Definition: openssl.h:247
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
#define NULL
Definition: types.h:166

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors