Advertisement
Guest User

proxy_auth.patch

a guest
Dec 9th, 2017
347
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.79 KB | None | 0 0
  1. # HG changeset patch
  2. # User Ian MacLeod <rubberdonkeysandwich@gmail.com>
  3. # Date 1512815238 28800
  4. # Sat Dec 09 02:27:18 2017 -0800
  5. # Node ID aa90a1a15c6f69745a517c156038cb0f2a8011e1
  6. # Parent 5f52c2488a831edbc33fa0bc6003ed4df9a62732
  7. Add support for proxy authentication
  8.  
  9. MozReview-Commit-ID: 5kTtXE7CMZS
  10.  
  11. diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_proxy.py b/testing/marionette/harness/marionette_harness/tests/unit/test_proxy.py
  12. --- a/testing/marionette/harness/marionette_harness/tests/unit/test_proxy.py
  13. +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_proxy.py
  14. @@ -1,16 +1,18 @@
  15. # This Source Code Form is subject to the terms of the Mozilla Public
  16. # License, v. 2.0. If a copy of the MPL was not distributed with this
  17. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  18.  
  19. from marionette_driver import errors
  20.  
  21. from marionette_harness import MarionetteTestCase
  22.  
  23. +from time import sleep
  24. +
  25.  
  26. class TestProxyCapabilities(MarionetteTestCase):
  27.  
  28. def setUp(self):
  29. super(TestProxyCapabilities, self).setUp()
  30.  
  31. self.marionette.delete_session()
  32.  
  33. @@ -61,16 +63,39 @@ class TestProxyCapabilities(MarionetteTe
  34. "socksProxy": proxy_hostname,
  35. "socksVersion": 4,
  36. }}
  37.  
  38. self.marionette.start_session(capabilities)
  39. self.assertEqual(self.marionette.session_capabilities["proxy"],
  40. capabilities["proxy"])
  41.  
  42. + def test_proxy_type_manual_with_authentication(self):
  43. + proxy_hostname = "104.236.137.24"
  44. + username = "username"
  45. + password = "password"
  46. + capabilities = {"proxy": {
  47. + "proxyType": "manual",
  48. + "ftpProxy": "{}:{}@{}:3128".format(username, password, proxy_hostname),
  49. + "httpProxy": "{}:{}@{}:3128".format(username, password, proxy_hostname),
  50. + "sslProxy": "{}:{}@{}:3128".format(username, password, proxy_hostname),
  51. + }}
  52. +
  53. + self.marionette.start_session(capabilities)
  54. + self.assertEqual(self.marionette.session_capabilities["proxy"],
  55. + capabilities["proxy"])
  56. +
  57. + url = "https://www.google.com/search?q=my+ip+address"
  58. + self.marionette.navigate(url)
  59. + sleep(3)
  60. + self.marionette.switch_to_alert().accept()
  61. + sleep(3)
  62. + self.assertEqual(self.marionette.get_url(), url)
  63. + self.assertIn("104.236.137.24", self.marionette.page_source)
  64. +
  65. def test_proxy_type_manual_socks_requires_version(self):
  66. proxy_port = 4444
  67. proxy_hostname = "marionette.test"
  68. proxy_host = "{}:{}".format(proxy_hostname, proxy_port)
  69. capabilities = {"proxy": {
  70. "proxyType": "manual",
  71. "socksProxy": proxy_host,
  72. }}
  73. diff --git a/testing/marionette/server.js b/testing/marionette/server.js
  74. --- a/testing/marionette/server.js
  75. +++ b/testing/marionette/server.js
  76. @@ -265,16 +265,23 @@ const RECOMMENDED_PREFS = new Map([
  77. ["security.fileuri.strict_origin_policy", false],
  78.  
  79. // Tests do not wait for the notification button security delay
  80. ["security.notification_enable_delay", 0],
  81.  
  82. // Ensure blocklist updates do not hit the network
  83. ["services.settings.server", "http://%(server)s/dummy/blocklist/"],
  84.  
  85. + // Prevent popup for proxy authentication when a login is stored
  86. + ["signon.autologin.proxy", true],
  87. + ["network.negotiate-auth.allow-proxies", false],
  88. + ["network.proxy.share_proxy_settings", false],
  89. + ["network.automatic-ntlm-auth.allow-proxies", false],
  90. + ["network.auth.use-sspi", false],
  91. +
  92. // Do not automatically fill sign-in forms with known usernames and
  93. // passwords
  94. ["signon.autofillForms", false],
  95.  
  96. // Disable password capture, so that tests that include forms are not
  97. // influenced by the presence of the persistent doorhanger notification
  98. ["signon.rememberSignons", false],
  99.  
  100. diff --git a/testing/marionette/session.js b/testing/marionette/session.js
  101. --- a/testing/marionette/session.js
  102. +++ b/testing/marionette/session.js
  103. @@ -3,16 +3,19 @@
  104. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  105.  
  106. "use strict";
  107.  
  108. const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
  109.  
  110. Cu.importGlobalProperties(["URL"]);
  111.  
  112. +Cu.import("resource://gre/modules/Log.jsm");
  113. +const logger = Log.repository.getLogger("Marionette");
  114. +
  115. Cu.import("resource://gre/modules/Preferences.jsm");
  116. Cu.import("resource://gre/modules/Services.jsm");
  117.  
  118. Cu.import("chrome://marionette/content/assert.js");
  119. const {
  120. InvalidArgumentError,
  121. } = Cu.import("chrome://marionette/content/error.js", {});
  122. const {
  123. @@ -125,16 +128,29 @@ session.Proxy = class {
  124. * Sets Firefox proxy settings.
  125. *
  126. * @return {boolean}
  127. * True if proxy settings were updated as a result of calling this
  128. * function, or false indicating that this function acted as
  129. * a no-op.
  130. */
  131. init() {
  132. + function addProxyLogin(login) {
  133. + if (login) {
  134. + const logins = Services.logins.findLogins({}, login.hostname, "", login.httpRealm, {});
  135. + if (logins.length) {
  136. + if (login.username != logins[0].username || login.hostname != logins[0].hostname) {
  137. + // Throw exception here?
  138. + logger.debug("Cannot add two different logins for the same host");
  139. + }
  140. + } else {
  141. + Services.logins.addLogin(login);
  142. + }
  143. + }
  144. + }
  145. switch (this.proxyType) {
  146. case "autodetect":
  147. Preferences.set("network.proxy.type", 4);
  148. return true;
  149.  
  150. case "direct":
  151. Preferences.set("network.proxy.type", 0);
  152. return true;
  153. @@ -142,30 +158,33 @@ session.Proxy = class {
  154. case "manual":
  155. Preferences.set("network.proxy.type", 1);
  156.  
  157. if (this.ftpProxy) {
  158. Preferences.set("network.proxy.ftp", this.ftpProxy);
  159. if (Number.isInteger(this.ftpProxyPort)) {
  160. Preferences.set("network.proxy.ftp_port", this.ftpProxyPort);
  161. }
  162. + addProxyLogin(this.ftpLogin);
  163. }
  164.  
  165. if (this.httpProxy) {
  166. Preferences.set("network.proxy.http", this.httpProxy);
  167. if (Number.isInteger(this.httpProxyPort)) {
  168. Preferences.set("network.proxy.http_port", this.httpProxyPort);
  169. }
  170. + addProxyLogin(this.httpLogin);
  171. }
  172.  
  173. if (this.sslProxy) {
  174. Preferences.set("network.proxy.ssl", this.sslProxy);
  175. if (Number.isInteger(this.sslProxyPort)) {
  176. Preferences.set("network.proxy.ssl_port", this.sslProxyPort);
  177. }
  178. + addProxyLogin(this.sslLogin);
  179. }
  180.  
  181. if (this.socksProxy) {
  182. Preferences.set("network.proxy.socks", this.socksProxy);
  183. if (Number.isInteger(this.socksProxyPort)) {
  184. Preferences.set("network.proxy.socks_port", this.socksProxyPort);
  185. }
  186. if (this.socksVersion) {
  187. @@ -224,39 +243,44 @@ session.Proxy = class {
  188. url = new URL("http://" + host);
  189. if (url.port == "") {
  190. url = new URL("https://" + host);
  191. }
  192. } catch (e) {
  193. throw new InvalidArgumentError(e.message);
  194. }
  195.  
  196. - let hostname = stripBracketsFromIpv6Hostname(url.hostname);
  197. -
  198. // If the port hasn't been set, use the default port of
  199. // the selected scheme (except for socks which doesn't have one).
  200. let port = parseInt(url.port);
  201. if (!Number.isInteger(port)) {
  202. if (scheme === "socks") {
  203. port = null;
  204. } else {
  205. port = Services.io.getProtocolHandler(scheme).defaultPort;
  206. }
  207. }
  208.  
  209. - if (url.username != "" ||
  210. - url.password != "" ||
  211. - url.pathname != "/" ||
  212. + let login = null;
  213. + if (url.username !== "") {
  214. + login = Cc["@mozilla.org/login-manager/loginInfo;1"]
  215. + .createInstance(Ci.nsILoginInfo);
  216. + login.init(`moz-proxy://${url.hostname}:${port}`, null, "Squid proxy-caching web server", url.username, url.password, "", "");
  217. + }
  218. +
  219. + let hostname = stripBracketsFromIpv6Hostname(url.hostname);
  220. +
  221. + if (url.pathname != "/" ||
  222. url.search != "" ||
  223. url.hash != "") {
  224. throw new InvalidArgumentError(
  225. - `${host} was not of the form host[:port]`);
  226. + `${host} was not of the form [username:password@]host[:port]`);
  227. }
  228.  
  229. - return [hostname, port];
  230. + return [hostname, port, login];
  231. }
  232.  
  233. let p = new session.Proxy();
  234. if (typeof json == "undefined" || json === null) {
  235. return p;
  236. }
  237.  
  238. assert.object(json, pprint`Expected "proxy" to be an object, got ${json}`);
  239. @@ -275,23 +299,23 @@ session.Proxy = class {
  240. case "pac":
  241. p.proxyAutoconfigUrl = assert.string(json.proxyAutoconfigUrl,
  242. `Expected "proxyAutoconfigUrl" to be a string, ` +
  243. pprint`got ${json.proxyAutoconfigUrl}`);
  244. break;
  245.  
  246. case "manual":
  247. if (typeof json.ftpProxy != "undefined") {
  248. - [p.ftpProxy, p.ftpProxyPort] = fromHost("ftp", json.ftpProxy);
  249. + [p.ftpProxy, p.ftpProxyPort, p.ftpLogin] = fromHost("ftp", json.ftpProxy);
  250. }
  251. if (typeof json.httpProxy != "undefined") {
  252. - [p.httpProxy, p.httpProxyPort] = fromHost("http", json.httpProxy);
  253. + [p.httpProxy, p.httpProxyPort, p.httpLogin] = fromHost("http", json.httpProxy);
  254. }
  255. if (typeof json.sslProxy != "undefined") {
  256. - [p.sslProxy, p.sslProxyPort] = fromHost("https", json.sslProxy);
  257. + [p.sslProxy, p.sslProxyPort, p.sslLogin] = fromHost("https", json.sslProxy);
  258. }
  259. if (typeof json.socksProxy != "undefined") {
  260. [p.socksProxy, p.socksProxyPort] = fromHost("socks", json.socksProxy);
  261. p.socksVersion = assert.positiveInteger(json.socksVersion);
  262. }
  263. if (typeof json.noProxy != "undefined") {
  264. let entries = assert.array(json.noProxy,
  265. pprint`Expected "noProxy" to be an array, got ${json.noProxy}`);
  266. @@ -324,17 +348,22 @@ session.Proxy = class {
  267. if (!hostname) {
  268. return null;
  269. }
  270.  
  271. // Add brackets around IPv6 addresses
  272. hostname = addBracketsToIpv6Hostname(hostname);
  273.  
  274. if (port != null) {
  275. - return `${hostname}:${port}`;
  276. + hostname = `${hostname}:${port}`;
  277. + }
  278. +
  279. + const logins = Services.logins.findLogins({}, `moz-proxy://${hostname}`, null, "Squid proxy-caching web server", {});
  280. + if (logins.length) {
  281. + hostname = `${logins[0].username}:${logins[0].password}@${hostname}`;
  282. }
  283.  
  284. return hostname;
  285. }
  286.  
  287. let excludes = this.noProxy;
  288. if (excludes) {
  289. excludes = excludes.map(addBracketsToIpv6Hostname);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement