]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/helper/Reply.cc
2 * Copyright (C) 1996-2018 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
),
26 Helper::Reply::accumulate(const char *buf
, size_t len
)
29 other_
.init(4*1024, 1*1024*1024);
31 if (other_
.potentialSpaceSize() < static_cast<mb_size_t
>(len
))
32 return false; // no space left
34 other_
.append(buf
, len
);
39 Helper::Reply::finalize()
41 debugs(84, 3, "Parsing helper buffer");
42 // check we have something to parse
43 if (!other_
.hasContent()) {
44 // empty line response was the old URL-rewriter interface ERR response.
45 result
= Helper::Error
;
46 // for now ensure that legacy handlers are not presented with NULL strings.
47 debugs(84, 3, "Zero length reply");
51 char *p
= other_
.content();
52 size_t len
= other_
.contentSize();
55 // optimization: do not consider parsing result code if the response is short.
56 // URL-rewriter may return relative URLs or empty response for a large portion
59 debugs(84, 3, "Buff length is larger than 2");
60 // some helper formats (digest auth, URL-rewriter) just send a data string
61 // we must also check for the ' ' character after the response token (if anything)
62 if (!strncmp(p
,"OK",2) && (len
== 2 || p
[2] == ' ')) {
63 debugs(84, 3, "helper Result = OK");
64 result
= Helper::Okay
;
66 } else if (!strncmp(p
,"ERR",3) && (len
== 3 || p
[3] == ' ')) {
67 debugs(84, 3, "helper Result = ERR");
68 result
= Helper::Error
;
70 } else if (!strncmp(p
,"BH",2) && (len
== 2 || p
[2] == ' ')) {
71 debugs(84, 3, "helper Result = BH");
72 result
= Helper::BrokenHelper
;
74 } else if (!strncmp(p
,"TT ",3)) {
75 // NTLM challenge token
78 // followed by an auth token
79 char *w1
= strwordtok(NULL
, &p
);
81 const char *authToken
= w1
;
82 notes
.add("token",authToken
);
84 // token field is mandatory on this response code
85 result
= Helper::BrokenHelper
;
86 notes
.add("message","Missing 'token' data");
89 } else if (!strncmp(p
,"AF ",3)) {
90 // NTLM/Negotate OK response
91 result
= Helper::Okay
;
94 // an optional auth token and user field
95 // or, an optional username field
96 char *w1
= strwordtok(NULL
, &p
);
97 char *w2
= strwordtok(NULL
, &p
);
99 // Negotiate "token user"
100 const char *authToken
= w1
;
101 notes
.add("token",authToken
);
103 const char *user
= w2
;
104 notes
.add("user",user
);
106 } else if (w1
!= NULL
) {
108 const char *user
= w1
;
109 notes
.add("user",user
);
111 } else if (!strncmp(p
,"NA ",3)) {
112 // NTLM fail-closed ERR response
113 result
= Helper::Error
;
118 for (; xisspace(*p
); ++p
); // skip whitespace
121 other_
.consume(p
- other_
.content());
122 other_
.consumeWhitespacePrefix();
124 // Hack for backward-compatibility: Do not parse for kv-pairs on NA response
128 // Hack for backward-compatibility: BH and NA used to be a text message...
129 if (other_
.hasContent() && (sawNA
|| result
== Helper::BrokenHelper
)) {
130 notes
.add("message", other_
.content());
135 /// restrict key names to alphanumeric, hyphen, underscore characters
137 isKeyNameChar(char c
)
139 if (c
>= 'a' && c
<= 'z')
142 if (c
>= 'A' && c
<= 'Z')
145 if (c
>= '0' && c
<= '9')
148 if (c
== '-' || c
== '_')
151 // prevent other characters matching the key=value
156 Helper::Reply::parseResponseKeys()
158 // parse a "key=value" pair off the 'other()' buffer.
159 while (other_
.hasContent()) {
160 char *p
= other_
.content();
162 while (*p
&& isKeyNameChar(*p
)) ++p
;
164 return; // done. Not a key.
166 // whitespace between key and value is prohibited.
167 // workaround strwordtok() which skips whitespace prefix.
168 if (xisspace(*(p
+1)))
169 return; // done. Not a key.
174 // the value may be a quoted string or a token
175 const bool urlDecode
= (*p
!= '"'); // check before moving p.
176 char *v
= strwordtok(NULL
, &p
);
177 if (v
!= NULL
&& urlDecode
&& (p
-v
) > 2) // 1-octet %-escaped requires 3 bytes
180 notes
.add(key
, v
? v
: ""); // value can be empty, but must not be NULL
182 other_
.consume(p
- other_
.content());
183 other_
.consumeWhitespacePrefix();
188 Helper::Reply::emptyBuf() const
197 operator <<(std::ostream
&os
, const Helper::Reply
&r
)
207 case Helper::BrokenHelper
:
213 case Helper::TimedOut
:
216 case Helper::Unknown
:
221 // dump the helper key=pair "notes" list
222 if (!r
.notes
.empty()) {
224 os
<< r
.notes
.toString("; ");
228 MemBuf
const &o
= r
.other();
230 os
<< ", other: \"" << o
.content() << '\"';