23 |
23 |
24 class EricSslErrorState(enum.Enum): |
24 class EricSslErrorState(enum.Enum): |
25 """ |
25 """ |
26 Class defining the SSL error handling states. |
26 Class defining the SSL error handling states. |
27 """ |
27 """ |
|
28 |
28 NOT_IGNORED = 0 |
29 NOT_IGNORED = 0 |
29 SYSTEM_IGNORED = 1 |
30 SYSTEM_IGNORED = 1 |
30 USER_IGNORED = 2 |
31 USER_IGNORED = 2 |
31 |
32 |
32 |
33 |
33 class EricSslErrorHandler(QObject): |
34 class EricSslErrorHandler(QObject): |
34 """ |
35 """ |
35 Class implementing a handler for SSL errors. |
36 Class implementing a handler for SSL errors. |
36 |
37 |
37 It also initializes the default SSL configuration with certificates |
38 It also initializes the default SSL configuration with certificates |
38 permanently accepted by the user already. |
39 permanently accepted by the user already. |
39 """ |
40 """ |
|
41 |
40 def __init__(self, parent=None): |
42 def __init__(self, parent=None): |
41 """ |
43 """ |
42 Constructor |
44 Constructor |
43 |
45 |
44 @param parent reference to the parent object (QObject) |
46 @param parent reference to the parent object (QObject) |
45 """ |
47 """ |
46 super().__init__(parent) |
48 super().__init__(parent) |
47 |
49 |
48 caList = self.__getSystemCaCertificates() |
50 caList = self.__getSystemCaCertificates() |
49 if Preferences.getSettings().contains("Help/CaCertificatesDict"): |
51 if Preferences.getSettings().contains("Help/CaCertificatesDict"): |
50 # port old entries stored under 'Help' |
52 # port old entries stored under 'Help' |
51 certificateDict = Globals.toDict( |
53 certificateDict = Globals.toDict( |
52 Preferences.getSettings().value("Help/CaCertificatesDict")) |
54 Preferences.getSettings().value("Help/CaCertificatesDict") |
|
55 ) |
53 Preferences.getSettings().setValue( |
56 Preferences.getSettings().setValue( |
54 "Ssl/CaCertificatesDict", certificateDict) |
57 "Ssl/CaCertificatesDict", certificateDict |
|
58 ) |
55 Preferences.getSettings().remove("Help/CaCertificatesDict") |
59 Preferences.getSettings().remove("Help/CaCertificatesDict") |
56 else: |
60 else: |
57 certificateDict = Globals.toDict( |
61 certificateDict = Globals.toDict( |
58 Preferences.getSettings().value("Ssl/CaCertificatesDict")) |
62 Preferences.getSettings().value("Ssl/CaCertificatesDict") |
|
63 ) |
59 for server in certificateDict: |
64 for server in certificateDict: |
60 for cert in QSslCertificate.fromData(certificateDict[server]): |
65 for cert in QSslCertificate.fromData(certificateDict[server]): |
61 if cert not in caList: |
66 if cert not in caList: |
62 caList.append(cert) |
67 caList.append(cert) |
63 sslCfg = QSslConfiguration.defaultConfiguration() |
68 sslCfg = QSslConfiguration.defaultConfiguration() |
64 sslCfg.setCaCertificates(caList) |
69 sslCfg.setCaCertificates(caList) |
65 try: |
70 try: |
66 sslProtocol = QSsl.SslProtocol.TlsV1_1OrLater |
71 sslProtocol = QSsl.SslProtocol.TlsV1_1OrLater |
67 if Globals.isWindowsPlatform() and platform.win32_ver()[0] == '7': |
72 if Globals.isWindowsPlatform() and platform.win32_ver()[0] == "7": |
68 sslProtocol = QSsl.SslProtocol.SecureProtocols |
73 sslProtocol = QSsl.SslProtocol.SecureProtocols |
69 except AttributeError: |
74 except AttributeError: |
70 sslProtocol = QSsl.SslProtocol.SecureProtocols |
75 sslProtocol = QSsl.SslProtocol.SecureProtocols |
71 sslCfg.setProtocol(sslProtocol) |
76 sslCfg.setProtocol(sslProtocol) |
72 with contextlib.suppress(AttributeError): |
77 with contextlib.suppress(AttributeError): |
73 sslCfg.setSslOption(QSsl.SslOption.SslOptionDisableCompression, |
78 sslCfg.setSslOption(QSsl.SslOption.SslOptionDisableCompression, True) |
74 True) |
|
75 QSslConfiguration.setDefaultConfiguration(sslCfg) |
79 QSslConfiguration.setDefaultConfiguration(sslCfg) |
76 |
80 |
77 def sslErrorsReplySlot(self, reply, errors): |
81 def sslErrorsReplySlot(self, reply, errors): |
78 """ |
82 """ |
79 Public slot to handle SSL errors for a network reply. |
83 Public slot to handle SSL errors for a network reply. |
80 |
84 |
81 @param reply reference to the reply object (QNetworkReply) |
85 @param reply reference to the reply object (QNetworkReply) |
82 @param errors list of SSL errors (list of QSslError) |
86 @param errors list of SSL errors (list of QSslError) |
83 """ |
87 """ |
84 self.sslErrorsReply(reply, errors) |
88 self.sslErrorsReply(reply, errors) |
85 |
89 |
86 def sslErrorsReply(self, reply, errors): |
90 def sslErrorsReply(self, reply, errors): |
87 """ |
91 """ |
88 Public slot to handle SSL errors for a network reply. |
92 Public slot to handle SSL errors for a network reply. |
89 |
93 |
90 @param reply reference to the reply object (QNetworkReply) |
94 @param reply reference to the reply object (QNetworkReply) |
91 @param errors list of SSL errors (list of QSslError) |
95 @param errors list of SSL errors (list of QSslError) |
92 @return tuple indicating to ignore the SSL errors (one of NotIgnored, |
96 @return tuple indicating to ignore the SSL errors (one of NotIgnored, |
93 SystemIgnored or UserIgnored) and indicating a change of the |
97 SystemIgnored or UserIgnored) and indicating a change of the |
94 default SSL configuration (boolean) |
98 default SSL configuration (boolean) |
95 """ |
99 """ |
96 url = reply.url() |
100 url = reply.url() |
97 ignore, defaultChanged = self.sslErrors(errors, url.host(), url.port()) |
101 ignore, defaultChanged = self.sslErrors(errors, url.host(), url.port()) |
98 if ignore: |
102 if ignore: |
99 if defaultChanged: |
103 if defaultChanged: |
100 reply.setSslConfiguration( |
104 reply.setSslConfiguration(QSslConfiguration.defaultConfiguration()) |
101 QSslConfiguration.defaultConfiguration()) |
|
102 reply.ignoreSslErrors() |
105 reply.ignoreSslErrors() |
103 else: |
106 else: |
104 reply.abort() |
107 reply.abort() |
105 |
108 |
106 return ignore, defaultChanged |
109 return ignore, defaultChanged |
107 |
110 |
108 def sslErrors(self, errors, server, port=-1): |
111 def sslErrors(self, errors, server, port=-1): |
109 """ |
112 """ |
110 Public method to handle SSL errors. |
113 Public method to handle SSL errors. |
111 |
114 |
112 @param errors list of SSL errors |
115 @param errors list of SSL errors |
113 @type list of QSslError |
116 @type list of QSslError |
114 @param server name of the server |
117 @param server name of the server |
115 @type str |
118 @type str |
116 @param port value of the port |
119 @param port value of the port |
183 sslCfg.setProtocol(QSsl.SslProtocol.TlsV1_1OrLater) |
189 sslCfg.setProtocol(QSsl.SslProtocol.TlsV1_1OrLater) |
184 except AttributeError: |
190 except AttributeError: |
185 sslCfg.setProtocol(QSsl.SslProtocol.SecureProtocols) |
191 sslCfg.setProtocol(QSsl.SslProtocol.SecureProtocols) |
186 with contextlib.suppress(AttributeError): |
192 with contextlib.suppress(AttributeError): |
187 sslCfg.setSslOption( |
193 sslCfg.setSslOption( |
188 QSsl.SslOption.SslOptionDisableCompression, |
194 QSsl.SslOption.SslOptionDisableCompression, True |
189 True) |
195 ) |
190 QSslConfiguration.setDefaultConfiguration(sslCfg) |
196 QSslConfiguration.setDefaultConfiguration(sslCfg) |
191 |
197 |
192 certificateDict = {} |
198 certificateDict = {} |
193 for server in caMerge: |
199 for server in caMerge: |
194 pems = QByteArray() |
200 pems = QByteArray() |
195 for cert in caMerge[server]: |
201 for cert in caMerge[server]: |
196 pems.append(cert.toPem() + b'\n') |
202 pems.append(cert.toPem() + b"\n") |
197 certificateDict[server] = pems |
203 certificateDict[server] = pems |
198 Preferences.getSettings().setValue( |
204 Preferences.getSettings().setValue( |
199 "Ssl/CaCertificatesDict", |
205 "Ssl/CaCertificatesDict", certificateDict |
200 certificateDict) |
206 ) |
201 |
207 |
202 return EricSslErrorState.USER_IGNORED, caRet |
208 return EricSslErrorState.USER_IGNORED, caRet |
203 |
209 |
204 else: |
210 else: |
205 return EricSslErrorState.NOT_IGNORED, False |
211 return EricSslErrorState.NOT_IGNORED, False |
206 |
212 |
207 def __certToString(self, cert): |
213 def __certToString(self, cert): |
208 """ |
214 """ |
209 Private method to convert a certificate to a formatted string. |
215 Private method to convert a certificate to a formatted string. |
210 |
216 |
211 @param cert certificate to convert (QSslCertificate) |
217 @param cert certificate to convert (QSslCertificate) |
212 @return formatted string (string) |
218 @return formatted string (string) |
213 """ |
219 """ |
214 result = "<p>" |
220 result = "<p>" |
215 |
221 |
216 result += self.tr( |
222 result += self.tr("Name: {0}").format( |
217 "Name: {0}" |
|
218 ).format( |
|
219 Utilities.html_encode( |
223 Utilities.html_encode( |
220 Utilities.decodeString( |
224 Utilities.decodeString( |
221 ", ".join(cert.subjectInfo( |
225 ", ".join(cert.subjectInfo(QSslCertificate.SubjectInfo.CommonName)) |
222 QSslCertificate.SubjectInfo.CommonName)) |
226 ) |
223 ) |
227 ) |
224 ) |
228 ) |
225 ) |
229 |
226 |
230 result += self.tr("<br/>Organization: {0}").format( |
227 result += self.tr( |
|
228 "<br/>Organization: {0}" |
|
229 ).format( |
|
230 Utilities.html_encode( |
231 Utilities.html_encode( |
231 Utilities.decodeString( |
232 Utilities.decodeString( |
232 ", ".join(cert.subjectInfo( |
233 ", ".join( |
233 QSslCertificate.SubjectInfo.Organization)) |
234 cert.subjectInfo(QSslCertificate.SubjectInfo.Organization) |
234 ) |
235 ) |
235 ) |
236 ) |
236 ) |
237 ) |
237 |
238 ) |
238 result += self.tr( |
239 |
239 "<br/>Issuer: {0}" |
240 result += self.tr("<br/>Issuer: {0}").format( |
240 ).format( |
|
241 Utilities.html_encode( |
241 Utilities.html_encode( |
242 Utilities.decodeString( |
242 Utilities.decodeString( |
243 ", ".join(cert.issuerInfo( |
243 ", ".join(cert.issuerInfo(QSslCertificate.SubjectInfo.CommonName)) |
244 QSslCertificate.SubjectInfo.CommonName)) |
244 ) |
245 ) |
245 ) |
246 ) |
246 ) |
247 ) |
247 result += self.tr("<br/>Not valid before: {0}<br/>Valid Until: {1}").format( |
248 result += self.tr( |
248 Utilities.html_encode(cert.effectiveDate().toString("yyyy-MM-dd")), |
249 "<br/>Not valid before: {0}<br/>Valid Until: {1}" |
249 Utilities.html_encode(cert.expiryDate().toString("yyyy-MM-dd")), |
250 ).format( |
250 ) |
251 Utilities.html_encode( |
251 |
252 cert.effectiveDate().toString("yyyy-MM-dd") |
|
253 ), |
|
254 Utilities.html_encode( |
|
255 cert.expiryDate().toString("yyyy-MM-dd") |
|
256 ) |
|
257 ) |
|
258 |
|
259 result += "</p>" |
252 result += "</p>" |
260 |
253 |
261 return result |
254 return result |
262 |
255 |
263 def __getSystemCaCertificates(self): |
256 def __getSystemCaCertificates(self): |
264 """ |
257 """ |
265 Private method to get the list of system certificates. |
258 Private method to get the list of system certificates. |
266 |
259 |
267 @return list of system certificates (list of QSslCertificate) |
260 @return list of system certificates (list of QSslCertificate) |
268 """ |
261 """ |
269 caList = QSslCertificate.fromData(Globals.toByteArray( |
262 caList = QSslCertificate.fromData( |
270 Preferences.getSettings().value("Ssl/SystemCertificates"))) |
263 Globals.toByteArray( |
|
264 Preferences.getSettings().value("Ssl/SystemCertificates") |
|
265 ) |
|
266 ) |
271 if not caList: |
267 if not caList: |
272 caList = QSslConfiguration.systemCaCertificates() |
268 caList = QSslConfiguration.systemCaCertificates() |
273 return caList |
269 return caList |