]>
Commit | Line | Data |
---|---|---|
15a12fe5 MW |
1 | Index: squid/src/cf.data.pre |
2 | diff -c squid/src/cf.data.pre:1.245.2.41 squid/src/cf.data.pre:1.245.2.42 | |
3 | *** squid/src/cf.data.pre:1.245.2.41 Sat Apr 26 18:33:17 2003 | |
4 | --- squid/src/cf.data.pre Sun May 18 15:49:19 2003 | |
5 | *************** | |
6 | *** 1351,1360 **** | |
7 | used. | |
8 | ||
9 | "nonce_strictness" on|off | |
10 | ! Determines if squid requires increment-by-1 behaviour for | |
11 | ! nonce counts (on - the default), or strictly incrementing | |
12 | ! (off - for use when useragents generate nonce counts that | |
13 | ! occasionally miss 1 (ie, 1,2,4,6)). | |
14 | ||
15 | === NTLM scheme options follow === | |
16 | ||
17 | --- 1351,1371 ---- | |
18 | used. | |
19 | ||
20 | "nonce_strictness" on|off | |
21 | ! Determines if squid requires strict increment-by-1 behaviour | |
22 | ! for nonce counts, or just incrementing (off - for use when | |
23 | ! useragents generate nonce counts that occasionally miss 1 | |
24 | ! (ie, 1,2,4,6)). Default off. | |
25 | ! | |
26 | ! "check_nonce_count" on|off | |
27 | ! This directive if set to off can disable the nonce count check | |
28 | ! completely to work around buggy digest qop implementations in | |
29 | ! certain mainstream browser versions. Default on to check the | |
30 | ! nonce count to protect from authentication replay attacks. | |
31 | ! | |
32 | ! "post_workaround" on|off | |
33 | ! This is a workaround to certain buggy browsers who sends | |
34 | ! an incorrect request digest in POST requests when reusing | |
35 | ! the same nonce as aquired earlier on a GET request. | |
36 | ||
37 | === NTLM scheme options follow === | |
38 | ||
39 | Index: squid/src/authenticate.c | |
40 | diff -c squid/src/authenticate.c:1.36.2.9 squid/src/authenticate.c:1.36.2.10 | |
41 | *** squid/src/authenticate.c:1.36.2.9 Sun May 11 15:44:31 2003 | |
42 | --- squid/src/authenticate.c Sun May 18 15:49:19 2003 | |
43 | *************** | |
44 | *** 538,543 **** | |
45 | --- 538,549 ---- | |
46 | conn, headertype); | |
47 | switch (authenticateDirection(*auth_user_request)) { | |
48 | case 1: | |
49 | + if (!request->auth_user_request) { | |
50 | + /* lock the user for the request structure link */ | |
51 | + authenticateAuthUserRequestLock(*auth_user_request); | |
52 | + request->auth_user_request = *auth_user_request; | |
53 | + } | |
54 | + /* fallthrough to -2 */ | |
55 | case -2: | |
56 | /* this ACL check is finished. Unlock. */ | |
57 | authenticateAuthUserRequestUnlock(*auth_user_request); | |
58 | Index: squid/src/auth/digest/auth_digest.h | |
59 | diff -c squid/src/auth/digest/auth_digest.h:1.5.2.2 squid/src/auth/digest/auth_digest.h:1.5.2.3 | |
60 | *** squid/src/auth/digest/auth_digest.h:1.5.2.2 Thu Feb 27 01:19:24 2003 | |
61 | --- squid/src/auth/digest/auth_digest.h Sun May 18 15:49:20 2003 | |
62 | *************** | |
63 | *** 42,48 **** | |
64 | char *response; | |
65 | struct { | |
66 | unsigned int authinfo_sent:1; | |
67 | ! unsigned int credentials_ok:2; /*0=unchecked,1=ok,2=failed */ | |
68 | } flags; | |
69 | digest_nonce_h *nonce; | |
70 | }; | |
71 | --- 42,49 ---- | |
72 | char *response; | |
73 | struct { | |
74 | unsigned int authinfo_sent:1; | |
75 | ! unsigned int credentials_ok:2; /*0=unchecked,1=ok,2=helper,3=failed */ | |
76 | ! unsigned int nonce_stale:1; | |
77 | } flags; | |
78 | digest_nonce_h *nonce; | |
79 | }; | |
80 | *************** | |
81 | *** 81,86 **** | |
82 | --- 82,89 ---- | |
83 | time_t noncemaxduration; | |
84 | int noncemaxuses; | |
85 | int NonceStrictness; | |
86 | + int CheckNonceCount; | |
87 | + int PostWorkaround; | |
88 | }; | |
89 | ||
90 | typedef struct _auth_digest_config auth_digest_config; | |
91 | Index: squid/src/auth/digest/auth_digest.c | |
92 | diff -c squid/src/auth/digest/auth_digest.c:1.10.2.5 squid/src/auth/digest/auth_digest.c:1.10.2.6 | |
93 | *** squid/src/auth/digest/auth_digest.c:1.10.2.5 Thu Feb 27 01:19:24 2003 | |
94 | --- squid/src/auth/digest/auth_digest.c Sun May 18 15:49:20 2003 | |
95 | *************** | |
96 | *** 343,359 **** | |
97 | if (!nonce) | |
98 | return 0; | |
99 | intnc = strtol(nc, NULL, 16); | |
100 | if ((digestConfig->NonceStrictness && intnc != nonce->nc + 1) || | |
101 | intnc < nonce->nc + 1) { | |
102 | debug(29, 4) ("authDigestNonceIsValid: Nonce count doesn't match\n"); | |
103 | nonce->flags.valid = 0; | |
104 | return 0; | |
105 | } | |
106 | - /* has it already been invalidated ? */ | |
107 | - if (!nonce->flags.valid) { | |
108 | - debug(29, 4) ("authDigestNonceIsValid: Nonce already invalidated\n"); | |
109 | - return 0; | |
110 | - } | |
111 | /* seems ok */ | |
112 | /* increment the nonce count - we've already checked that intnc is a | |
113 | * valid representation for us, so we don't need the test here. | |
114 | --- 343,364 ---- | |
115 | if (!nonce) | |
116 | return 0; | |
117 | intnc = strtol(nc, NULL, 16); | |
118 | + /* has it already been invalidated ? */ | |
119 | + if (!nonce->flags.valid) { | |
120 | + debug(29, 4) ("authDigestNonceIsValid: Nonce already invalidated\n"); | |
121 | + return 0; | |
122 | + } | |
123 | + /* is the nonce-count ok ? */ | |
124 | + if (!digestConfig->CheckNonceCount) { | |
125 | + nonce->nc++; | |
126 | + return -1; /* forced OK by configuration */ | |
127 | + } | |
128 | if ((digestConfig->NonceStrictness && intnc != nonce->nc + 1) || | |
129 | intnc < nonce->nc + 1) { | |
130 | debug(29, 4) ("authDigestNonceIsValid: Nonce count doesn't match\n"); | |
131 | nonce->flags.valid = 0; | |
132 | return 0; | |
133 | } | |
134 | /* seems ok */ | |
135 | /* increment the nonce count - we've already checked that intnc is a | |
136 | * valid representation for us, so we don't need the test here. | |
137 | *************** | |
138 | *** 691,701 **** | |
139 | "squid is = '%s'\n", digest_request->response, Response); | |
140 | ||
141 | if (strcasecmp(digest_request->response, Response)) { | |
142 | digest_request->flags.credentials_ok = 3; | |
143 | return; | |
144 | } | |
145 | - digest_request->flags.credentials_ok = 1; | |
146 | /* password was checked and did match */ | |
147 | debug(29, 4) ("authenticateDigestAuthenticateuser: user '%s' validated OK\n", | |
148 | digest_user->username); | |
149 | ||
150 | --- 696,739 ---- | |
151 | "squid is = '%s'\n", digest_request->response, Response); | |
152 | ||
153 | if (strcasecmp(digest_request->response, Response)) { | |
154 | + if (digestConfig->PostWorkaround && request->method != METHOD_GET) { | |
155 | + /* Ugly workaround for certain very broken browsers using the | |
156 | + * wrong method to calculate the request-digest on POST request. | |
157 | + * This should be deleted once Digest authentication becomes more | |
158 | + * widespread and such broken browsers no longer are commonly | |
159 | + * used. | |
160 | + */ | |
161 | + DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce), | |
162 | + digest_request->nc, digest_request->cnonce, digest_request->qop, | |
163 | + RequestMethodStr[METHOD_GET], digest_request->uri, HA2, Response); | |
164 | + if (strcasecmp(digest_request->response, Response)) { | |
165 | + digest_request->flags.credentials_ok = 3; | |
166 | + return; | |
167 | + } else { | |
168 | + const char *useragent = httpHeaderGetStr(&request->header, HDR_USER_AGENT); | |
169 | + static struct in_addr last_broken_addr = | |
170 | + {0}; | |
171 | + if (memcmp(&last_broken_addr, &request->client_addr, sizeof(last_broken_addr)) != 0) { | |
172 | + debug(29, 1) ("\nDigest POST bug detected from %s using '%s'. Please upgrade browser. See Bug #630 for details.\n", inet_ntoa(request->client_addr), useragent ? useragent : "-"); | |
173 | + last_broken_addr = request->client_addr; | |
174 | + } | |
175 | + } | |
176 | + } else { | |
177 | + digest_request->flags.credentials_ok = 3; | |
178 | + return; | |
179 | + } | |
180 | + } | |
181 | + /* check for stale nonce */ | |
182 | + if (!authDigestNonceIsValid(digest_request->nonce, digest_request->nc)) { | |
183 | + debug(29, 3) ("authenticateDigestAuthenticateuser: user '%s' validated OK but nonce stale\n", | |
184 | + digest_user->username); | |
185 | + digest_request->flags.nonce_stale = 1; | |
186 | digest_request->flags.credentials_ok = 3; | |
187 | return; | |
188 | } | |
189 | /* password was checked and did match */ | |
190 | + digest_request->flags.credentials_ok = 1; | |
191 | + | |
192 | debug(29, 4) ("authenticateDigestAuthenticateuser: user '%s' validated OK\n", | |
193 | digest_user->username); | |
194 | ||
195 | *************** | |
196 | *** 714,726 **** | |
197 | case 0: /* not checked */ | |
198 | return -1; | |
199 | case 1: /* checked & ok */ | |
200 | - if (authDigestNonceIsStale(digest_request->nonce)) | |
201 | - /* send stale response to the client agent */ | |
202 | - return -2; | |
203 | return 0; | |
204 | case 2: /* partway through checking. */ | |
205 | return -1; | |
206 | case 3: /* authentication process failed. */ | |
207 | return -2; | |
208 | } | |
209 | return -2; | |
210 | --- 752,764 ---- | |
211 | case 0: /* not checked */ | |
212 | return -1; | |
213 | case 1: /* checked & ok */ | |
214 | return 0; | |
215 | case 2: /* partway through checking. */ | |
216 | return -1; | |
217 | case 3: /* authentication process failed. */ | |
218 | + if (digest_request->flags.nonce_stale) | |
219 | + /* nonce is stale, send new challenge */ | |
220 | + return 1; | |
221 | return -2; | |
222 | } | |
223 | return -2; | |
224 | *************** | |
225 | *** 787,795 **** | |
226 | digest_request_h *digest_request; | |
227 | int stale = 0; | |
228 | digest_nonce_h *nonce = authenticateDigestNonceNew(); | |
229 | ! if (auth_user_request && auth_user_request->scheme_data && authDigestAuthenticated(auth_user_request)) { | |
230 | digest_request = auth_user_request->scheme_data; | |
231 | ! stale = authDigestNonceIsStale(digest_request->nonce); | |
232 | } | |
233 | if (digestConfig->authenticate) { | |
234 | debug(29, 9) ("authenticateFixHeader: Sending type:%d header: 'Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s\n", type, digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); | |
235 | --- 825,833 ---- | |
236 | digest_request_h *digest_request; | |
237 | int stale = 0; | |
238 | digest_nonce_h *nonce = authenticateDigestNonceNew(); | |
239 | ! if (auth_user_request && auth_user_request->scheme_data) { | |
240 | digest_request = auth_user_request->scheme_data; | |
241 | ! stale = digest_request->flags.nonce_stale; | |
242 | } | |
243 | if (digestConfig->authenticate) { | |
244 | debug(29, 9) ("authenticateFixHeader: Sending type:%d header: 'Digest realm=\"%s\", nonce=\"%s\", qop=\"%s\", stale=%s\n", type, digestConfig->digestAuthRealm, authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false"); | |
245 | *************** | |
246 | *** 915,922 **** | |
247 | digestConfig->noncemaxduration = 30 * 60; | |
248 | /* 50 requests */ | |
249 | digestConfig->noncemaxuses = 50; | |
250 | ! /* strict nonce count behaviour */ | |
251 | ! digestConfig->NonceStrictness = 1; | |
252 | } | |
253 | digestConfig = scheme->scheme_data; | |
254 | if (strcasecmp(param_str, "program") == 0) { | |
255 | --- 953,962 ---- | |
256 | digestConfig->noncemaxduration = 30 * 60; | |
257 | /* 50 requests */ | |
258 | digestConfig->noncemaxuses = 50; | |
259 | ! /* Not strict nonce count behaviour */ | |
260 | ! digestConfig->NonceStrictness = 0; | |
261 | ! /* Verify nonce count */ | |
262 | ! digestConfig->CheckNonceCount = 1; | |
263 | } | |
264 | digestConfig = scheme->scheme_data; | |
265 | if (strcasecmp(param_str, "program") == 0) { | |
266 | *************** | |
267 | *** 936,941 **** | |
268 | --- 976,985 ---- | |
269 | parse_int(&digestConfig->noncemaxuses); | |
270 | } else if (strcasecmp(param_str, "nonce_strictness") == 0) { | |
271 | parse_onoff(&digestConfig->NonceStrictness); | |
272 | + } else if (strcasecmp(param_str, "check_nonce_count") == 0) { | |
273 | + parse_onoff(&digestConfig->CheckNonceCount); | |
274 | + } else if (strcasecmp(param_str, "post_workaround") == 0) { | |
275 | + parse_onoff(&digestConfig->PostWorkaround); | |
276 | } else { | |
277 | debug(28, 0) ("unrecognised digest auth scheme parameter '%s'\n", param_str); | |
278 | } | |
279 | *************** | |
280 | *** 1184,1190 **** | |
281 | } | |
282 | /* now the nonce */ | |
283 | nonce = authenticateDigestNonceFindNonce(digest_request->nonceb64); | |
284 | ! if ((nonce == NULL) || !(authDigestNonceIsValid(nonce, digest_request->nc))) { | |
285 | /* we couldn't find a matching nonce! */ | |
286 | debug(29, 4) ("authenticateDigestDecode: Unexpected or invalid nonce recieved\n"); | |
287 | authDigestLogUsername(auth_user_request, username); | |
288 | --- 1228,1234 ---- | |
289 | } | |
290 | /* now the nonce */ | |
291 | nonce = authenticateDigestNonceFindNonce(digest_request->nonceb64); | |
292 | ! if (!nonce) { | |
293 | /* we couldn't find a matching nonce! */ | |
294 | debug(29, 4) ("authenticateDigestDecode: Unexpected or invalid nonce recieved\n"); | |
295 | authDigestLogUsername(auth_user_request, username); |