131 self.serversCertificatesTree.indexOfTopLevelItem(parent)) |
133 self.serversCertificatesTree.indexOfTopLevelItem(parent)) |
132 |
134 |
133 # delete the certificate from the user certificate store |
135 # delete the certificate from the user certificate store |
134 certificateDict = Preferences.toDict( |
136 certificateDict = Preferences.toDict( |
135 Preferences.Prefs.settings.value("Help/CaCertificatesDict")) |
137 Preferences.Prefs.settings.value("Help/CaCertificatesDict")) |
136 del certificateDict[server] |
138 if server in certificateDict: |
|
139 certs = QSslCertificate.fromData(certificateDict[server]) |
|
140 if cert in certs: |
|
141 certs.remove(cert) |
|
142 if certs: |
|
143 pems = QByteArray() |
|
144 for cert in certs: |
|
145 pems.append(cert.toPem() + '\n') |
|
146 certificateDict[server] = pems |
|
147 else: |
|
148 del certificateDict[server] |
137 Preferences.Prefs.settings.setValue("Help/CaCertificatesDict", |
149 Preferences.Prefs.settings.setValue("Help/CaCertificatesDict", |
138 certificateDict) |
150 certificateDict) |
139 |
151 |
140 # delete the certificate from the default certificates |
152 # delete the certificate from the default certificates |
141 caNew = [] |
153 self.__updateDefaultConfiguration() |
142 for topLevelIndex in range(self.serversCertificatesTree.topLevelItemCount()): |
154 |
143 parent = self.serversCertificatesTree.topLevelItem(topLevelIndex) |
155 @pyqtSlot() |
144 for childIndex in range(parent.childCount()): |
156 def on_serversImportButton_clicked(self): |
145 cert = parent.child(childIndex).data(0, self.CertRole) |
157 """ |
146 if cert not in caNew: |
158 Private slot to import server certificates. |
147 caNew.append(cert) |
159 """ |
|
160 certs = self.__importCertificate() |
|
161 if certs: |
|
162 server = "*" |
|
163 certificateDict = Preferences.toDict( |
|
164 Preferences.Prefs.settings.value("Help/CaCertificatesDict")) |
|
165 if server in certificateDict: |
|
166 sCerts = QSslCertificate.fromData(certificateDict[server]) |
|
167 else: |
|
168 sCerts = [] |
|
169 |
|
170 pems = QByteArray() |
|
171 for cert in certs: |
|
172 if cert in sCerts: |
|
173 E5MessageBox.warning(self, |
|
174 self.trUtf8("Import Certificate"), |
|
175 self.trUtf8("""<p>The certificate <b>{0}</b> already exists.""" |
|
176 """ Skipping.</p>""") |
|
177 .format(Utilities.decodeString( |
|
178 cert.subjectInfo(QSslCertificate.CommonName)))) |
|
179 else: |
|
180 pems.append(cert.toPem() + '\n') |
|
181 if server not in certificateDict: |
|
182 certificateDict[server] = QByteArray() |
|
183 certificateDict[server].append(pems) |
|
184 Preferences.Prefs.settings.setValue("Help/CaCertificatesDict", |
|
185 certificateDict) |
|
186 |
|
187 self.serversCertificatesTree.clear() |
|
188 self.__populateServerCertificatesTree() |
|
189 |
|
190 self.__updateDefaultConfiguration() |
|
191 |
|
192 @pyqtSlot() |
|
193 def on_serversExportButton_clicked(self): |
|
194 """ |
|
195 Private slot to export the selected server certificate. |
|
196 """ |
|
197 cert = self.serversCertificatesTree.currentItem().data(0, self.CertRole) |
|
198 fname = self.serversCertificatesTree.currentItem().text(0)\ |
|
199 .replace(" ", "").replace("\t", "") |
|
200 self.__exportCertificate(fname, cert) |
|
201 |
|
202 def __updateDefaultConfiguration(self): |
|
203 """ |
|
204 Private method to update the default SSL configuration. |
|
205 """ |
|
206 caList = self.__getSystemCaCertificates() |
|
207 certificateDict = Preferences.toDict( |
|
208 Preferences.Prefs.settings.value("Help/CaCertificatesDict")) |
|
209 for server in certificateDict: |
|
210 for cert in QSslCertificate.fromData(certificateDict[server]): |
|
211 if cert not in caList: |
|
212 caList.append(cert) |
|
213 sslCfg = QSslConfiguration.defaultConfiguration() |
|
214 sslCfg.setCaCertificates(caList) |
|
215 QSslConfiguration.setDefaultConfiguration(sslCfg) |
|
216 |
|
217 def __getSystemCaCertificates(self): |
|
218 """ |
|
219 Private method to get the list of system certificates. |
|
220 |
|
221 @return list of system certificates (list of QSslCertificate) |
|
222 """ |
|
223 caList = QSslCertificate.fromData(Preferences.toByteArray( |
|
224 Preferences.Prefs.settings.value("Help/SystemCertificates"))) |
|
225 if not caList: |
148 caList = QSslSocket.systemCaCertificates() |
226 caList = QSslSocket.systemCaCertificates() |
149 caList.extend(caNew) |
227 return caList |
150 sslCfg = QSslConfiguration.defaultConfiguration() |
|
151 sslCfg.setCaCertificates(caList) |
|
152 QSslConfiguration.setDefaultConfiguration(sslCfg) |
|
153 |
228 |
154 def __populateCaCertificatesTree(self): |
229 def __populateCaCertificatesTree(self): |
155 """ |
230 """ |
156 Private slot to populate the CA certificates tree. |
231 Private slot to populate the CA certificates tree. |
157 """ |
232 """ |
158 for cert in QSslSocket.systemCaCertificates(): |
233 for cert in self.__getSystemCaCertificates(): |
159 self.__createCaCertificateEntry(cert) |
234 self.__createCaCertificateEntry(cert) |
160 |
235 |
161 self.caCertificatesTree.expandAll() |
236 self.caCertificatesTree.expandAll() |
162 for i in range(self.caCertificatesTree.columnCount()): |
237 for i in range(self.caCertificatesTree.columnCount()): |
163 self.caCertificatesTree.resizeColumnToContents(i) |
238 self.caCertificatesTree.resizeColumnToContents(i) |
200 @param current new current item (QTreeWidgetItem) |
275 @param current new current item (QTreeWidgetItem) |
201 @param previous previous current item (QTreeWidgetItem) |
276 @param previous previous current item (QTreeWidgetItem) |
202 """ |
277 """ |
203 enable = current is not None and current.parent() is not None |
278 enable = current is not None and current.parent() is not None |
204 self.caViewButton.setEnabled(enable) |
279 self.caViewButton.setEnabled(enable) |
|
280 self.caDeleteButton.setEnabled(enable) |
|
281 self.caExportButton.setEnabled(enable) |
205 |
282 |
206 @pyqtSlot() |
283 @pyqtSlot() |
207 def on_caViewButton_clicked(self): |
284 def on_caViewButton_clicked(self): |
208 """ |
285 """ |
209 Private slot to show data of the selected CA certificate. |
286 Private slot to show data of the selected CA certificate. |
210 """ |
287 """ |
211 cert = self.caCertificatesTree.currentItem().data(0, self.CertRole) |
288 cert = self.caCertificatesTree.currentItem().data(0, self.CertRole) |
212 dlg = SslInfoDialog(cert, self) |
289 dlg = SslInfoDialog(cert, self) |
213 dlg.exec_() |
290 dlg.exec_() |
|
291 |
|
292 @pyqtSlot() |
|
293 def on_caDeleteButton_clicked(self): |
|
294 """ |
|
295 Private slot to delete the selected CA certificate. |
|
296 """ |
|
297 itm = self.caCertificatesTree.currentItem() |
|
298 res = E5MessageBox.yesNo(self, |
|
299 self.trUtf8("Delete CA Certificate"), |
|
300 self.trUtf8("""<p>Shall the CA certificate really be deleted?</p>""" |
|
301 """<p>{0}</p>""" |
|
302 """<p>If the CA certificate is deleted, the browser""" |
|
303 """ will not trust any certificate issued by this CA.</p>""")\ |
|
304 .format(itm.text(0))) |
|
305 if res: |
|
306 cert = self.caCertificatesTree.currentItem().data(0, self.CertRole) |
|
307 |
|
308 # delete the selected entry and it's parent entry, if it was the only one |
|
309 parent = itm.parent() |
|
310 parent.takeChild(parent.indexOfChild(itm)) |
|
311 if parent.childCount() == 0: |
|
312 self.caCertificatesTree.takeTopLevelItem( |
|
313 self.caCertificatesTree.indexOfTopLevelItem(parent)) |
|
314 |
|
315 # delete the certificate from the CA certificate store |
|
316 caCerts = self.__getSystemCaCertificates() |
|
317 if cert in caCerts: |
|
318 caCerts.remove(cert) |
|
319 pems = QByteArray() |
|
320 for cert in caCerts: |
|
321 pems.append(cert.toPem() + '\n') |
|
322 Preferences.Prefs.settings.setValue("Help/SystemCertificates", pems) |
|
323 |
|
324 # delete the certificate from the default certificates |
|
325 self.__updateDefaultConfiguration() |
|
326 |
|
327 @pyqtSlot() |
|
328 def on_caImportButton_clicked(self): |
|
329 """ |
|
330 Private slot to import server certificates. |
|
331 """ |
|
332 certs = self.__importCertificate() |
|
333 if certs: |
|
334 caCerts = self.__getSystemCaCertificates() |
|
335 for cert in certs: |
|
336 if cert in caCerts: |
|
337 E5MessageBox.warning(self, |
|
338 self.trUtf8("Import Certificate"), |
|
339 self.trUtf8("""<p>The certificate <b>{0}</b> already exists.""" |
|
340 """ Skipping.</p>""") |
|
341 .format(Utilities.decodeString( |
|
342 cert.subjectInfo(QSslCertificate.CommonName)))) |
|
343 else: |
|
344 caCerts.append(cert) |
|
345 |
|
346 pems = QByteArray() |
|
347 for cert in caCerts: |
|
348 pems.append(cert.toPem() + '\n') |
|
349 Preferences.Prefs.settings.setValue("Help/SystemCertificates", pems) |
|
350 |
|
351 self.caCertificatesTree.clear() |
|
352 self.__populateCaCertificatesTree() |
|
353 |
|
354 self.__updateDefaultConfiguration() |
|
355 |
|
356 @pyqtSlot() |
|
357 def on_caExportButton_clicked(self): |
|
358 """ |
|
359 Private slot to export the selected CA certificate. |
|
360 """ |
|
361 cert = self.caCertificatesTree.currentItem().data(0, self.CertRole) |
|
362 fname = self.caCertificatesTree.currentItem().text(0)\ |
|
363 .replace(" ", "").replace("\t", "") |
|
364 self.__exportCertificate(fname, cert) |
|
365 |
|
366 def __exportCertificate(self, name, cert): |
|
367 """ |
|
368 Private slot to export a certificate. |
|
369 |
|
370 @param name default file name without extension (string) |
|
371 @param cert certificate to be exported (QSslCertificate) |
|
372 """ |
|
373 if cert is not None: |
|
374 fname, selectedFilter = QFileDialog.getSaveFileNameAndFilter( |
|
375 self, |
|
376 self.trUtf8("Export Certificate"), |
|
377 name, |
|
378 self.trUtf8("Certificate File (PEM) (*.pem);;" |
|
379 "Certificate File (DER) (*.der)"), |
|
380 None, |
|
381 QFileDialog.Options(QFileDialog.DontConfirmOverwrite)) |
|
382 |
|
383 if fname: |
|
384 ext = QFileInfo(fname).suffix() |
|
385 if not ext or ext not in ["pem", "der"]: |
|
386 ex = selectedFilter.split("(*")[1].split(")")[0] |
|
387 if ex: |
|
388 fname += ex |
|
389 if QFileInfo(fname).exists(): |
|
390 res = E5MessageBox.yesNo(self, |
|
391 self.trUtf8("Export Certificate"), |
|
392 self.trUtf8("<p>The file <b>{0}</b> already exists." |
|
393 " Overwrite it?</p>").format(fname), |
|
394 icon = E5MessageBox.Warning) |
|
395 if not res: |
|
396 return |
|
397 |
|
398 f = QFile(fname) |
|
399 if not f.open(QIODevice.WriteOnly): |
|
400 E5MessageBox.critical(self, |
|
401 self.trUtf8("Export Certificate"), |
|
402 self.trUtf8("""<p>The certificate could not be written to file""" |
|
403 """ <b>{0}</b></p><p>Error: {1}</p>""") |
|
404 .format(fname, f.errorString())) |
|
405 return |
|
406 |
|
407 if fname.endswith(".pem"): |
|
408 crt = cert.toPem() |
|
409 else: |
|
410 crt = cert.toDer() |
|
411 f.write(crt) |
|
412 f.close() |
|
413 |
|
414 def __importCertificate(self): |
|
415 """ |
|
416 Private method to read a certificate. |
|
417 |
|
418 @return certificates read (list of QSslCertificate) |
|
419 """ |
|
420 fname, selectedFilter = QFileDialog.getOpenFileNameAndFilter( |
|
421 self, |
|
422 self.trUtf8("Import Certificate"), |
|
423 "", |
|
424 self.trUtf8("Certificate Files (*.pem *.crt *.der *.cer *.ca);;" |
|
425 "All Files (*)"), |
|
426 None) |
|
427 |
|
428 if fname: |
|
429 f = QFile(fname) |
|
430 if not f.open(QIODevice.ReadOnly): |
|
431 E5MessageBox.critical(self, |
|
432 self.trUtf8("Export Certificate"), |
|
433 self.trUtf8("""<p>The certificate could not be read from file""" |
|
434 """ <b>{0}</b></p><p>Error: {1}</p>""") |
|
435 .format(fname, f.errorString())) |
|
436 return [] |
|
437 |
|
438 crt = f.readAll() |
|
439 f.close() |
|
440 cert = QSslCertificate.fromData(crt, QSsl.Pem) |
|
441 if not cert: |
|
442 cert = QSslCertificate.fromData(crt, QSsl.Der) |
|
443 ## if fname.endswith((".pem", ".crt")): |
|
444 ## cert = QSslCertificate.fromData(crt, QSsl.Pem) |
|
445 ## elif fname.endswith((".der", ".cer", ".ca")): |
|
446 ## cert = QSslCertificate.fromData(crt, QSsl.Der) |
|
447 |
|
448 return cert |
|
449 |
|
450 return [] |