From: Christos Tsantilas Date: Thu, 22 Sep 2011 16:37:55 +0000 (+0300) Subject: Bug fix: "(ssl_crtd): Cannot add certificate to db" when updating expired cert X-Git-Tag: BumpSslServerFirst.take01~137 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1bf6c6e76a1a40721e597297757eaaa4d4d970bf;p=thirdparty%2Fsquid.git Bug fix: "(ssl_crtd): Cannot add certificate to db" when updating expired cert When ssl_crtd helper needs to add a fresh certificate to the database but finds an expired certificate already stored, ssl_crtd deletes the expired certificate file from disk before adding the fresh one. However, the addition still fails because the expired certificate was not removed from database indexes. This fix: - Adds code to update database indexes upon deletion of a row. - Polishes certificates deletion code to avoid duplication. TODO: Report failure details to Squid and make certificate-specific failures not fatal for the ssl_crtd helper. This is a Measurement Factory project. --- diff --git a/src/ssl/certificate_db.cc b/src/ssl/certificate_db.cc index 487d29ddf2..9f15ca3a4b 100644 --- a/src/ssl/certificate_db.cc +++ b/src/ssl/certificate_db.cc @@ -427,6 +427,35 @@ void Ssl::CertificateDb::save() throw std::runtime_error("Failed to write " + db_full + " file"); } +// Normally defined in defines.h file +#define countof(arr) (sizeof(arr)/sizeof(*arr)) +void Ssl::CertificateDb::deleteRow(const char **row, int rowIndex) +{ + const std::string filename(cert_full + "/" + row[cnlSerial] + ".pem"); + const FileLocker cert_locker(filename); +#if OPENSSL_VERSION_NUMBER >= 0x1000004fL + sk_OPENSSL_PSTRING_delete(db.get()->data, rowIndex); +#else + sk_delete(db.get()->data, rowIndex); +#endif + + const Columns db_indexes[]={cnlSerial, cnlName}; + for (unsigned int i = 0; i < countof(db_indexes); i++) { +#if OPENSSL_VERSION_NUMBER >= 0x1000004fL + if (LHASH_OF(OPENSSL_STRING) *fieldIndex = db.get()->index[db_indexes[i]]) + lh_OPENSSL_STRING_delete(fieldIndex, (char **)row); +#else + if (LHASH *fieldIndex = db.get()->index[db_indexes[i]]) + lh_delete(fieldIndex, row); +#endif + } + + subSize(filename); + int ret = remove(filename.c_str()); + if (ret < 0) + throw std::runtime_error("Failed to remove certficate file " + filename + " from db"); +} + bool Ssl::CertificateDb::deleteInvalidCertificate() { if (!db) @@ -442,15 +471,7 @@ bool Ssl::CertificateDb::deleteInvalidCertificate() #endif if (!sslDateIsInTheFuture(current_row[cnlExp_date])) { - std::string filename(cert_full + "/" + current_row[cnlSerial] + ".pem"); - FileLocker cert_locker(filename); -#if OPENSSL_VERSION_NUMBER >= 0x1000004fL - sk_OPENSSL_PSTRING_delete(db.get()->data, i); -#else - sk_delete(db.get()->data, i); -#endif - subSize(filename); - remove(filename.c_str()); + deleteRow(current_row, i); removed_one = true; break; } @@ -478,17 +499,8 @@ bool Ssl::CertificateDb::deleteOldestCertificate() #else const char **row = (const char **)sk_value(db.get()->data, 0); #endif - std::string filename(cert_full + "/" + row[cnlSerial] + ".pem"); - FileLocker cert_locker(filename); -#if OPENSSL_VERSION_NUMBER >= 0x1000004fL - sk_OPENSSL_PSTRING_delete(db.get()->data, 0); -#else - sk_delete(db.get()->data, 0); -#endif - - subSize(filename); - remove(filename.c_str()); + deleteRow(row, 0); return true; } @@ -506,15 +518,7 @@ bool Ssl::CertificateDb::deleteByHostname(std::string const & host) const char ** current_row = ((const char **)sk_value(db.get()->data, i)); #endif if (host == current_row[cnlName]) { - std::string filename(cert_full + "/" + current_row[cnlSerial] + ".pem"); - FileLocker cert_locker(filename); -#if OPENSSL_VERSION_NUMBER >= 0x1000004fL - sk_OPENSSL_PSTRING_delete(db.get()->data, i); -#else - sk_delete(db.get()->data, i); -#endif - subSize(filename); - remove(filename.c_str()); + deleteRow(current_row, i); return true; } } diff --git a/src/ssl/certificate_db.h b/src/ssl/certificate_db.h index 4c301bb3dd..0ed15d6fd7 100644 --- a/src/ssl/certificate_db.h +++ b/src/ssl/certificate_db.h @@ -98,6 +98,7 @@ private: /// Only find certificate in current db and return it. bool pure_find(std::string const & host_name, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey); + void deleteRow(const char **row, int rowIndex); ///< Delete a row from TXT_DB bool deleteInvalidCertificate(); ///< Delete invalid certificate. bool deleteOldestCertificate(); ///< Delete oldest certificate. bool deleteByHostname(std::string const & host); ///< Delete using host name.