]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
bbc27441 AJ |
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 | ||
95d2589c CT |
9 | #ifndef SQUID_SSL_CERTIFICATE_DB_H |
10 | #define SQUID_SSL_CERTIFICATE_DB_H | |
11 | ||
0efecd32 | 12 | #include "base/Here.h" |
95d2589c | 13 | #include "ssl/gadgets.h" |
074d6a40 | 14 | |
074d6a40 | 15 | #include <string> |
95d2589c CT |
16 | |
17 | namespace Ssl | |
18 | { | |
5b3d088d | 19 | /// maintains an exclusive blocking file-based lock |
e29ccb57 A |
20 | class Lock |
21 | { | |
95d2589c | 22 | public: |
5b3d088d CT |
23 | explicit Lock(std::string const &filename); ///< creates an unlocked lock |
24 | ~Lock(); ///< releases the lock if it is locked | |
25 | void lock(); ///< locks the lock, may block | |
26 | void unlock(); ///< unlocks locked lock or throws | |
27 | bool locked() const; ///< whether our lock is locked | |
28 | const char *name() const { return filename.c_str(); } | |
95d2589c | 29 | private: |
5b3d088d | 30 | std::string filename; |
7aa9bb3e | 31 | #if _SQUID_WINDOWS_ |
95d2589c CT |
32 | HANDLE hFile; ///< Windows file handle. |
33 | #else | |
34 | int fd; ///< Linux file descriptor. | |
35 | #endif | |
36 | }; | |
37 | ||
5b3d088d CT |
38 | /// an exception-safe way to obtain and release a lock |
39 | class Locker | |
40 | { | |
41 | public: | |
42 | /// locks the lock if the lock was unlocked | |
0efecd32 | 43 | Locker(Lock &, const SourceLocation &); |
5b3d088d CT |
44 | /// unlocks the lock if it was locked by us |
45 | ~Locker(); | |
46 | private: | |
47 | bool weLocked; ///< whether we locked the lock | |
48 | Lock &lock; ///< the lock we are operating on | |
5b3d088d | 49 | |
0efecd32 AR |
50 | /// where the lock was needed (currently not reported anywhere) |
51 | const SourceLocation caller; | |
52 | }; | |
5b3d088d | 53 | |
95d2589c CT |
54 | /** |
55 | * Database class for storing SSL certificates and their private keys. | |
56 | * A database consist by: | |
57 | * - A disk file to store current serial number | |
58 | * - A disk file to store the current database size | |
59 | * - A disk file which is a normal TXT_DB openSSL database | |
60 | * - A directory under which the certificates and their private keys stored. | |
61 | * The database before used must initialized with CertificateDb::create static method. | |
62 | */ | |
63 | class CertificateDb | |
64 | { | |
65 | public: | |
66 | /// Names of db columns. | |
67 | enum Columns { | |
5107d2c4 | 68 | cnlKey = 0, //< The key to use for storing/retrieving entries from DB. |
95d2589c CT |
69 | cnlExp_date, |
70 | cnlRev_date, | |
71 | cnlSerial, | |
95d2589c CT |
72 | cnlName, |
73 | cnlNumber | |
74 | }; | |
75 | ||
76 | /// A wrapper for OpenSSL database row of TXT_DB database. | |
77 | class Row | |
78 | { | |
79 | public: | |
80 | /// Create row wrapper. | |
81 | Row(); | |
f385ac29 CT |
82 | ///Create row wrapper for row with width items |
83 | Row(char **row, size_t width); | |
95d2589c CT |
84 | /// Delete all row. |
85 | ~Row(); | |
86 | void setValue(size_t number, char const * value); ///< Set cell's value in row | |
87 | char ** getRow(); ///< Raw row | |
88 | void reset(); ///< Abandon row and don't free memory | |
89 | private: | |
90 | char **row; ///< Raw row | |
91 | size_t width; ///< Number of cells in the row | |
92 | }; | |
93 | ||
94 | CertificateDb(std::string const & db_path, size_t aMax_db_size, size_t aFs_block_size); | |
5107d2c4 | 95 | /// finds matching generated certificate and its private key |
cf487124 | 96 | bool find(std::string const & key, const Security::CertPointer &expectedOrig, Security::CertPointer & cert, Security::PrivateKeyPointer & pkey); |
4ece76b2 CT |
97 | /// Delete a certificate from database |
98 | bool purgeCert(std::string const & key); | |
95d2589c | 99 | /// Save certificate to disk. |
cf487124 | 100 | bool addCertAndPrivateKey(std::string const & useKey, const Security::CertPointer & cert, const Security::PrivateKeyPointer & pkey, const Security::CertPointer &orig); |
5107d2c4 | 101 | |
95d2589c | 102 | /// Create and initialize a database under the db_path |
5107d2c4 | 103 | static void Create(std::string const & db_path); |
95d2589c | 104 | /// Check the database stored under the db_path. |
5107d2c4 | 105 | static void Check(std::string const & db_path, size_t max_db_size, size_t fs_block_size); |
95d2589c CT |
106 | private: |
107 | void load(); ///< Load db from disk. | |
108 | void save(); ///< Save db to disk. | |
a066059b | 109 | size_t size(); ///< Get db size on disk in bytes. |
95d2589c CT |
110 | /// Increase db size by the given file size and update size_file |
111 | void addSize(std::string const & filename); | |
112 | /// Decrease db size by the given file size and update size_file | |
113 | void subSize(std::string const & filename); | |
a066059b | 114 | size_t readSize(); ///< Read size from file size_file |
95d2589c CT |
115 | void writeSize(size_t db_size); ///< Write size to file size_file. |
116 | size_t getFileSize(std::string const & filename); ///< get file size on disk. | |
a066059b | 117 | size_t rebuildSize(); ///< Rebuild size_file |
95d2589c | 118 | /// Only find certificate in current db and return it. |
cf487124 | 119 | bool pure_find(std::string const & key, const Security::CertPointer & expectedOrig, Security::CertPointer & cert, Security::PrivateKeyPointer & pkey); |
95d2589c | 120 | |
1bf6c6e7 | 121 | void deleteRow(const char **row, int rowIndex); ///< Delete a row from TXT_DB |
95d2589c CT |
122 | bool deleteInvalidCertificate(); ///< Delete invalid certificate. |
123 | bool deleteOldestCertificate(); ///< Delete oldest certificate. | |
5107d2c4 | 124 | bool deleteByKey(std::string const & key); ///< Delete using key. |
541e6ab5 | 125 | bool hasRows() const; ///< Whether the TXT_DB has stored items. |
95d2589c | 126 | |
5107d2c4 | 127 | /// stores the db entry into a file |
cf487124 | 128 | static bool WriteEntry(const std::string &filename, const Security::CertPointer & cert, const Security::PrivateKeyPointer & pkey, const Security::CertPointer &orig); |
5107d2c4 CT |
129 | |
130 | /// loads a db entry from the file | |
cf487124 | 131 | static bool ReadEntry(std::string filename, Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, Security::CertPointer &orig); |
5107d2c4 | 132 | |
f385ac29 CT |
133 | /// Removes the first matching row from TXT_DB. Ignores failures. |
134 | static void sq_TXT_DB_delete(TXT_DB *db, const char **row); | |
135 | /// Remove the row on position idx from TXT_DB. Ignores failures. | |
136 | static void sq_TXT_DB_delete_row(TXT_DB *db, int idx); | |
137 | ||
95d2589c CT |
138 | /// Callback hash function for serials. Used to create TXT_DB index of serials. |
139 | static unsigned long index_serial_hash(const char **a); | |
140 | /// Callback compare function for serials. Used to create TXT_DB index of serials. | |
141 | static int index_serial_cmp(const char **a, const char **b); | |
142 | /// Callback hash function for names. Used to create TXT_DB index of names.. | |
143 | static unsigned long index_name_hash(const char **a); | |
144 | /// Callback compare function for names. Used to create TXT_DB index of names.. | |
145 | static int index_name_cmp(const char **a, const char **b); | |
146 | ||
147 | /// Definitions required by openSSL, to use the index_* functions defined above | |
148 | ///with TXT_DB_create_index. | |
fee5325b CT |
149 | #if SQUID_USE_SSLLHASH_HACK |
150 | static unsigned long index_serial_hash_LHASH_HASH(const void *a) { | |
3eee6040 CT |
151 | return index_serial_hash((const char **)a); |
152 | } | |
fee5325b | 153 | static int index_serial_cmp_LHASH_COMP(const void *arg1, const void *arg2) { |
3eee6040 CT |
154 | return index_serial_cmp((const char **)arg1, (const char **)arg2); |
155 | } | |
fee5325b | 156 | static unsigned long index_name_hash_LHASH_HASH(const void *a) { |
3eee6040 CT |
157 | return index_name_hash((const char **)a); |
158 | } | |
fee5325b | 159 | static int index_name_cmp_LHASH_COMP(const void *arg1, const void *arg2) { |
3eee6040 CT |
160 | return index_name_cmp((const char **)arg1, (const char **)arg2); |
161 | } | |
162 | #else | |
95d2589c CT |
163 | static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **) |
164 | static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **) | |
165 | static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **) | |
166 | static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **) | |
3eee6040 | 167 | #endif |
95d2589c | 168 | |
95d2589c CT |
169 | static const std::string db_file; ///< Base name of the database index file. |
170 | static const std::string cert_dir; ///< Base name of the directory to store the certs. | |
171 | static const std::string size_file; ///< Base name of the file to store db size. | |
172 | /// Min size of disk db. If real size < min_db_size the db will be disabled. | |
173 | static const size_t min_db_size; | |
174 | ||
175 | const std::string db_path; ///< The database directory. | |
95d2589c CT |
176 | const std::string db_full; ///< Full path of the database index file. |
177 | const std::string cert_full; ///< Full path of the directory to store the certs. | |
178 | const std::string size_full; ///< Full path of the file to store the db size. | |
179 | ||
180 | TXT_DB_Pointer db; ///< Database with certificates info. | |
181 | const size_t max_db_size; ///< Max size of db. | |
182 | const size_t fs_block_size; ///< File system block size. | |
5b3d088d | 183 | mutable Lock dbLock; ///< protects the database file |
95d2589c CT |
184 | }; |
185 | ||
186 | } // namespace Ssl | |
187 | #endif // SQUID_SSL_CERTIFICATE_DB_H | |
f53969cc | 188 |