{
public:
// not explicit: allow "aclMatchCode to allow_t" conversions (for now)
- allow_t(const aclMatchCode aCode): code(aCode), kind(0) {}
+ allow_t(const aclMatchCode aCode, int aKind = 0): code(aCode), kind(aKind) {}
allow_t(): code(ACCESS_DUNNO), kind(0) {}
return !(*this == aCode);
}
+ bool operator ==(const allow_t allow) const {
+ return code == allow.code && kind == allow.kind;
+ }
+
operator aclMatchCode() const {
return code;
}
return new OrNode;
}
+bool
+Acl::OrNode::bannedAction(ACLChecklist *, Nodes::const_iterator) const
+{
+ return false;
+}
+
int
Acl::OrNode::doMatch(ACLChecklist *checklist, Nodes::const_iterator start) const
{
// find the first node that matches, but stop if things go wrong
for (Nodes::const_iterator i = start; i != nodes.end(); ++i) {
+ if (bannedAction(checklist, i))
+ continue;
if (checklist->matchChild(this, i, *i)) {
lastMatch_ = i;
return 1;
MEMPROXY_CLASS(OrNode);
public:
+ /// whether the given rule should be excluded from matching tests based
+ /// on its action
+ virtual bool bannedAction(ACLChecklist *, Nodes::const_iterator) const;
+
/* ACL API */
virtual char const *typeString() const;
virtual ACL *clone() const;
#include "Debug.h"
#include "profiler/Profiler.h"
+#include <algorithm>
+
/// common parts of nonBlockingCheck() and resumeNonBlockingCheck()
bool
ACLChecklist::prepNonBlocking()
return !cbdataReferenceValid(callback_data);
}
+bool
+ACLChecklist::bannedAction(const allow_t &action) const
+{
+ const bool found = std::find(bannedActions_.begin(), bannedActions_.end(), action) != bannedActions_.end();
+ debugs(28, 5, "Action '" << action << "/" << action.kind << (found ? " is " : "is not") << " banned");
+ return found;
+}
+
+void
+ACLChecklist::banAction(const allow_t &action)
+{
+ bannedActions_.push_back(action);
+}
+
#include "acl/InnerNode.h"
#include <stack>
+#include <vector>
/// ACL checklist callback
typedef void ACLCB(allow_t, void *);
const allow_t ¤tAnswer() const { return allow_; }
+ /// whether the action is banned or not
+ bool bannedAction(const allow_t &action) const;
+ /// add action to the list of banned actions
+ void banAction(const allow_t &action);
+
// XXX: ACLs that need request or reply have to use ACLFilledChecklist and
// should do their own checks so that we do not have to povide these two
// for ACL::checklistMatches to use
/// suspended (due to an async lookup) matches() in the ACL tree
std::stack<Breadcrumb> matchPath;
+ /// the list of actions which must ignored during acl checks
+ std::vector<allow_t> bannedActions_;
};
#endif /* SQUID_ACLCHECKLIST_H */
*/
#include "squid.h"
+#include "acl/Checklist.h"
#include "acl/Tree.h"
#include "wordlist.h"
return text;
}
+bool
+Acl::Tree::bannedAction(ACLChecklist *checklist, Nodes::const_iterator node) const
+{
+ if (actions.size()) {
+ assert(actions.size() == nodes.size());
+ const Nodes::size_type pos = node - nodes.begin();
+ return checklist->bannedAction(actions.at(pos));
+ }
+ return false;
+}
void add(ACL *rule); ///< same as InnerNode::add()
protected:
+ /// Acl::OrNode API
+ virtual bool bannedAction(ACLChecklist *, Nodes::const_iterator) const override;
allow_t actionAt(const Nodes::size_type pos) const;
/// if not empty, contains actions corresponding to InnerNode::nodes
assert(connState->serverBump());
Ssl::BumpMode bumpAction;
if (answer == ACCESS_ALLOWED) {
- if (answer.kind == Ssl::bumpNone)
- bumpAction = Ssl::bumpSplice;
- else if (answer.kind == Ssl::bumpClientFirst || answer.kind == Ssl::bumpServerFirst)
- bumpAction = Ssl::bumpBump;
- else
- bumpAction = (Ssl::BumpMode)answer.kind;
+ bumpAction = (Ssl::BumpMode)answer.kind;
} else
bumpAction = Ssl::bumpSplice;
ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(Config.accessList.ssl_bump, sslServerBump->request.getRaw(), NULL);
//acl_checklist->src_addr = params.conn->remote;
//acl_checklist->my_addr = s->s;
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpNone));
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpClientFirst));
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpServerFirst));
acl_checklist->nonBlockingCheck(httpsSslBumpStep2AccessCheckDone, this);
return;
}
ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(
::Config.accessList.ssl_bump,
request.getRaw(), NULL);
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpNone));
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpPeek));
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpStare));
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpClientFirst));
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpServerFirst));
+ SSL *ssl = fd_table[serverConn->fd].ssl;
+ BIO *b = SSL_get_rbio(ssl);
+ Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
+ if (!srvBio->canSplice())
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpSplice));
+ if (!srvBio->canBump())
+ acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpBump));
acl_checklist->nonBlockingCheck(Ssl::PeekingPeerConnector::cbCheckForPeekAndSpliceDone, this);
}
debugs(83,5, "Will check for peek and splice on FD " << serverConn->fd);
Ssl::BumpMode finalAction = action;
- // adjust the final bumping mode if needed
- if (finalAction < Ssl::bumpSplice)
- finalAction = Ssl::bumpBump;
-
- if (finalAction == Ssl::bumpSplice && !srvBio->canSplice())
- finalAction = Ssl::bumpBump;
- else if (finalAction == Ssl::bumpBump && !srvBio->canBump())
- finalAction = Ssl::bumpSplice;
-
+ Must(finalAction == Ssl::bumpSplice || finalAction == Ssl::bumpBump || finalAction == Ssl::bumpTerminate);
// Record final decision
if (request->clientConnectionManager.valid()) {
request->clientConnectionManager->sslBumpMode = finalAction;