]> git.ipfire.org Git - thirdparty/squid.git/blob - src/errorpage.h
Detail client closures of CONNECT tunnels during TLS handshake (#691)
[thirdparty/squid.git] / src / errorpage.h
1 /*
2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
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
9 /* DEBUG: section 04 Error Generation */
10
11 #ifndef SQUID_ERRORPAGE_H
12 #define SQUID_ERRORPAGE_H
13
14 #include "cbdata.h"
15 #include "comm/forward.h"
16 #include "error/Detail.h"
17 #include "error/forward.h"
18 #include "http/forward.h"
19 #include "http/StatusCode.h"
20 #include "ip/Address.h"
21 #include "log/forward.h"
22 #include "sbuf/SBuf.h"
23 #include "SquidString.h"
24 /* auth/UserRequest.h is empty unless USE_AUTH is defined */
25 #include "auth/UserRequest.h"
26
27 /// error page callback
28 typedef void ERCB(int fd, void *, size_t);
29
30 /**
31 \defgroup ErrorPageAPI Error Pages API
32 \ingroup Components
33 \section ErrorPageStringCodes Error Page % codes for text insertion.
34 *
35 \verbatim
36 a - User identity x
37 A - Local listening IP address x
38 B - URL with FTP %2f hack x
39 c - Squid error code x
40 d - seconds elapsed since request received x
41 D - Error details x
42 e - errno x
43 E - strerror() x
44 f - FTP request line x
45 F - FTP reply line x
46 g - FTP server message x
47 h - cache hostname x
48 H - server host name x
49 i - client IP address x
50 I - server IP address x
51 l - HREF link for CSS stylesheet inclusion x
52 L - HREF link for more info/contact x
53 M - Request Method x
54 m - Error message returned by auth helper x
55 o - Message returned external acl helper x
56 p - URL port # x
57 P - Protocol x
58 R - Full HTTP Request x
59 S - squid signature from ERR_SIGNATURE x
60 s - caching proxy software with version x
61 t - local time x
62 T - UTC x
63 U - URL without password x
64 u - URL with password x
65 w - cachemgr email address x
66 W - error data (to be included in the mailto links)
67 x - error name x
68 z - dns server error message x
69 Z - Preformatted error message x
70 \endverbatim
71 *
72 * Plus logformat %codes embedded using @Squid{%logformat_code} syntax.
73 */
74
75 class MemBuf;
76 class StoreEntry;
77 class wordlist;
78
79 namespace ErrorPage {
80
81 class Build;
82
83 } // namespace ErrorPage
84
85 /// \ingroup ErrorPageAPI
86 class ErrorState
87 {
88 CBDATA_CLASS(ErrorState);
89
90 public:
91 /// creates an error of type other than ERR_RELAY_REMOTE
92 ErrorState(err_type type, Http::StatusCode, HttpRequest * request, const AccessLogEntryPointer &al);
93 ErrorState() = delete; // not implemented.
94
95 /// creates an ERR_RELAY_REMOTE error
96 ErrorState(HttpRequest * request, HttpReply *);
97
98 ~ErrorState();
99
100 /// Creates a general request forwarding error with the right http_status.
101 static ErrorState *NewForwarding(err_type, HttpRequestPointer &, const AccessLogEntryPointer &);
102
103 /**
104 * Allocates and initializes an error response
105 */
106 HttpReply *BuildHttpReply(void);
107
108 /// set error type-specific detail code
109 void detailError(const ErrorDetail::Pointer &dCode) { detail = dCode; }
110
111 /// ensures that a future BuildHttpReply() is likely to succeed
112 void validate();
113
114 /// the source of the error template (for reporting purposes)
115 SBuf inputLocation;
116
117 private:
118 typedef ErrorPage::Build Build;
119
120 /// initializations shared by public constructors
121 explicit ErrorState(err_type type);
122
123 /// locates the right error page template for this error and compiles it
124 SBuf buildBody();
125
126 /// compiles error page or error detail template (i.e. anything but deny_url)
127 /// \param input the template text to be compiled
128 /// \param allowRecursion whether to compile %codes which produce %codes
129 SBuf compileBody(const char *text, bool allowRecursion);
130
131 /// compile a single-letter %code like %D
132 void compileLegacyCode(Build &build);
133
134 /// compile @Squid{%code} sequence containing a single logformat %code
135 void compileLogformatCode(Build &build);
136
137 /// replaces all legacy and logformat %codes in the given input
138 /// \param input the template text to be converted
139 /// \param building_deny_info_url whether input is a deny_info URL parameter
140 /// \param allowRecursion whether to compile %codes which produce %codes
141 /// \returns the given input with all %codes substituted
142 SBuf compile(const char *input, bool building_deny_info_url, bool allowRecursion);
143
144 /// React to a compile() error, throwing if buildContext allows.
145 /// \param msg description of what went wrong
146 /// \param near approximate start of the problematic input
147 void noteBuildError(const char *msg, const char *near) {
148 noteBuildError_(msg, near, false);
149 }
150
151 /// Note a compile() error but do not throw for backwards
152 /// compatibility with older configurations that may have such errors.
153 /// Should eventually be replaced with noteBuildError().
154 /// \param msg description of what went wrong
155 /// \param near approximate start of the problematic input
156 void bypassBuildErrorXXX(const char *msg, const char *near) {
157 noteBuildError_(msg, near, true);
158 }
159
160 /**
161 * CacheManager / Debug dump of the ErrorState object.
162 * Writes output into the given MemBuf.
163 \retval 0 successful completion.
164 */
165 int Dump(MemBuf * mb);
166
167 public:
168 err_type type = ERR_NONE;
169 int page_id = ERR_NONE;
170 char *err_language = nullptr;
171 Http::StatusCode httpStatus = Http::scNone;
172 #if USE_AUTH
173 Auth::UserRequest::Pointer auth_user_request;
174 #endif
175 HttpRequestPointer request;
176 char *url = nullptr;
177 int xerrno = 0;
178 unsigned short port = 0;
179 String dnsError; ///< DNS lookup error message
180 time_t ttl = 0;
181
182 Ip::Address src_addr;
183 char *redirect_url = nullptr;
184 ERCB *callback;
185 void *callback_data = nullptr;
186
187 struct {
188 wordlist *server_msg = nullptr;
189 char *request = nullptr;
190 char *reply = nullptr;
191 char *cwd_msg = nullptr;
192 MemBuf *listing = nullptr;
193 } ftp;
194
195 char *request_hdrs = nullptr;
196 char *err_msg = nullptr; /* Preformatted error message from the cache */
197
198 AccessLogEntryPointer ale; ///< transaction details (or nil)
199
200 // TODO: Replace type, xerrno and detail with Error while adding a virtual
201 // Error::Detail::sysError() method to extract errno in detailError().
202 /// type-specific detail about the transaction error;
203 /// overwrites xerrno;
204 ErrorDetail::Pointer detail;
205
206 HttpReplyPointer response_;
207
208 private:
209 void noteBuildError_(const char *msg, const char *near, const bool forceBypass);
210
211 static const SBuf LogformatMagic; ///< marks each embedded logformat entry
212 };
213
214 /**
215 \ingroup ErrorPageAPI
216 *
217 * This function finds the error messages formats, and stores
218 * them in error_text[]
219 *
220 \par Global effects:
221 * error_text[] - is modified
222 */
223 void errorInitialize(void);
224
225 /// \ingroup ErrorPageAPI
226 void errorClean(void);
227
228 /**
229 * \ingroup ErrorPageAPI
230 *
231 * This function generates a error page from the info contained
232 * by err and then sends it to the client.
233 * The callback function errorSendComplete() is called after
234 * the page has been written to the client (clientConn).
235 * errorSendComplete() deallocates err. We need to add
236 * err to the cbdata because comm_write() requires it
237 * for all callback data pointers.
238 *
239 \note normally errorSend() should only be called from
240 * routines in ssl.c and pass.c, where we don't have any
241 * StoreEntry's. In client_side.c we must allocate a StoreEntry
242 * for errors and use errorAppendEntry() to account for
243 * persistent/pipeline connections.
244 *
245 \param clientConn socket where page object is to be written
246 \param err This object is destroyed after use in this function.
247 */
248 void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err);
249
250 /**
251 \ingroup ErrorPageAPI
252 *
253 * This function generates a error page from the info contained
254 * by err and then stores the text in the specified store
255 * entry.
256 * This function should only be called by "server
257 * side routines" which need to communicate errors to the
258 * client side. It should also be called from client_side.c
259 * because we now support persistent connections, and
260 * cannot assume that we can immediately write to the socket
261 * for an error.
262 *
263 \param entry ??
264 \param err This object is destroyed after use in this function.
265 */
266 void errorAppendEntry(StoreEntry *entry, ErrorState *err);
267
268 /// allocates a new slot for the error page
269 err_type errorReservePageId(const char *page_name, const SBuf &cfgLocation);
270
271 const char *errorPageName(int pageId); ///< error ID to string
272
273 /**
274 \ingroup ErrorPageAPI
275 *
276 * loads text templates used for error pages and details;
277 * supports translation of templates
278 */
279 class TemplateFile
280 {
281 public:
282 TemplateFile(const char *name, const err_type code);
283 virtual ~TemplateFile() {}
284
285 /// return true if the data loaded from disk without any problem
286 bool loaded() const {return wasLoaded;}
287
288 /**
289 * Load the page_name template from a file which probably exist at:
290 * (a) admin specified custom directory (error_directory)
291 * (b) default language translation directory (error_default_language)
292 * (c) English sub-directory where errors should ALWAYS exist
293 * If all of the above fail, setDefault() is called.
294 */
295 void loadDefault();
296
297 /**
298 * Load an error template for a given HTTP request. This function examines the
299 * Accept-Language header and select the first available template. If the default
300 * template selected (eg because of a "Accept-Language: *"), or not available
301 * template found this function return false.
302 */
303 bool loadFor(const HttpRequest *request);
304
305 /**
306 * Load the file given by "path". It uses the "parse()" method.
307 * On success return true and sets the "defined" member
308 */
309 bool loadFromFile(const char *path);
310
311 /// The language used for the template
312 const char *language() {return errLanguage.termedBuf();}
313
314 SBuf filename; ///< where the template was loaded from
315
316 bool silent; ///< Whether to print error messages on cache.log file or not. It is user defined.
317
318 protected:
319 /// post-process the loaded template
320 virtual bool parse() { return true; }
321
322 /// recover from loadDefault() failure to load or parse() a template
323 virtual void setDefault() {}
324
325 /**
326 * Try to load the "page_name" template for a given language "lang"
327 * from squid errors directory
328 \return true on success false otherwise
329 */
330 bool tryLoadTemplate(const char *lang);
331
332 SBuf template_; ///< raw template contents
333 bool wasLoaded; ///< True if the template data read from disk without any problem
334 String errLanguage; ///< The error language of the template.
335 String templateName; ///< The name of the template
336 err_type templateCode; ///< The internal code for this template.
337 };
338
339 /**
340 * Parses the Accept-Language header value and return one language item on
341 * each call.
342 * Will ignore any whitespace, q-values, and detectably invalid language
343 * codes in the header.
344 *
345 * \param hdr is the Accept-Language header value
346 * \param lang a buffer to store parsed language code in
347 * \param langlen the length of the lang buffer
348 * \param pos is used to store the offset state of parsing. Must be "0" on first call.
349 * Will be altered to point at the start of next field-value.
350 * \return true if something looking like a language token has been placed in lang, false otherwise
351 */
352 bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos);
353
354 #endif /* SQUID_ERRORPAGE_H */
355