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