|
1 <?xml version="1.0" encoding="UTF-8"?> |
|
2 |
|
3 <!DOCTYPE html [ |
|
4 <!ENTITY % htmlDTD |
|
5 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
|
6 "DTD/xhtml1-strict.dtd"> |
|
7 %htmlDTD; |
|
8 <!ENTITY % globalDTD |
|
9 SYSTEM "chrome://global/locale/global.dtd"> |
|
10 %globalDTD; |
|
11 <!ENTITY % certerrorDTD |
|
12 SYSTEM "chrome://browser/locale/aboutCertError.dtd"> |
|
13 %certerrorDTD; |
|
14 ]> |
|
15 |
|
16 <!-- This Source Code Form is subject to the terms of the Mozilla Public |
|
17 - License, v. 2.0. If a copy of the MPL was not distributed with this |
|
18 - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
|
19 <html xmlns="http://www.w3.org/1999/xhtml"> |
|
20 <head> |
|
21 <title>&certerror.pagetitle;</title> |
|
22 <meta name="viewport" content="width=device-width; user-scalable=false" /> |
|
23 <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" /> |
|
24 <!-- This page currently uses the same favicon as neterror.xhtml. |
|
25 If the location of the favicon is changed for both pages, the |
|
26 FAVICON_ERRORPAGE_URL symbol in toolkit/components/places/src/nsFaviconService.h |
|
27 should be updated. If this page starts using a different favicon |
|
28 than neterrorm nsFaviconService->SetAndLoadFaviconForPage |
|
29 should be updated to ignore this one as well. --> |
|
30 <link rel="icon" type="image/png" id="favicon" sizes="64x64" href="chrome://browser/skin/images/certerror-warning.png"/> |
|
31 |
|
32 <script type="application/javascript"><![CDATA[ |
|
33 // Error url MUST be formatted like this: |
|
34 // about:certerror?e=error&u=url&d=desc |
|
35 |
|
36 // Note that this file uses document.documentURI to get |
|
37 // the URL (with the format from above). This is because |
|
38 // document.location.href gets the current URI off the docshell, |
|
39 // which is the URL displayed in the location bar, i.e. |
|
40 // the URI that the user attempted to load. |
|
41 |
|
42 function getCSSClass() |
|
43 { |
|
44 var url = document.documentURI; |
|
45 var matches = url.match(/s\=([^&]+)\&/); |
|
46 // s is optional, if no match just return nothing |
|
47 if (!matches || matches.length < 2) |
|
48 return ""; |
|
49 |
|
50 // parenthetical match is the second entry |
|
51 return decodeURIComponent(matches[1]); |
|
52 } |
|
53 |
|
54 function getDescription() |
|
55 { |
|
56 var url = document.documentURI; |
|
57 var desc = url.search(/d\=/); |
|
58 |
|
59 // desc == -1 if not found; if so, return an empty string |
|
60 // instead of what would turn out to be portions of the URI |
|
61 if (desc == -1) |
|
62 return ""; |
|
63 |
|
64 return decodeURIComponent(url.slice(desc + 2)); |
|
65 } |
|
66 |
|
67 function initPage() |
|
68 { |
|
69 // Replace the "#1" string in the intro with the hostname. Trickier |
|
70 // than it might seem since we want to preserve the <b> tags, but |
|
71 // not allow for any injection by just using innerHTML. Instead, |
|
72 // just find the right target text node. |
|
73 var intro = document.getElementById('introContentP1'); |
|
74 function replaceWithHost(node) { |
|
75 if (node.textContent == "#1") |
|
76 node.textContent = location.host; |
|
77 else |
|
78 for(var i = 0; i < node.childNodes.length; i++) |
|
79 replaceWithHost(node.childNodes[i]); |
|
80 }; |
|
81 replaceWithHost(intro); |
|
82 |
|
83 if (getCSSClass() == "expertBadCert") { |
|
84 toggle('technicalContent'); |
|
85 toggle('expertContent'); |
|
86 } |
|
87 |
|
88 // Disallow overrides if this is a Strict-Transport-Security |
|
89 // host and the cert is bad (STS Spec section 7.3) or if the |
|
90 // certerror is in a frame (bug 633691). |
|
91 if (getCSSClass() == "badStsCert" || window != top) |
|
92 document.getElementById("expertContent").setAttribute("hidden", "true"); |
|
93 |
|
94 var tech = document.getElementById("technicalContentText"); |
|
95 if (tech) |
|
96 tech.textContent = getDescription(); |
|
97 |
|
98 addDomainErrorLink(); |
|
99 } |
|
100 |
|
101 /* In the case of SSL error pages about domain mismatch, see if |
|
102 we can hyperlink the user to the correct site. We don't want |
|
103 to do this generically since it allows MitM attacks to redirect |
|
104 users to a site under attacker control, but in certain cases |
|
105 it is safe (and helpful!) to do so. Bug 402210 |
|
106 */ |
|
107 function addDomainErrorLink() { |
|
108 // Rather than textContent, we need to treat description as HTML |
|
109 var sd = document.getElementById("technicalContentText"); |
|
110 if (sd) { |
|
111 var desc = getDescription(); |
|
112 |
|
113 // sanitize description text - see bug 441169 |
|
114 |
|
115 // First, find the index of the <a> tag we care about, being careful not to |
|
116 // use an over-greedy regex |
|
117 var re = /<a id="cert_domain_link" title="([^"]+)">/; |
|
118 var result = re.exec(desc); |
|
119 if(!result) |
|
120 return; |
|
121 |
|
122 // Remove sd's existing children |
|
123 sd.textContent = ""; |
|
124 |
|
125 // Everything up to the link should be text content |
|
126 sd.appendChild(document.createTextNode(desc.slice(0, result.index))); |
|
127 |
|
128 // Now create the link itself |
|
129 var anchorEl = document.createElement("a"); |
|
130 anchorEl.setAttribute("id", "cert_domain_link"); |
|
131 anchorEl.setAttribute("title", result[1]); |
|
132 anchorEl.appendChild(document.createTextNode(result[1])); |
|
133 sd.appendChild(anchorEl); |
|
134 |
|
135 // Finally, append text for anything after the closing </a> |
|
136 sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length))); |
|
137 } |
|
138 |
|
139 var link = document.getElementById('cert_domain_link'); |
|
140 if (!link) |
|
141 return; |
|
142 |
|
143 var okHost = link.getAttribute("title"); |
|
144 var thisHost = document.location.hostname; |
|
145 var proto = document.location.protocol; |
|
146 |
|
147 // If okHost is a wildcard domain ("*.example.com") let's |
|
148 // use "www" instead. "*.example.com" isn't going to |
|
149 // get anyone anywhere useful. bug 432491 |
|
150 okHost = okHost.replace(/^\*\./, "www."); |
|
151 |
|
152 /* case #1: |
|
153 * example.com uses an invalid security certificate. |
|
154 * |
|
155 * The certificate is only valid for www.example.com |
|
156 * |
|
157 * Make sure to include the "." ahead of thisHost so that |
|
158 * a MitM attack on paypal.com doesn't hyperlink to "notpaypal.com" |
|
159 * |
|
160 * We'd normally just use a RegExp here except that we lack a |
|
161 * library function to escape them properly (bug 248062), and |
|
162 * domain names are famous for having '.' characters in them, |
|
163 * which would allow spurious and possibly hostile matches. |
|
164 */ |
|
165 if (endsWith(okHost, "." + thisHost)) |
|
166 link.href = proto + okHost; |
|
167 |
|
168 /* case #2: |
|
169 * browser.garage.maemo.org uses an invalid security certificate. |
|
170 * |
|
171 * The certificate is only valid for garage.maemo.org |
|
172 */ |
|
173 if (endsWith(thisHost, "." + okHost)) |
|
174 link.href = proto + okHost; |
|
175 |
|
176 // If we set a link, meaning there's something helpful for |
|
177 // the user here, expand the section by default |
|
178 if (link.href && getCSSClass() != "expertBadCert") |
|
179 toggle("technicalContent"); |
|
180 } |
|
181 |
|
182 function endsWith(haystack, needle) { |
|
183 return haystack.slice(-needle.length) == needle; |
|
184 } |
|
185 |
|
186 function toggle(id) { |
|
187 var el = document.getElementById(id); |
|
188 if (el.hasAttribute("collapsed")) |
|
189 el.removeAttribute("collapsed"); |
|
190 else |
|
191 el.setAttribute("collapsed", true); |
|
192 } |
|
193 ]]></script> |
|
194 </head> |
|
195 |
|
196 <body id="errorPage" class="certerror" dir="&locale.dir;"> |
|
197 |
|
198 <!-- PAGE CONTAINER (for styling purposes only) --> |
|
199 <div id="errorPageContainer"> |
|
200 |
|
201 <!-- Error Title --> |
|
202 <div id="errorTitle"> |
|
203 <h1 class="errorTitleText">&certerror.longpagetitle;</h1> |
|
204 </div> |
|
205 |
|
206 <!-- LONG CONTENT (the section most likely to require scrolling) --> |
|
207 <div id="errorLongContent"> |
|
208 <div id="introContent"> |
|
209 <p id="introContentP1">&certerror.introPara1;</p> |
|
210 </div> |
|
211 |
|
212 <div id="whatShouldIDoContent"> |
|
213 <h2>&certerror.whatShouldIDo.heading;</h2> |
|
214 <div id="whatShouldIDoContentText"> |
|
215 <p>&certerror.whatShouldIDo.content;</p> |
|
216 <button id="getMeOutOfHereButton">&certerror.getMeOutOfHere.label;</button> |
|
217 </div> |
|
218 </div> |
|
219 |
|
220 <!-- The following sections can be unhidden by default by setting the |
|
221 "browser.xul.error_pages.expert_bad_cert" pref to true --> |
|
222 <div id="technicalContent" collapsed="true"> |
|
223 <h2 class="expander" onclick="toggle('technicalContent');" id="technicalContentHeading">&certerror.technical.heading;</h2> |
|
224 <p id="technicalContentText"/> |
|
225 </div> |
|
226 |
|
227 <div id="expertContent" collapsed="true"> |
|
228 <h2 class="expander" onclick="toggle('expertContent');" id="expertContentHeading">&certerror.expert.heading;</h2> |
|
229 <div> |
|
230 <p>&certerror.expert.content;</p> |
|
231 <p>&certerror.expert.contentPara2;</p> |
|
232 <button id="temporaryExceptionButton">&certerror.addTemporaryException.label;</button> |
|
233 <button id="permanentExceptionButton">&certerror.addPermanentException.label;</button> |
|
234 </div> |
|
235 </div> |
|
236 </div> |
|
237 </div> |
|
238 |
|
239 <!-- |
|
240 - Note: It is important to run the script this way, instead of using |
|
241 - an onload handler. This is because error pages are loaded as |
|
242 - LOAD_BACKGROUND, which means that onload handlers will not be executed. |
|
243 --> |
|
244 <script type="application/javascript">initPage();</script> |
|
245 |
|
246 </body> |
|
247 </html> |