]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/HelperReply.cc
2 * Copyright (C) 1996-2014 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 "HelperReply.h"
17 #include "SquidString.h"
19 HelperReply::HelperReply(char *buf
, size_t len
) :
20 result(HelperReply::Unknown
),
27 HelperReply::parse(char *buf
, size_t len
)
29 debugs(84, 3, "Parsing helper buffer");
30 // check we have something to parse
31 if (!buf
|| len
< 1) {
32 // empty line response was the old URL-rewriter interface ERR response.
33 result
= HelperReply::Error
;
34 // for now ensure that legacy handlers are not presented with NULL strings.
35 debugs(84, 3, "Reply length is smaller than 1 or none at all ");
44 // optimization: do not consider parsing result code if the response is short.
45 // URL-rewriter may return relative URLs or empty response for a large portion
48 debugs(84, 3, "Buff length is larger than 2");
49 // some helper formats (digest auth, URL-rewriter) just send a data string
50 // we must also check for the ' ' character after the response token (if anything)
51 if (!strncmp(p
,"OK",2) && (len
== 2 || p
[2] == ' ')) {
52 debugs(84, 3, "helper Result = OK");
53 result
= HelperReply::Okay
;
55 } else if (!strncmp(p
,"ERR",3) && (len
== 3 || p
[3] == ' ')) {
56 debugs(84, 3, "helper Result = ERR");
57 result
= HelperReply::Error
;
59 } else if (!strncmp(p
,"BH",2) && (len
== 2 || p
[2] == ' ')) {
60 debugs(84, 3, "helper Result = BH");
61 result
= HelperReply::BrokenHelper
;
63 } else if (!strncmp(p
,"TT ",3)) {
64 // NTLM challenge token
65 result
= HelperReply::TT
;
67 // followed by an auth token
68 char *w1
= strwordtok(NULL
, &p
);
72 authToken
.append(w1
, strlen(w1
));
73 notes
.add("token",authToken
.content());
75 // token field is mandatory on this response code
76 result
= HelperReply::BrokenHelper
;
77 notes
.add("message","Missing 'token' data");
80 } else if (!strncmp(p
,"AF ",3)) {
81 // NTLM/Negotate OK response
82 result
= HelperReply::Okay
;
85 // an optional auth token and user field
86 // or, an optional username field
87 char *w1
= strwordtok(NULL
, &p
);
88 char *w2
= strwordtok(NULL
, &p
);
90 // Negotiate "token user"
93 authToken
.append(w1
, strlen(w1
));
94 notes
.add("token",authToken
.content());
98 user
.append(w2
,strlen(w2
));
99 notes
.add("user",user
.content());
101 } else if (w1
!= NULL
) {
105 user
.append(w1
,strlen(w1
));
106 notes
.add("user",user
.content());
108 } else if (!strncmp(p
,"NA ",3)) {
109 // NTLM fail-closed ERR response
110 result
= HelperReply::Error
;
115 for (; xisspace(*p
); ++p
); // skip whitespace
118 const mb_size_t blobSize
= (buf
+len
-p
);
119 other_
.init(blobSize
+1, blobSize
+1);
120 other_
.append(p
, blobSize
); // remainders of the line.
122 // NULL-terminate so the helper callback handlers do not buffer-overrun
125 // Hack for backward-compatibility: Do not parse for kv-pairs on NA response
129 // Hack for backward-compatibility: BH and NA used to be a text message...
130 if (other().hasContent() && (sawNA
|| result
== HelperReply::BrokenHelper
)) {
131 notes
.add("message",other().content());
132 modifiableOther().clean();
136 /// restrict key names to alphanumeric, hyphen, underscore characters
138 isKeyNameChar(char c
)
140 if (c
>= 'a' && c
<= 'z')
143 if (c
>= 'A' && c
<= 'Z')
146 if (c
>= '0' && c
<= '9')
149 if (c
== '-' || c
== '_')
152 // prevent other characters matching the key=value
157 HelperReply::parseResponseKeys()
159 // parse a "key=value" pair off the 'other()' buffer.
160 while (other().hasContent()) {
161 char *p
= modifiableOther().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 const char *key
= other().content();
176 // the value may be a quoted string or a token
177 const bool urlDecode
= (*p
!= '"'); // check before moving p.
178 char *v
= strwordtok(NULL
, &p
);
179 if (v
!= NULL
&& urlDecode
&& (p
-v
) > 2) // 1-octet %-escaped requires 3 bytes
182 notes
.add(key
, v
? v
: ""); // value can be empty, but must not be NULL
184 modifiableOther().consume(p
- other().content());
185 modifiableOther().consumeWhitespacePrefix();
190 operator <<(std::ostream
&os
, const HelperReply
&r
)
194 case HelperReply::Okay
:
197 case HelperReply::Error
:
200 case HelperReply::BrokenHelper
:
203 case HelperReply::TT
:
206 case HelperReply::Unknown
:
211 // dump the helper key=pair "notes" list
212 if (!r
.notes
.empty()) {
214 os
<< r
.notes
.toString("; ");
218 if (r
.other().hasContent())
219 os
<< ", other: \"" << r
.other().content() << '\"';