|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 const nsIX509Cert = Components.interfaces.nsIX509Cert; |
|
6 const nsIX509Cert3 = Components.interfaces.nsIX509Cert3; |
|
7 const nsX509CertDB = "@mozilla.org/security/x509certdb;1"; |
|
8 const nsIX509CertDB = Components.interfaces.nsIX509CertDB; |
|
9 const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1"; |
|
10 const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB; |
|
11 const nsIPKIParamBlock = Components.interfaces.nsIPKIParamBlock; |
|
12 const nsIASN1Object = Components.interfaces.nsIASN1Object; |
|
13 const nsIASN1Sequence = Components.interfaces.nsIASN1Sequence; |
|
14 const nsIASN1PrintableItem = Components.interfaces.nsIASN1PrintableItem; |
|
15 const nsIASN1Tree = Components.interfaces.nsIASN1Tree; |
|
16 const nsASN1Tree = "@mozilla.org/security/nsASN1Tree;1" |
|
17 |
|
18 var bundle; |
|
19 |
|
20 function doPrompt(msg) |
|
21 { |
|
22 let prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]. |
|
23 getService(Components.interfaces.nsIPromptService); |
|
24 prompts.alert(window, null, msg); |
|
25 } |
|
26 |
|
27 function AddCertChain(node, chain, idPrefix) |
|
28 { |
|
29 var idfier = idPrefix+"chain_"; |
|
30 var child = document.getElementById(node); |
|
31 var numCerts = chain.length; |
|
32 var currCert; |
|
33 var displayVal; |
|
34 var addTwistie; |
|
35 for (var i=numCerts-1; i>=0; i--) { |
|
36 currCert = chain.queryElementAt(i, nsIX509Cert); |
|
37 if (currCert.commonName) { |
|
38 displayVal = currCert.commonName; |
|
39 } else { |
|
40 displayVal = currCert.windowTitle; |
|
41 } |
|
42 if (0 == i) { |
|
43 addTwistie = false; |
|
44 } else { |
|
45 addTwistie = true; |
|
46 } |
|
47 child = addChildrenToTree(child, displayVal, currCert.dbKey,addTwistie); |
|
48 } |
|
49 } |
|
50 |
|
51 function AddUsage(usage,verifyInfoBox) |
|
52 { |
|
53 var text = document.createElement("textbox"); |
|
54 text.setAttribute("value", usage); |
|
55 text.setAttribute("style", "margin: 2px 5px"); |
|
56 text.setAttribute("readonly", "true"); |
|
57 text.setAttribute("class", "scrollfield"); |
|
58 verifyInfoBox.appendChild(text); |
|
59 } |
|
60 |
|
61 function setWindowName() |
|
62 { |
|
63 // Get the cert from the cert database |
|
64 var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB); |
|
65 var myName = self.name; |
|
66 bundle = document.getElementById("pippki_bundle"); |
|
67 var cert; |
|
68 |
|
69 var certDetails = bundle.getString('certDetails'); |
|
70 if (myName != "") { |
|
71 document.title = certDetails + '"' + myName + '"'; // XXX l10n? |
|
72 // Get the token |
|
73 // XXX ignore this for now. NSS will find the cert on a token |
|
74 // by "tokenname:certname", which is what we have. |
|
75 //var tokenName = ""; |
|
76 //var pk11db = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB); |
|
77 //var token = pk11db.findTokenByName(tokenName); |
|
78 |
|
79 //var cert = certdb.findCertByNickname(token, myName); |
|
80 cert = certdb.findCertByNickname(null, myName); |
|
81 } else { |
|
82 var pkiParams = window.arguments[0].QueryInterface(nsIPKIParamBlock); |
|
83 var isupport = pkiParams.getISupportAtIndex(1); |
|
84 cert = isupport.QueryInterface(nsIX509Cert); |
|
85 document.title = certDetails + '"' + cert.windowTitle + '"'; // XXX l10n? |
|
86 } |
|
87 |
|
88 // |
|
89 // Set the cert attributes for viewing |
|
90 // |
|
91 |
|
92 // The chain of trust |
|
93 var chain = cert.getChain(); |
|
94 AddCertChain("treesetDump", chain, "dump_"); |
|
95 DisplayGeneralDataFromCert(cert); |
|
96 BuildPrettyPrint(cert); |
|
97 |
|
98 if (cert instanceof nsIX509Cert3) |
|
99 { |
|
100 cert.requestUsagesArrayAsync(new listener()); |
|
101 } |
|
102 } |
|
103 |
|
104 |
|
105 function addChildrenToTree(parentTree,label,value,addTwistie) |
|
106 { |
|
107 var treeChild1 = document.createElement("treechildren"); |
|
108 var treeElement = addTreeItemToTreeChild(treeChild1,label,value,addTwistie); |
|
109 parentTree.appendChild(treeChild1); |
|
110 return treeElement; |
|
111 } |
|
112 |
|
113 function addTreeItemToTreeChild(treeChild,label,value,addTwistie) |
|
114 { |
|
115 var treeElem1 = document.createElement("treeitem"); |
|
116 if (addTwistie) { |
|
117 treeElem1.setAttribute("container","true"); |
|
118 treeElem1.setAttribute("open","true"); |
|
119 } |
|
120 var treeRow = document.createElement("treerow"); |
|
121 var treeCell = document.createElement("treecell"); |
|
122 treeCell.setAttribute("label",label); |
|
123 if (value) |
|
124 treeCell.setAttribute("display",value); |
|
125 treeRow.appendChild(treeCell); |
|
126 treeElem1.appendChild(treeRow); |
|
127 treeChild.appendChild(treeElem1); |
|
128 return treeElem1; |
|
129 } |
|
130 |
|
131 function displaySelected() { |
|
132 var asn1Tree = document.getElementById('prettyDumpTree'). |
|
133 treeBoxObject.view.QueryInterface(nsIASN1Tree); |
|
134 var items = asn1Tree.selection; |
|
135 var certDumpVal = document.getElementById('certDumpVal'); |
|
136 if (items.currentIndex != -1) { |
|
137 var value = asn1Tree.getDisplayData(items.currentIndex); |
|
138 certDumpVal.value = value; |
|
139 } else { |
|
140 certDumpVal.value =""; |
|
141 } |
|
142 } |
|
143 |
|
144 function BuildPrettyPrint(cert) |
|
145 { |
|
146 var certDumpTree = Components.classes[nsASN1Tree]. |
|
147 createInstance(nsIASN1Tree); |
|
148 certDumpTree.loadASN1Structure(cert.ASN1Structure); |
|
149 document.getElementById('prettyDumpTree'). |
|
150 treeBoxObject.view = certDumpTree; |
|
151 } |
|
152 |
|
153 function addAttributeFromCert(nodeName, value) |
|
154 { |
|
155 var node = document.getElementById(nodeName); |
|
156 if (!value) { |
|
157 value = bundle.getString('notPresent'); |
|
158 } |
|
159 node.setAttribute('value', value); |
|
160 } |
|
161 |
|
162 |
|
163 |
|
164 function listener() { |
|
165 } |
|
166 |
|
167 listener.prototype.QueryInterface = |
|
168 function(iid) { |
|
169 if (iid.equals(Components.interfaces.nsISupports) || |
|
170 iid.equals(Components.interfaces.nsICertVerificationListener)) |
|
171 return this; |
|
172 |
|
173 throw Components.results.NS_ERROR_NO_INTERFACE; |
|
174 } |
|
175 |
|
176 listener.prototype.notify = |
|
177 function(cert, result) { |
|
178 DisplayVerificationData(cert, result); |
|
179 } |
|
180 |
|
181 function DisplayVerificationData(cert, result) |
|
182 { |
|
183 document.getElementById("verify_pending").setAttribute("hidden", "true"); |
|
184 |
|
185 if (!result || !cert) |
|
186 return; // no results could be produced |
|
187 |
|
188 if (!(cert instanceof Components.interfaces.nsIX509Cert)) |
|
189 return; |
|
190 |
|
191 // Verification and usage |
|
192 var verifystr = ""; |
|
193 var o1 = {}; |
|
194 var o2 = {}; |
|
195 var o3 = {}; |
|
196 |
|
197 if (!(result instanceof Components.interfaces.nsICertVerificationResult)) |
|
198 return; |
|
199 |
|
200 result.getUsagesArrayResult(o1, o2, o3); |
|
201 |
|
202 var verifystate = o1.value; |
|
203 var count = o2.value; |
|
204 var usageList = o3.value; |
|
205 if (verifystate == cert.VERIFIED_OK) { |
|
206 verifystr = bundle.getString('certVerified'); |
|
207 } else if (verifystate == cert.CERT_REVOKED) { |
|
208 verifystr = bundle.getString('certNotVerified_CertRevoked'); |
|
209 } else if (verifystate == cert.CERT_EXPIRED) { |
|
210 verifystr = bundle.getString('certNotVerified_CertExpired'); |
|
211 } else if (verifystate == cert.CERT_NOT_TRUSTED) { |
|
212 verifystr = bundle.getString('certNotVerified_CertNotTrusted'); |
|
213 } else if (verifystate == cert.ISSUER_NOT_TRUSTED) { |
|
214 verifystr = bundle.getString('certNotVerified_IssuerNotTrusted'); |
|
215 } else if (verifystate == cert.ISSUER_UNKNOWN) { |
|
216 verifystr = bundle.getString('certNotVerified_IssuerUnknown'); |
|
217 } else if (verifystate == cert.INVALID_CA) { |
|
218 verifystr = bundle.getString('certNotVerified_CAInvalid'); |
|
219 } else if (verifystate == cert.SIGNATURE_ALGORITHM_DISABLED) { |
|
220 verifystr = bundle.getString('certNotVerified_AlgorithmDisabled'); |
|
221 } else { /* if (verifystate == cert.NOT_VERIFIED_UNKNOWN || == USAGE_NOT_ALLOWED) */ |
|
222 verifystr = bundle.getString('certNotVerified_Unknown'); |
|
223 } |
|
224 var verified=document.getElementById('verified'); |
|
225 verified.textContent = verifystr; |
|
226 if (count > 0) { |
|
227 var verifyInfoBox = document.getElementById('verify_info_box'); |
|
228 for (var i=0; i<count; i++) { |
|
229 AddUsage(usageList[i],verifyInfoBox); |
|
230 } |
|
231 } |
|
232 } |
|
233 |
|
234 function DisplayGeneralDataFromCert(cert) |
|
235 { |
|
236 // Common Name |
|
237 addAttributeFromCert('commonname', cert.commonName); |
|
238 // Organization |
|
239 addAttributeFromCert('organization', cert.organization); |
|
240 // Organizational Unit |
|
241 addAttributeFromCert('orgunit', cert.organizationalUnit); |
|
242 // Serial Number |
|
243 addAttributeFromCert('serialnumber',cert.serialNumber); |
|
244 // SHA1 Fingerprint |
|
245 addAttributeFromCert('sha1fingerprint',cert.sha1Fingerprint); |
|
246 // MD5 Fingerprint |
|
247 addAttributeFromCert('md5fingerprint',cert.md5Fingerprint); |
|
248 // Validity start |
|
249 addAttributeFromCert('validitystart', cert.validity.notBeforeLocalDay); |
|
250 // Validity end |
|
251 addAttributeFromCert('validityend', cert.validity.notAfterLocalDay); |
|
252 |
|
253 //Now to populate the fields that correspond to the issuer. |
|
254 var issuerCommonname, issuerOrg, issuerOrgUnit; |
|
255 issuerCommonname = cert.issuerCommonName; |
|
256 issuerOrg = cert.issuerOrganization; |
|
257 issuerOrgUnit = cert.issuerOrganizationUnit; |
|
258 addAttributeFromCert('issuercommonname', issuerCommonname); |
|
259 addAttributeFromCert('issuerorganization', issuerOrg); |
|
260 addAttributeFromCert('issuerorgunit', issuerOrgUnit); |
|
261 } |
|
262 |
|
263 function updateCertDump() |
|
264 { |
|
265 var asn1Tree = document.getElementById('prettyDumpTree'). |
|
266 treeBoxObject.view.QueryInterface(nsIASN1Tree); |
|
267 |
|
268 var tree = document.getElementById('treesetDump'); |
|
269 if (tree.currentIndex < 0) { |
|
270 doPrompt("No items are selected."); //This should never happen. |
|
271 } else { |
|
272 var item = tree.contentView.getItemAtIndex(tree.currentIndex); |
|
273 var dbKey = item.firstChild.firstChild.getAttribute('display'); |
|
274 // Get the cert from the cert database |
|
275 var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB); |
|
276 var cert = certdb.findCertByDBKey(dbKey,null); |
|
277 asn1Tree.loadASN1Structure(cert.ASN1Structure); |
|
278 } |
|
279 displaySelected(); |
|
280 } |
|
281 |
|
282 function getCurrentCert() |
|
283 { |
|
284 var realIndex; |
|
285 var tree = document.getElementById('treesetDump'); |
|
286 if (tree.view.selection.isSelected(tree.currentIndex) |
|
287 && document.getElementById('prettyprint_tab').selected) { |
|
288 /* if the user manually selected a cert on the Details tab, |
|
289 then take that one */ |
|
290 realIndex = tree.currentIndex; |
|
291 } else { |
|
292 /* otherwise, take the one at the bottom of the chain |
|
293 (i.e. the one of the end-entity, unless we're displaying |
|
294 CA certs) */ |
|
295 realIndex = tree.view.rowCount - 1; |
|
296 } |
|
297 if (realIndex >= 0) { |
|
298 var item = tree.contentView.getItemAtIndex(realIndex); |
|
299 var dbKey = item.firstChild.firstChild.getAttribute('display'); |
|
300 var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB); |
|
301 var cert = certdb.findCertByDBKey(dbKey,null); |
|
302 return cert; |
|
303 } |
|
304 /* shouldn't really happen */ |
|
305 return null; |
|
306 } |