2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_SRC_HTTPUPGRADEPROTOCOLACCESS_H
10 #define SQUID_SRC_HTTPUPGRADEPROTOCOLACCESS_H
12 #include "acl/forward.h"
13 #include "sbuf/SBuf.h"
18 /// a reference to a protocol name[/version] string; no 0-termination is assumed
22 ProtocolView(const char * const start
, const size_t len
);
23 explicit ProtocolView(const SBuf
&proto
);
25 SBuf name
; ///< everything up to (but excluding) the first slash('/')
26 SBuf version
; ///< everything after the name, including the slash('/')
29 std::ostream
&operator <<(std::ostream
&, const ProtocolView
&);
31 // HTTP is not explicit about case sensitivity of Upgrade protocol strings, but
32 // there are bug reports showing different case variants used for WebSocket. We
33 // conservatively preserve the received case and compare case-sensitively.
35 /// Either b has no version restrictions or both have the same version.
36 /// For example, "ws/1" is in "ws" but "ws" is not in "ws/1".
38 vAinB(const ProtocolView
&a
, const ProtocolView
&b
)
40 // Optimization: Do not assert(a.name == b.name).
41 return b
.version
.isEmpty() || (a
.version
== b
.version
);
46 /// Allows or blocks HTTP Upgrade protocols (see http_upgrade_request_protocols)
47 class HttpUpgradeProtocolAccess
50 HttpUpgradeProtocolAccess() = default;
51 ~HttpUpgradeProtocolAccess();
52 HttpUpgradeProtocolAccess(HttpUpgradeProtocolAccess
&&) = delete; // no copying of any kind
54 /// \returns the ACLs matching the given "name[/version]" protocol (or nil)
55 const acl_access
*findGuard(const SBuf
&proto
) const;
57 /// parses a single allow/deny rule
58 void configureGuard(ConfigParser
&);
60 /// iterates over all configured rules, calling the given visitor
61 template <typename Visitor
> inline void forEach(const Visitor
&) const;
63 /// iterates over rules applicable to the given protocol, calling visitor;
64 /// breaks iteration if the visitor returns true
65 template <typename Visitor
> inline void forApplicable(const ProtocolView
&, const Visitor
&) const;
68 /// a single configured access rule for an explicitly named protocol
72 NamedGuard(const char *rawProtocol
, acl_access
*);
73 NamedGuard(const NamedGuard
&&) = delete; // no copying of any kind
76 const SBuf protocol
; ///< configured protocol name (and version)
77 const ProtocolView proto
; ///< optimization: compiled this->protocol
78 acl_access
*guard
= nullptr; ///< configured access rule; never nil
81 /// maps HTTP Upgrade protocol name/version to the ACLs guarding its usage
82 typedef std::deque
<NamedGuard
> NamedGuards
;
84 /// pseudonym to specify rules for "all other protocols"
85 inline static const SBuf
&ProtoOther();
87 /// rules governing upgrades to explicitly named protocols
88 NamedGuards namedGuards
;
90 /// OTHER rules governing unnamed protocols
91 acl_access
*other
= nullptr;
94 template <typename Visitor
>
96 HttpUpgradeProtocolAccess::forEach(const Visitor
&visitor
) const
98 for (const auto &namedGuard
: namedGuards
)
99 visitor(namedGuard
.protocol
, namedGuard
.guard
);
101 visitor(ProtoOther(), other
);
104 template <typename Visitor
>
106 HttpUpgradeProtocolAccess::forApplicable(const ProtocolView
&offer
, const Visitor
&visitor
) const
108 auto seenApplicable
= false;
109 for (const auto &namedGuard
: namedGuards
) {
110 if (offer
.name
!= namedGuard
.proto
.name
)
112 if (vAinB(offer
, namedGuard
.proto
) && visitor(namedGuard
.protocol
, namedGuard
.guard
))
114 seenApplicable
= true; // may already be true
116 if (!seenApplicable
&& other
) // OTHER is applicable if named rules were not
117 (void)visitor(ProtoOther(), other
);
121 HttpUpgradeProtocolAccess::ProtoOther()
123 static const auto proto
= new SBuf("OTHER");
127 #endif /* SQUID_SRC_HTTPUPGRADEPROTOCOLACCESS_H */