Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /**
7 * This tests the automatic login to the proxy with password,
8 * if the password is stored and the browser is restarted.
9 *
10 * <copied from="test_authentication.js"/>
11 */
13 Cu.import("resource://testing-common/httpd.js");
15 const FLAG_RETURN_FALSE = 1 << 0;
16 const FLAG_WRONG_PASSWORD = 1 << 1;
17 const FLAG_PREVIOUS_FAILED = 1 << 2;
19 function AuthPrompt2(proxyFlags, hostFlags) {
20 this.proxyCred.flags = proxyFlags;
21 this.hostCred.flags = hostFlags;
22 }
23 AuthPrompt2.prototype = {
24 proxyCred : { user: "proxy", pass: "guest",
25 realmExpected: "intern", flags : 0 },
26 hostCred : { user: "host", pass: "guest",
27 realmExpected: "extern", flags : 0 },
29 QueryInterface: function authprompt2_qi(iid) {
30 if (iid.equals(Ci.nsISupports) ||
31 iid.equals(Ci.nsIAuthPrompt2))
32 return this;
33 throw Cr.NS_ERROR_NO_INTERFACE;
34 },
36 promptAuth:
37 function ap2_promptAuth(channel, encryptionLevel, authInfo)
38 {
39 try {
41 // never HOST and PROXY set at the same time in prompt
42 do_check_eq((authInfo.flags & Ci.nsIAuthInformation.AUTH_HOST) != 0,
43 (authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) == 0);
45 var isProxy = (authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) != 0;
46 var cred = isProxy ? this.proxyCred : this.hostCred;
48 dump("with flags: " +
49 ((cred.flags & FLAG_WRONG_PASSWORD) !=0 ? "wrong password" : "")+" "+
50 ((cred.flags & FLAG_PREVIOUS_FAILED) !=0 ? "previous failed" : "")+" "+
51 ((cred.flags & FLAG_RETURN_FALSE) !=0 ? "return false" : "") + "\n");
53 // PROXY properly set by necko (checked using realm)
54 do_check_eq(cred.realmExpected, authInfo.realm);
56 // PREVIOUS_FAILED properly set by necko
57 do_check_eq((cred.flags & FLAG_PREVIOUS_FAILED) != 0,
58 (authInfo.flags & Ci.nsIAuthInformation.PREVIOUS_FAILED) != 0);
60 if (cred.flags & FLAG_RETURN_FALSE)
61 {
62 cred.flags |= FLAG_PREVIOUS_FAILED;
63 cred.flags &= ~FLAG_RETURN_FALSE;
64 return false;
65 }
67 authInfo.username = cred.user;
68 if (cred.flags & FLAG_WRONG_PASSWORD) {
69 authInfo.password = cred.pass + ".wrong";
70 cred.flags |= FLAG_PREVIOUS_FAILED;
71 // Now clear the flag to avoid an infinite loop
72 cred.flags &= ~FLAG_WRONG_PASSWORD;
73 } else {
74 authInfo.password = cred.pass;
75 cred.flags &= ~FLAG_PREVIOUS_FAILED;
76 }
77 return true;
79 } catch (e) { do_throw(e); }
80 },
82 asyncPromptAuth:
83 function ap2_async(channel, callback, context, encryptionLevel, authInfo)
84 {
85 try {
86 var me = this;
87 var allOverAndDead = false;
88 do_execute_soon(function() {
89 try {
90 if (allOverAndDead)
91 throw "already canceled";
92 var ret = me.promptAuth(channel, encryptionLevel, authInfo);
93 if (!ret)
94 callback.onAuthCancelled(context, true);
95 else
96 callback.onAuthAvailable(context, authInfo);
97 allOverAndDead = true;
98 } catch (e) { do_throw(e); }
99 });
100 return new Cancelable(function() {
101 if (allOverAndDead)
102 throw "can't cancel, already ran";
103 callback.onAuthAvailable(context, authInfo);
104 allOverAndDead = true;
105 });
106 } catch (e) { do_throw(e); }
107 }
108 };
110 function Cancelable(onCancelFunc) {
111 this.onCancelFunc = onCancelFunc;
112 }
113 Cancelable.prototype = {
114 QueryInterface: function cancelable_qi(iid) {
115 if (iid.equals(Ci.nsISupports) ||
116 iid.equals(Ci.nsICancelable))
117 return this;
118 throw Cr.NS_ERROR_NO_INTERFACE;
119 },
120 cancel: function cancel() {
121 try {
122 this.onCancelFunc();
123 } catch (e) { do_throw(e); }
124 }
125 };
127 function Requestor(proxyFlags, hostFlags) {
128 this.proxyFlags = proxyFlags;
129 this.hostFlags = hostFlags;
130 }
131 Requestor.prototype = {
132 QueryInterface: function requestor_qi(iid) {
133 if (iid.equals(Ci.nsISupports) ||
134 iid.equals(Ci.nsIInterfaceRequestor))
135 return this;
136 throw Cr.NS_ERROR_NO_INTERFACE;
137 },
139 getInterface: function requestor_gi(iid) {
140 if (iid.equals(Ci.nsIAuthPrompt)) {
141 dump("authprompt1 not implemented\n");
142 throw Cr.NS_ERROR_NO_INTERFACE;
143 }
144 if (iid.equals(Ci.nsIAuthPrompt2)) {
145 try {
146 // Allow the prompt to store state by caching it here
147 if (!this.prompt2)
148 this.prompt2 = new AuthPrompt2(this.proxyFlags, this.hostFlags);
149 return this.prompt2;
150 } catch (e) { do_throw(e); }
151 }
152 throw Cr.NS_ERROR_NO_INTERFACE;
153 },
155 prompt2: null
156 };
158 var listener = {
159 expectedCode: -1, // uninitialized
161 onStartRequest: function test_onStartR(request, ctx) {
162 try {
163 // Proxy auth cancellation return failures to avoid spoofing
164 if (!Components.isSuccessCode(request.status) &&
165 (this.expectedCode != 407))
166 do_throw("Channel should have a success code!");
168 if (!(request instanceof Ci.nsIHttpChannel))
169 do_throw("Expecting an HTTP channel");
171 do_check_eq(this.expectedCode, request.responseStatus);
172 // If we expect 200, the request should have succeeded
173 do_check_eq(this.expectedCode == 200, request.requestSucceeded);
175 } catch (e) {
176 do_throw("Unexpected exception: " + e);
177 }
179 throw Cr.NS_ERROR_ABORT;
180 },
182 onDataAvailable: function test_ODA() {
183 do_throw("Should not get any data!");
184 },
186 onStopRequest: function test_onStopR(request, ctx, status) {
187 do_check_eq(status, Cr.NS_ERROR_ABORT);
189 if (current_test < (tests.length - 1)) {
190 // First, need to clear the auth cache
191 Cc["@mozilla.org/network/http-auth-manager;1"]
192 .getService(Ci.nsIHttpAuthManager)
193 .clearAll();
195 current_test++;
196 tests[current_test]();
197 } else {
198 do_test_pending();
199 httpserv.stop(do_test_finished);
200 }
202 do_test_finished();
203 }
204 };
206 function makeChan(url) {
207 if (!url)
208 url = "http://somesite/";
209 var ios = Cc["@mozilla.org/network/io-service;1"]
210 .getService(Ci.nsIIOService);
211 var chan = ios.newChannel(url, null, null)
212 .QueryInterface(Ci.nsIHttpChannel);
214 return chan;
215 }
217 var current_test = 0;
218 var httpserv = null;
220 function run_test() {
221 httpserv = new HttpServer();
222 httpserv.registerPathHandler("/", proxyAuthHandler);
223 httpserv.identity.add("http", "somesite", 80);
224 httpserv.start(-1);
226 const prefs = Cc["@mozilla.org/preferences-service;1"]
227 .getService(Ci.nsIPrefBranch);
228 prefs.setCharPref("network.proxy.http", "localhost");
229 prefs.setIntPref("network.proxy.http_port", httpserv.identity.primaryPort);
230 prefs.setCharPref("network.proxy.no_proxies_on", "");
231 prefs.setIntPref("network.proxy.type", 1);
233 tests[current_test]();
234 }
236 function test_proxy_returnfalse() {
237 dump("\ntest: proxy returnfalse\n");
238 var chan = makeChan();
239 chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 0);
240 listener.expectedCode = 407; // Proxy Unauthorized
241 chan.asyncOpen(listener, null);
243 do_test_pending();
244 }
246 function test_proxy_wrongpw() {
247 dump("\ntest: proxy wrongpw\n");
248 var chan = makeChan();
249 chan.notificationCallbacks = new Requestor(FLAG_WRONG_PASSWORD, 0);
250 listener.expectedCode = 200; // Eventually OK
251 chan.asyncOpen(listener, null);
252 do_test_pending();
253 }
255 function test_all_ok() {
256 dump("\ntest: all ok\n");
257 var chan = makeChan();
258 chan.notificationCallbacks = new Requestor(0, 0);
259 listener.expectedCode = 200; // OK
260 chan.asyncOpen(listener, null);
261 do_test_pending();
262 }
264 function test_host_returnfalse() {
265 dump("\ntest: host returnfalse\n");
266 var chan = makeChan();
267 chan.notificationCallbacks = new Requestor(0, FLAG_RETURN_FALSE);
268 listener.expectedCode = 401; // Host Unauthorized
269 chan.asyncOpen(listener, null);
271 do_test_pending();
272 }
274 function test_host_wrongpw() {
275 dump("\ntest: host wrongpw\n");
276 var chan = makeChan();
277 chan.notificationCallbacks = new Requestor(0, FLAG_WRONG_PASSWORD);
278 listener.expectedCode = 200; // Eventually OK
279 chan.asyncOpen(listener, null);
280 do_test_pending();
281 }
283 function test_proxy_wrongpw_host_wrongpw() {
284 dump("\ntest: proxy wrongpw, host wrongpw\n");
285 var chan = makeChan();
286 chan.notificationCallbacks =
287 new Requestor(FLAG_WRONG_PASSWORD, FLAG_WRONG_PASSWORD);
288 listener.expectedCode = 200; // OK
289 chan.asyncOpen(listener, null);
290 do_test_pending();
291 }
293 function test_proxy_wrongpw_host_returnfalse() {
294 dump("\ntest: proxy wrongpw, host return false\n");
295 var chan = makeChan();
296 chan.notificationCallbacks =
297 new Requestor(FLAG_WRONG_PASSWORD, FLAG_RETURN_FALSE);
298 listener.expectedCode = 401; // Host Unauthorized
299 chan.asyncOpen(listener, null);
300 do_test_pending();
301 }
303 var tests = [test_proxy_returnfalse, test_proxy_wrongpw, test_all_ok,
304 test_host_returnfalse, test_host_wrongpw,
305 test_proxy_wrongpw_host_wrongpw, test_proxy_wrongpw_host_returnfalse];
308 // PATH HANDLERS
310 // Proxy
311 function proxyAuthHandler(metadata, response) {
312 try {
313 var realm = "intern";
314 // btoa("proxy:guest"), but that function is not available here
315 var expectedHeader = "Basic cHJveHk6Z3Vlc3Q=";
317 var body;
318 if (metadata.hasHeader("Proxy-Authorization") &&
319 metadata.getHeader("Proxy-Authorization") == expectedHeader)
320 {
321 dump("proxy password ok\n");
322 response.setHeader("Proxy-Authenticate",
323 'Basic realm="' + realm + '"', false);
325 hostAuthHandler(metadata, response);
326 }
327 else
328 {
329 dump("proxy password required\n");
330 response.setStatusLine(metadata.httpVersion, 407,
331 "Unauthorized by HTTP proxy");
332 response.setHeader("Proxy-Authenticate",
333 'Basic realm="' + realm + '"', false);
334 body = "failed";
335 response.bodyOutputStream.write(body, body.length);
336 }
337 } catch (e) { do_throw(e); }
338 }
340 // Host /auth
341 function hostAuthHandler(metadata, response) {
342 try {
343 var realm = "extern";
344 // btoa("host:guest"), but that function is not available here
345 var expectedHeader = "Basic aG9zdDpndWVzdA==";
347 var body;
348 if (metadata.hasHeader("Authorization") &&
349 metadata.getHeader("Authorization") == expectedHeader)
350 {
351 dump("host password ok\n");
352 response.setStatusLine(metadata.httpVersion, 200,
353 "OK, authorized for host");
354 response.setHeader("WWW-Authenticate",
355 'Basic realm="' + realm + '"', false);
356 body = "success";
357 }
358 else
359 {
360 dump("host password required\n");
361 response.setStatusLine(metadata.httpVersion, 401,
362 "Unauthorized by HTTP server host");
363 response.setHeader("WWW-Authenticate",
364 'Basic realm="' + realm + '"', false);
365 body = "failed";
366 }
367 response.bodyOutputStream.write(body, body.length);
368 } catch (e) { do_throw(e); }
369 }