]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/helper/Reply.cc
2 * Copyright (C) 1996-2021 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 /* DEBUG: section 84 Helper process maintenance */
12 #include "ConfigParser.h"
15 #include "helper/Reply.h"
17 #include "SquidString.h"
19 Helper::Reply::Reply() :
20 result(Helper::Unknown
)
25 Helper::Reply::accumulate(const char *buf
, size_t len
)
28 other_
.init(4*1024, 1*1024*1024);
30 if (other_
.potentialSpaceSize() < static_cast<mb_size_t
>(len
))
31 return false; // no space left
33 other_
.append(buf
, len
);
38 Helper::Reply::finalize()
40 debugs(84, 3, "Parsing helper buffer");
41 // check we have something to parse
42 if (!other_
.hasContent()) {
43 // empty line response was the old URL-rewriter interface ERR response.
44 result
= Helper::Error
;
45 // for now ensure that legacy handlers are not presented with NULL strings.
46 debugs(84, 3, "Zero length reply");
50 char *p
= other_
.content();
51 size_t len
= other_
.contentSize();
54 // optimization: do not consider parsing result code if the response is short.
55 // URL-rewriter may return relative URLs or empty response for a large portion
58 debugs(84, 3, "Buff length is larger than 2");
59 // some helper formats (digest auth, URL-rewriter) just send a data string
60 // we must also check for the ' ' character after the response token (if anything)
61 if (!strncmp(p
,"OK",2) && (len
== 2 || p
[2] == ' ')) {
62 debugs(84, 3, "helper Result = OK");
63 result
= Helper::Okay
;
65 } else if (!strncmp(p
,"ERR",3) && (len
== 3 || p
[3] == ' ')) {
66 debugs(84, 3, "helper Result = ERR");
67 result
= Helper::Error
;
69 } else if (!strncmp(p
,"BH",2) && (len
== 2 || p
[2] == ' ')) {
70 debugs(84, 3, "helper Result = BH");
71 result
= Helper::BrokenHelper
;
73 } else if (!strncmp(p
,"TT ",3)) {
74 // NTLM challenge token
77 // followed by an auth token
78 char *w1
= strwordtok(NULL
, &p
);
80 const char *authToken
= w1
;
81 notes
.add("token",authToken
);
83 // token field is mandatory on this response code
84 result
= Helper::BrokenHelper
;
85 notes
.add("message","Missing 'token' data");
88 } else if (!strncmp(p
,"AF ",3)) {
89 // NTLM/Negotiate OK response
90 result
= Helper::Okay
;
93 // an optional auth token and user field
94 // or, an optional username field
95 char *w1
= strwordtok(NULL
, &p
);
96 char *w2
= strwordtok(NULL
, &p
);
98 // Negotiate "token user"
99 const char *authToken
= w1
;
100 notes
.add("token",authToken
);
102 const char *user
= w2
;
103 notes
.add("user",user
);
105 } else if (w1
!= NULL
) {
107 const char *user
= w1
;
108 notes
.add("user",user
);
110 } else if (!strncmp(p
,"NA ",3)) {
111 // NTLM fail-closed ERR response
112 result
= Helper::Error
;
117 for (; xisspace(*p
); ++p
); // skip whitespace
120 other_
.consume(p
- other_
.content());
121 other_
.consumeWhitespacePrefix();
123 // Hack for backward-compatibility: Do not parse for kv-pairs on NA response
127 // Hack for backward-compatibility: BH and NA used to be a text message...
128 if (other_
.hasContent() && (sawNA
|| result
== Helper::BrokenHelper
)) {
129 notes
.add("message", other_
.content());
134 /// restrict key names to alphanumeric, hyphen, underscore characters
136 isKeyNameChar(char c
)
138 if (c
>= 'a' && c
<= 'z')
141 if (c
>= 'A' && c
<= 'Z')
144 if (c
>= '0' && c
<= '9')
147 if (c
== '-' || c
== '_')
150 // prevent other characters matching the key=value
155 Helper::Reply::parseResponseKeys()
157 // parse a "key=value" pair off the 'other()' buffer.
158 while (other_
.hasContent()) {
159 char *p
= other_
.content();
161 while (*p
&& isKeyNameChar(*p
)) ++p
;
163 return; // done. Not a key.
165 // whitespace between key and value is prohibited.
166 // workaround strwordtok() which skips whitespace prefix.
167 if (xisspace(*(p
+1)))
168 return; // done. Not a key.
173 // the value may be a quoted string or a token
174 const bool urlDecode
= (*p
!= '"'); // check before moving p.
175 char *v
= strwordtok(NULL
, &p
);
176 if (v
!= NULL
&& urlDecode
&& (p
-v
) > 2) // 1-octet %-escaped requires 3 bytes
179 notes
.add(key
, v
? v
: ""); // value can be empty, but must not be NULL
181 other_
.consume(p
- other_
.content());
182 other_
.consumeWhitespacePrefix();
187 Helper::Reply::emptyBuf() const
196 operator <<(std::ostream
&os
, const Helper::Reply
&r
)
206 case Helper::BrokenHelper
:
212 case Helper::TimedOut
:
215 case Helper::Unknown
:
220 // dump the helper key=pair "notes" list
221 if (!r
.notes
.empty()) {
223 os
<< r
.notes
.toString("; ");
227 MemBuf
const &o
= r
.other();
229 os
<< ", other: \"" << o
.content() << '\"';