This patch add squid internal cache for cert validator helper. It is
posted as separate patch because investigates the LruMap template class
which can be used to implement object caches inside squid.
The new LruMap template class used to replace old
Ssl::LocalContextStorage class which is used as SSL contexts cache.
Patch description:
This patch add cache to cert validation helper. The following new
options added to "sslcrtvalidator_program" configuration parameter to
control cache behaviour:
ttl=n TTL in seconds for cached results.The default is 60 secs
cache=n limit the result cache size. The default value is 2048
SSL contexts cache.
This is a Measurement Factory project
cert validation cache
This patch add cache to cert validation helper. The following new options
added to "sslcrtvalidator_program" configuration parameter to control cache
behaviour:
ttl=n TTL in seconds for cached results.The default is 60 secs
cache=n limit the result cache size. The default value is 2048
To implement the cert validation cache a new template class investigated,
the LruMap which implements a simple lru cache.
The LruMap templete class also used to replace the old Ssl::LocalContextStorage
class which implements a SSL contexts cache.
This is a Measurement Factory project
=== added file 'src/LruMap.h'
--- src/LruMap.h 1970-01-01 00:00:00 +0000
+++ src/LruMap.h 2012-11-09 19:50:45 +0000
@@ -0,0 +1,212 @@
+
+/*
+ * $Id$
+ */
+
+#ifndef SQUID_LRUMAP_H
+#define SQUID_LRUMAP_H
+
+#include "SquidTime.h"
+#if HAVE_LIST
+#include <list>
+#endif
+#if HAVE_MAP
+#include <map>
+#endif
+
+template <class EntryValue, size_t EntryCost = sizeof(EntryValue)> class LruMap
+{
+public:
+ class Entry
+ {
+ public:
+ Entry(const char *aKey, EntryValue *t): key(aKey), value(t), date(squid_curtime) {}
+ ~Entry() {delete value;}
+ private:
+ Entry(LruMap<EntryValue, EntryCost>::Entry &);
+ LruMap<EntryValue, EntryCost>::Entry & operator = (LruMap<EntryValue, EntryCost>::Entry &);
+ public:
+ std::string key; ///< the key of entry
+ EntryValue *value; ///< A pointer to the stored value
+ time_t date; ///< The date the entry created
+ };
+ typedef std::list<Entry *> Queue;
+ typedef typename std::list<Entry *>::iterator QueueIterator;
+
+ /// key:queue_item mapping for fast lookups by key
+ typedef std::map<std::string, QueueIterator> Map;
+ typedef typename Map::iterator MapIterator;
+ typedef std::pair<std::string, QueueIterator> MapPair;
+
+
+ LruMap(int ttl, size_t size);
+ ~LruMap();
+ /// Search for an entry, and return a pointer
+ EntryValue *get(const char *key);
+ /// Add an entry to the map
+ bool add(const char *key, EntryValue *t);
+ /// Delete an entry from the map
+ bool del(const char *key);
+ /// (Re-)set the maximum size for this map
+ void setMemLimit(size_t aSize);
+ /// The available size for the map
+ size_t memLimit() const {return memLimit_;}
+ /// The free space of the map
+ size_t freeMem() const { return (memLimit() - size());}
+ /// The current size of the map
+ size_t size() const {return (entries_ * EntryCost);}
+ /// The number of stored entries
+ int entries() const {return entries_;}
+private:
+ LruMap(LruMap<EntryValue, EntryCost> const &);
+ LruMap<EntryValue, EntryCost> & operator = (LruMap<EntryValue, EntryCost> const &);
+
+ bool expired(Entry &e);
+ void trim();
+ void touch(const MapIterator &i);
+ bool del(const MapIterator &i);
+ void findEntry(const char *key, LruMap::MapIterator &i);
+
+ Map storage; ///< The Key/value * pairs
+ Queue index; ///< LRU cache index
+ int ttl;///< >0 ttl for caching, == 0 cache is disabled, < 0 store for ever
+ size_t memLimit_; ///< The maximum memory to use
+ int entries_; ///< The stored entries
+};
+
+template <class EntryValue, size_t EntryCost>
+LruMap<EntryValue, EntryCost>::LruMap(int aTtl, size_t aSize): entries_(0)
+{
+ ttl = aTtl;
+
+ setMemLimit(aSize);
+}
+
+template <class EntryValue, size_t EntryCost>
+LruMap<EntryValue, EntryCost>::~LruMap()
+{
+ for (QueueIterator i = index.begin(); i != index.end(); ++i) {
+ delete *i;
+ }
+}
+
+template <class EntryValue, size_t EntryCost>
+void
+LruMap<EntryValue, EntryCost>::setMemLimit(size_t aSize)
+{
+ if (aSize > 0)
+ memLimit_ = aSize;
+ else
+ memLimit_ = 0;
+}
+
+template <class EntryValue, size_t EntryCost>
+void
+LruMap<EntryValue, EntryCost>::findEntry(const char *key, LruMap::MapIterator &i)
+{
+ i = storage.find(key);
+ if (i == storage.end()) {
+ return;
+ }
+ index.push_front(*(i->second));
+ index.erase(i->second);
+ i->second = index.begin();
+
+ LruMap::Entry *e = *i->second;
+
+ if (e && expired(*e)) {
+ del(i);
+ e = NULL;
+ }
+}
+
+template <class EntryValue, size_t EntryCost>
+EntryValue *
+LruMap<EntryValue, EntryCost>::get(const char *key)
+{
+ LruMap::MapIterator i;
+ findEntry(key, i);
+ LruMap::Entry *e = *i->second;
+ if (i != storage.end()) {
+ touch(i);
+ return e->value;
+ }
+ return NULL;
+}
+
+template <class EntryValue, size_t EntryCost>
+bool
+LruMap<EntryValue, EntryCost>::add(const char *key, EntryValue *t)
+{
+ if (ttl == 0)
+ return false;
+
+ del(key);
+ trim();
+ index.push_front(new Entry(key, t));
+ storage.insert(MapPair(key, index.begin()));
+
+ ++entries_;
+ return true;
+}
+
+template <class EntryValue, size_t EntryCost>
+bool
+LruMap<EntryValue, EntryCost>::expired(LruMap::Entry &entry)
+{
+ if (ttl < 0)
+ return false;
+
+ return (entry.date + ttl < squid_curtime);
+}
+
+template <class EntryValue, size_t EntryCost>
+bool
+LruMap<EntryValue, EntryCost>::del(LruMap::MapIterator const &i)
+{
+ if (i != storage.end()) {
+ delete *(i->second);
+ index.erase(i->second);
+ storage.erase(i);
+ --entries_;
+ return true;
+ }
+ return false;
+}
+
+template <class EntryValue, size_t EntryCost>
+bool
+LruMap<EntryValue, EntryCost>::del(const char *key)
+{
+ LruMap::MapIterator i;
+ findEntry(key, i);
+ return del(i);
+}
+
+template <class EntryValue, size_t EntryCost>
+void
+LruMap<EntryValue, EntryCost>::trim()
+{
+ while(memLimit() > 0 && size() >= memLimit()) {
+ LruMap::QueueIterator i = index.end();
+ --i;
+ if (i != index.end()) {
+ del((*i)->key.c_str());
+ }
+ }
+}
+
+template <class EntryValue, size_t EntryCost>
+void
+LruMap<EntryValue, EntryCost>::touch(LruMap::MapIterator const &i)
+{
+ // this must not be done when nothing is being cached.
+ if (ttl == 0)
+ return;
+
+ index.push_front(*(i->second));
+ index.erase(i->second);
+ i->second = index.begin();
+}
+
+#endif
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2012-11-02 23:54:44 +0000
+++ src/Makefile.am 2012-11-13 21:29:49 +0000
@@ -407,40 +407,41 @@
HttpRequest.cc \
HttpRequest.h \
HttpRequestMethod.cc \
HttpRequestMethod.h \
HttpVersion.h \
ICP.h \
icp_opcode.h \
icp_v2.cc \
icp_v3.cc \
int.h \
int.cc \
internal.h \
internal.cc \
$(IPC_SOURCE) \
ipcache.cc \
ipcache.h \
$(LEAKFINDERSOURCE) \
SquidList.h \
SquidList.cc \
lookup_t.h \
+ LruMap.h \
main.cc \
Mem.h \
mem.cc \
mem_node.cc \
mem_node.h \
Mem.h \
MemBuf.cc \
MemObject.cc \
MemObject.h \
mime.h \
mime.cc \
mime_header.h \
mime_header.cc \
multicast.h \
multicast.cc \
neighbors.h \
neighbors.cc \
Notes.cc \
Notes.h \
Packer.cc \
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2012-11-13 18:13:50 +0000
+++ src/cf.data.pre 2012-11-13 21:29:49 +0000
@@ -2343,41 +2343,46 @@
Starting too few children temporary slows Squid under load while it
tries to spawn enough additional processes to cope with traffic.
idle=N
Sets a minimum of how many processes Squid is to try and keep available
at all times. When traffic begins to rise above what the existing
processes can handle this many more will be spawned up to the maximum
configured. A minimum setting of 1 is required.
You must have at least one ssl_crtd process.
DOC_END
NAME: sslcrtvalidator_program
TYPE: eol
IFDEF: USE_SSL
DEFAULT: none
LOC: Ssl::TheConfig.ssl_crt_validator
DOC_START
Specify the location and options of the executable for ssl_crt_validator
- process.
+ process. Usage:
+ sslcrtvalidator_program [ttl=n] [cache=n] path ...
+
+ Options:
+ ttl=n TTL in seconds for cached results.The default is 60 secs
+ cache=n limit the result cache size. The default value is 2048
DOC_END
NAME: sslcrtvalidator_children
TYPE: HelperChildConfig
IFDEF: USE_SSL
DEFAULT: 32 startup=5 idle=1
LOC: Ssl::TheConfig.ssl_crt_validator_Children
DOC_START
The maximum number of processes spawn to service ssl server.
The maximum this may be safely set to is 32.
The startup= and idle= options allow some measure of skew in your
tuning.
startup=N
Sets the minimum number of processes to spawn when Squid
starts or reconfigures. When set to zero the first request will
cause spawning of the first child process to handle it.
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2012-11-07 19:26:45 +0000
+++ src/client_side.cc 2012-11-13 21:29:49 +0000
@@ -3802,50 +3802,51 @@
certProperties.signWithPkey.resetAndLock(port->signPkey.get());
}
signAlgorithm = certProperties.signAlgorithm;
}
void
ConnStateData::getSslContextStart()
{
assert(areAllContextsForThisConnection());
freeAllContexts();
/* careful: freeAllContexts() above frees request, host, etc. */
if (port->generateHostCertificates) {
Ssl::CertificateProperties certProperties;
buildSslCertGenerationParams(certProperties);
sslBumpCertKey = certProperties.dbKey().c_str();
assert(sslBumpCertKey.defined() && sslBumpCertKey[0] != '\0');
debugs(33, 5, HERE << "Finding SSL certificate for " << sslBumpCertKey << " in cache");
Ssl::LocalContextStorage & ssl_ctx_cache(Ssl::TheGlobalContextStorage.getLocalStorage(port->s));
- SSL_CTX * dynCtx = ssl_ctx_cache.find(sslBumpCertKey.termedBuf());
- if (dynCtx) {
+ SSL_CTX * dynCtx = NULL;
+ Ssl::SSL_CTX_Pointer *cachedCtx = ssl_ctx_cache.get(sslBumpCertKey.termedBuf());
+ if (cachedCtx && (dynCtx = cachedCtx->get())) {
debugs(33, 5, HERE << "SSL certificate for " << sslBumpCertKey << " have found in cache");
if (Ssl::verifySslCertificate(dynCtx, certProperties)) {
debugs(33, 5, HERE << "Cached SSL certificate for " << sslBumpCertKey << " is valid");
getSslContextDone(dynCtx);
return;
} else {
debugs(33, 5, HERE << "Cached SSL certificate for " << sslBumpCertKey << " is out of date. Delete this certificate from cache");
- ssl_ctx_cache.remove(sslBumpCertKey.termedBuf());
+ ssl_ctx_cache.del(sslBumpCertKey.termedBuf());
}
} else {
debugs(33, 5, HERE << "SSL certificate for " << sslBumpCertKey << " haven't found in cache");
}
#if USE_SSL_CRTD
try {
debugs(33, 5, HERE << "Generating SSL certificate for " << certProperties.commonName << " using ssl_crtd.");
Ssl::CrtdMessage request_message(Ssl::CrtdMessage::REQUEST);
request_message.setCode(Ssl::CrtdMessage::code_new_certificate);
request_message.composeRequest(certProperties);
debugs(33, 5, HERE << "SSL crtd request: " << request_message.compose().c_str());
Ssl::Helper::GetInstance()->sslSubmit(request_message, sslCrtdHandleReplyWrapper, this);
return;
} catch (const std::exception &e) {
debugs(33, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtd " <<
"request for " << certProperties.commonName <<
" certificate: " << e.what() << "; will now block to " <<
"generate that certificate.");
// fall through to do blocking in-process generation.
@@ -3856,41 +3857,41 @@
dynCtx = Ssl::generateSslContext(certProperties, *port);
getSslContextDone(dynCtx, true);
return;
}
getSslContextDone(NULL);
}
void
ConnStateData::getSslContextDone(SSL_CTX * sslContext, bool isNew)
{
// Try to add generated ssl context to storage.
if (port->generateHostCertificates && isNew) {
if (signAlgorithm == Ssl::algSignTrusted)
Ssl::addChainToSslContext(sslContext, port->certsToChain.get());
//else it is self-signed or untrusted do not attrach any certificate
Ssl::LocalContextStorage & ssl_ctx_cache(Ssl::TheGlobalContextStorage.getLocalStorage(port->s));
assert(sslBumpCertKey.defined() && sslBumpCertKey[0] != '\0');
if (sslContext) {
- if (!ssl_ctx_cache.add(sslBumpCertKey.termedBuf(), sslContext)) {
+ if (!ssl_ctx_cache.add(sslBumpCertKey.termedBuf(), new Ssl::SSL_CTX_Pointer(sslContext))) {
// If it is not in storage delete after using. Else storage deleted it.
fd_table[clientConnection->fd].dynamicSslContext = sslContext;
}
} else {
debugs(33, 2, HERE << "Failed to generate SSL cert for " << sslConnectHostOrIp);
}
}
// If generated ssl context = NULL, try to use static ssl context.
if (!sslContext) {
if (!port->staticSslContext) {
debugs(83, DBG_IMPORTANT, "Closing SSL " << clientConnection->remote << " as lacking SSL context");
clientConnection->close();
return;
} else {
debugs(33, 5, HERE << "Using static ssl context.");
sslContext = port->staticSslContext.get();
}
}
=== modified file 'src/forward.cc'
--- src/forward.cc 2012-11-13 18:13:50 +0000
+++ src/forward.cc 2012-11-14 11:12:40 +0000
@@ -728,170 +728,143 @@
// remember the server certificate from the ErrorDetail object
if (Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
serverBump->serverCert.reset(SSL_get_peer_certificate(ssl));
// remember validation errors, if any
if (Ssl::Errors *errs = static_cast<Ssl::Errors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)))
serverBump->sslErrors = cbdataReference(errs);
}
}
if (serverConnection()->getPeer() && !SSL_session_reused(ssl)) {
if (serverConnection()->getPeer()->sslSession)
SSL_SESSION_free(serverConnection()->getPeer()->sslSession);
serverConnection()->getPeer()->sslSession = SSL_get1_session(ssl);
}
#if 1 // USE_SSL_CERT_VALIDATOR
if (Ssl::TheConfig.ssl_crt_validator) {
Ssl::CertValidationRequest validationRequest;
- // WARNING: The STACK_OF(*) OpenSSL objects does not support locking.
- // If we need to support locking we need to sk_X509_dup the STACK_OF(X509)
- // list and lock all of the X509 members of the list.
- // Currently we do not use any locking for any of the members of the
- // Ssl::CertValidationRequest class. If the ssl object gone, the value returned
- // from SSL_get_peer_cert_chain may not exist any more. In this code the
+ // WARNING: Currently we do not use any locking for any of the
+ // members of the Ssl::CertValidationRequest class. In this code the
// Ssl::CertValidationRequest object used only to pass data to
// Ssl::CertValidationHelper::submit method.
- validationRequest.peerCerts = SSL_get_peer_cert_chain(ssl);
+ validationRequest.ssl = ssl;
validationRequest.domainName = request->GetHost();
if (Ssl::Errors *errs = static_cast<Ssl::Errors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)))
// validationRequest disappears on return so no need to cbdataReference
validationRequest.errors = errs;
else
validationRequest.errors = NULL;
try {
debugs(83, 5, HERE << "Sending SSL certificate for validation to ssl_crtvd.");
- Ssl::CertValidationMsg requestMsg(Ssl::CrtdMessage::REQUEST);
- requestMsg.setCode(Ssl::CertValidationMsg::code_cert_validate);
- requestMsg.composeRequest(validationRequest);
- debugs(83, 5, HERE << "SSL crtvd request: " << requestMsg.compose().c_str());
- Ssl::CertValidationHelper::GetInstance()->sslSubmit(requestMsg, sslCrtvdHandleReplyWrapper, this);
+ Ssl::CertValidationHelper::GetInstance()->sslSubmit(validationRequest, sslCrtvdHandleReplyWrapper, this);
return;
} catch (const std::exception &e) {
debugs(33, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtd " <<
"request for " << validationRequest.domainName <<
" certificate: " << e.what() << "; will now block to " <<
"validate that certificate.");
// fall through to do blocking in-process generation.
ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
fail(anErr);
if (serverConnection()->getPeer()) {
peerConnectFailed(serverConnection()->getPeer());
}
serverConn->close();
self = NULL;
return;
}
}
#endif // USE_SSL_CERT_VALIDATOR
dispatch();
}
#if 1 // USE_SSL_CERT_VALIDATOR
void
-FwdState::sslCrtvdHandleReplyWrapper(void *data, const HelperReply &reply)
+FwdState::sslCrtvdHandleReplyWrapper(void *data, Ssl::CertValidationResponse const &validationResponse)
{
FwdState * fwd = (FwdState *)(data);
- fwd->sslCrtvdHandleReply(reply);
+ fwd->sslCrtvdHandleReply(validationResponse);
}
void
-FwdState::sslCrtvdHandleReply(const HelperReply &reply)
+FwdState::sslCrtvdHandleReply(Ssl::CertValidationResponse const &validationResponse)
{
Ssl::Errors *errs = NULL;
Ssl::ErrorDetail *errDetails = NULL;
bool validatorFailed = false;
if (!Comm::IsConnOpen(serverConnection())) {
return;
}
- SSL *ssl = fd_table[serverConnection()->fd].ssl;
- if (!reply.other().hasContent()) {
- debugs(83, 1, HERE << "\"ssl_crtvd\" helper return <NULL> reply");
+ debugs(83,5, HERE << request->GetHost() << " cert validation result: " << validationResponse.resultCode);
+
+ if (validationResponse.resultCode == HelperReply::Error)
+ errs = sslCrtvdCheckForErrors(validationResponse, errDetails);
+ else if (validationResponse.resultCode != HelperReply::Okay)
validatorFailed = true;
- } else {
- Ssl::CertValidationMsg replyMsg(Ssl::CrtdMessage::REPLY);
- Ssl::CertValidationResponse validationResponse;
- std::string error;
- STACK_OF(X509) *peerCerts = SSL_get_peer_cert_chain(ssl);
- if (replyMsg.parse(reply.other().content(), reply.other().contentSize()) != Ssl::CrtdMessage::OK ||
- !replyMsg.parseResponse(validationResponse, peerCerts, error) ) {
- debugs(83, 5, HERE << "Reply from ssl_crtvd for " << request->GetHost() << " is incorrect");
- validatorFailed = true;
- } else {
- if (reply.result == HelperReply::Okay) {
- debugs(83, 5, HERE << "Certificate for " << request->GetHost() << " was successfully validated from ssl_crtvd");
- } else if (reply.result == HelperReply::Error) {
- debugs(83, 5, HERE << "Certificate for " << request->GetHost() << " found buggy by ssl_crtvd");
- errs = sslCrtvdCheckForErrors(validationResponse, errDetails);
- } else {
- debugs(83, 5, HERE << "Certificate for " << request->GetHost() << " cannot be validated. ssl_crtvd response: " << replyMsg.getBody());
- validatorFailed = true;
- }
- if (!errDetails && !validatorFailed) {
- dispatch();
- return;
- }
- }
+ if (!errDetails && !validatorFailed) {
+ dispatch();
+ return;
}
ErrorState *anErr = NULL;
if (validatorFailed) {
anErr = new ErrorState(ERR_GATEWAY_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
} else {
// Check the list error with
if (errDetails && request->clientConnectionManager.valid()) {
// remember the server certificate from the ErrorDetail object
if (Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
// remember validation errors, if any
if (errs) {
if (serverBump->sslErrors)
cbdataReferenceDone(serverBump->sslErrors);
serverBump->sslErrors = cbdataReference(errs);
}
}
}
anErr = makeConnectingError(ERR_SECURE_CONNECT_FAIL);
anErr->detail = errDetails;
/*anErr->xerrno= Should preserved*/
}
fail(anErr);
if (serverConnection()->getPeer()) {
peerConnectFailed(serverConnection()->getPeer());
}
serverConn->close();
self = NULL;
return;
}
/// Checks errors in the cert. validator response against sslproxy_cert_error.
/// The first honored error, if any, is returned via errDetails parameter.
/// The method returns all seen errors except SSL_ERROR_NONE as Ssl::Errors.
Ssl::Errors *
-FwdState::sslCrtvdCheckForErrors(Ssl::CertValidationResponse &resp, Ssl::ErrorDetail *& errDetails)
+FwdState::sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &resp, Ssl::ErrorDetail *& errDetails)
{
Ssl::Errors *errs = NULL;
ACLFilledChecklist *check = NULL;
if (acl_access *acl = Config.ssl_client.cert_error)
check = new ACLFilledChecklist(acl, request, dash_str);
SSL *ssl = fd_table[serverConnection()->fd].ssl;
typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI;
for (SVCRECI i = resp.errors.begin(); i != resp.errors.end(); ++i) {
debugs(83, 7, "Error item: " << i->error_no << " " << i->error_reason);
if (i->error_no == SSL_ERROR_NONE)
continue; //ignore????
if (!errDetails) {
bool allowed = false;
if (check) {
check->sslErrors = new Ssl::Errors(i->error_no);
if (check->fastCheck() == ACCESS_ALLOWED)
=== modified file 'src/forward.h'
--- src/forward.h 2012-11-13 18:13:50 +0000
+++ src/forward.h 2012-11-13 21:35:41 +0000
@@ -68,45 +68,45 @@
void serverClosed(int fd);
void connectStart();
void connectDone(const Comm::ConnectionPointer & conn, comm_err_t status, int xerrno);
void connectTimeout(int fd);
void initiateSSL();
void negotiateSSL(int fd);
bool checkRetry();
bool checkRetriable();
void dispatch();
void pconnPush(Comm::ConnectionPointer & conn, const char *domain);
bool dontRetry() { return flags.dont_retry; }
void dontRetry(bool val) { flags.dont_retry = val; }
/** return a ConnectionPointer to the current server connection (may or may not be open) */
Comm::ConnectionPointer const & serverConnection() const { return serverConn; };
#if USE_SSL //&& USE_SSL_CERT_VALIDATOR
/// Callback function called when squid receive message from cert validator helper
- static void sslCrtvdHandleReplyWrapper(void *data, const HelperReply &reply);
+ static void sslCrtvdHandleReplyWrapper(void *data, Ssl::CertValidationResponse const &);
/// Process response from cert validator helper
- void sslCrtvdHandleReply(const HelperReply &reply);
+ void sslCrtvdHandleReply(Ssl::CertValidationResponse const &);
/// Check SSL errors returned from cert validator against sslproxy_cert_error access list
- Ssl::Errors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse &, Ssl::ErrorDetail *&);
+ Ssl::Errors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&);
#endif
private:
// hidden for safer management of self; use static fwdStart
FwdState(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *, const AccessLogEntryPointer &alp);
void start(Pointer aSelf);
#if STRICT_ORIGINAL_DST
void selectPeerForIntercepted();
#endif
static void logReplyStatus(int tries, http_status status);
void doneWithRetries();
void completed();
void retryOrBail();
ErrorState *makeConnectingError(const err_type type) const;
static void RegisterWithCacheManager(void);
public:
StoreEntry *entry;
HttpRequest *request;
AccessLogEntryPointer al; ///< info for the future access.log entry
=== modified file 'src/ssl/cert_validate_message.cc'
--- src/ssl/cert_validate_message.cc 2012-09-20 18:17:40 +0000
+++ src/ssl/cert_validate_message.cc 2012-10-02 15:48:00 +0000
@@ -3,45 +3,46 @@
#include "ssl/support.h"
#include "ssl/cert_validate_message.h"
#include "ssl/ErrorDetail.h"
void
Ssl::CertValidationMsg::composeRequest(CertValidationRequest const &vcert)
{
body.clear();
body += Ssl::CertValidationMsg::param_host + "=" + vcert.domainName;
if (vcert.errors) {
body += "\n" + Ssl::CertValidationMsg::param_error + "=";
bool comma = false;
for (const Ssl::Errors *err = vcert.errors; err; err = err->next ) {
if (comma)
body += ",";
body += GetErrorName(err->element);
comma = true;
}
}
- if (vcert.peerCerts) {
+ STACK_OF(X509) *peerCerts = SSL_get_peer_cert_chain(vcert.ssl);
+ if (peerCerts) {
body +="\n";
Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
- for (int i = 0; i < sk_X509_num(vcert.peerCerts); ++i) {
- X509 *cert = sk_X509_value(vcert.peerCerts, i);
+ for (int i = 0; i < sk_X509_num(peerCerts); ++i) {
+ X509 *cert = sk_X509_value(peerCerts, i);
PEM_write_bio_X509(bio.get(), cert);
body = body + "cert_" + xitoa(i) + "=";
char *ptr;
long len = BIO_get_mem_data(bio.get(), &ptr);
body.append(ptr, len);
// Normally openssl toolkit terminates Certificate with a '\n'.
if (ptr[len-1] != '\n')
body +="\n";
if (!BIO_reset(bio.get())) {
// print an error?
}
}
}
}
static int
get_error_id(const char *label, size_t len)
{
const char *e = label + len -1;
while (e != label && xisdigit(*e)) --e;
=== modified file 'src/ssl/cert_validate_message.h'
--- src/ssl/cert_validate_message.h 2012-11-13 18:13:50 +0000
+++ src/ssl/cert_validate_message.h 2012-11-14 10:00:46 +0000
@@ -2,77 +2,78 @@
* $Id$
*/
#ifndef SQUID_SSL_CERT_VALIDATE_MESSAGE_H
#define SQUID_SSL_CERT_VALIDATE_MESSAGE_H
#include "ssl/support.h"
#include "ssl/crtd_message.h"
#include <vector>
namespace Ssl
{
/**
* This class is used to hold the required informations to build
* a request message for the certificate validator helper
*/
class CertValidationRequest
{
public:
- STACK_OF(X509) *peerCerts; ///< The list of sent by SSL server
+ SSL *ssl;
Errors *errors; ///< The list of errors detected
std::string domainName; ///< The server name
- CertValidationRequest() : peerCerts(NULL), errors(NULL) {}
+ CertValidationRequest() : ssl(NULL), errors(NULL) {}
};
/**
* This class is used to store informations found in certificate validation
* response messages read from certificate validator helper
*/
class CertValidationResponse
{
public:
/**
* This class used to hold error informations returned from
* cert validator helper.
*/
class RecvdError
{
public:
RecvdError(): id(0), error_no(SSL_ERROR_NONE), cert(NULL) {}
RecvdError(const RecvdError &);
~RecvdError();
RecvdError & operator = (const RecvdError &);
void setCert(X509 *); ///< Sets cert to the given certificate
int id; ///< The id of the error
ssl_error_t error_no; ///< The OpenSSL error code
std::string error_reason; ///< A string describing the error
X509 *cert; ///< The broken certificate
};
typedef std::vector<RecvdError> RecvdErrors;
/// Search in errors list for the error item with id=errorId.
/// If none found a new RecvdError item added with the given id;
RecvdError &getError(int errorId);
RecvdErrors errors; ///< The list of parsed errors
+ HelperReply::Result_ resultCode; ///< The helper result code
};
/**
* This class is responsible for composing or parsing messages destined to
* or comming from a cert validator helper.
* The messages format is:
* <response/request code> <whitespace> <body length> <whitespace> <key=value> ...\1
*/
class CertValidationMsg: public CrtdMessage
{
private:
/**
* This class used to hold the certId/cert pairs found
* in cert validation messages.
*/
class CertItem
{
public:
std::string name; ///< The certificate Id to use
X509 *cert; ///< A pointer to certificate
=== modified file 'src/ssl/context_storage.cc'
--- src/ssl/context_storage.cc 2012-10-04 11:10:17 +0000
+++ src/ssl/context_storage.cc 2012-11-13 21:29:49 +0000
@@ -17,127 +17,50 @@
Ssl::CertificateStorageAction::Pointer
Ssl::CertificateStorageAction::Create(const Mgr::Command::Pointer &cmd)
{
return new CertificateStorageAction(cmd);
}
void Ssl::CertificateStorageAction::dump (StoreEntry *sentry)
{
StoreEntryStream stream(sentry);
const char delimiter = '\t';
const char endString = '\n';
// Page title.
stream << "Cached ssl certificates statistic.\n";
// Title of statistic table.
stream << "Port" << delimiter << "Max mem(KB)" << delimiter << "Cert number" << delimiter << "KB/cert" << delimiter << "Mem used(KB)" << delimiter << "Mem free(KB)" << endString;
// Add info for each port.
for (std::map<Ip::Address, LocalContextStorage *>::iterator i = TheGlobalContextStorage.storage.begin(); i != TheGlobalContextStorage.storage.end(); ++i) {
stream << i->first << delimiter;
LocalContextStorage & ssl_store_policy(*(i->second));
- stream << ssl_store_policy.max_memory / 1024 << delimiter;
- stream << ssl_store_policy.memory_used / SSL_CTX_SIZE << delimiter;
+ stream << ssl_store_policy.memLimit() / 1024 << delimiter;
+ stream << ssl_store_policy.entries() << delimiter;
stream << SSL_CTX_SIZE / 1024 << delimiter;
- stream << ssl_store_policy.memory_used / 1024 << delimiter;
- stream << (ssl_store_policy.max_memory - ssl_store_policy.memory_used) / 1024 << endString;
+ stream << ssl_store_policy.size() / 1024 << delimiter;
+ stream << ssl_store_policy.freeMem() / 1024 << endString;
}
stream << endString;
stream.flush();
}
-Ssl::LocalContextStorage::LocalContextStorage(size_t aMax_memory)
- : max_memory(aMax_memory), memory_used(0)
-{}
-
-Ssl::LocalContextStorage::~LocalContextStorage()
-{
- for (QueueIterator i = lru_queue.begin(); i != lru_queue.end(); ++i) {
- delete *i;
- }
-}
-
-SSL_CTX * Ssl::LocalContextStorage::add(const char * host_name, SSL_CTX * ssl_ctx)
-{
- if (max_memory < SSL_CTX_SIZE) {
- return NULL;
- }
- remove(host_name);
- while (SSL_CTX_SIZE + memory_used > max_memory) {
- purgeOne();
- }
- lru_queue.push_front(new Item(ssl_ctx, host_name));
- storage.insert(MapPair(host_name, lru_queue.begin()));
- memory_used += SSL_CTX_SIZE;
- return ssl_ctx;
-}
-
-SSL_CTX * Ssl::LocalContextStorage::find(char const * host_name)
-{
- MapIterator i = storage.find(host_name);
- if (i == storage.end()) {
- return NULL;
- }
- lru_queue.push_front(*(i->second));
- lru_queue.erase(i->second);
- i->second = lru_queue.begin();
- return (*lru_queue.begin())->ssl_ctx;
-}
-
-void Ssl::LocalContextStorage::remove(char const * host_name)
-{
- deleteAt(storage.find(host_name));
-}
-
-void Ssl::LocalContextStorage::purgeOne()
-{
- QueueIterator i = lru_queue.end();
- --i;
- if (i != lru_queue.end()) {
- remove((*i)->host_name.c_str());
- }
-}
-
-void Ssl::LocalContextStorage::deleteAt(LocalContextStorage::MapIterator i)
-{
- if (i != storage.end()) {
-
- delete *(i->second);
- lru_queue.erase(i->second);
- storage.erase(i);
- memory_used -= SSL_CTX_SIZE;
- }
-}
-
-void Ssl::LocalContextStorage::SetSize(size_t aMax_memory)
-{
- max_memory = aMax_memory;
-}
-
-Ssl::LocalContextStorage::Item::Item(SSL_CTX * aSsl_ctx, std::string const & aName)
- : ssl_ctx(aSsl_ctx), host_name(aName)
-{}
-
-Ssl::LocalContextStorage::Item::~Item()
-{
- SSL_CTX_free(ssl_ctx);
-}
-
///////////////////////////////////////////////////////
Ssl::GlobalContextStorage::GlobalContextStorage()
: reconfiguring(true)
{
RegisterAction("cached_ssl_cert", "Statistic of cached generated ssl certificates", &CertificateStorageAction::Create, 0, 1);
}
Ssl::GlobalContextStorage::~GlobalContextStorage()
{
for (std::map<Ip::Address, LocalContextStorage *>::iterator i = storage.begin(); i != storage.end(); ++i) {
delete i->second;
}
}
void Ssl::GlobalContextStorage::addLocalStorage(Ip::Address const & address, size_t size_of_store)
{
assert(reconfiguring);
configureStorage.insert(std::pair<Ip::Address, size_t>(address, size_of_store));
}
@@ -149,34 +72,34 @@
assert (i != storage.end());
return *(i->second);
}
void Ssl::GlobalContextStorage::reconfigureStart()
{
reconfiguring = true;
}
void Ssl::GlobalContextStorage::reconfigureFinish()
{
if (reconfiguring) {
reconfiguring = false;
// remove or change old local storages.
for (std::map<Ip::Address, LocalContextStorage *>::iterator i = storage.begin(); i != storage.end(); ++i) {
std::map<Ip::Address, size_t>::iterator conf_i = configureStorage.find(i->first);
if (conf_i == configureStorage.end()) {
storage.erase(i);
} else {
- i->second->SetSize(conf_i->second);
+ i->second->setMemLimit(conf_i->second);
}
}
// add new local storages.
for (std::map<Ip::Address, size_t>::iterator conf_i = configureStorage.begin(); conf_i != configureStorage.end(); ++conf_i ) {
if (storage.find(conf_i->first) == storage.end()) {
- storage.insert(std::pair<Ip::Address, LocalContextStorage *>(conf_i->first, new LocalContextStorage(conf_i->second)));
+ storage.insert(std::pair<Ip::Address, LocalContextStorage *>(conf_i->first, new LocalContextStorage(-1, conf_i->second)));
}
}
}
}
Ssl::GlobalContextStorage Ssl::TheGlobalContextStorage;
=== modified file 'src/ssl/context_storage.h'
--- src/ssl/context_storage.h 2012-10-04 11:10:17 +0000
+++ src/ssl/context_storage.h 2012-11-13 21:29:49 +0000
@@ -1,107 +1,63 @@
#ifndef SQUID_SSL_CONTEXT_STORAGE_H
#define SQUID_SSL_CONTEXT_STORAGE_H
#if USE_SSL
#include "SquidTime.h"
#include "CacheManager.h"
#include "ip/Address.h"
#include "mgr/Action.h"
#include "mgr/Command.h"
+#include "LruMap.h"
+#include "ssl/gadgets.h"
#if HAVE_MAP
#include <map>
#endif
#if HAVE_LIST
#include <list>
#endif
#include <openssl/ssl.h>
/// TODO: Replace on real size.
#define SSL_CTX_SIZE 1024
namespace Ssl
{
/** Reports cached SSL certificate stats to Cache Manager.
* TODO: Use "Report" functions instead friend class.
*/
class CertificateStorageAction : public Mgr::Action
{
public:
CertificateStorageAction(const Mgr::Command::Pointer &cmd);
static Pointer Create(const Mgr::Command::Pointer &cmd);
virtual void dump (StoreEntry *sentry);
/**
* We do not support aggregation of information across workers
* TODO: aggregate these stats
*/
virtual bool aggregatable() const { return false; }
};
-/**
- * Memory cache for store generated SSL context. Enforces total size limits
- * using an LRU algorithm.
- */
-class LocalContextStorage
-{
- friend class CertificateStorageAction;
-public:
- /// Cache item is an (SSL_CTX, host name) tuple.
- class Item
- {
- public:
- Item(SSL_CTX * aSsl_ctx, std::string const & aName);
- ~Item();
- public:
- SSL_CTX * ssl_ctx; ///< The SSL context.
- std::string host_name; ///< The host name of the SSL context.
- };
-
- typedef std::list<Item *> Queue;
- typedef Queue::iterator QueueIterator;
-
- /// host_name:queue_item mapping for fast lookups by host name
- typedef std::map<std::string, QueueIterator> Map;
- typedef Map::iterator MapIterator;
- typedef std::pair<std::string, QueueIterator> MapPair;
-
- LocalContextStorage(size_t aMax_memory);
- ~LocalContextStorage();
- /// Set maximum memory size for this storage.
- void SetSize(size_t aMax_memory);
- /// Return a pointer to the added ssl_ctx or NULL if fails (eg. max cache size equal 0).
- SSL_CTX * add(char const * host_name, SSL_CTX * ssl_ctx);
- /// Find SSL_CTX in storage by host name. Lru queue will be updated.
- SSL_CTX * find(char const * host_name);
- void remove(char const * host_name); ///< Delete the SSL context by hostname
-
-private:
- void purgeOne(); ///< Delete oldest object.
- /// Delete object by iterator. It is used in deletePurge() and remove(...) methods.
- void deleteAt(MapIterator i);
-
- size_t max_memory; ///< Max cache size.
- size_t memory_used; ///< Used cache size.
- Map storage; ///< The hostnames/SSL_CTX * pairs
- Queue lru_queue; ///< LRU cache index
-};
+typedef LruMap<SSL_CTX_Pointer, SSL_CTX_SIZE> LocalContextStorage;
/// Class for storing/manipulating LocalContextStorage per local listening address/port.
class GlobalContextStorage
{
friend class CertificateStorageAction;
public:
GlobalContextStorage();
~GlobalContextStorage();
/// Create new SSL context storage for the local listening address/port.
void addLocalStorage(Ip::Address const & address, size_t size_of_store);
/// Return the local storage for the given listening address/port.
LocalContextStorage & getLocalStorage(Ip::Address const & address);
/// When reconfigring should be called this method.
void reconfigureStart();
private:
/// Called by getLocalStorage method
void reconfigureFinish();
bool reconfiguring; ///< True if system reconfiguring now.
/// Storage used on configure or reconfigure.
std::map<Ip::Address, size_t> configureStorage;
=== modified file 'src/ssl/helper.cc'
--- src/ssl/helper.cc 2012-11-13 18:13:50 +0000
+++ src/ssl/helper.cc 2012-11-14 10:03:53 +0000
@@ -1,30 +1,33 @@
#include "squid.h"
#include "anyp/PortCfg.h"
#include "ssl/Config.h"
#include "ssl/helper.h"
#include "SquidString.h"
#include "SquidTime.h"
#include "SwapDir.h"
+#include "ssl/cert_validate_message.h"
#include "wordlist.h"
#include "SquidConfig.h"
+LruMap<Ssl::CertValidationResponse> *Ssl::CertValidationHelper::HelperCache = NULL;
+
Ssl::Helper * Ssl::Helper::GetInstance()
{
static Ssl::Helper sslHelper;
return &sslHelper;
}
Ssl::Helper::Helper()
{
}
Ssl::Helper::~Helper()
{
Shutdown();
}
void Ssl::Helper::Init()
{
assert(ssl_crtd == NULL);
// we need to start ssl_crtd only if some port(s) need to bump SSL
@@ -127,64 +130,148 @@
void Ssl::CertValidationHelper::Init()
{
assert(ssl_crt_validator == NULL);
// we need to start ssl_crtd only if some port(s) need to bump SSL
bool found = false;
for (AnyP::PortCfg *s = ::Config.Sockaddr.http; !found && s; s = s->next)
found = s->sslBump;
for (AnyP::PortCfg *s = ::Config.Sockaddr.https; !found && s; s = s->next)
found = s->sslBump;
if (!found)
return;
ssl_crt_validator = new helper("ssl_crt_validator");
ssl_crt_validator->childs.updateLimits(Ssl::TheConfig.ssl_crt_validator_Children);
ssl_crt_validator->ipc_type = IPC_STREAM;
// The crtd messages may contain the eol ('\n') character. We are
// going to use the '\1' char as the end-of-message mark.
ssl_crt_validator->eom = '\1';
assert(ssl_crt_validator->cmdline == NULL);
+
+ int ttl = 60;
+ size_t cache = 2048;
{
char *tmp = xstrdup(Ssl::TheConfig.ssl_crt_validator);
char *tmp_begin = tmp;
char * token = NULL;
+ bool parseParams = true;
while ((token = strwordtok(NULL, &tmp))) {
+ if (parseParams) {
+ if (strncmp(token, "ttl=", 4) == 0) {
+ ttl = atoi(token + 4);
+ continue;
+ } else if (strncmp(token, "cache=", 6) == 0) {
+ cache = atoi(token + 6);
+ continue;
+ } else
+ parseParams = false;
+ }
wordlistAdd(&ssl_crt_validator->cmdline, token);
}
safe_free(tmp_begin);
}
helperOpenServers(ssl_crt_validator);
+
+ //WARNING: initializing static member in an object initialization method
+ assert(HelperCache == NULL);
+ HelperCache = new LruMap<Ssl::CertValidationResponse>(ttl, cache);
}
void Ssl::CertValidationHelper::Shutdown()
{
if (!ssl_crt_validator)
return;
helperShutdown(ssl_crt_validator);
wordlistDestroy(&ssl_crt_validator->cmdline);
delete ssl_crt_validator;
ssl_crt_validator = NULL;
+
+ // CertValidationHelper::HelperCache is a static member, it is not good policy to
+ // reset it here. Will work because the current Ssl::CertValidationHelper is
+ // always the same static object.
+ delete HelperCache;
+ HelperCache = NULL;
+}
+
+struct submitData {
+ std::string query;
+ Ssl::CertValidationHelper::CVHCB *callback;
+ void *data;
+ SSL *ssl;
+ CBDATA_CLASS2(submitData);
+};
+CBDATA_CLASS_INIT(submitData);
+
+static void
+sslCrtvdHandleReplyWrapper(void *data, const HelperReply &reply)
+{
+ Ssl::CertValidationMsg replyMsg(Ssl::CrtdMessage::REPLY);
+ Ssl::CertValidationResponse *validationResponse = new Ssl::CertValidationResponse;
+ std::string error;
+
+ submitData *crtdvdData = static_cast<submitData *>(data);
+ STACK_OF(X509) *peerCerts = SSL_get_peer_cert_chain(crtdvdData->ssl);
+ if (replyMsg.parse(reply.other().content(), reply.other().contentSize()) != Ssl::CrtdMessage::OK ||
+ !replyMsg.parseResponse(*validationResponse, peerCerts, error) ) {
+ debugs(83, 5, HERE << "Reply from ssl_crtvd for " << " is incorrect");
+ debugs(83, 5, HERE << "Certificate for " << " cannot be validated. ssl_crtvd response: " << replyMsg.getBody());
+ validationResponse->resultCode = HelperReply::BrokenHelper;
+ }
+ else
+ validationResponse->resultCode = reply.result;
+
+ crtdvdData->callback(crtdvdData->data, *validationResponse);
+
+ if (Ssl::CertValidationHelper::HelperCache &&
+ (validationResponse->resultCode == HelperReply::Okay || validationResponse->resultCode == HelperReply::Error)) {
+ Ssl::CertValidationHelper::HelperCache->add(crtdvdData->query.c_str(), validationResponse);
+ } else
+ delete validationResponse;
+
+ cbdataReferenceDone(crtdvdData->data);
+ SSL_free(crtdvdData->ssl);
+ delete crtdvdData;
}
-void Ssl::CertValidationHelper::sslSubmit(CrtdMessage const & message, HLPCB * callback, void * data)
+void Ssl::CertValidationHelper::sslSubmit(Ssl::CertValidationRequest const &request, Ssl::CertValidationHelper::CVHCB * callback, void * data)
{
static time_t first_warn = 0;
assert(ssl_crt_validator);
if (ssl_crt_validator->stats.queue_size >= (int)(ssl_crt_validator->childs.n_running * 2)) {
if (first_warn == 0)
first_warn = squid_curtime;
if (squid_curtime - first_warn > 3 * 60)
fatal("SSL servers not responding for 3 minutes");
debugs(83, 1, HERE << "Queue overload, rejecting");
- const char *errMsg = "BH error 45 Temporary network problem, please retry later";
- HelperReply failReply(errMsg,strlen(errMsg));
- callback(data, failReply);
+ Ssl::CertValidationResponse resp;
+ resp.resultCode = HelperReply::BrokenHelper;
+ callback(data, resp);
return;
}
-
first_warn = 0;
- std::string msg = message.compose();
- msg += '\n';
- helperSubmit(ssl_crt_validator, msg.c_str(), callback, data);
+
+ Ssl::CertValidationMsg message(Ssl::CrtdMessage::REQUEST);
+ message.setCode(Ssl::CertValidationMsg::code_cert_validate);
+ message.composeRequest(request);
+ debugs(83, 5, HERE << "SSL crtvd request: " << message.compose().c_str());
+
+ submitData *crtdvdData = new submitData;
+ crtdvdData->query = message.compose();
+ crtdvdData->query += '\n';
+ crtdvdData->callback = callback;
+ crtdvdData->data = cbdataReference(data);
+ crtdvdData->ssl = request.ssl;
+ CRYPTO_add(&crtdvdData->ssl->references,1,CRYPTO_LOCK_SSL);
+ Ssl::CertValidationResponse const*validationResponse;
+
+ if (CertValidationHelper::HelperCache &&
+ (validationResponse = CertValidationHelper::HelperCache->get(crtdvdData->query.c_str()))) {
+ callback(data, *validationResponse);
+ cbdataReferenceDone(crtdvdData->data);
+ SSL_free(crtdvdData->ssl);
+ delete crtdvdData;
+ return;
+ }
+ helperSubmit(ssl_crt_validator, crtdvdData->query.c_str(), sslCrtvdHandleReplyWrapper, crtdvdData);
}
=== modified file 'src/ssl/helper.h'
--- src/ssl/helper.h 2012-11-13 18:13:50 +0000
+++ src/ssl/helper.h 2012-11-13 21:29:49 +0000
@@ -1,45 +1,52 @@
#ifndef SQUID_SSL_HELPER_H
#define SQUID_SSL_HELPER_H
#include "../helper.h"
+#include "LruMap.h"
+#include "ssl/cert_validate_message.h"
#include "ssl/crtd_message.h"
namespace Ssl
{
/**
* Set of thread for ssl_crtd. This class is singleton. Use this class only
* over GetIntance() static method. This class use helper structure
* for threads management.
*/
class Helper
{
public:
static Helper * GetInstance(); ///< Instance class.
void Init(); ///< Init helper structure.
void Shutdown(); ///< Shutdown helper structure.
/// Submit crtd message to external crtd server.
void sslSubmit(CrtdMessage const & message, HLPCB * callback, void *data);
private:
Helper();
~Helper();
helper * ssl_crtd; ///< helper for management of ssl_crtd.
};
+class CertValidationRequest;
+class CertValidationResponse;
class CertValidationHelper
{
public:
+ typedef void CVHCB(void *, Ssl::CertValidationResponse const &);
static CertValidationHelper * GetInstance(); ///< Instance class.
void Init(); ///< Init helper structure.
void Shutdown(); ///< Shutdown helper structure.
- /// Submit crtd message to external crtd server.
- void sslSubmit(CrtdMessage const & message, HLPCB * callback, void *data);
+ /// Submit crtd request message to external crtd server.
+ void sslSubmit(Ssl::CertValidationRequest const & request, CVHCB * callback, void *data);
private:
CertValidationHelper();
~CertValidationHelper();
helper * ssl_crt_validator; ///< helper for management of ssl_crtd.
+public:
+ static LruMap<Ssl::CertValidationResponse> *HelperCache; ///< cache for cert validation helper
};
} //namespace Ssl
#endif // SQUID_SSL_HELPER_H
=== modified file 'src/tests/stub_libsslsquid.cc'
--- src/tests/stub_libsslsquid.cc 2012-09-20 16:26:47 +0000
+++ src/tests/stub_libsslsquid.cc 2012-10-24 18:18:55 +0000
@@ -1,53 +1,43 @@
#include "squid.h"
#if USE_SSL
#include "fatal.h"
/* Stub File for the ssl/libsslsquid.la convenience library */
#define STUB_API "ssl/libsslsquid.la"
#include "tests/STUB.h"
#include "ssl/Config.h"
Ssl::Config::Config() { printf("Ssl::Config::Config No implemented\n"); }
Ssl::Config::~Config() { printf("Ssl::Config::Config No implemented\n"); }
Ssl::Config Ssl::TheConfig;
#include "ssl/context_storage.h"
//Ssl::CertificateStorageAction::CertificateStorageAction(const Mgr::Command::Pointer &cmd) STUB
Ssl::CertificateStorageAction::Pointer Ssl::CertificateStorageAction::Create(const Mgr::Command::Pointer &cmd) STUB_RETSTATREF(Ssl::CertificateStorageAction::Pointer)
void Ssl::CertificateStorageAction::dump(StoreEntry *sentry) STUB
-Ssl::LocalContextStorage::Item::Item(SSL_CTX * aSsl_ctx, std::string const & aName) STUB
-Ssl::LocalContextStorage::Item::~Item() STUB
-Ssl::LocalContextStorage::LocalContextStorage(size_t aMax_memory) STUB
-Ssl::LocalContextStorage::~LocalContextStorage() STUB
-void Ssl::LocalContextStorage::SetSize(size_t aMax_memory) STUB
-SSL_CTX * Ssl::LocalContextStorage::add(char const * host_name, SSL_CTX * ssl_ctx) STUB_RETVAL(NULL)
-SSL_CTX * Ssl::LocalContextStorage::find(char const * host_name) STUB_RETVAL(NULL)
-void Ssl::LocalContextStorage::remove(char const * host_name) STUB
-//Ssl::GlobalContextStorage::GlobalContextStorage() STUB
-//Ssl::GlobalContextStorage::~GlobalContextStorage() STUB
void Ssl::GlobalContextStorage::addLocalStorage(Ip::Address const & address, size_t size_of_store) STUB
Ssl::LocalContextStorage & Ssl::GlobalContextStorage::getLocalStorage(Ip::Address const & address)
-{ fatal(STUB_API " required"); static Ssl::LocalContextStorage v(0); return v; }
+{ fatal(STUB_API " required"); static Ssl::LocalContextStorage v(0,0); return v; }
void Ssl::GlobalContextStorage::reconfigureStart() STUB
//Ssl::GlobalContextStorage Ssl::TheGlobalContextStorage;
#include "ssl/ErrorDetail.h"
Ssl::ssl_error_t parseErrorString(const char *name) STUB_RETVAL(0)
//const char *Ssl::getErrorName(ssl_error_t value) STUB_RETVAL(NULL)
Ssl::ErrorDetail::ErrorDetail(ssl_error_t err_no, X509 *, X509 *, const char *) STUB
Ssl::ErrorDetail::ErrorDetail(ErrorDetail const &) STUB
const String & Ssl::ErrorDetail::toString() const STUB_RETSTATREF(String)
#include "ssl/support.h"
SSL_CTX *sslCreateServerContext(AnyP::PortCfg &) STUB_RETVAL(NULL)
SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile) STUB_RETVAL(NULL)
int ssl_read_method(int, char *, int) STUB_RETVAL(0)
int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
void ssl_shutdown_method(SSL *) STUB
const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
// typedef char const *SSLGETATTRIBUTE(SSL *, const char *);
// SSLGETATTRIBUTE sslGetUserAttribute;
// SSLGETATTRIBUTE sslGetCAAttribute;